Skip to content

Commit f317a0b

Browse files
committed
WIP
1 parent 0061772 commit f317a0b

File tree

4 files changed

+94
-219
lines changed

4 files changed

+94
-219
lines changed

test-framework/junit5/src/main/java/io/quarkus/test/junit/AbstractJvmQuarkusTestExtension.java

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.junit.jupiter.api.extension.ExtensionContext;
2626

2727
import io.quarkus.bootstrap.BootstrapException;
28-
import io.quarkus.bootstrap.app.AugmentAction;
2928
import io.quarkus.bootstrap.app.CuratedApplication;
3029
import io.quarkus.bootstrap.app.RunningQuarkusApplication;
3130
import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
@@ -56,13 +55,13 @@ public class AbstractJvmQuarkusTestExtension extends AbstractQuarkusTestWithCont
5655
protected static Class<?> currentJUnitTestClass;
5756

5857
// TODO only used by QuarkusMainTest, fix that class and delete this
59-
protected PrepareResult createAugmentor(ExtensionContext context, Class<? extends QuarkusTestProfile> profile,
58+
protected QuarkusTestPrepareResult createAugmentor(ExtensionContext context, Class<? extends QuarkusTestProfile> profile,
6059
Collection<Runnable> shutdownTasks) throws Exception {
6160

6261
originalCl = Thread.currentThread().getContextClassLoader();
6362
final Class<?> requiredTestClass = context.getRequiredTestClass();
6463

65-
CuratedApplication curatedApplication = getCuratedApplication(requiredTestClass, context, shutdownTasks);
64+
CuratedApplication curatedApplication = getCuratedApplication(requiredTestClass, context.getDisplayName());
6665

6766
// TODO need to handle the gradle case - can we put it in that method?
6867
Path testClassLocation = getTestClassesLocation(requiredTestClass, curatedApplication);
@@ -90,17 +89,15 @@ protected PrepareResult createAugmentor(ExtensionContext context, Class<? extend
9089
props.put(TEST_PROFILE, profile.getName());
9190
}
9291
quarkusTestProfile = profile;
93-
return new PrepareResult(curatedApplication
92+
return new QuarkusTestPrepareResult(curatedApplication
9493
.createAugmentor(TestBuildChainFunction.class.getName(), props), profileInstance,
95-
curatedApplication, testClassLocation);
94+
curatedApplication);
9695
}
9796

98-
protected CuratedApplication getCuratedApplication(Class<?> requiredTestClass, ExtensionContext context,
99-
Collection<Runnable> shutdownTasks) throws BootstrapException, AppModelResolverException, IOException {
97+
protected CuratedApplication getCuratedApplication(Class<?> requiredTestClass, String displayName)
98+
throws AppModelResolverException, IOException, BootstrapException {
10099
// TODO make this abstract, push this implementation down to QuarkusTestExtension, since that is the only place it will work
101-
CuratedApplication curatedApplication = ((QuarkusClassLoader) requiredTestClass.getClassLoader())
102-
.getCuratedApplication();
103-
return curatedApplication;
100+
return ((QuarkusClassLoader) requiredTestClass.getClassLoader()).getCuratedApplication();
104101
}
105102

106103
protected static QuarkusTestProfile getQuarkusTestProfile(Class<? extends QuarkusTestProfile> profile,
@@ -298,19 +295,4 @@ public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext con
298295
return ConditionEvaluationResult.disabled("Test '" + context.getRequiredTestClass()
299296
+ "' disabled because 'quarkus.profile.test.tags' don't match the tags of '" + testProfile + "'");
300297
}
301-
302-
protected static class PrepareResult {
303-
protected final AugmentAction augmentAction;
304-
protected final QuarkusTestProfile profileInstance;
305-
protected final CuratedApplication curatedApplication;
306-
protected final Path testClassLocation;
307-
308-
public PrepareResult(AugmentAction augmentAction, QuarkusTestProfile profileInstance,
309-
CuratedApplication curatedApplication, Path testClassLocation) {
310-
this.augmentAction = augmentAction;
311-
this.profileInstance = profileInstance;
312-
this.curatedApplication = curatedApplication;
313-
this.testClassLocation = testClassLocation;
314-
}
315-
}
316298
}

test-framework/junit5/src/main/java/io/quarkus/test/junit/AppMakerHelper.java

Lines changed: 69 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import io.quarkus.bootstrap.workspace.SourceDir;
3838
import io.quarkus.bootstrap.workspace.WorkspaceModule;
3939
import io.quarkus.commons.classloading.ClassLoaderHelper;
40+
import io.quarkus.maven.dependency.DependencyFlags;
4041
import io.quarkus.paths.PathList;
4142
import io.quarkus.runtime.LaunchMode;
4243
import io.quarkus.test.common.PathTestHelper;
@@ -57,27 +58,14 @@ public class AppMakerHelper {
5758
private static List<Object> testMethodInvokers;
5859
private Runnable configCleanup;
5960

60-
public static class PrepareResult {
61-
protected final AugmentAction augmentAction;
62-
public final QuarkusTestProfile profileInstance;
63-
protected final CuratedApplication curatedApplication;
64-
65-
public PrepareResult(AugmentAction augmentAction, QuarkusTestProfile profileInstance,
66-
CuratedApplication curatedApplication) {
67-
68-
this.augmentAction = augmentAction;
69-
this.profileInstance = profileInstance;
70-
this.curatedApplication = curatedApplication;
71-
}
72-
}
73-
7461
public static ApplicationModel getGradleAppModelForIDE(Path projectRoot) throws IOException, AppModelResolverException {
7562
return System.getProperty(BootstrapConstants.SERIALIZED_TEST_APP_MODEL) == null
7663
? BuildToolHelper.enableGradleAppModelForTest(projectRoot)
7764
: null;
7865
}
7966

80-
private PrepareResult createAugmentor(final Class<?> requiredTestClass, String displayName, boolean isContinuousTesting,
67+
private QuarkusTestPrepareResult createAugmentor(final Class<?> requiredTestClass, String displayName,
68+
boolean isContinuousTesting,
8169
CuratedApplication curatedApplication,
8270
Class<? extends QuarkusTestProfile> profile,
8371
Collection<Runnable> shutdownTasks) throws AppModelResolverException, BootstrapException, IOException,
@@ -86,65 +74,70 @@ private PrepareResult createAugmentor(final Class<?> requiredTestClass, String d
8674
if (curatedApplication == null) {
8775
curatedApplication = makeCuratedApplication(requiredTestClass, displayName, isContinuousTesting, shutdownTasks);
8876
}
77+
8978
Path testClassLocation = getTestClassesLocation(requiredTestClass, curatedApplication);
9079

9180
// clear the test.url system property as the value leaks into the run when using different profiles
9281
System.clearProperty("test.url");
93-
Map<String, String> additional = new HashMap<>();
94-
95-
QuarkusTestProfile profileInstance = null;
96-
if (profile != null) {
97-
98-
profileInstance = new ClassCoercingTestProfile(profile.getConstructor()
99-
.newInstance());
100-
// TODO we make this twice, also in abstractjvmextension can we streamline that?
101-
// TODO We can't get rid of the one here because config needs to be set before augmentation, but maybe we can get rid of it on the test side?
102-
additional.putAll(profileInstance.getConfigOverrides());
103-
if (!profileInstance.getEnabledAlternatives()
104-
.isEmpty()) {
105-
additional.put("quarkus.arc.selected-alternatives", profileInstance.getEnabledAlternatives()
106-
.stream()
107-
.peek((c) -> {
108-
try {
109-
// TODO is string comparison more efficient?
110-
if (!c.isAnnotationPresent((Class<? extends Annotation>) profile.getClassLoader()
111-
.loadClass(Alternative.class.getName()))) {
112-
throw new RuntimeException(
113-
"Enabled alternative " + c + " is not annotated with @Alternative");
114-
}
115-
} catch (ClassNotFoundException e) {
116-
throw new RuntimeException(e);
117-
}
118-
})
119-
.map(Class::getName)
120-
.collect(Collectors.joining(",")));
121-
}
122-
if (profileInstance.disableApplicationLifecycleObservers()) {
123-
additional.put("quarkus.arc.test.disable-application-lifecycle-observers", "true");
124-
}
125-
if (profileInstance.getConfigProfile() != null) {
126-
additional.put(LaunchMode.TEST.getProfileKey(), profileInstance.getConfigProfile());
127-
}
128-
129-
//we just use system properties for now
130-
//it's a lot simpler
131-
// TODO this is really ugly, set proper config on the app
132-
// Sadly, I don't think #42715 helps, because it kicks in after this code
133-
configCleanup = RestorableSystemProperties.setProperties(additional)::close;
134-
}
135-
136-
if (curatedApplication
137-
.getApplicationModel().getRuntimeDependencies().isEmpty()) {
138-
throw new RuntimeException(
139-
"The tests were run against a directory that does not contain a Quarkus project. Please ensure that the test is configured to use the proper working directory.");
140-
}
14182

14283
// TODO should we do this here, or when we prepare the curated application?
14384
// Or is it needed at all?
14485
Index testClassesIndex = TestClassIndexer.indexTestClasses(testClassLocation);
14586
// we need to write the Index to make it reusable from other parts of the testing infrastructure that run in different ClassLoaders
14687
TestClassIndexer.writeIndex(testClassesIndex, testClassLocation, requiredTestClass);
14788

89+
return getPrepareResult(requiredTestClass, curatedApplication, profile, testClassLocation);
90+
}
91+
92+
private QuarkusTestProfile getQuarkusTestProfile(Class<? extends QuarkusTestProfile> profile)
93+
throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
94+
if (profile == null) {
95+
return null;
96+
}
97+
final QuarkusTestProfile profileInstance = new ClassCoercingTestProfile(profile.getConstructor()
98+
.newInstance());
99+
final Map<String, String> additional = new HashMap<>();
100+
// TODO we make this twice, also in abstractjvmextension can we streamline that?
101+
// TODO We can't get rid of the one here because config needs to be set before augmentation, but maybe we can get rid of it on the test side?
102+
additional.putAll(profileInstance.getConfigOverrides());
103+
if (!profileInstance.getEnabledAlternatives()
104+
.isEmpty()) {
105+
additional.put("quarkus.arc.selected-alternatives", profileInstance.getEnabledAlternatives()
106+
.stream()
107+
.peek((c) -> {
108+
try {
109+
// TODO is string comparison more efficient?
110+
if (!c.isAnnotationPresent((Class<? extends Annotation>) profile.getClassLoader()
111+
.loadClass(Alternative.class.getName()))) {
112+
throw new RuntimeException(
113+
"Enabled alternative " + c + " is not annotated with @Alternative");
114+
}
115+
} catch (ClassNotFoundException e) {
116+
throw new RuntimeException(e);
117+
}
118+
})
119+
.map(Class::getName)
120+
.collect(Collectors.joining(",")));
121+
}
122+
if (profileInstance.disableApplicationLifecycleObservers()) {
123+
additional.put("quarkus.arc.test.disable-application-lifecycle-observers", "true");
124+
}
125+
if (profileInstance.getConfigProfile() != null) {
126+
additional.put(LaunchMode.TEST.getProfileKey(), profileInstance.getConfigProfile());
127+
}
128+
129+
//we just use system properties for now
130+
//it's a lot simpler
131+
// TODO this is really ugly, set proper config on the app
132+
// Sadly, I don't think #42715 helps, because it kicks in after this code
133+
configCleanup = RestorableSystemProperties.setProperties(additional)::close;
134+
return profileInstance;
135+
}
136+
137+
private QuarkusTestPrepareResult getPrepareResult(Class<?> requiredTestClass, CuratedApplication curatedApplication,
138+
Class<? extends QuarkusTestProfile> profile, Path testClassLocation)
139+
throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
140+
QuarkusTestProfile profileInstance = getQuarkusTestProfile(profile);
148141
Timing.staticInitStarted(curatedApplication
149142
.getOrCreateBaseRuntimeClassLoader(),
150143
curatedApplication
@@ -156,12 +149,12 @@ private PrepareResult createAugmentor(final Class<?> requiredTestClass, String d
156149
if (profile != null) {
157150
props.put(TEST_PROFILE, profile.getName());
158151
}
159-
return new PrepareResult(curatedApplication
152+
return new QuarkusTestPrepareResult(curatedApplication
160153
.createAugmentor(TestBuildChainFunction.class.getName(), props), profileInstance,
161154
curatedApplication);
162155
}
163156

164-
public CuratedApplication makeCuratedApplication(Class<?> requiredTestClass, String displayName,
157+
public static CuratedApplication makeCuratedApplication(Class<?> requiredTestClass, String displayName,
165158
boolean isContinuousTesting,
166159
Collection<Runnable> shutdownTasks) throws IOException, AppModelResolverException, BootstrapException {
167160
final PathList.Builder rootBuilder = PathList.builder();
@@ -255,6 +248,12 @@ public CuratedApplication makeCuratedApplication(Class<?> requiredTestClass, Str
255248
.bootstrap();
256249
shutdownTasks.add(curatedApplication::close);
257250

251+
if (!curatedApplication.getApplicationModel().getDependencies(DependencyFlags.RUNTIME_CP).iterator().hasNext()) {
252+
throw new RuntimeException(
253+
"The tests were run against a directory that does not contain a Quarkus project. Please ensure that the test is configured to use the proper working directory.");
254+
255+
}
256+
258257
// TODO can we consolidate some of this with TestSupport? The code over there is
259258
// final QuarkusBootstrap.Builder bootstrapConfig = curatedApplication.getQuarkusBootstrap().clonedBuilder()
260259
// .setMode(QuarkusBootstrap.Mode.TEST)
@@ -276,14 +275,14 @@ public CuratedApplication makeCuratedApplication(Class<?> requiredTestClass, Str
276275
// Note that curated application cannot be re-used between restarts, so this application
277276
// should have been freshly created
278277
// TODO maybe don't even accept one? is that comment right?
279-
public StartupAction getStartupAction(Class testClass, CuratedApplication curatedApplication,
278+
public StartupAction getStartupAction(Class<?> testClass, CuratedApplication curatedApplication,
280279
boolean isContinuousTesting, Class profile) throws AppModelResolverException, BootstrapException, IOException,
281280
InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
282281

283-
Collection<Runnable> shutdownTasks = new HashSet();
284-
PrepareResult result = createAugmentor(testClass, "(QuarkusTest)", isContinuousTesting, curatedApplication, profile,
285-
shutdownTasks);
286-
AugmentAction augmentAction = result.augmentAction;
282+
Collection<Runnable> shutdownTasks = new HashSet<>();
283+
final AugmentAction augmentAction = createAugmentor(testClass, "(QuarkusTest)", isContinuousTesting, curatedApplication,
284+
profile,
285+
shutdownTasks).augmentAction();
287286

288287
try {
289288
StartupAction startupAction = augmentAction.createInitialRuntimeApplication();

0 commit comments

Comments
 (0)