Skip to content

Commit 8be85c5

Browse files
authored
Check the diagnostic's report without naming Maven Central's or the plugin portal's URL (#206)
Which URL a build reaches Maven Central and the Gradle Plugin Portal at depends on the machine. Where CI names a mirror, as the Code Genome Project's builds do, the mirror stands in for both, and gradle(), gradleNoDefaultRepos() and dependencyNotFound() failed there: gradle() found 3 rows instead of 4, the mirror counting once for both. The tests now check the repositories they declare by URL, and Central and the plugin portal only by being reachable. maven() forced empty settings, so it always pinged Maven Central itself; it now reaches Central through MAVEN_CENTRAL_MIRROR_URL when that is set.
1 parent b488e9c commit 8be85c5

1 file changed

Lines changed: 72 additions & 22 deletions

File tree

‎src/test/java/org/openrewrite/java/dependencies/DependencyResolutionDiagnosticTest.java‎

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import org.junit.jupiter.api.Test;
1919
import org.openrewrite.DocumentExample;
20+
import org.openrewrite.ExecutionContext;
2021
import org.openrewrite.InMemoryExecutionContext;
2122
import org.openrewrite.Parser;
2223
import org.openrewrite.java.dependencies.table.RepositoryAccessibilityReport;
@@ -27,12 +28,18 @@
2728

2829
import java.io.ByteArrayInputStream;
2930
import java.nio.file.Path;
31+
import java.util.List;
3032

3133
import static org.assertj.core.api.Assertions.assertThat;
3234
import static org.openrewrite.gradle.Assertions.buildGradle;
3335
import static org.openrewrite.gradle.toolingapi.Assertions.withToolingApi;
3436
import static org.openrewrite.maven.Assertions.pomXml;
3537

38+
/**
39+
* Which URL Maven Central and the Gradle Plugin Portal are reached at depends on the machine the tests run on: where
40+
* CI names a mirror in MAVEN_CENTRAL_MIRROR_URL, the mirror stands in for both. So these tests check the repositories
41+
* they declare themselves by URL, and Central and the plugin portal only by being reachable.
42+
*/
3643
@SuppressWarnings("GroovyAssignabilityCheck")
3744
class DependencyResolutionDiagnosticTest implements RewriteTest {
3845

@@ -68,15 +75,11 @@ void gradle() {
6875
// It is a limitation of the tooling API which prevents configuration-granularity error information from being collected.
6976
// So the GradleDependencyConfigurationErrors table will never be populated in unit tests.
7077
.dataTable(RepositoryAccessibilityReport.Row.class, rows -> {
71-
assertThat(rows)
72-
.hasSize(4)
73-
.contains(
74-
new RepositoryAccessibilityReport.Row("https://repo.maven.apache.org/maven2", "", "", 200, "", ""));
7578
assertThat(rows).filteredOn(row -> row.getUri().startsWith("file:/") && "".equals(row.getPingExceptionMessage())).hasSize(1);
76-
assertThat(rows).contains(
77-
new RepositoryAccessibilityReport.Row("https://plugins.gradle.org/m2", "", "", 200, "", ""));
7879
assertThat(rows)
7980
.filteredOn(row -> "https://nonexistent.moderne.io/maven2".equals(row.getUri()) && row.getPingHttpCode() == null).hasSize(1);
81+
// Maven Central and the plugin portal, which are one row where a mirror stands in for both
82+
assertThat(remote(rows)).hasSizeBetween(1, 2).allSatisfy(DependencyResolutionDiagnosticTest::reachable);
8083
}),
8184
//language=groovy
8285
buildGradle(
@@ -107,12 +110,14 @@ void gradleNoDefaultRepos() {
107110
spec -> spec.beforeRecipe(withToolingApi())
108111
// It is a limitation of the tooling API which prevents configuration-granularity error information from being collected.
109112
// So the GradleDependencyConfigurationErrors table will never be populated in unit tests.
110-
.dataTable(RepositoryAccessibilityReport.Row.class, rows -> assertThat(rows)
111-
.hasSize(2)
112-
.contains(
113-
new RepositoryAccessibilityReport.Row("https://plugins.gradle.org/m2", "", "", 200, "", ""))
114-
.contains(
115-
new RepositoryAccessibilityReport.Row("https://nonexistent.moderne.io/maven2", "java.net.UnknownHostException", "nonexistent.moderne.io", null, "", ""))),
113+
.dataTable(RepositoryAccessibilityReport.Row.class, rows -> {
114+
assertThat(rows)
115+
.hasSize(2)
116+
.contains(
117+
new RepositoryAccessibilityReport.Row("https://nonexistent.moderne.io/maven2", "java.net.UnknownHostException", "nonexistent.moderne.io", null, "", ""));
118+
// The plugin portal, which Gradle adds
119+
assertThat(remote(rows)).singleElement().satisfies(DependencyResolutionDiagnosticTest::reachable);
120+
}),
116121
//language=groovy
117122
buildGradle(
118123
"""
@@ -182,19 +187,19 @@ void maven() {
182187
spec -> {
183188
// CI may inject ~/.m2/settings.xml with `<mirrorOf>*</mirrorOf>` to route Maven through a cache.
184189
// That rewrites the pom-declared `nonexistent` repo to the mirror URL, so neither Maven Central
185-
// nor the test's `nonexistent.moderne.io` repo appear in the diagnostic. Force empty settings
186-
// here so the recipe sees the pom-declared repositories directly.
190+
// nor the test's `nonexistent.moderne.io` repo appear in the diagnostic. Use settings of the test's
191+
// own here, so the recipe sees the pom-declared repositories directly.
187192
MavenExecutionContextView ctx = MavenExecutionContextView.view(new InMemoryExecutionContext());
188-
ctx.setMavenSettings(new MavenSettings(null, null, null, null, null, null));
193+
ctx.setMavenSettings(settingsMirroringOnlyCentral(ctx));
189194
spec
190195
.executionContext(ctx)
191196
.dataTable(RepositoryAccessibilityReport.Row.class, rows -> {
192-
assertThat(rows).contains(
193-
new RepositoryAccessibilityReport.Row("https://repo.maven.apache.org/maven2", "", "", 200, "", ""));
194197
assertThat(rows).filteredOn(row -> row.getUri().startsWith("file:/") && "".equals(row.getPingExceptionMessage())).hasSize(1);
195198
assertThat(rows).contains(
196199
new RepositoryAccessibilityReport.Row("https://nonexistent.moderne.io/maven2", "java.net.UnknownHostException", "nonexistent.moderne.io", null, "", "")
197200
);
201+
// Maven Central, which the recipe adds
202+
assertThat(remote(rows)).singleElement().satisfies(DependencyResolutionDiagnosticTest::reachable);
198203
});
199204
},
200205
//language=xml
@@ -223,11 +228,14 @@ void dependencyNotFound() {
223228
spec -> spec.recipe(new DependencyResolutionDiagnostic("org.nonexistent", "nonexistent", "0"))
224229
.beforeRecipe(withToolingApi())
225230
.dataTable(RepositoryAccessibilityReport.Row.class, rows ->
226-
assertThat(rows).contains(
227-
new RepositoryAccessibilityReport.Row("https://repo.maven.apache.org/maven2",
228-
"", "", 200, "org.openrewrite.maven.MavenDownloadingException",
229-
"org.nonexistent:nonexistent:0 failed. Unable to download POM: org.nonexistent:nonexistent:0. Tried repositories:\nhttps://repo.maven.apache.org/maven2/: HTTP 404")
230-
)
231+
// Maven Central, which is reachable but has no such dependency
232+
assertThat(rows).anySatisfy(row -> {
233+
reachable(row);
234+
assertThat(row.getDependencyResolveExceptionType()).isEqualTo("org.openrewrite.maven.MavenDownloadingException");
235+
assertThat(row.getDependencyResolveExceptionMessage())
236+
.startsWith("org.nonexistent:nonexistent:0 failed. Unable to download POM: org.nonexistent:nonexistent:0. Tried repositories:\n" + row.getUri())
237+
.endsWith(": HTTP 404");
238+
})
231239
),
232240
//language=groovy
233241
buildGradle(
@@ -242,4 +250,46 @@ void dependencyNotFound() {
242250
)
243251
);
244252
}
253+
254+
/** The rows of the repositories other than the local one and the one that doesn't exist. */
255+
private static List<RepositoryAccessibilityReport.Row> remote(List<RepositoryAccessibilityReport.Row> rows) {
256+
return rows.stream()
257+
.filter(row -> !row.getUri().startsWith("file:/") && !row.getUri().contains("nonexistent.moderne.io"))
258+
.toList();
259+
}
260+
261+
private static void reachable(RepositoryAccessibilityReport.Row row) {
262+
assertThat(row.getPingHttpCode()).as("what %s answered", row.getUri()).isEqualTo(200);
263+
assertThat(row.getPingExceptionType()).as("what reaching %s threw", row.getUri()).isEmpty();
264+
}
265+
266+
/**
267+
* Settings with no mirror but one of Maven Central, the mirror CI names in MAVEN_CENTRAL_MIRROR_URL, _USERNAME and
268+
* _PASSWORD, so that Central is reached as the rest of the build reaches it. With no mirror named, none at all.
269+
*/
270+
private static MavenSettings settingsMirroringOnlyCentral(ExecutionContext ctx) {
271+
if (System.getenv("MAVEN_CENTRAL_MIRROR_URL") == null) {
272+
return new MavenSettings(null, null, null, null, null, null);
273+
}
274+
return MavenSettings.parse(new Parser.Input(Path.of("settings.xml"), () -> new ByteArrayInputStream(
275+
//language=xml
276+
"""
277+
<settings>
278+
<servers>
279+
<server>
280+
<id>central-mirror</id>
281+
<username>${env.MAVEN_CENTRAL_MIRROR_USERNAME}</username>
282+
<password>${env.MAVEN_CENTRAL_MIRROR_PASSWORD}</password>
283+
</server>
284+
</servers>
285+
<mirrors>
286+
<mirror>
287+
<id>central-mirror</id>
288+
<mirrorOf>central</mirrorOf>
289+
<url>${env.MAVEN_CENTRAL_MIRROR_URL}</url>
290+
</mirror>
291+
</mirrors>
292+
</settings>
293+
""".getBytes())), ctx);
294+
}
245295
}

0 commit comments

Comments
 (0)