5050import org .apache .maven .plugins .annotations .Parameter ;
5151import org .apache .maven .plugins .annotations .ResolutionScope ;
5252import org .codehaus .plexus .util .xml .Xpp3Dom ;
53+ import org .eclipse .aether .DefaultRepositorySystemSession ;
54+ import org .eclipse .aether .RepositorySystemSession ;
55+ import org .eclipse .aether .artifact .DefaultArtifact ;
56+ import org .eclipse .aether .collection .CollectRequest ;
57+ import org .eclipse .aether .graph .Dependency ;
58+ import org .eclipse .aether .repository .RemoteRepository ;
59+ import org .eclipse .aether .resolution .ArtifactResult ;
60+ import org .eclipse .aether .resolution .DependencyRequest ;
61+ import org .eclipse .aether .resolution .DependencyResolutionException ;
62+ import org .eclipse .aether .resolution .DependencyResult ;
5363import org .graalvm .buildtools .utils .NativeImageConfigurationUtils ;
54- import org .graalvm .junit .platform .JUnitPlatformFeature ;
5564
56- import java .io .File ;
5765import java .io .IOException ;
5866import java .io .UncheckedIOException ;
59- import java .net .URISyntaxException ;
6067import java .nio .file .Files ;
6168import java .nio .file .Path ;
6269import java .nio .file .Paths ;
6370import java .util .ArrayList ;
6471import java .util .Arrays ;
72+ import java .util .Collections ;
6573import java .util .HashMap ;
74+ import java .util .HashSet ;
6675import java .util .List ;
67- import java .util .Optional ;
76+ import java .util .Set ;
77+ import java .util .stream .Collectors ;
6878import java .util .stream .Stream ;
6979
7080import static org .graalvm .buildtools .utils .NativeImageConfigurationUtils .NATIVE_TESTS_EXE ;
7181
7282/**
7383 * This goal builds and runs native tests.
84+ *
7485 * @author Sebastien Deleuze
7586 */
7687@ Mojo (name = "test" , defaultPhase = LifecyclePhase .TEST , threadSafe = true ,
77- requiresDependencyResolution = ResolutionScope .TEST ,
78- requiresDependencyCollection = ResolutionScope .TEST )
88+ requiresDependencyResolution = ResolutionScope .TEST ,
89+ requiresDependencyCollection = ResolutionScope .TEST )
7990public class NativeTestMojo extends AbstractNativeImageMojo {
8091
8192 @ Parameter (property = "skipTests" , defaultValue = "false" )
@@ -89,31 +100,39 @@ protected void populateApplicationClasspath() throws MojoExecutionException {
89100 super .populateApplicationClasspath ();
90101 imageClasspath .add (Paths .get (project .getBuild ().getTestOutputDirectory ()));
91102 project .getBuild ()
92- .getTestResources ()
93- .stream ()
94- .map (FileSet ::getDirectory )
95- .map (Paths ::get )
96- .forEach (imageClasspath ::add );
103+ .getTestResources ()
104+ .stream ()
105+ .map (FileSet ::getDirectory )
106+ .map (Paths ::get )
107+ .forEach (imageClasspath ::add );
97108 }
98109
99110 @ Override
100111 protected List <String > getDependencyScopes () {
101112 return Arrays .asList (
102- Artifact .SCOPE_COMPILE ,
103- Artifact .SCOPE_RUNTIME ,
104- Artifact .SCOPE_TEST ,
105- Artifact .SCOPE_COMPILE_PLUS_RUNTIME
113+ Artifact .SCOPE_COMPILE ,
114+ Artifact .SCOPE_RUNTIME ,
115+ Artifact .SCOPE_TEST ,
116+ Artifact .SCOPE_COMPILE_PLUS_RUNTIME
106117 );
107118 }
108119
109120 @ Override
110121 protected void addDependenciesToClasspath () throws MojoExecutionException {
111122 super .addDependenciesToClasspath ();
123+ Set <Module > modules = new HashSet <>();
124+ //noinspection SimplifyStreamApiCallChains
112125 pluginArtifacts .stream ()
113- .filter (it -> it .getGroupId ().startsWith (NativeImageConfigurationUtils .MAVEN_GROUP_ID ) || it .getGroupId ().startsWith ("org.junit" ))
114- .map (it -> it .getFile ().toPath ())
115- .forEach (imageClasspath ::add );
116- findNativePlatformJar ().ifPresent (imageClasspath ::add );
126+ // do not use peek as Stream implementations are free to discard it
127+ .map (a -> {
128+ modules .add (new Module (a .getGroupId (), a .getArtifactId ()));
129+ return a ;
130+ })
131+ .filter (it -> it .getGroupId ().startsWith (NativeImageConfigurationUtils .MAVEN_GROUP_ID ) || it .getGroupId ().startsWith ("org.junit" ))
132+ .map (it -> it .getFile ().toPath ())
133+ .forEach (imageClasspath ::add );
134+ var jars = findJunitPlatformNativeJars (modules );
135+ imageClasspath .addAll (jars );
117136 }
118137
119138 @ Override
@@ -142,7 +161,7 @@ public void execute() throws MojoExecutionException {
142161 systemProperties = new HashMap <>();
143162 }
144163 systemProperties .put ("junit.platform.listeners.uid.tracking.output.dir" ,
145- NativeExtension .testIdsDirectory (outputDirectory .getAbsolutePath ()));
164+ NativeExtension .testIdsDirectory (outputDirectory .getAbsolutePath ()));
146165
147166 imageName = NATIVE_TESTS_EXE ;
148167 mainClass = "org.graalvm.junit.platform.NativeImageJUnitLauncher" ;
@@ -248,15 +267,71 @@ private static Stream<Path> findFiles(Path dir, String prefix) throws IOExceptio
248267 return Stream .empty ();
249268 }
250269 return Files .find (dir , Integer .MAX_VALUE ,
251- (path , basicFileAttributes ) -> (basicFileAttributes .isRegularFile ()
252- && path .getFileName ().toString ().startsWith (prefix )));
270+ (path , basicFileAttributes ) -> (basicFileAttributes .isRegularFile ()
271+ && path .getFileName ().toString ().startsWith (prefix )));
253272 }
254273
255- private static Optional <Path > findNativePlatformJar () {
274+ private List <Path > findJunitPlatformNativeJars (Set <Module > modulesAlreadyOnClasspath ) {
275+ RepositorySystemSession repositorySession = mavenSession .getRepositorySession ();
276+ DefaultRepositorySystemSession newSession = new DefaultRepositorySystemSession (repositorySession );
277+ CollectRequest collectRequest = new CollectRequest ();
278+ List <RemoteRepository > repositories = project .getRemoteProjectRepositories ();
279+ collectRequest .setRepositories (repositories );
280+ DefaultArtifact artifact = new DefaultArtifact (
281+ RuntimeMetadata .GROUP_ID ,
282+ RuntimeMetadata .JUNIT_PLATFORM_NATIVE_ARTIFACT_ID ,
283+ null ,
284+ "jar" ,
285+ RuntimeMetadata .VERSION
286+ );
287+ Dependency dependency = new Dependency (artifact , "runtime" );
288+ collectRequest .addDependency (dependency );
289+ DependencyRequest dependencyRequest = new DependencyRequest (collectRequest , null );
290+ DependencyResult dependencyResult ;
256291 try {
257- return Optional .of (new File (JUnitPlatformFeature .class .getProtectionDomain ().getCodeSource ().getLocation ().toURI ()).toPath ());
258- } catch (URISyntaxException e ) {
259- return Optional .empty ();
292+ dependencyResult = repositorySystem .resolveDependencies (newSession , dependencyRequest );
293+ } catch (DependencyResolutionException e ) {
294+ return Collections .emptyList ();
295+ }
296+ return dependencyResult .getArtifactResults ()
297+ .stream ()
298+ .map (ArtifactResult ::getArtifact )
299+ .filter (a -> !modulesAlreadyOnClasspath .contains (new Module (a .getGroupId (), a .getArtifactId ())))
300+ .map (a -> a .getFile ().toPath ())
301+ .collect (Collectors .toList ());
302+ }
303+
304+ private static final class Module {
305+ private final String groupId ;
306+ private final String artifactId ;
307+
308+ private Module (String groupId , String artifactId ) {
309+ this .groupId = groupId ;
310+ this .artifactId = artifactId ;
311+ }
312+
313+ @ Override
314+ public boolean equals (Object o ) {
315+ if (this == o ) {
316+ return true ;
317+ }
318+ if (o == null || getClass () != o .getClass ()) {
319+ return false ;
320+ }
321+
322+ Module module = (Module ) o ;
323+
324+ if (!groupId .equals (module .groupId )) {
325+ return false ;
326+ }
327+ return artifactId .equals (module .artifactId );
328+ }
329+
330+ @ Override
331+ public int hashCode () {
332+ int result = groupId .hashCode ();
333+ result = 31 * result + artifactId .hashCode ();
334+ return result ;
260335 }
261336 }
262337}
0 commit comments