Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test sourceset support to MRJAR plugin #106571

Merged
merged 9 commits into from
Mar 21, 2024
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,46 +60,33 @@ public void apply(Project project) {
project.getPluginManager().apply(ElasticsearchJavaBasePlugin.class);
var javaExtension = project.getExtensions().getByType(JavaPluginExtension.class);

var srcDir = project.getProjectDir().toPath().resolve("src");
List<Integer> mainVersions = new ArrayList<>();
try (var subdirStream = Files.list(srcDir)) {
for (Path sourceset : subdirStream.toList()) {
assert Files.isDirectory(sourceset);
String sourcesetName = sourceset.getFileName().toString();
Matcher sourcesetMatcher = MRJAR_SOURCESET_PATTERN.matcher(sourcesetName);
if (sourcesetMatcher.matches()) {
mainVersions.add(Integer.parseInt(sourcesetMatcher.group(1)));
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}

Collections.sort(mainVersions);
List<String> parentSourceSets = new ArrayList<>();
parentSourceSets.add(SourceSet.MAIN_SOURCE_SET_NAME);
List<Integer> mainVersions = findSourceVersions(project);
List<String> mainSourceSets = new ArrayList<>();
mainSourceSets.add(SourceSet.MAIN_SOURCE_SET_NAME);
List<String> testSourceSets = new ArrayList<>(mainSourceSets);
testSourceSets.add(SourceSet.TEST_SOURCE_SET_NAME);
for (int javaVersion : mainVersions) {
String sourcesetName = "main" + javaVersion;
addMrjarSourceset(project, javaExtension, sourcesetName, parentSourceSets, javaVersion);
parentSourceSets.add(sourcesetName);
String mainSourceSetName = SourceSet.MAIN_SOURCE_SET_NAME + javaVersion;
addSourceSet(project, javaExtension, mainSourceSetName, mainSourceSets, javaVersion);
mainSourceSets.add(mainSourceSetName);
testSourceSets.add(SourceSet.MAIN_SOURCE_SET_NAME + javaVersion);

String testSourceSetName = SourceSet.TEST_SOURCE_SET_NAME + javaVersion;
SourceSet testSourceSet = addSourceSet(project, javaExtension, testSourceSetName, testSourceSets, javaVersion);
testSourceSets.add(testSourceSetName);
createTestTask(project, testSourceSet, javaVersion);
}
}

private void addMrjarSourceset(
Project project,
JavaPluginExtension javaExtension,
String sourcesetName,
List<String> parentSourceSets,
int javaVersion
) {
SourceSet sourceSet = javaExtension.getSourceSets().maybeCreate(sourcesetName);
for (String parentSourceSetName : parentSourceSets) {
GradleUtils.extendSourceSet(project, parentSourceSetName, sourcesetName);
}
configureMrjar(project, javaExtension, mainVersions, "main");
}

private void configureMrjar(Project project, JavaPluginExtension javaExtension, List<Integer> versions, String baseSourceSetName) {
var jarTask = project.getTasks().withType(Jar.class).named(JavaPlugin.JAR_TASK_NAME);
jarTask.configure(task -> {
task.into("META-INF/versions/" + javaVersion, copySpec -> copySpec.from(sourceSet.getOutput()));
for (var version : versions) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this more, this feels a bit awkward. I feel like we should be doing this in addSourceSet instead.

SourceSet sourceSet = javaExtension.getSourceSets().getByName(baseSourceSetName + version);
task.into("META-INF/versions/" + version, copySpec -> copySpec.from(sourceSet.getOutput()));
}
task.manifest(manifest -> { manifest.attributes(Map.of("Multi-Release", "true")); });
});

Expand All @@ -111,6 +98,19 @@ private void addMrjarSourceset(
FileCollection testRuntime = sourceSets.getByName(SourceSet.TEST_SOURCE_SET_NAME).getRuntimeClasspath();
testTask.setClasspath(testRuntime.minus(mainRuntime).plus(project.files(jarTask)));
});
}

private SourceSet addSourceSet(
Project project,
JavaPluginExtension javaExtension,
String sourceSetName,
List<String> parentSourceSets,
int javaVersion
) {
SourceSet sourceSet = javaExtension.getSourceSets().maybeCreate(sourceSetName);
for (String parentSourceSetName : parentSourceSets) {
GradleUtils.extendSourceSet(project, parentSourceSetName, sourceSetName);
}

project.getTasks().withType(JavaCompile.class).named(sourceSet.getCompileJavaTaskName()).configure(compileTask -> {
compileTask.getJavaCompiler()
Expand All @@ -132,6 +132,44 @@ private void addMrjarSourceset(
project.getTasks().withType(CheckForbiddenApisTask.class).named(forbiddenApisTaskName).configure(forbiddenApisTask -> {
forbiddenApisTask.setIgnoreMissingClasses(true);
});

return sourceSet;
}

private void createTestTask(Project project, SourceSet sourceSet, int javaVersion) {
var jarTask = project.getTasks().withType(Jar.class).named(JavaPlugin.JAR_TASK_NAME);
project.getTasks().register(JavaPlugin.TEST_TASK_NAME + javaVersion, Test.class).configure(testTask -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want to have the check task depend on this so that they actually get run.

testTask.dependsOn(jarTask);

SourceSetContainer sourceSets = GradleUtils.getJavaSourceSets(project);
FileCollection mainRuntime = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME + javaVersion).getOutput();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to remove all the parent main source sets here. So if this was test23 we'd need to remove main21, main22 and main23 or else we'll hit jar hell.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, you are right. I've fixed this to loop over the main sourcesets up to that point.

FileCollection testRuntime = sourceSet.getRuntimeClasspath();
testTask.setClasspath(testRuntime.minus(mainRuntime).plus(project.files(jarTask)));

testTask.getJavaLauncher().set(
javaToolchains.launcherFor(spec -> { spec.getLanguageVersion().set(JavaLanguageVersion.of(javaVersion)); })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can omit the curly braces in this lambda.

);
});
}

private static List<Integer> findSourceVersions(Project project) {
var srcDir = project.getProjectDir().toPath().resolve("src");
List<Integer> versions = new ArrayList<>();
try (var subdirStream = Files.list(srcDir)) {
for (Path sourceSetPath : subdirStream.toList()) {
assert Files.isDirectory(sourceSetPath);
String sourcesetName = sourceSetPath.getFileName().toString();
Matcher sourcesetMatcher = MRJAR_SOURCESET_PATTERN.matcher(sourcesetName);
if (sourcesetMatcher.matches()) {
versions.add(Integer.parseInt(sourcesetMatcher.group(1)));
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}

Collections.sort(versions);
return versions;
}

private static void stripPreviewFromFiles(Path compileDir) {
Expand Down