Rename @CompileWithTargetClassAccess

Rename `@CompileWithTargetClassAccess` to
`@CompileWithForkedClassLoaderClassLoader`.

Closes gh-29173
This commit is contained in:
Phillip Webb
2022-09-19 09:37:36 -07:00
parent 7168141504
commit cc7552ec61
12 changed files with 37 additions and 36 deletions

View File

@@ -26,8 +26,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
/**
* Annotation that registers a JUnit Jupiter extension for test classes or test
* methods that need a {@link TestCompiler} with non-public access to target
* classes.
* methods that need to use a forked classloader with compiled code.
*
* <p>The extension allows the compiler to define classes without polluting the
* test {@link ClassLoader}.
@@ -45,6 +44,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@ExtendWith(CompileWithTargetClassAccessExtension.class)
public @interface CompileWithTargetClassAccess {
@ExtendWith(CompileWithForkedClassLoaderExtension.class)
public @interface CompileWithForkedClassLoader {
}

View File

@@ -26,29 +26,38 @@ import org.springframework.lang.Nullable;
/**
* {@link ClassLoader} implementation to support
* {@link CompileWithTargetClassAccess @CompileWithTargetClassAccess}.
* {@link CompileWithForkedClassLoader @CompileWithForkedClassLoader}.
*
* @author Phillip Webb
* @author Andy Wilkinson
* @author Stephane Nicoll
* @since 6.0
*/
final class CompileWithTargetClassAccessClassLoader extends ClassLoader {
final class CompileWithForkedClassLoaderClassLoader extends ClassLoader {
private final ClassLoader testClassLoader;
private Function<String, byte[]> classResourceLookup = name -> null;
public CompileWithTargetClassAccessClassLoader(ClassLoader testClassLoader) {
public CompileWithForkedClassLoaderClassLoader(ClassLoader testClassLoader) {
super(testClassLoader.getParent());
this.testClassLoader = testClassLoader;
}
// Invoked reflectively by DynamicClassLoader constructor
// Invoked reflectively by DynamicClassLoader
@SuppressWarnings("unused")
void setClassResourceLookup(Function<String, byte[]> classResourceLookup) {
this.classResourceLookup = classResourceLookup;
}
// Invoked reflectively by DynamicClassLoader
@SuppressWarnings("unused")
Class<?> defineDynamicClass(String name, byte[] b, int off, int len) {
return super.defineClass(name, b, off, len);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.startsWith("org.junit") || name.startsWith("org.testng")) {
@@ -82,13 +91,6 @@ final class CompileWithTargetClassAccessClassLoader extends ClassLoader {
return null;
}
// Invoked reflectively by DynamicClassLoader.findDefineClassMethod(ClassLoader)
@SuppressWarnings("unused")
Class<?> defineClassWithTargetAccess(String name, byte[] b, int off, int len) {
return super.defineClass(name, b, off, len);
}
@Override
protected Enumeration<URL> findResources(String name) throws IOException {
return this.testClassLoader.getResources(name);

View File

@@ -34,14 +34,14 @@ import static org.junit.platform.launcher.EngineFilter.includeEngines;
/**
* JUnit Jupiter {@link InvocationInterceptor} to support
* {@link CompileWithTargetClassAccess @CompileWithTargetClassAccess}.
* {@link CompileWithForkedClassLoader @CompileWithForkedClassLoader}.
*
* @author Christoph Dreis
* @author Phillip Webb
* @author Sam Brannen
* @since 6.0
*/
class CompileWithTargetClassAccessExtension implements InvocationInterceptor {
class CompileWithForkedClassLoaderExtension implements InvocationInterceptor {
@Override
public void interceptBeforeAllMethod(Invocation<Void> invocation,
@@ -105,7 +105,7 @@ class CompileWithTargetClassAccessExtension implements InvocationInterceptor {
Class<?> testClass = extensionContext.getRequiredTestClass();
ClassLoader classLoader = testClass.getClassLoader();
return classLoader.getClass().getName()
.equals(CompileWithTargetClassAccessClassLoader.class.getName());
.equals(CompileWithForkedClassLoaderClassLoader.class.getName());
}
private void runTestWithModifiedClassPath(
@@ -115,7 +115,7 @@ class CompileWithTargetClassAccessExtension implements InvocationInterceptor {
Class<?> testClass = extensionContext.getRequiredTestClass();
Method testMethod = invocationContext.getExecutable();
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader forkedClassPathClassLoader = new CompileWithTargetClassAccessClassLoader(
ClassLoader forkedClassPathClassLoader = new CompileWithForkedClassLoaderClassLoader(
testClass.getClassLoader());
Thread.currentThread().setContextClassLoader(forkedClassPathClassLoader);
try {

View File

@@ -63,14 +63,14 @@ public class DynamicClassLoader extends ClassLoader {
this.classFiles = classFiles;
this.compiledClasses = compiledClasses;
Class<? extends ClassLoader> parentClass = parent.getClass();
if (parentClass.getName().equals(CompileWithTargetClassAccessClassLoader.class.getName())) {
if (parentClass.getName().equals(CompileWithForkedClassLoaderClassLoader.class.getName())) {
Method setClassResourceLookupMethod = ReflectionUtils.findMethod(parentClass,
"setClassResourceLookup", Function.class);
ReflectionUtils.makeAccessible(setClassResourceLookupMethod);
ReflectionUtils.invokeMethod(setClassResourceLookupMethod,
getParent(), (Function<String, byte[]>) this::findClassBytes);
this.defineClassMethod = ReflectionUtils.findMethod(parentClass,
"defineClassWithTargetAccess", String.class, byte[].class, int.class, int.class);
"defineDynamicClass", String.class, byte[].class, int.class, int.class);
ReflectionUtils.makeAccessible(this.defineClassMethod);
this.compiledClasses.forEach((name, file) -> defineClass(name, file.getBytes()));
}

View File

@@ -276,7 +276,7 @@ public final class TestCompiler {
}
catch (IllegalAccessError ex) {
throw new IllegalAccessError(ex.getMessage() + ". " +
"For non-public access ensure you annotate your test class or test method with @CompileWithTargetClassAccess");
"For non-public access ensure you annotate your test class or test method with @CompileWithForkedClassLoader");
}
finally {
Thread.currentThread().setContextClassLoader(previousClassLoader);

View File

@@ -206,7 +206,7 @@ class TestCompilerTests {
}
@Test
@CompileWithTargetClassAccess
@CompileWithForkedClassLoader
void compiledCodeCanAccessExistingPackagePrivateClassIfAnnotated() throws LinkageError {
SourceFiles sourceFiles = SourceFiles.of(SourceFile.of("""
package com.example;
@@ -240,7 +240,7 @@ class TestCompilerTests {
assertThatExceptionOfType(IllegalAccessError.class)
.isThrownBy(() -> TestCompiler.forSystem().compile(sourceFiles,
compiled -> compiled.getInstance(PublicInterface.class, "com.example.Test").perform()))
.withMessageContaining(ClassUtils.getShortName(CompileWithTargetClassAccess.class));
.withMessageContaining(ClassUtils.getShortName(CompileWithForkedClassLoader.class));
}
@Test