Skip to content

Commit 68e6194

Browse files
committed
Avoid classpath inspection by special casing gradle additional-source-set-case
1 parent ca4f707 commit 68e6194

File tree

6 files changed

+153
-48
lines changed

6 files changed

+153
-48
lines changed

core/deployment/src/main/java/io/quarkus/deployment/dev/testing/CoreQuarkusTestExtension.java

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.quarkus.deployment.dev.testing;
22

3-
import static io.quarkus.deployment.dev.testing.PathTestHelper.getAppClassLocationForTestLocation;
3+
import static io.quarkus.deployment.dev.testing.PathTestHelper.getAppClassLocationForRootLocation;
44
import static io.quarkus.deployment.dev.testing.PathTestHelper.getTestClassesLocation;
55

66
import java.io.IOException;
@@ -109,6 +109,8 @@ protected PrepareResult createAugmentor(Class requiredTestClass, Class<? extends
109109

110110
// TODO Re-used from AbstractJvmQuarkusTestExtension
111111
protected ApplicationModel getGradleAppModelForIDE(Path projectRoot) throws IOException, AppModelResolverException {
112+
System.out.println(
113+
"HOLLY checking gradleness, guard is " + System.getProperty(BootstrapConstants.SERIALIZED_TEST_APP_MODEL));
112114
return System.getProperty(BootstrapConstants.SERIALIZED_TEST_APP_MODEL) == null
113115
? BuildToolHelper.enableGradleAppModelForTest(projectRoot)
114116
: null;
@@ -184,7 +186,18 @@ protected PrepareResult createAugmentor(Path testClassLocation, Class<?> require
184186
testClassLocation = testClassesDir;
185187

186188
} else {
187-
if (System.getProperty(BootstrapConstants.OUTPUT_SOURCES_DIR) != null) {
189+
// TODO sort out duplication
190+
if (System.getProperty(BootstrapConstants.ALL_OUTPUT_SOURCES_DIR) != null) {
191+
System.out.println("HOLLY ALLS processing " + System.getProperty(BootstrapConstants.ALL_OUTPUT_SOURCES_DIR));
192+
final String[] sourceDirectories = System.getProperty(
193+
BootstrapConstants.ALL_OUTPUT_SOURCES_DIR)
194+
.split(",");
195+
for (String sourceDirectory : sourceDirectories) {
196+
final Path directory = Paths.get(sourceDirectory);
197+
addToBuilderIfConditionMet.accept(directory);
198+
}
199+
} else if (System.getProperty(BootstrapConstants.OUTPUT_SOURCES_DIR) != null) {
200+
System.out.println("HOLLY processing " + System.getProperty(BootstrapConstants.OUTPUT_SOURCES_DIR));
188201
final String[] sourceDirectories = System.getProperty(
189202
BootstrapConstants.OUTPUT_SOURCES_DIR)
190203
.split(",");
@@ -193,13 +206,17 @@ protected PrepareResult createAugmentor(Path testClassLocation, Class<?> require
193206
addToBuilderIfConditionMet.accept(directory);
194207
}
195208
}
209+
196210
}
197211

198212
// testClassLocation = getTestClassesLocation(requiredTestClass);
199213
System.out.println("test class location is " + testClassLocation);
200-
appClassLocation = getAppClassLocationForTestLocation(testClassLocation.toString());
214+
215+
// TODO rename test class location, it's a root
216+
appClassLocation = getAppClassLocationForRootLocation(testClassLocation.toString());
201217
System.out.println("app class location is " + appClassLocation);
202218
if (!appClassLocation.equals(testClassLocation)) {
219+
System.out.println("Adding test class location explicitly");
203220
addToBuilderIfConditionMet.accept(testClassLocation);
204221
// if test classes is a dir, we should also check whether test resources dir exists
205222
// as a separate dir (gradle)
@@ -210,6 +227,7 @@ protected PrepareResult createAugmentor(Path testClassLocation, Class<?> require
210227
addToBuilderIfConditionMet.accept(testResourcesLocation);
211228
}
212229

230+
System.out.println("Adding app class location explicitly");
213231
addToBuilderIfConditionMet.accept(appClassLocation);
214232
final Path appResourcesLocation = PathTestHelper.getResourcesForClassesDirOrNull(
215233
appClassLocation, "main");

core/deployment/src/main/java/io/quarkus/deployment/dev/testing/PathTestHelper.java

+74
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,55 @@ public final class PathTestHelper {
125125
private PathTestHelper() {
126126
}
127127

128+
/**
129+
* We normally start with a test class and work out the runtime classpath
130+
* from that;
131+
* here we need to go in the other direction. There's probably existing logic we
132+
* can re-use, because this
133+
* is seriously brittle
134+
* This method finds directories not in BootstrapConstants.OUTPUT_SOURCES_DIR (in the case of Gradle additional sources)
135+
*/
136+
// TODO can be deleted now that we have changed the quarkus plugin?
137+
public static Path getTestClassesLocationWithNoContext() {
138+
139+
// TODO can we be more elegant about this? What about multi-module?
140+
// TODO should we cross-reference against the classpath?
141+
Path projectRoot = Paths.get("")
142+
.normalize()
143+
.toAbsolutePath();
144+
145+
Path applicationRoot = null;
146+
147+
// TODO this cannot be the right pattern because we don't do it anywhere else, but
148+
String[] ses = System.getProperty("java.class.path")
149+
.split(File.pathSeparator);
150+
for (String s : ses) {
151+
Path path = Paths.get(s);
152+
if (path.normalize()
153+
.toAbsolutePath()
154+
.startsWith(projectRoot)) {
155+
System.out.println("CANDIDATE CLASSPATH " + s);
156+
// TODO ugly; set it if we didn't set it to something on the classpath
157+
// TODO fragile, we miss other modules in multi-module
158+
// things like us to take the first element on the classpath that fits
159+
// TODO we take the first classpath that matches, which is rather arbitrary and brittle
160+
161+
// The application root needs to be a directory that holds test classes `(or TODO maybe application classes)
162+
if (applicationRoot == null) {
163+
applicationRoot = path;
164+
System.out.println("made app root" + applicationRoot);
165+
// TODO we do not break so we can continue logging
166+
}
167+
}
168+
}
169+
170+
if (applicationRoot == null) {
171+
throw new RuntimeException("Could not find any elements of the classpath inside the project root " + projectRoot);
172+
}
173+
174+
return applicationRoot;
175+
}
176+
128177
/**
129178
* Resolves the directory or the JAR file containing the test class.
130179
*
@@ -169,6 +218,31 @@ public static Path getAppClassLocation(Class<?> testClass) {
169218
return getAppClassLocationForTestLocation(getTestClassesLocation(testClass).toString());
170219
}
171220

221+
public static Path getAppClassLocationForRootLocation(String rootLocation) {
222+
if (rootLocation.endsWith(".jar")) {
223+
if (rootLocation.endsWith("-tests.jar")) {
224+
return Paths.get(new StringBuilder()
225+
.append(rootLocation, 0, rootLocation.length() - "-tests.jar".length())
226+
.append(".jar")
227+
.toString());
228+
}
229+
return Path.of(rootLocation);
230+
}
231+
Optional<Path> mainClassesDir = TEST_TO_MAIN_DIR_FRAGMENTS.entrySet()
232+
.stream()
233+
.map(e -> {
234+
return Path.of(
235+
rootLocation + File.separator + e.getValue());
236+
})
237+
.filter(path -> Files.exists(path))
238+
.findFirst();
239+
if (mainClassesDir.isPresent()) {
240+
System.out.println("WAHOO GOT A MAIN PATH" + mainClassesDir.get());
241+
return mainClassesDir.get();
242+
}
243+
throw new IllegalStateException("Unable to find any application content in " + rootLocation);
244+
}
245+
172246
/**
173247
* Resolves the directory or the JAR file containing the application being tested by a test from the given location.
174248
*

devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/extension/QuarkusPluginExtension.java

+24
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public void beforeTest(Test task) {
7070
final Map<String, Object> props = task.getSystemProperties();
7171

7272
final ApplicationModel appModel = getApplicationModel(LaunchMode.TEST);
73+
System.out.println("HOLLY gradle plugin path made an app model" + appModel);
7374
final Path serializedModel = ToolingUtils.serializeAppModel(appModel, task, true);
7475
props.put(BootstrapConstants.SERIALIZED_TEST_APP_MODEL, serializedModel.toString());
7576

@@ -79,6 +80,13 @@ public void beforeTest(Test task) {
7980
}
8081
props.put(BootstrapConstants.OUTPUT_SOURCES_DIR, outputSourcesDir.toString());
8182

83+
StringJoiner allOutputSourcesDir = new StringJoiner(",");
84+
for (File outputSourceDir : allOutputSourceDirs()) {
85+
allOutputSourcesDir.add(outputSourceDir.getAbsolutePath());
86+
}
87+
System.out.println("HOLLY gradle made all output " + allOutputSourcesDir);
88+
props.put(BootstrapConstants.ALL_OUTPUT_SOURCES_DIR, allOutputSourcesDir.toString());
89+
8290
final SourceSetContainer sourceSets = getSourceSets();
8391
final SourceSet mainSourceSet = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
8492

@@ -160,12 +168,28 @@ public Set<File> resourcesDir() {
160168

161169
public Set<File> combinedOutputSourceDirs() {
162170
Set<File> sourcesDirs = new LinkedHashSet<>();
171+
// TODO should this include the additional source sets? The name kind of implies it should, but I confirm it doesn't - at least not test source sets
163172
SourceSetContainer sourceSets = getSourceSets();
164173
sourcesDirs.addAll(sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput().getClassesDirs().getFiles());
165174
sourcesDirs.addAll(sourceSets.getByName(SourceSet.TEST_SOURCE_SET_NAME).getOutput().getClassesDirs().getFiles());
166175
return sourcesDirs;
167176
}
168177

178+
public Set<File> allOutputSourceDirs() {
179+
Set<File> sourcesDirs = new LinkedHashSet<>();
180+
SourceSetContainer sourceSets = getSourceSets();
181+
182+
// TODO old-fashioned, but coding is hard without IDE help
183+
for (Object thing : sourceSets.toArray()) {
184+
185+
sourcesDirs.addAll(((SourceSet) thing).getOutput()
186+
.getClassesDirs()
187+
.getFiles());
188+
}
189+
//System.out.println("HOLLY MADE SET " + Arrays.toString(sourcesDirs.toArray()));
190+
return sourcesDirs;
191+
}
192+
169193
public AppModelResolver getAppModelResolver() {
170194
return getAppModelResolver(LaunchMode.NORMAL);
171195
}

independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/BootstrapConstants.java

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ public interface BootstrapConstants {
2020

2121
String OUTPUT_SOURCES_DIR = "OUTPUT_SOURCES_DIR";
2222

23+
// Added because OUTPUT_SOURCES_DIR does not include additional sources and we sometimes (always?) need them
24+
String ALL_OUTPUT_SOURCES_DIR = "ALL_OUTPUT_SOURCES_DIR";
25+
2326
@Deprecated
2427
String EXTENSION_PROPS_JSON_FILE_NAME = "quarkus-extension.json";
2528

independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/utils/BuildToolHelper.java

+3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public static Path getProjectDir(Path p) {
6666
}
6767

6868
public static BuildTool findBuildTool(Path project) {
69+
System.out.println("HOLLY finding build tool on " + project);
6970
Path currentPath = project;
7071
while (currentPath != null) {
7172
if (BuildTool.MAVEN.exists(currentPath)) {
@@ -107,6 +108,8 @@ public static ApplicationModel enableGradleAppModelForTest(Path projectRoot)
107108

108109
public static ApplicationModel enableGradleAppModel(Path projectRoot, String mode, List<String> jvmArgs, String... tasks)
109110
throws IOException, AppModelResolverException {
111+
System.out.println("HOLLY OK! trying to gradle this up");
112+
System.out.println("Is it gradle? " + isGradleProject(projectRoot));
110113
if (isGradleProject(projectRoot)) {
111114
log.infof("Loading Quarkus Gradle application model for %s", projectRoot);
112115
final ApplicationModel model = QuarkusGradleModelFactory.create(

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

+28-45
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package io.quarkus.test.junit.launcher;
22

33
import java.io.IOException;
4-
import java.nio.file.Files;
54
import java.nio.file.Path;
65
import java.nio.file.Paths;
6+
import java.util.Arrays;
7+
import java.util.Set;
78

89
import org.eclipse.microprofile.config.ConfigProvider;
910
import org.junit.platform.launcher.LauncherDiscoveryListener;
@@ -18,6 +19,7 @@
1819
import io.quarkus.bootstrap.model.ApplicationModel;
1920
import io.quarkus.bootstrap.resolver.AppModelResolverException;
2021
import io.quarkus.bootstrap.utils.BuildToolHelper;
22+
import io.quarkus.bootstrap.workspace.WorkspaceModule;
2123
import io.quarkus.deployment.dev.testing.CoreQuarkusTestExtension;
2224
import io.quarkus.deployment.dev.testing.CurrentTestApplication;
2325
import io.quarkus.deployment.dev.testing.TestSupport;
@@ -104,53 +106,14 @@ public void launcherDiscoveryStarted(LauncherDiscoveryRequest request) {
104106
System.out.println("HOLLY interceipt original" + originalClassLoader);
105107
CoreQuarkusTestExtension coreQuarkusTestExtension = new CoreQuarkusTestExtension();
106108

107-
// TODO we normally start with a test class and work out the runtime classpath
108-
// from that;
109-
// here we need to go in the other direction. There's probably existing logic we
110-
// can re-use, because this
111-
// is seriously brittle
112-
// TODO massi ve assumptions, completely ignoring multi module projects
113-
// Assume the test class lives in the first element on the classpath
114109
Path projectRoot = Paths.get("")
115110
.normalize()
116111
.toAbsolutePath();
117112

118-
// TODO can we be more elegant about this? What about multi-module?
119-
// TODO should we cross-reference against the classpath?
120-
121-
Path targetDir = projectRoot.resolve("target/test-classes");
122-
123-
// The gradle case; can we know in advance which it is?
124-
Path buildDir = projectRoot.resolve("build");
125-
126-
System.out.println(
127-
"HOLLY whole class path is " + System.getProperty("java.class.path"));
128-
Path applicationRoot;
129-
130-
// TODO probably pointless, to make sure it's shown as set
131-
if (Files.exists(targetDir)) {
132-
applicationRoot = targetDir;
133-
} else {
134-
applicationRoot = buildDir;
135-
}
136-
137-
String[] ses = System.getProperty("java.class.path")
138-
.split(":");
139-
for (String s : ses) {
140-
Path path = Paths.get(s);
141-
if (path.normalize()
142-
.toAbsolutePath()
143-
.startsWith(projectRoot)) {
144-
System.out.println("CANDIDATE CLASSPATH " + s);
145-
// TODO ugly; set it if we didn't set it to something on the classpath
146-
// TODO fragile, we miss other modules in multi-module
147-
// things like us to take the first element on the classpath that fits
148-
if (applicationRoot == targetDir || applicationRoot == buildDir) {
149-
applicationRoot = path;
150-
System.out.println("made app root" + applicationRoot);
151-
}
152-
}
153-
}
113+
// Why do we do this rather than just using the project root?
114+
// BootstrapConstants.OUTPUT_SOURCES_DIR does not have gradle additional source sets, but the classpath does
115+
// Path applicationRoot = getTestClassesLocationWithNoContext();
116+
Path applicationRoot = projectRoot;
154117

155118
CuratedApplication curatedApplication;
156119
// TODO this makes no sense here because we're on the wrong classloader unless a
@@ -164,7 +127,7 @@ public void launcherDiscoveryStarted(LauncherDiscoveryRequest request) {
164127

165128
System.out.println("An alternate root we couuld do is " + projectRoot);
166129
System.out.println(
167-
"That gives gradlle " + getGradleAppModelForIDE(Paths.get("")
130+
"That gives gradle " + getGradleAppModelForIDE(Paths.get("")
168131
.normalize()
169132
.toAbsolutePath()));
170133

@@ -208,6 +171,26 @@ public void launcherDiscoveryStarted(LauncherDiscoveryRequest request) {
208171
// currentTestAppConsumer.accept(curatedApplication);
209172

210173
// TODO move this to close shutdownTasks.add(curatedApplication::close);
174+
175+
var appModelFactory = curatedApplication.getQuarkusBootstrap().newAppModelFactory();
176+
appModelFactory.setBootstrapAppModelResolver(null);
177+
appModelFactory.setTest(true);
178+
appModelFactory.setLocalArtifacts(Set.of());
179+
// TODO if (!mainModule) {
180+
// appModelFactory.setAppArtifact(null);
181+
appModelFactory.setProjectRoot(projectRoot);
182+
// }
183+
184+
// To do this deserialization, we need to have an app root, so we can't use it to find the application model
185+
186+
final ApplicationModel testModel = appModelFactory.resolveAppModel().getApplicationModel();
187+
System.out.println("HOLLY test model is " + testModel);
188+
System.out.println(
189+
"module dir is " + Arrays.toString(testModel.getWorkspaceModules().toArray()));
190+
System.out.println(
191+
"module dir is " + ((WorkspaceModule) testModel.getWorkspaceModules().toArray()[0]).getModuleDir());
192+
System.out.println(
193+
"app dir is " + testModel.getApplicationModule().getModuleDir());
211194
}
212195

213196
System.out.println("HOLLY after launch mode is " + LaunchMode.current());

0 commit comments

Comments
 (0)