Commit bd81bb90 authored by Phillip Webb's avatar Phillip Webb

Polish ModifiedClassPath support

See gh-17491
parent 0f0278e6
......@@ -225,19 +225,16 @@ final class ModifiedClassPathClassLoaderFactory {
}
private boolean isExcluded(URL url) {
if (!"file".equals(url.getProtocol())) {
return false;
}
String name;
try {
name = new File(url.toURI()).getName();
}
catch (URISyntaxException ex) {
return false;
}
for (String exclusion : this.exclusions) {
if (this.matcher.match(exclusion, name)) {
return true;
if ("file".equals(url.getProtocol())) {
try {
String name = new File(url.toURI()).getName();
for (String exclusion : this.exclusions) {
if (this.matcher.match(exclusion, name)) {
return true;
}
}
}
catch (URISyntaxException ex) {
}
}
return false;
......
......@@ -52,25 +52,25 @@ public class ModifiedClassPathExtension implements InvocationInterceptor {
@Override
public void interceptBeforeAllMethod(Invocation<Void> invocation,
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
interceptInvocation(invocation, extensionContext);
intercept(invocation, extensionContext);
}
@Override
public void interceptBeforeEachMethod(Invocation<Void> invocation,
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
interceptInvocation(invocation, extensionContext);
intercept(invocation, extensionContext);
}
@Override
public void interceptAfterEachMethod(Invocation<Void> invocation,
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
interceptInvocation(invocation, extensionContext);
intercept(invocation, extensionContext);
}
@Override
public void interceptAfterAllMethod(Invocation<Void> invocation,
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
interceptInvocation(invocation, extensionContext);
intercept(invocation, extensionContext);
}
@Override
......@@ -80,62 +80,64 @@ public class ModifiedClassPathExtension implements InvocationInterceptor {
invocation.proceed();
return;
}
fakeInvocation(invocation);
runTestWithModifiedClassPath(invocationContext, extensionContext);
}
private void runTestWithModifiedClassPath(ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext) throws ClassNotFoundException, Throwable {
Class<?> testClass = extensionContext.getRequiredTestClass();
Method testMethod = invocationContext.getExecutable();
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
URLClassLoader classLoader = ModifiedClassPathClassLoaderFactory
.createTestClassLoader(extensionContext.getRequiredTestClass());
Thread.currentThread().setContextClassLoader(classLoader);
URLClassLoader modifiedClassLoader = ModifiedClassPathClassLoaderFactory.createTestClassLoader(testClass);
Thread.currentThread().setContextClassLoader(modifiedClassLoader);
try {
fakeInvocation(invocation);
TestExecutionSummary summary = launchTests(invocationContext, extensionContext, classLoader);
if (!CollectionUtils.isEmpty(summary.getFailures())) {
throw summary.getFailures().get(0).getException();
}
}
catch (Exception ex) {
throw ex;
runTest(modifiedClassLoader, testClass.getName(), testMethod.getName());
}
finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
private TestExecutionSummary launchTests(ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext, URLClassLoader classLoader) throws ClassNotFoundException {
Class<?> testClass = classLoader.loadClass(extensionContext.getRequiredTestClass().getName());
Method method = ReflectionUtils.findMethod(testClass, invocationContext.getExecutable().getName());
private void runTest(URLClassLoader classLoader, String testClassName, String testMethodName)
throws ClassNotFoundException, Throwable {
Class<?> testClass = classLoader.loadClass(testClassName);
Method testMethod = ReflectionUtils.findMethod(testClass, testMethodName);
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(DiscoverySelectors.selectMethod(testClass, method)).build();
.selectors(DiscoverySelectors.selectMethod(testClass, testMethod)).build();
Launcher launcher = LauncherFactory.create();
TestPlan testPlan = launcher.discover(request);
SummaryGeneratingListener listener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(listener);
launcher.execute(testPlan);
return listener.getSummary();
}
private boolean isModifiedClassPathClassLoader(ExtensionContext extensionContext) {
return extensionContext.getRequiredTestClass().getClassLoader().getClass().getName()
.equals(ModifiedClassPathClassLoader.class.getName());
TestExecutionSummary summary = listener.getSummary();
if (!CollectionUtils.isEmpty(summary.getFailures())) {
throw summary.getFailures().get(0).getException();
}
}
private void interceptInvocation(Invocation<Void> invocation, ExtensionContext extensionContext) throws Throwable {
private void intercept(Invocation<Void> invocation, ExtensionContext extensionContext) throws Throwable {
if (isModifiedClassPathClassLoader(extensionContext)) {
invocation.proceed();
return;
}
else {
fakeInvocation(invocation);
}
fakeInvocation(invocation);
}
private void fakeInvocation(Invocation invocation) {
private void fakeInvocation(Invocation<Void> invocation) {
try {
Field field = ReflectionUtils.findField(invocation.getClass(), "invoked");
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, invocation, new AtomicBoolean(true));
}
catch (Throwable ignore) {
catch (Throwable ex) {
}
}
private boolean isModifiedClassPathClassLoader(ExtensionContext extensionContext) {
Class<?> testClass = extensionContext.getRequiredTestClass();
ClassLoader classLoader = testClass.getClassLoader();
return classLoader.getClass().getName().equals(ModifiedClassPathClassLoader.class.getName());
}
}
......@@ -18,7 +18,6 @@ package org.springframework.boot.context.logging;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
......@@ -38,6 +37,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.slf4j.impl.StaticLoggerBinder;
......@@ -69,7 +69,6 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.FileSystemUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
......@@ -102,7 +101,8 @@ class LoggingApplicationListenerTests {
private final GenericApplicationContext context = new GenericApplicationContext();
private Path tempDir;
@TempDir
public Path tempDir;
private File logFile;
......@@ -111,7 +111,6 @@ class LoggingApplicationListenerTests {
@BeforeEach
void init(CapturedOutput output) throws SecurityException, IOException {
this.output = output;
this.tempDir = Files.createTempDirectory("logging-application-listener-tests");
this.logFile = new File(this.tempDir.toFile(), "foo.log");
LogManager.getLogManager().readConfiguration(JavaLoggingSystem.class.getResourceAsStream("logging.properties"));
multicastEvent(new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
......@@ -128,7 +127,6 @@ class LoggingApplicationListenerTests {
if (loggingSystem.getShutdownHandler() != null) {
loggingSystem.getShutdownHandler().run();
}
FileSystemUtils.deleteRecursively(this.tempDir);
System.clearProperty(LoggingSystem.class.getName());
System.clearProperty(LoggingSystemProperties.LOG_FILE);
System.clearProperty(LoggingSystemProperties.LOG_PATH);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment