Redesign AOT processors for consistency and simplification
There's currently a considerable amount of overlap between the implementations of AotProcessor and TestAotProcessor. In addition AotProcessor is abstract and does not include a main() method; whereas, TestAotProcessor is concrete and does include a main() method. To address these issues, this commit: - Introduces an AbstractAotProcessor base class that AotProcessor and TestAotProcessor now both extend - Moves common properties/functionality to AbstractAotProcessor - Renames AotProcessor to ContextAotProcessor - Makes TestAotProcessor abstract like ContextAotProcessor - Removes the main() method from TestAotProcessor Closes gh-29266
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.aot;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.springframework.aot.generate.FileSystemGeneratedFiles;
|
||||
import org.springframework.aot.generate.GeneratedFiles.Kind;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.nativex.FileNativeConfigurationWriter;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for filesystem-based ahead-of-time (AOT) processing.
|
||||
*
|
||||
* <p>Concrete implementations are typically used to kick off optimization of an
|
||||
* application or test suite in a build tool.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
* @since 6.0
|
||||
* @see FileSystemGeneratedFiles
|
||||
* @see FileNativeConfigurationWriter
|
||||
* @see org.springframework.context.aot.ContextAotProcessor
|
||||
* @see org.springframework.test.context.aot.TestAotProcessor
|
||||
*/
|
||||
public abstract class AbstractAotProcessor {
|
||||
|
||||
private final Path sourceOutput;
|
||||
|
||||
private final Path resourceOutput;
|
||||
|
||||
private final Path classOutput;
|
||||
|
||||
private final String groupId;
|
||||
|
||||
private final String artifactId;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new processor instance.
|
||||
* @param sourceOutput the location of generated sources
|
||||
* @param resourceOutput the location of generated resources
|
||||
* @param classOutput the location of generated classes
|
||||
* @param groupId the group ID of the application, used to locate
|
||||
* {@code native-image.properties}
|
||||
* @param artifactId the artifact ID of the application, used to locate
|
||||
* {@code native-image.properties}
|
||||
*/
|
||||
protected AbstractAotProcessor(Path sourceOutput, Path resourceOutput,
|
||||
Path classOutput, String groupId, String artifactId) {
|
||||
|
||||
this.sourceOutput = sourceOutput;
|
||||
this.resourceOutput = resourceOutput;
|
||||
this.classOutput = classOutput;
|
||||
this.groupId = groupId;
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the output directory for generated sources.
|
||||
*/
|
||||
protected Path getSourceOutput() {
|
||||
return this.sourceOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the output directory for generated resources.
|
||||
*/
|
||||
protected Path getResourceOutput() {
|
||||
return this.resourceOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the output directory for generated classes.
|
||||
*/
|
||||
protected Path getClassOutput() {
|
||||
return this.classOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the group ID of the application.
|
||||
*/
|
||||
protected String getGroupId() {
|
||||
return this.groupId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the artifact ID of the application.
|
||||
*/
|
||||
protected String getArtifactId() {
|
||||
return this.artifactId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the source, resource, and class output directories.
|
||||
*/
|
||||
protected void deleteExistingOutput() {
|
||||
deleteExistingOutput(getSourceOutput(), getResourceOutput(), getClassOutput());
|
||||
}
|
||||
|
||||
private void deleteExistingOutput(Path... paths) {
|
||||
for (Path path : paths) {
|
||||
try {
|
||||
FileSystemUtils.deleteRecursively(path);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException("Failed to delete existing output in '" + path + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected FileSystemGeneratedFiles createFileSystemGeneratedFiles() {
|
||||
return new FileSystemGeneratedFiles(this::getRoot);
|
||||
}
|
||||
|
||||
private Path getRoot(Kind kind) {
|
||||
return switch (kind) {
|
||||
case SOURCE -> getSourceOutput();
|
||||
case RESOURCE -> getResourceOutput();
|
||||
case CLASS -> getClassOutput();
|
||||
};
|
||||
}
|
||||
|
||||
protected void writeHints(RuntimeHints hints) {
|
||||
FileNativeConfigurationWriter writer =
|
||||
new FileNativeConfigurationWriter(getResourceOutput(), getGroupId(), getArtifactId());
|
||||
writer.write(hints);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,40 +26,29 @@ import java.util.List;
|
||||
import org.springframework.aot.generate.ClassNameGenerator;
|
||||
import org.springframework.aot.generate.DefaultGenerationContext;
|
||||
import org.springframework.aot.generate.FileSystemGeneratedFiles;
|
||||
import org.springframework.aot.generate.GeneratedFiles.Kind;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.ReflectionHints;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.TypeReference;
|
||||
import org.springframework.aot.nativex.FileNativeConfigurationWriter;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
|
||||
/**
|
||||
* Filesystem-based ahead-of-time processing base implementation. Typically
|
||||
* used to kick off the optimizations of an application in a build tool.
|
||||
* Filesystem-based ahead-of-time (AOT) processing base implementation.
|
||||
*
|
||||
* <p>Concrete implementations are typically used to kick off optimization of an
|
||||
* application in a build tool.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 6.0
|
||||
* @see org.springframework.test.context.aot.TestAotProcessor
|
||||
*/
|
||||
public abstract class AotProcessor {
|
||||
public abstract class ContextAotProcessor extends AbstractAotProcessor {
|
||||
|
||||
private final Class<?> application;
|
||||
|
||||
private final Path sourceOutput;
|
||||
|
||||
private final Path resourceOutput;
|
||||
|
||||
private final Path classOutput;
|
||||
|
||||
private final String groupId;
|
||||
|
||||
private final String artifactId;
|
||||
|
||||
/**
|
||||
* Create a new processor instance.
|
||||
* @param application the application entry point
|
||||
@@ -71,25 +60,13 @@ public abstract class AotProcessor {
|
||||
* @param artifactId the artifact ID of the application, used to locate
|
||||
* {@code native-image.properties}
|
||||
*/
|
||||
protected AotProcessor(Class<?> application, Path sourceOutput, Path resourceOutput,
|
||||
protected ContextAotProcessor(Class<?> application, Path sourceOutput, Path resourceOutput,
|
||||
Path classOutput, String groupId, String artifactId) {
|
||||
|
||||
super(sourceOutput, resourceOutput, classOutput, groupId, artifactId);
|
||||
this.application = application;
|
||||
this.sourceOutput = sourceOutput;
|
||||
this.resourceOutput = resourceOutput;
|
||||
this.classOutput = classOutput;
|
||||
this.groupId = groupId;
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the {@link GenericApplicationContext} for the specified
|
||||
* application to be used against an {@link ApplicationContextAotGenerator}.
|
||||
* @return a non-refreshed {@link GenericApplicationContext}
|
||||
*/
|
||||
protected abstract GenericApplicationContext prepareApplicationContext(Class<?> application);
|
||||
|
||||
|
||||
/**
|
||||
* Invoke the processing by clearing output directories first, followed by
|
||||
* {@link #performAotProcessing(GenericApplicationContext)}.
|
||||
@@ -103,11 +80,11 @@ public abstract class AotProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the source, resource, and class output directories.
|
||||
* Prepare the {@link GenericApplicationContext} for the specified
|
||||
* application to be used against an {@link ApplicationContextAotGenerator}.
|
||||
* @return a non-refreshed {@link GenericApplicationContext}
|
||||
*/
|
||||
protected void deleteExistingOutput() {
|
||||
deleteExistingOutput(this.sourceOutput, this.resourceOutput, this.classOutput);
|
||||
}
|
||||
protected abstract GenericApplicationContext prepareApplicationContext(Class<?> application);
|
||||
|
||||
/**
|
||||
* Perform ahead-of-time processing of the specified context.
|
||||
@@ -117,7 +94,7 @@ public abstract class AotProcessor {
|
||||
* @param applicationContext the context to process
|
||||
*/
|
||||
protected ClassName performAotProcessing(GenericApplicationContext applicationContext) {
|
||||
FileSystemGeneratedFiles generatedFiles = new FileSystemGeneratedFiles(this::getRoot);
|
||||
FileSystemGeneratedFiles generatedFiles = createFileSystemGeneratedFiles();
|
||||
DefaultGenerationContext generationContext = new DefaultGenerationContext(
|
||||
createClassNameGenerator(), generatedFiles);
|
||||
ApplicationContextAotGenerator generator = new ApplicationContextAotGenerator();
|
||||
@@ -167,12 +144,6 @@ public abstract class AotProcessor {
|
||||
.withConstructor(Collections.emptyList(), ExecutableMode.INVOKE));
|
||||
}
|
||||
|
||||
private void writeHints(RuntimeHints hints) {
|
||||
FileNativeConfigurationWriter writer =
|
||||
new FileNativeConfigurationWriter(this.resourceOutput, this.groupId, this.artifactId);
|
||||
writer.write(hints);
|
||||
}
|
||||
|
||||
private void writeNativeImageProperties(List<String> args) {
|
||||
if (CollectionUtils.isEmpty(args)) {
|
||||
return;
|
||||
@@ -180,8 +151,8 @@ public abstract class AotProcessor {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Args = ");
|
||||
sb.append(String.join(String.format(" \\%n"), args));
|
||||
Path file = this.resourceOutput
|
||||
.resolve("META-INF/native-image/" + this.groupId + "/" + this.artifactId + "/native-image.properties");
|
||||
Path file = getResourceOutput()
|
||||
.resolve("META-INF/native-image/" + getGroupId() + "/" + getArtifactId() + "/native-image.properties");
|
||||
try {
|
||||
if (!Files.exists(file)) {
|
||||
Files.createDirectories(file.getParent());
|
||||
@@ -190,27 +161,8 @@ public abstract class AotProcessor {
|
||||
Files.writeString(file, sb.toString());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Failed to write native-image properties", ex);
|
||||
throw new IllegalStateException("Failed to write native-image.properties", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteExistingOutput(Path... paths) {
|
||||
for (Path path : paths) {
|
||||
try {
|
||||
FileSystemUtils.deleteRecursively(path);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException("Failed to delete existing output in '" + path + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Path getRoot(Kind kind) {
|
||||
return switch (kind) {
|
||||
case SOURCE -> this.sourceOutput;
|
||||
case RESOURCE -> this.resourceOutput;
|
||||
case CLASS -> this.classOutput;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,20 +35,20 @@ import org.springframework.javapoet.ClassName;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link AotProcessor}.
|
||||
* Tests for {@link ContextAotProcessor}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class AotProcessorTests {
|
||||
class ContextAotProcessorTests {
|
||||
|
||||
@Test
|
||||
void processGeneratesAssets(@TempDir Path directory) {
|
||||
GenericApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.registerBean(SampleApplication.class);
|
||||
AotProcessor processor = new TestAotProcessor(SampleApplication.class, directory);
|
||||
ContextAotProcessor processor = new DemoContextAotProcessor(SampleApplication.class, directory);
|
||||
ClassName className = processor.process();
|
||||
assertThat(className).isEqualTo(ClassName.get(SampleApplication.class.getPackageName(),
|
||||
"AotProcessorTests_SampleApplication__ApplicationContextInitializer"));
|
||||
"ContextAotProcessorTests_SampleApplication__ApplicationContextInitializer"));
|
||||
assertThat(directory).satisfies(hasGeneratedAssetsForSampleApplication());
|
||||
context.close();
|
||||
}
|
||||
@@ -61,7 +61,7 @@ class AotProcessorTests {
|
||||
Path existingSourceOutput = createExisting(sourceOutput);
|
||||
Path existingResourceOutput = createExisting(resourceOutput);
|
||||
Path existingClassOutput = createExisting(classOutput);
|
||||
AotProcessor processor = new TestAotProcessor(SampleApplication.class,
|
||||
ContextAotProcessor processor = new DemoContextAotProcessor(SampleApplication.class,
|
||||
sourceOutput, resourceOutput, classOutput);
|
||||
processor.process();
|
||||
assertThat(existingSourceOutput).doesNotExist();
|
||||
@@ -73,7 +73,7 @@ class AotProcessorTests {
|
||||
void processWithEmptyNativeImageArgumentsDoesNotCreateNativeImageProperties(@TempDir Path directory) {
|
||||
GenericApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.registerBean(SampleApplication.class);
|
||||
AotProcessor processor = new TestAotProcessor(SampleApplication.class, directory) {
|
||||
ContextAotProcessor processor = new DemoContextAotProcessor(SampleApplication.class, directory) {
|
||||
@Override
|
||||
protected List<String> getDefaultNativeImageArguments(String application) {
|
||||
return Collections.emptyList();
|
||||
@@ -95,19 +95,19 @@ class AotProcessorTests {
|
||||
private Consumer<Path> hasGeneratedAssetsForSampleApplication() {
|
||||
return directory -> {
|
||||
assertThat(directory.resolve(
|
||||
"source/org/springframework/context/aot/AotProcessorTests_SampleApplication__ApplicationContextInitializer.java"))
|
||||
"source/org/springframework/context/aot/ContextAotProcessorTests_SampleApplication__ApplicationContextInitializer.java"))
|
||||
.exists().isRegularFile();
|
||||
assertThat(directory.resolve("source/org/springframework/context/aot/AotProcessorTests__BeanDefinitions.java"))
|
||||
assertThat(directory.resolve("source/org/springframework/context/aot/ContextAotProcessorTests__BeanDefinitions.java"))
|
||||
.exists().isRegularFile();
|
||||
assertThat(directory.resolve(
|
||||
"source/org/springframework/context/aot/AotProcessorTests_SampleApplication__BeanFactoryRegistrations.java"))
|
||||
"source/org/springframework/context/aot/ContextAotProcessorTests_SampleApplication__BeanFactoryRegistrations.java"))
|
||||
.exists().isRegularFile();
|
||||
assertThat(directory.resolve("resource/META-INF/native-image/com.example/example/reflect-config.json"))
|
||||
.exists().isRegularFile();
|
||||
Path nativeImagePropertiesFile = directory
|
||||
.resolve("resource/META-INF/native-image/com.example/example/native-image.properties");
|
||||
assertThat(nativeImagePropertiesFile).exists().isRegularFile().hasContent("""
|
||||
Args = -H:Class=org.springframework.context.aot.AotProcessorTests$SampleApplication \\
|
||||
Args = -H:Class=org.springframework.context.aot.ContextAotProcessorTests$SampleApplication \\
|
||||
--report-unsupported-elements-at-runtime \\
|
||||
--no-fallback \\
|
||||
--install-exit-handlers
|
||||
@@ -116,14 +116,14 @@ class AotProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
private static class TestAotProcessor extends AotProcessor {
|
||||
private static class DemoContextAotProcessor extends ContextAotProcessor {
|
||||
|
||||
public TestAotProcessor(Class<?> application,
|
||||
DemoContextAotProcessor(Class<?> application,
|
||||
Path sourceOutput, Path resourceOutput, Path classOutput) {
|
||||
super(application, sourceOutput, resourceOutput, classOutput, "com.example", "example");
|
||||
}
|
||||
|
||||
public TestAotProcessor(Class<?> application, Path rootPath) {
|
||||
DemoContextAotProcessor(Class<?> application, Path rootPath) {
|
||||
super(application, rootPath.resolve("source"), rootPath.resolve("resource"),
|
||||
rootPath.resolve("class"), "com.example", "example");
|
||||
}
|
||||
@@ -16,52 +16,29 @@
|
||||
|
||||
package org.springframework.test.context.aot;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.aot.generate.FileSystemGeneratedFiles;
|
||||
import org.springframework.aot.generate.GeneratedFiles;
|
||||
import org.springframework.aot.generate.GeneratedFiles.Kind;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.nativex.FileNativeConfigurationWriter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.context.aot.AbstractAotProcessor;
|
||||
|
||||
/**
|
||||
* Filesystem-based ahead-of-time (AOT) processing base implementation that scans
|
||||
* the provided classpath roots for Spring integration test classes and then
|
||||
* generates AOT artifacts for those test classes in the configured output directories.
|
||||
*
|
||||
* <p>Typically used in a build tool.
|
||||
* <p>Concrete implementations are typically used to kick off optimization of a
|
||||
* test suite in a build tool.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Stephane Nicoll
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 6.0
|
||||
* @see TestContextAotGenerator
|
||||
* @see FileNativeConfigurationWriter
|
||||
* @see org.springframework.context.aot.AotProcessor
|
||||
* @see org.springframework.context.aot.ContextAotProcessor
|
||||
*/
|
||||
public class TestAotProcessor {
|
||||
public abstract class TestAotProcessor extends AbstractAotProcessor {
|
||||
|
||||
private final Path[] classpathRoots;
|
||||
|
||||
private final Path sourceOutput;
|
||||
|
||||
private final Path resourceOutput;
|
||||
|
||||
private final Path classOutput;
|
||||
|
||||
private final String groupId;
|
||||
|
||||
private final String artifactId;
|
||||
private final Set<Path> classpathRoots;
|
||||
|
||||
|
||||
/**
|
||||
@@ -76,15 +53,11 @@ public class TestAotProcessor {
|
||||
* @param artifactId the artifact ID of the application, used to locate
|
||||
* {@code native-image.properties}
|
||||
*/
|
||||
public TestAotProcessor(Path[] classpathRoots, Path sourceOutput, Path resourceOutput, Path classOutput,
|
||||
public TestAotProcessor(Set<Path> classpathRoots, Path sourceOutput, Path resourceOutput, Path classOutput,
|
||||
String groupId, String artifactId) {
|
||||
|
||||
super(sourceOutput, resourceOutput, classOutput, groupId, artifactId);
|
||||
this.classpathRoots = classpathRoots;
|
||||
this.sourceOutput = sourceOutput;
|
||||
this.resourceOutput = resourceOutput;
|
||||
this.classOutput = classOutput;
|
||||
this.groupId = groupId;
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,24 +71,6 @@ public class TestAotProcessor {
|
||||
performAotProcessing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the source, resource, and class output directories.
|
||||
*/
|
||||
protected void deleteExistingOutput() {
|
||||
deleteExistingOutput(this.sourceOutput, this.resourceOutput, this.classOutput);
|
||||
}
|
||||
|
||||
private void deleteExistingOutput(Path... paths) {
|
||||
for (Path path : paths) {
|
||||
try {
|
||||
FileSystemUtils.deleteRecursively(path);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException("Failed to delete existing output in '%s'".formatted(path), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform ahead-of-time processing of Spring integration test classes.
|
||||
* <p>Code, resources, and generated classes are stored in the configured
|
||||
@@ -124,43 +79,14 @@ public class TestAotProcessor {
|
||||
* components used by the tests.
|
||||
*/
|
||||
protected void performAotProcessing() {
|
||||
TestClassScanner scanner = new TestClassScanner(Set.of(this.classpathRoots));
|
||||
TestClassScanner scanner = new TestClassScanner(this.classpathRoots);
|
||||
Stream<Class<?>> testClasses = scanner.scan();
|
||||
|
||||
GeneratedFiles generatedFiles = new FileSystemGeneratedFiles(this::getRoot);
|
||||
GeneratedFiles generatedFiles = createFileSystemGeneratedFiles();
|
||||
TestContextAotGenerator generator = new TestContextAotGenerator(generatedFiles);
|
||||
generator.processAheadOfTime(testClasses);
|
||||
|
||||
writeHints(generator.getRuntimeHints());
|
||||
}
|
||||
|
||||
private Path getRoot(Kind kind) {
|
||||
return switch (kind) {
|
||||
case SOURCE -> this.sourceOutput;
|
||||
case RESOURCE -> this.resourceOutput;
|
||||
case CLASS -> this.classOutput;
|
||||
};
|
||||
}
|
||||
|
||||
private void writeHints(RuntimeHints hints) {
|
||||
FileNativeConfigurationWriter writer =
|
||||
new FileNativeConfigurationWriter(this.resourceOutput, this.groupId, this.artifactId);
|
||||
writer.write(hints);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
int requiredArgs = 6;
|
||||
Assert.isTrue(args.length >= requiredArgs, () ->
|
||||
"Usage: %s <classpathRoots> <sourceOutput> <resourceOutput> <classOutput> <groupId> <artifactId>"
|
||||
.formatted(TestAotProcessor.class.getName()));
|
||||
Path[] classpathRoots = Arrays.stream(args[0].split(File.pathSeparator)).map(Paths::get).toArray(Path[]::new);
|
||||
Path sourceOutput = Paths.get(args[1]);
|
||||
Path resourceOutput = Paths.get(args[2]);
|
||||
Path classOutput = Paths.get(args[3]);
|
||||
String groupId = args[4];
|
||||
String artifactId = args[5];
|
||||
new TestAotProcessor(classpathRoots, sourceOutput, resourceOutput, classOutput, groupId, artifactId).process();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -58,14 +59,15 @@ class TestAotProcessorTests extends AbstractAotTests {
|
||||
BasicSpringVintageTests.class
|
||||
).forEach(testClass -> copy(testClass, classpathRoot));
|
||||
|
||||
Path[] classpathRoots = { classpathRoot };
|
||||
Set<Path> classpathRoots = Set.of(classpathRoot);
|
||||
Path sourceOutput = tempDir.resolve("generated/sources");
|
||||
Path resourceOutput = tempDir.resolve("generated/resources");
|
||||
Path classOutput = tempDir.resolve("generated/classes");
|
||||
String groupId = "org.example";
|
||||
String artifactId = "app-tests";
|
||||
|
||||
TestAotProcessor processor = new TestAotProcessor(classpathRoots, sourceOutput, resourceOutput, classOutput, groupId, artifactId);
|
||||
TestAotProcessor processor =
|
||||
new DemoTestAotProcessor(classpathRoots, sourceOutput, resourceOutput, classOutput, groupId, artifactId);
|
||||
processor.process();
|
||||
|
||||
assertThat(findFiles(sourceOutput)).containsExactlyInAnyOrderElementsOf(expectedSourceFiles());
|
||||
@@ -97,4 +99,13 @@ class TestAotProcessorTests extends AbstractAotTests {
|
||||
return Arrays.stream(expectedSourceFilesForBasicSpringTests).map(Path::of).toList();
|
||||
}
|
||||
|
||||
|
||||
private static class DemoTestAotProcessor extends TestAotProcessor {
|
||||
|
||||
DemoTestAotProcessor(Set<Path> classpathRoots, Path sourceOutput, Path resourceOutput, Path classOutput,
|
||||
String groupId, String artifactId) {
|
||||
super(classpathRoots, sourceOutput, resourceOutput, classOutput, groupId, artifactId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user