Skip to content

Commit 5cf6e0d

Browse files
authored
Ignore module-info in jar hell checks (#33011)
* Ignore module-info in JarHell checks * Add unit test * integration test to test that jarhell is ran with precommit
1 parent 51cbc61 commit 5cf6e0d

File tree

11 files changed

+149
-26
lines changed

11 files changed

+149
-26
lines changed

buildSrc/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ if (project != rootProject) {
176176
it.tasks.matching { it.name == 'publishNebulaPublicationToLocalTestRepository'}
177177
}
178178
exclude "**/*Tests.class"
179-
include "**/*IT.class"
180179
testClassesDirs = sourceSets.test.output.classesDirs
181180
classpath = sourceSets.test.runtimeClasspath
182181
inputs.dir(file("src/testKit"))

buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/JarHellTask.groovy

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ package org.elasticsearch.gradle.precommit
2222
import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
2323
import org.elasticsearch.gradle.LoggedExec
2424
import org.gradle.api.file.FileCollection
25+
import org.gradle.api.tasks.Classpath
2526
import org.gradle.api.tasks.OutputFile
26-
2727
/**
2828
* Runs CheckJarHell on a classpath.
2929
*/
@@ -35,9 +35,13 @@ public class JarHellTask extends LoggedExec {
3535
* inputs (ie the jars/class files).
3636
*/
3737
@OutputFile
38-
File successMarker = new File(project.buildDir, 'markers/jarHell')
38+
File successMarker
39+
40+
@Classpath
41+
FileCollection classpath
3942

4043
public JarHellTask() {
44+
successMarker = new File(project.buildDir, 'markers/jarHell-' + getName())
4145
project.afterEvaluate {
4246
FileCollection classpath = project.sourceSets.test.runtimeClasspath
4347
if (project.plugins.hasPlugin(ShadowPlugin)) {

buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class PrecommitTasks {
3131

3232
/** Adds a precommit task, which depends on non-test verification tasks. */
3333
public static Task create(Project project, boolean includeDependencyLicenses) {
34-
Configuration forbiddenApisConfiguration = project.configurations.create("forbiddenApisCliJar")
34+
project.configurations.create("forbiddenApisCliJar")
3535
project.dependencies {
3636
forbiddenApisCliJar ('de.thetaphi:forbiddenapis:2.5')
3737
}
@@ -43,7 +43,7 @@ class PrecommitTasks {
4343
project.tasks.create('forbiddenPatterns', ForbiddenPatternsTask.class),
4444
project.tasks.create('licenseHeaders', LicenseHeadersTask.class),
4545
project.tasks.create('filepermissions', FilePermissionsTask.class),
46-
project.tasks.create('jarHell', JarHellTask.class),
46+
configureJarHell(project),
4747
configureThirdPartyAudit(project)
4848
]
4949

@@ -80,6 +80,12 @@ class PrecommitTasks {
8080
return project.tasks.create(precommitOptions)
8181
}
8282

83+
private static Task configureJarHell(Project project) {
84+
Task task = project.tasks.create('jarHell', JarHellTask.class)
85+
task.classpath = project.sourceSets.test.runtimeClasspath
86+
return task
87+
}
88+
8389
private static Task configureThirdPartyAudit(Project project) {
8490
ThirdPartyAuditTask thirdPartyAuditTask = project.tasks.create('thirdPartyAudit', ThirdPartyAuditTask.class)
8591
ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources')

buildSrc/src/test/java/org/elasticsearch/gradle/BuildExamplePluginsIT.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,4 @@ private Path writeBuildScript(String script) {
153153
}
154154
}
155155

156-
private String getLocalTestRepoPath() {
157-
String property = System.getProperty("test.local-test-repo-path");
158-
Objects.requireNonNull(property, "test.local-test-repo-path not passed to tests");
159-
File file = new File(property);
160-
assertTrue("Expected " + property + " to exist, but it did not!", file.exists());
161-
if (File.separator.equals("\\")) {
162-
// Use / on Windows too, the build script is not happy with \
163-
return file.getAbsolutePath().replace(File.separator, "/");
164-
} else {
165-
return file.getAbsolutePath();
166-
}
167-
}
168-
169156
}

buildSrc/src/test/java/org/elasticsearch/gradle/ExportElasticsearchBuildResourcesTaskIT.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public void testUpToDateWithSourcesConfigured() {
4040
.withArguments("buildResources", "-s", "-i")
4141
.withPluginClasspath()
4242
.build();
43-
assertTaskSuccessfull(result, ":buildResources");
43+
assertTaskSuccessful(result, ":buildResources");
4444
assertBuildFileExists(result, PROJECT_NAME, "build-tools-exported/checkstyle.xml");
4545
assertBuildFileExists(result, PROJECT_NAME, "build-tools-exported/checkstyle_suppressions.xml");
4646

@@ -61,8 +61,8 @@ public void testImplicitTaskDependencyCopy() {
6161
.withPluginClasspath()
6262
.build();
6363

64-
assertTaskSuccessfull(result, ":buildResources");
65-
assertTaskSuccessfull(result, ":sampleCopyAll");
64+
assertTaskSuccessful(result, ":buildResources");
65+
assertTaskSuccessful(result, ":sampleCopyAll");
6666
assertBuildFileExists(result, PROJECT_NAME, "sampleCopyAll/checkstyle.xml");
6767
// This is a side effect of compile time reference
6868
assertBuildFileExists(result, PROJECT_NAME, "sampleCopyAll/checkstyle_suppressions.xml");
@@ -75,7 +75,7 @@ public void testImplicitTaskDependencyInputFileOfOther() {
7575
.withPluginClasspath()
7676
.build();
7777

78-
assertTaskSuccessfull(result, ":sample");
78+
assertTaskSuccessful(result, ":sample");
7979
assertBuildFileExists(result, PROJECT_NAME, "build-tools-exported/checkstyle.xml");
8080
assertBuildFileExists(result, PROJECT_NAME, "build-tools-exported/checkstyle_suppressions.xml");
8181
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.elasticsearch.gradle.precommit;
2+
3+
import org.elasticsearch.gradle.test.GradleIntegrationTestCase;
4+
import org.gradle.testkit.runner.BuildResult;
5+
import org.gradle.testkit.runner.GradleRunner;
6+
7+
/*
8+
* Licensed to Elasticsearch under one or more contributor
9+
* license agreements. See the NOTICE file distributed with
10+
* this work for additional information regarding copyright
11+
* ownership. Elasticsearch licenses this file to you under
12+
* the Apache License, Version 2.0 (the "License"); you may
13+
* not use this file except in compliance with the License.
14+
* You may obtain a copy of the License at
15+
*
16+
* http://www.apache.org/licenses/LICENSE-2.0
17+
*
18+
* Unless required by applicable law or agreed to in writing,
19+
* software distributed under the License is distributed on an
20+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21+
* KIND, either express or implied. See the License for the
22+
* specific language governing permissions and limitations
23+
* under the License.
24+
*/
25+
public class JarHellTaskIT extends GradleIntegrationTestCase {
26+
27+
public void testJarHellDetected() {
28+
BuildResult result = GradleRunner.create()
29+
.withProjectDir(getProjectDir("jarHell"))
30+
.withArguments("clean", "precommit", "-s", "-Dlocal.repo.path=" + getLocalTestRepoPath())
31+
.withPluginClasspath()
32+
.buildAndFail();
33+
34+
assertTaskFailed(result, ":jarHell");
35+
assertOutputContains(
36+
result.getOutput(),
37+
"Exception in thread \"main\" java.lang.IllegalStateException: jar hell!",
38+
"class: org.apache.logging.log4j.Logger"
39+
);
40+
}
41+
42+
}

buildSrc/src/test/java/org/elasticsearch/gradle/test/GradleIntegrationTestCase.java

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.nio.file.Files;
1010
import java.nio.file.Path;
1111
import java.util.List;
12+
import java.util.Objects;
1213
import java.util.stream.Collectors;
1314
import java.util.stream.Stream;
1415

@@ -66,15 +67,24 @@ protected void assertOutputDoesNotContain(String output, String... lines) {
6667
}
6768
}
6869

69-
protected void assertTaskSuccessfull(BuildResult result, String taskName) {
70+
protected void assertTaskFailed(BuildResult result, String taskName) {
71+
assertTaskOutcome(result, taskName, TaskOutcome.FAILED);
72+
}
73+
74+
protected void assertTaskSuccessful(BuildResult result, String taskName) {
75+
assertTaskOutcome(result, taskName, TaskOutcome.SUCCESS);
76+
}
77+
78+
private void assertTaskOutcome(BuildResult result, String taskName, TaskOutcome taskOutcome) {
7079
BuildTask task = result.task(taskName);
7180
if (task == null) {
72-
fail("Expected task `" + taskName + "` to be successful, but it did not run");
81+
fail("Expected task `" + taskName + "` to be " + taskOutcome +", but it did not run" +
82+
"\n\nOutput is:\n" + result.getOutput());
7383
}
7484
assertEquals(
7585
"Expected task to be successful but it was: " + task.getOutcome() +
76-
"\n\nOutput is:\n" + result.getOutput() ,
77-
TaskOutcome.SUCCESS,
86+
taskOutcome + "\n\nOutput is:\n" + result.getOutput() ,
87+
taskOutcome,
7888
task.getOutcome()
7989
);
8090
}
@@ -109,4 +119,17 @@ protected void assertBuildFileDoesNotExists(BuildResult result, String projectNa
109119
Files.exists(absPath)
110120
);
111121
}
122+
123+
protected String getLocalTestRepoPath() {
124+
String property = System.getProperty("test.local-test-repo-path");
125+
Objects.requireNonNull(property, "test.local-test-repo-path not passed to tests");
126+
File file = new File(property);
127+
assertTrue("Expected " + property + " to exist, but it did not!", file.exists());
128+
if (File.separator.equals("\\")) {
129+
// Use / on Windows too, the build script is not happy with \
130+
return file.getAbsolutePath().replace(File.separator, "/");
131+
} else {
132+
return file.getAbsolutePath();
133+
}
134+
}
112135
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
plugins {
2+
id 'java'
3+
id 'elasticsearch.build'
4+
}
5+
6+
dependencyLicenses.enabled = false
7+
dependenciesInfo.enabled = false
8+
forbiddenApisMain.enabled = false
9+
forbiddenApisTest.enabled = false
10+
thirdPartyAudit.enabled = false
11+
namingConventions.enabled = false
12+
ext.licenseFile = file("$buildDir/dummy/license")
13+
ext.noticeFile = file("$buildDir/dummy/notice")
14+
15+
repositories {
16+
mavenCentral()
17+
repositories {
18+
maven {
19+
url System.getProperty("local.repo.path")
20+
}
21+
}
22+
}
23+
24+
dependencies {
25+
// Needed for the JarHell task
26+
testCompile ("org.elasticsearch.test:framework:${versions.elasticsearch}")
27+
// causes jar hell with local sources
28+
compile "org.apache.logging.log4j:log4j-api:${versions.log4j}"
29+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.apache.logging.log4j;
2+
3+
// Jar Hell !
4+
public class Logger {
5+
6+
}
7+

libs/core/src/main/java/org/elasticsearch/bootstrap/JarHell.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ public static void checkJavaVersion(String resource, String targetVersion) {
255255
}
256256

257257
private static void checkClass(Map<String, Path> clazzes, String clazz, Path jarpath) {
258+
if (clazz.equals("module-info") || clazz.endsWith(".module-info")) {
259+
// Ignore jigsaw module descriptions
260+
return;
261+
}
258262
Path previous = clazzes.put(clazz, jarpath);
259263
if (previous != null) {
260264
if (previous.equals(jarpath)) {

libs/core/src/test/java/org/elasticsearch/bootstrap/JarHellTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,28 @@ public void testDifferentJars() throws Exception {
7676
}
7777
}
7878

79+
public void testModuleInfo() throws Exception {
80+
Path dir = createTempDir();
81+
JarHell.checkJarHell(
82+
asSet(
83+
makeJar(dir, "foo.jar", null, "module-info.class"),
84+
makeJar(dir, "bar.jar", null, "module-info.class")
85+
),
86+
logger::debug
87+
);
88+
}
89+
90+
public void testModuleInfoPackage() throws Exception {
91+
Path dir = createTempDir();
92+
JarHell.checkJarHell(
93+
asSet(
94+
makeJar(dir, "foo.jar", null, "foo/bar/module-info.class"),
95+
makeJar(dir, "bar.jar", null, "foo/bar/module-info.class")
96+
),
97+
logger::debug
98+
);
99+
}
100+
79101
public void testDirsOnClasspath() throws Exception {
80102
Path dir1 = createTempDir();
81103
Path dir2 = createTempDir();

0 commit comments

Comments
 (0)