Browse Source

Polish ModifiedClassPath support

See gh-17491
pull/17516/head
Phillip Webb 7 years ago
parent
commit
bd81bb90eb
  1. 23
      spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/runner/classpath/ModifiedClassPathClassLoaderFactory.java
  2. 68
      spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/runner/classpath/ModifiedClassPathExtension.java
  3. 8
      spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/logging/LoggingApplicationListenerTests.java

23
spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/runner/classpath/ModifiedClassPathClassLoaderFactory.java

@ -225,19 +225,16 @@ final class ModifiedClassPathClassLoaderFactory { @@ -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;

68
spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/runner/classpath/ModifiedClassPathExtension.java

@ -52,25 +52,25 @@ public class ModifiedClassPathExtension implements InvocationInterceptor { @@ -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 { @@ -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());
}
}

8
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/logging/LoggingApplicationListenerTests.java

@ -18,7 +18,6 @@ package org.springframework.boot.context.logging; @@ -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; @@ -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; @@ -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 { @@ -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 { @@ -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 { @@ -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);

Loading…
Cancel
Save