1717
1818import org .junit .jupiter .api .Test ;
1919import org .openrewrite .DocumentExample ;
20+ import org .openrewrite .ExecutionContext ;
2021import org .openrewrite .InMemoryExecutionContext ;
2122import org .openrewrite .Parser ;
2223import org .openrewrite .java .dependencies .table .RepositoryAccessibilityReport ;
2728
2829import java .io .ByteArrayInputStream ;
2930import java .nio .file .Path ;
31+ import java .util .List ;
3032
3133import static org .assertj .core .api .Assertions .assertThat ;
3234import static org .openrewrite .gradle .Assertions .buildGradle ;
3335import static org .openrewrite .gradle .toolingapi .Assertions .withToolingApi ;
3436import 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" )
3744class 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:\n https://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