Improve TestCompiler and allow lookup based class defines

Update the `TestCompiler` so that classes can be defined using
a `Lookup`. This update allows package-private classes to be
accessed without needing a quite so unusual classloader setup.

The `@CompileWithTargetClassAccess` should be added to any
test that needs to use `Lookup` based defines. The test will
run with a completed forked classloader so not to pollute the
main classloader.

This commit also adds some useful additional APIs.

See gh-28120
This commit is contained in:
Phillip Webb
2022-04-13 16:48:13 -07:00
parent b3efdf3c2b
commit 4b82546b97
18 changed files with 622 additions and 60 deletions

View File

@@ -18,6 +18,9 @@ package org.springframework.aot.test.generator.compile;
import org.junit.jupiter.api.Test;
import org.springframework.aot.test.generator.file.ResourceFiles;
import org.springframework.aot.test.generator.file.SourceFiles;
import static org.assertj.core.api.Assertions.assertThat;
@@ -31,8 +34,8 @@ class CompilationExceptionTests {
@Test
void getMessageReturnsMessage() {
CompilationException exception = new CompilationException("message");
assertThat(exception).hasMessage("message");
CompilationException exception = new CompilationException("message", SourceFiles.none(), ResourceFiles.none());
assertThat(exception).hasMessageContaining("message");
}
}

View File

@@ -26,6 +26,7 @@ import org.springframework.aot.test.generator.file.ResourceFiles;
import org.springframework.aot.test.generator.file.SourceFile;
import org.springframework.aot.test.generator.file.SourceFiles;
import org.springframework.aot.test.generator.file.WritableContent;
import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -170,7 +171,8 @@ class TestCompilerTests {
}
@Test
void compiledCodeCanAccessExistingPackagePrivateClass() {
@CompileWithTargetClassAccess(classNames = "com.example.PackagePrivate")
void compiledCodeCanAccessExistingPackagePrivateClassIfAnnotated() throws ClassNotFoundException, LinkageError {
SourceFiles sourceFiles = SourceFiles.of(SourceFile.of("""
package com.example;
@@ -187,6 +189,26 @@ class TestCompilerTests {
.isEqualTo("Hello from PackagePrivate"));
}
@Test
void compiledCodeCannotAccessExistingPackagePrivateClassIfNotAnnotated() {
SourceFiles sourceFiles = SourceFiles.of(SourceFile.of("""
package com.example;
public class Test implements PublicInterface {
public String perform() {
return new PackagePrivate().perform();
}
}
"""));
assertThatExceptionOfType(IllegalAccessError.class)
.isThrownBy(() -> TestCompiler.forSystem().compile(sourceFiles,
compiled -> compiled.getInstance(PublicInterface.class, "com.example.Test").perform()))
.withMessageContaining(ClassUtils.getShortName(CompileWithTargetClassAccess.class));
}
private void assertSuppliesHelloWorld(Compiled compiled) {
assertThat(compiled.getInstance(Supplier.class).get()).isEqualTo("Hello World!");
}