View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugin.surefire;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.OutputStream;
24  import java.io.UncheckedIOException;
25  import java.lang.reflect.Field;
26  import java.lang.reflect.Method;
27  import java.nio.file.Files;
28  import java.nio.file.Path;
29  import java.nio.file.Paths;
30  import java.util.ArrayList;
31  import java.util.Collection;
32  import java.util.Collections;
33  import java.util.HashMap;
34  import java.util.HashSet;
35  import java.util.LinkedHashMap;
36  import java.util.LinkedHashSet;
37  import java.util.LinkedList;
38  import java.util.List;
39  import java.util.Map;
40  import java.util.Properties;
41  import java.util.Set;
42  
43  import org.apache.commons.io.FileUtils;
44  import org.apache.maven.artifact.Artifact;
45  import org.apache.maven.artifact.DefaultArtifact;
46  import org.apache.maven.artifact.handler.ArtifactHandler;
47  import org.apache.maven.artifact.handler.DefaultArtifactHandler;
48  import org.apache.maven.artifact.versioning.VersionRange;
49  import org.apache.maven.execution.MavenSession;
50  import org.apache.maven.model.Dependency;
51  import org.apache.maven.model.Plugin;
52  import org.apache.maven.plugin.MojoFailureException;
53  import org.apache.maven.plugin.descriptor.PluginDescriptor;
54  import org.apache.maven.plugin.surefire.booterclient.Platform;
55  import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
56  import org.apache.maven.project.MavenProject;
57  import org.apache.maven.surefire.api.suite.RunResult;
58  import org.apache.maven.surefire.api.util.DefaultScanResult;
59  import org.apache.maven.surefire.api.util.SureFireFileManager;
60  import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
61  import org.apache.maven.surefire.booter.Classpath;
62  import org.apache.maven.surefire.booter.ModularClasspathConfiguration;
63  import org.apache.maven.surefire.booter.StartupConfiguration;
64  import org.apache.maven.surefire.extensions.ForkNodeFactory;
65  import org.apache.maven.surefire.providerapi.ProviderInfo;
66  import org.apache.maven.toolchain.Toolchain;
67  import org.assertj.core.api.Assertions;
68  import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
69  import org.codehaus.plexus.languages.java.jpms.LocationManager;
70  import org.codehaus.plexus.languages.java.jpms.ResolvePathRequest;
71  import org.codehaus.plexus.languages.java.jpms.ResolvePathResult;
72  import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest;
73  import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult;
74  import org.junit.jupiter.api.BeforeEach;
75  import org.junit.jupiter.api.Test;
76  import org.junit.jupiter.api.extension.ExtendWith;
77  import org.junit.jupiter.api.io.TempDir;
78  import org.mockito.ArgumentCaptor;
79  import org.mockito.Mock;
80  import org.mockito.junit.jupiter.MockitoExtension;
81  import org.mockito.junit.jupiter.MockitoSettings;
82  import org.mockito.quality.Strictness;
83  import org.slf4j.Logger;
84  
85  import static java.io.File.separatorChar;
86  import static java.nio.charset.StandardCharsets.UTF_8;
87  import static java.nio.file.Files.write;
88  import static java.util.Arrays.asList;
89  import static java.util.Collections.emptyList;
90  import static java.util.Collections.emptyMap;
91  import static java.util.Collections.singleton;
92  import static java.util.Collections.singletonList;
93  import static org.apache.maven.artifact.ArtifactUtils.artifactMapByVersionlessId;
94  import static org.apache.maven.artifact.versioning.VersionRange.createFromVersion;
95  import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec;
96  import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_9;
97  import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_RECENT;
98  import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
99  import static org.assertj.core.api.Assertions.assertThat;
100 import static org.codehaus.plexus.languages.java.jpms.ModuleNameSource.MODULEDESCRIPTOR;
101 import static org.junit.jupiter.api.Assertions.assertThrows;
102 import static org.mockito.ArgumentMatchers.any;
103 import static org.mockito.ArgumentMatchers.anyString;
104 import static org.mockito.ArgumentMatchers.eq;
105 import static org.mockito.Mockito.doNothing;
106 import static org.mockito.Mockito.doReturn;
107 import static org.mockito.Mockito.mock;
108 import static org.mockito.Mockito.spy;
109 import static org.mockito.Mockito.times;
110 import static org.mockito.Mockito.verify;
111 import static org.mockito.Mockito.when;
112 
113 /**
114  * Test for {@link AbstractSurefireMojo}.
115  */
116 @ExtendWith(MockitoExtension.class)
117 @MockitoSettings(strictness = Strictness.LENIENT)
118 public class AbstractSurefireMojoTest {
119 
120     @TempDir
121     Path tempFolder;
122 
123     @Mock
124     private ArtifactHandler handler;
125 
126     private final Mojo mojo = new Mojo();
127 
128     @BeforeEach
129     public void setupMojo() {
130         Artifact mojoArtifact = mojo.getMojoArtifact();
131 
132         mojo.setProperties(new Properties());
133 
134         mojo.setPluginArtifactMap(new LinkedHashMap<>());
135         mojo.getPluginArtifactMap().put(mojoArtifact.getGroupId() + ":" + mojoArtifact.getArtifactId(), mojoArtifact);
136         Artifact forkedBooter = new DefaultArtifact(
137                 "org.apache.maven.surefire",
138                 "surefire-booter",
139                 mojoArtifact.getVersion(),
140                 null,
141                 "jar",
142                 null,
143                 mock(ArtifactHandler.class));
144         mojo.getPluginArtifactMap().put("org.apache.maven.surefire:surefire-booter", forkedBooter);
145 
146         mojo.setProjectArtifactMap(new LinkedHashMap<>());
147 
148         MavenSession session = mock(MavenSession.class);
149         mojo.setSession(session);
150 
151         PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
152         Plugin plugin = new Plugin();
153         plugin.setGroupId(mojoArtifact.getGroupId());
154         plugin.setArtifactId(mojoArtifact.getArtifactId());
155         plugin.setVersion(mojoArtifact.getVersion());
156         when(pluginDescriptor.getPlugin()).thenReturn(plugin);
157         mojo.setPluginDescriptor(pluginDescriptor);
158     }
159 
160     @Test
161     public void noModuleDescriptorFile() throws Exception {
162         AbstractSurefireMojo mojo = spy(new Mojo());
163         mojo.setMainBuildPath(Files.createTempDirectory(tempFolder, "test").toFile());
164         File testClassesDir = Files.createTempDirectory(tempFolder, "test").toFile();
165         mojo.setTestClassesDirectory(testClassesDir);
166         File jdkHome = new File(System.getProperty("java.home"));
167         ResolvePathResultWrapper wrapper = invokeMethod(mojo, "findModuleDescriptor", jdkHome);
168 
169         assertThat(wrapper).isNotNull();
170 
171         assertThat(wrapper.getResolvePathResult()).isNull();
172 
173         assertThat((boolean) invokeMethod(mojo, "existsModuleDescriptor", wrapper))
174                 .isEqualTo(false);
175 
176         when(mojo.useModulePath()).thenReturn(true);
177 
178         File jvmExecutable = new File(jdkHome, IS_OS_WINDOWS ? "bin\\java.exe" : "bin/java");
179         JdkAttributes jdkAttributes = new JdkAttributes(jvmExecutable, jdkHome, true);
180         Platform platform = new Platform().withJdkExecAttributesForTests(jdkAttributes);
181         assertThat((boolean) invokeMethod(mojo, "canExecuteProviderWithModularPath", platform, wrapper))
182                 .isEqualTo(false);
183     }
184 
185     @Test
186     public void correctModuleDescriptor() throws Exception {
187         AbstractSurefireMojo mojo = spy(new Mojo());
188         LocationManager locationManager = mock(LocationManager.class);
189         ResolvePathResult result = mock(ResolvePathResult.class);
190         when(result.getModuleNameSource()).thenReturn(MODULEDESCRIPTOR);
191         JavaModuleDescriptor descriptor = mock(JavaModuleDescriptor.class);
192         when(result.getModuleDescriptor()).thenReturn(descriptor);
193         when(locationManager.resolvePath(any(ResolvePathRequest.class))).thenReturn(result);
194         setInternalState(mojo, "locationManager", locationManager);
195         File classesDir = Files.createTempDirectory(tempFolder, "test").toFile();
196         mojo.setMainBuildPath(classesDir);
197         File testClassesDir = Files.createTempDirectory(tempFolder, "test").toFile();
198         mojo.setTestClassesDirectory(testClassesDir);
199         File descriptorFile = new File(classesDir, "module-info.class");
200         assertThat(descriptorFile.createNewFile()).isTrue();
201         File jdkHome = new File(System.getProperty("java.home"));
202         ResolvePathResultWrapper wrapper = invokeMethod(mojo, "findModuleDescriptor", jdkHome);
203 
204         assertThat(wrapper).isNotNull();
205 
206         assertThat(wrapper.getResolvePathResult()).isSameAs(result);
207 
208         assertThat(wrapper.getResolvePathResult().getModuleNameSource()).isSameAs(MODULEDESCRIPTOR);
209 
210         assertThat(wrapper.getResolvePathResult().getModuleDescriptor()).isSameAs(descriptor);
211 
212         assertThat((boolean) invokeMethod(mojo, "existsModuleDescriptor", wrapper))
213                 .isEqualTo(true);
214 
215         when(mojo.useModulePath()).thenReturn(true);
216 
217         File jvmExecutable = new File(jdkHome, IS_OS_WINDOWS ? "bin\\java.exe" : "bin/java");
218         JdkAttributes jdkAttributes = new JdkAttributes(jvmExecutable, jdkHome, true);
219         Platform platform = new Platform().withJdkExecAttributesForTests(jdkAttributes);
220         assertThat((boolean) invokeMethod(mojo, "canExecuteProviderWithModularPath", platform, wrapper))
221                 .isEqualTo(true);
222 
223         jdkAttributes = new JdkAttributes(jvmExecutable, jdkHome, false);
224         platform = new Platform().withJdkExecAttributesForTests(jdkAttributes);
225         assertThat((boolean) invokeMethod(mojo, "canExecuteProviderWithModularPath", platform, wrapper))
226                 .isEqualTo(false);
227 
228         when(mojo.useModulePath()).thenReturn(false);
229 
230         jdkAttributes = new JdkAttributes(jvmExecutable, jdkHome, true);
231         platform = new Platform().withJdkExecAttributesForTests(jdkAttributes);
232         assertThat((boolean) invokeMethod(mojo, "canExecuteProviderWithModularPath", platform, wrapper))
233                 .isEqualTo(false);
234     }
235 
236     @Test
237     @SuppressWarnings("checkstyle:magicnumber")
238     public void corruptedModuleDescriptor() throws Exception {
239         if (!JAVA_RECENT.atLeast(JAVA_9)) {
240             return;
241         }
242 
243         AbstractSurefireMojo mojo = spy(new Mojo());
244         setInternalState(mojo, "locationManager", new LocationManager());
245         File classesDir = Files.createTempDirectory(tempFolder, "test").toFile();
246         mojo.setMainBuildPath(classesDir);
247         File testClassesDir = Files.createTempDirectory(tempFolder, "test").toFile();
248         mojo.setTestClassesDirectory(testClassesDir);
249 
250         File descriptorFile = new File(classesDir, "module-info.class");
251         assertThat(descriptorFile.createNewFile()).isTrue();
252         write(descriptorFile.toPath(), new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE});
253 
254         File jdkHome = new File(System.getProperty("java.home"));
255         ResolvePathResultWrapper wrapper = invokeMethod(mojo, "findModuleDescriptor", jdkHome);
256 
257         assertThat(wrapper).isNotNull();
258 
259         assertThat(wrapper.getResolvePathResult()).isNull();
260 
261         assertThat((boolean) invokeMethod(mojo, "existsModuleDescriptor", wrapper))
262                 .isEqualTo(false);
263     }
264 
265     @Test
266     public void shouldShowArray() throws Exception {
267         Logger logger = mock(Logger.class);
268         when(logger.isDebugEnabled()).thenReturn(true);
269         doNothing().when(logger).debug(anyString());
270 
271         AbstractSurefireMojo mojo = spy(this.mojo);
272 
273         when(mojo.getConsoleLogger()).thenReturn(new PluginConsoleLogger(logger));
274 
275         Object[] array = {"ABC", "XYZ"};
276         invokeMethod(mojo, "showArray", array, "prefix");
277 
278         ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
279         verify(logger, times(2)).debug(argument.capture());
280         assertThat(argument.getAllValues()).containsExactly("Setting prefix [ABC]", "Setting prefix [XYZ]");
281     }
282 
283     @Test
284     public void shouldShowMap() throws Exception {
285         Logger logger = mock(Logger.class);
286         when(logger.isDebugEnabled()).thenReturn(true);
287         doNothing().when(logger).debug(anyString());
288 
289         AbstractSurefireMojo mojo = spy(this.mojo);
290 
291         when(mojo.getConsoleLogger()).thenReturn(new PluginConsoleLogger(logger));
292 
293         Map<String, String> map = new LinkedHashMap<>();
294         map.put("ABC", "123");
295         map.put("XYZ", "987");
296         invokeMethod(mojo, "showMap", map, "prefix");
297 
298         ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
299         verify(logger, times(2)).debug(argument.capture());
300         assertThat(argument.getAllValues()).containsExactly("Setting prefix [ABC]=[123]", "Setting prefix [XYZ]=[987]");
301     }
302 
303     @Test
304     public void shouldRetainInPluginArtifacts() throws Exception {
305         Artifact provider = new DefaultArtifact("g", "a", createFromVersionSpec("1"), "compile", "jar", "", null);
306         Artifact common = new DefaultArtifact("g", "c", createFromVersionSpec("1"), "compile", "jar", "", null);
307         Artifact api = new DefaultArtifact("g", "a", createFromVersionSpec("1"), "compile", "jar", "", null);
308 
309         Set<Artifact> providerArtifacts = singleton(provider);
310         Artifact[] inPluginArtifacts = {common, api};
311         Set<Artifact> inPluginClasspath = invokeMethod(
312                 AbstractSurefireMojo.class, "retainInProcArtifactsUnique", providerArtifacts, inPluginArtifacts);
313 
314         assertThat(inPluginClasspath).containsOnly(common);
315     }
316 
317     @Test
318     public void shouldRetainInProcArtifactsUnique() throws Exception {
319         Artifact provider = new DefaultArtifact("g", "p", createFromVersionSpec("1"), "compile", "jar", "", null);
320         Artifact common = new DefaultArtifact("g", "c", createFromVersionSpec("1"), "compile", "jar", "", null);
321         Artifact api = new DefaultArtifact("g", "a", createFromVersionSpec("1"), "compile", "jar", "", null);
322 
323         Set<Artifact> providerArtifacts = singleton(provider);
324         Artifact[] inPluginArtifacts = {common, api};
325         Set<Artifact> inPluginClasspath = invokeMethod(
326                 AbstractSurefireMojo.class, "retainInProcArtifactsUnique", providerArtifacts, inPluginArtifacts);
327 
328         assertThat(inPluginClasspath).containsOnly(common, api);
329     }
330 
331     @Test
332     public void shouldCreateInProcClasspath() throws Exception {
333         Artifact provider = new DefaultArtifact("g", "p", createFromVersionSpec("1"), "compile", "jar", "", null);
334         provider.setFile(mockFile("provider.jar"));
335 
336         Artifact common = new DefaultArtifact("g", "c", createFromVersionSpec("1"), "compile", "jar", "", null);
337         common.setFile(mockFile("maven-surefire-common.jar"));
338 
339         Artifact api = new DefaultArtifact("g", "a", createFromVersionSpec("1"), "compile", "jar", "", null);
340         api.setFile(mockFile("surefire-api.jar"));
341 
342         Set<Artifact> newArtifacts = new LinkedHashSet<>();
343         newArtifacts.add(common);
344         newArtifacts.add(api);
345 
346         Classpath providerClasspath = new Classpath(singleton(provider.getFile().getAbsolutePath()));
347 
348         Classpath inPluginClasspath =
349                 invokeMethod(AbstractSurefireMojo.class, "createInProcClasspath", providerClasspath, newArtifacts);
350 
351         Classpath expectedClasspath = new Classpath(asList(
352                 provider.getFile().getAbsolutePath(),
353                 common.getFile().getAbsolutePath(),
354                 api.getFile().getAbsolutePath()));
355 
356         assertThat((Object) inPluginClasspath).isEqualTo(expectedClasspath);
357     }
358 
359     @Test
360     public void shouldGenerateTestClasspath() throws Exception {
361         AbstractSurefireMojo mojo = spy(this.mojo);
362 
363         when(mojo.getMainBuildPath()).thenReturn(new File("target" + separatorChar + "classes"));
364         when(mojo.getTestClassesDirectory()).thenReturn(new File("target" + separatorChar + "test-classes"));
365         when(mojo.getClasspathDependencyScopeExclude()).thenReturn("runtime");
366         when(mojo.getClasspathDependencyExcludes()).thenReturn(new String[] {"g3:a3"});
367 
368         Set<Artifact> artifacts = new HashSet<>();
369 
370         Artifact a1 = mock(Artifact.class);
371         when(a1.getGroupId()).thenReturn("g1");
372         when(a1.getArtifactId()).thenReturn("a1");
373         when(a1.getVersion()).thenReturn("1");
374         when(a1.getScope()).thenReturn("runtime");
375         when(a1.getDependencyConflictId()).thenReturn("g1:a1:jar");
376         when(a1.getId()).thenReturn("g1:a1:jar:1");
377         artifacts.add(a1);
378 
379         ArtifactHandler artifactHandler = mock(ArtifactHandler.class);
380         when(artifactHandler.isAddedToClasspath()).thenReturn(true);
381 
382         Artifact a2 = mock(Artifact.class);
383         when(a2.getGroupId()).thenReturn("g2");
384         when(a2.getArtifactId()).thenReturn("a2");
385         when(a2.getVersion()).thenReturn("2");
386         when(a2.getScope()).thenReturn("test");
387         when(a2.getDependencyConflictId()).thenReturn("g2:a2:jar");
388         when(a2.getId()).thenReturn("g2:a2:jar:2");
389         when(a2.getFile()).thenReturn(new File("a2-2.jar"));
390         when(a2.getArtifactHandler()).thenReturn(artifactHandler);
391         artifacts.add(a2);
392 
393         Artifact a3 = mock(Artifact.class);
394         when(a3.getGroupId()).thenReturn("g3");
395         when(a3.getArtifactId()).thenReturn("a3");
396         when(a3.getVersion()).thenReturn("3");
397         when(a3.getScope()).thenReturn("test");
398         when(a3.getDependencyConflictId()).thenReturn("g3:a3:jar");
399         when(a3.getId()).thenReturn("g3:a3:jar:3");
400         when(a3.getFile()).thenReturn(new File("a3-3.jar"));
401         when(a3.getArtifactHandler()).thenReturn(artifactHandler);
402         artifacts.add(a3);
403 
404         MavenProject project = mock(MavenProject.class);
405         when(project.getArtifacts()).thenReturn(artifacts);
406         when(mojo.getProject()).thenReturn(project);
407 
408         TestClassPath cp = invokeMethod(mojo, "generateTestClasspath");
409 
410         verify(mojo, times(1)).getMainBuildPath();
411         verify(mojo, times(1)).getTestClassesDirectory();
412         verify(mojo, times(3)).getClasspathDependencyScopeExclude();
413         verify(mojo, times(2)).getClasspathDependencyExcludes();
414         verify(mojo, times(1)).getAdditionalClasspathElements();
415 
416         assertThat(cp.toClasspath().getClassPath()).hasSize(3);
417         assertThat(cp.toClasspath().getClassPath().get(0)).endsWith("test-classes");
418         assertThat(cp.toClasspath().getClassPath().get(1)).endsWith("classes");
419         assertThat(cp.toClasspath().getClassPath().get(2)).endsWith("a2-2.jar");
420     }
421 
422     @Test
423     @SuppressWarnings("checkstyle:linelength")
424     public void shouldHaveStartupConfigForNonModularClasspath() throws Exception {
425         AbstractSurefireMojo mojo = spy(this.mojo);
426 
427         Artifact common = new DefaultArtifact(
428                 "org.apache.maven.surefire",
429                 "maven-surefire-common",
430                 createFromVersion("1"),
431                 "runtime",
432                 "jar",
433                 "",
434                 handler);
435         common.setFile(mockFile("maven-surefire-common.jar"));
436 
437         Artifact ext = new DefaultArtifact(
438                 "org.apache.maven.surefire",
439                 "surefire-extensions-api",
440                 createFromVersion("1"),
441                 "runtime",
442                 "jar",
443                 "",
444                 handler);
445         ext.setFile(mockFile("surefire-extensions-api.jar"));
446 
447         Artifact api = new DefaultArtifact(
448                 "org.apache.maven.surefire", "surefire-api", createFromVersion("1"), "runtime", "jar", "", handler);
449         api.setFile(mockFile("surefire-api.jar"));
450 
451         Artifact loggerApi = new DefaultArtifact(
452                 "org.apache.maven.surefire",
453                 "surefire-logger-api",
454                 createFromVersion("1"),
455                 "runtime",
456                 "jar",
457                 "",
458                 handler);
459         loggerApi.setFile(mockFile("surefire-logger-api.jar"));
460 
461         Artifact spi = new DefaultArtifact(
462                 "org.apache.maven.surefire",
463                 "surefire-extensions-spi",
464                 createFromVersion("1"),
465                 "runtime",
466                 "jar",
467                 "",
468                 handler);
469         spi.setFile(mockFile("surefire-extensions-spi.jar"));
470 
471         Artifact booter = new DefaultArtifact(
472                 "org.apache.maven.surefire", "surefire-booter", createFromVersion("1"), "runtime", "jar", "", handler);
473         booter.setFile(mockFile("surefire-booter.jar"));
474 
475         Artifact utils = new DefaultArtifact(
476                 "org.apache.maven.surefire",
477                 "surefire-shared-utils",
478                 createFromVersion("1"),
479                 "runtime",
480                 "jar",
481                 "",
482                 handler);
483         utils.setFile(mockFile("surefire-shared-utils.jar"));
484 
485         Map<String, Artifact> providerArtifactsMap = new HashMap<>();
486         providerArtifactsMap.put("org.apache.maven.surefire:maven-surefire-common", common);
487         providerArtifactsMap.put("org.apache.maven.surefire:surefire-extensions-api", ext);
488         providerArtifactsMap.put("org.apache.maven.surefire:surefire-api", api);
489         providerArtifactsMap.put("org.apache.maven.surefire:surefire-logger-api", loggerApi);
490         providerArtifactsMap.put("org.apache.maven.surefire:surefire-extensions-spi", spi);
491         providerArtifactsMap.put("org.apache.maven.surefire:surefire-booter", booter);
492         providerArtifactsMap.put("org.apache.maven.surefire:surefire-shared-utils", utils);
493 
494         when(mojo.getPluginArtifactMap()).thenReturn(providerArtifactsMap);
495 
496         when(handler.isAddedToClasspath()).thenReturn(true);
497 
498         VersionRange v1 = createFromVersion("4.12");
499         Artifact junit = new DefaultArtifact("junit", "junit", v1, "test", "jar", "", handler);
500         junit.setFile(mockFile("junit.jar"));
501 
502         VersionRange v2 = createFromVersion("1.3.0");
503         Artifact hamcrest = new DefaultArtifact("org.hamcrest", "hamcrest-core", v2, "test", "jar", "", handler);
504         hamcrest.setFile(mockFile("hamcrest.jar"));
505 
506         File classesDir = mockFile("classes");
507         File testClassesDir = mockFile("test-classes");
508         TestClassPath testClasspath = new TestClassPath(asList(junit, hamcrest), classesDir, testClassesDir, null);
509 
510         doReturn(1).when(mojo).getEffectiveForkCount();
511         doReturn(true).when(mojo).effectiveIsEnableAssertions();
512         when(mojo.isChildDelegation()).thenReturn(false);
513 
514         ClassLoaderConfiguration classLoaderConfiguration = new ClassLoaderConfiguration(false, true);
515 
516         VersionRange v3 = createFromVersion("1");
517         Artifact provider = new DefaultArtifact("x", "surefire-provider", v3, "runtime", "jar", "", handler);
518         provider.setFile(mockFile("surefire-provider.jar"));
519         Set<Artifact> providerArtifacts = singleton(provider);
520 
521         Logger logger = mock(Logger.class);
522         when(logger.isDebugEnabled()).thenReturn(true);
523         doNothing().when(logger).debug(anyString());
524         when(mojo.getConsoleLogger()).thenReturn(new PluginConsoleLogger(logger));
525 
526         ProviderInfo providerInfo = mock(ProviderInfo.class);
527         when(providerInfo.getProviderName()).thenReturn("org.asf.Provider");
528         when(providerInfo.getProviderClasspath()).thenReturn(providerArtifacts);
529         when(providerInfo.decorateTestClassPath(any())).thenReturn(testClasspath);
530 
531         StartupConfiguration conf = invokeMethod(
532                 mojo, "newStartupConfigWithClasspath", classLoaderConfiguration, providerInfo, testClasspath);
533 
534         verify(mojo, times(1)).effectiveIsEnableAssertions();
535         verify(mojo, times(1)).isChildDelegation();
536         ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
537         verify(logger, times(6)).debug(argument.capture());
538         assertThat(argument.getAllValues())
539                 .containsExactly(
540                         "test classpath:  test-classes  classes  junit.jar  hamcrest.jar",
541                         "provider classpath:  surefire-provider.jar",
542                         "test(compact) classpath:  test-classes  classes  junit.jar  hamcrest.jar",
543                         "provider(compact) classpath:  surefire-provider.jar",
544                         "in-process classpath:  surefire-provider.jar  maven-surefire-common.jar  surefire-booter.jar  surefire-extensions-api.jar  surefire-api.jar  surefire-extensions-spi.jar  surefire-logger-api.jar  surefire-shared-utils.jar",
545                         "in-process(compact) classpath:  surefire-provider.jar  maven-surefire-common.jar  surefire-booter.jar  surefire-extensions-api.jar  surefire-api.jar  surefire-extensions-spi.jar  surefire-logger-api.jar  surefire-shared-utils.jar");
546 
547         assertThat(conf.getClassLoaderConfiguration()).isSameAs(classLoaderConfiguration);
548 
549         assertThat((Object) conf.getClasspathConfiguration().getTestClasspath()).isEqualTo(testClasspath.toClasspath());
550 
551         Collection<String> files = new ArrayList<>();
552         for (Artifact providerArtifact : providerArtifacts) {
553             files.add(providerArtifact.getFile().getAbsolutePath());
554         }
555         assertThat((Object) conf.getClasspathConfiguration().getProviderClasspath())
556                 .isEqualTo(new Classpath(files));
557 
558         assertThat((Object) conf.getClasspathConfiguration().isClassPathConfig())
559                 .isEqualTo(true);
560 
561         assertThat((Object) conf.getClasspathConfiguration().isModularPathConfig())
562                 .isEqualTo(false);
563 
564         assertThat((Object) conf.getClasspathConfiguration().isEnableAssertions())
565                 .isEqualTo(true);
566 
567         assertThat(conf.getProviderClassName()).isEqualTo("org.asf.Provider");
568     }
569 
570     @Test
571     public void providerClasspathCachingIsNotSharedAcrossMojoInstances() throws Exception {
572         ProviderInfo providerInfo = mock(ProviderInfo.class);
573         when(providerInfo.getProviderName()).thenReturn("test-provider");
574         Artifact provider =
575                 new DefaultArtifact("com.example", "provider", createFromVersion("1"), "runtime", "jar", "", handler);
576         provider.setFile(mockFile("original-test-provider.jar"));
577         Set<Artifact> providerClasspath = singleton(provider);
578         when(providerInfo.getProviderClasspath()).thenReturn(providerClasspath);
579         TestClassPath testClassPath =
580                 new TestClassPath(providerClasspath, new File("target"), new File("target"), Collections.emptyList());
581         when(providerInfo.decorateTestClassPath(any())).thenReturn(testClassPath);
582 
583         StartupConfiguration startupConfiguration = startupConfigurationForProvider(providerInfo);
584         assertThat(startupConfiguration
585                         .getClasspathConfiguration()
586                         .getProviderClasspath()
587                         .getClassPath())
588                 .containsExactly("original-test-provider.jar");
589 
590         provider.setFile(mockFile("modified-test-provider.jar"));
591         startupConfiguration = startupConfigurationForProvider(providerInfo);
592         assertThat(startupConfiguration
593                         .getClasspathConfiguration()
594                         .getProviderClasspath()
595                         .getClassPath())
596                 .containsExactly("modified-test-provider.jar");
597     }
598 
599     private StartupConfiguration startupConfigurationForProvider(ProviderInfo providerInfo) throws Exception {
600         AbstractSurefireMojo mojo = spy(new Mojo());
601 
602         Logger logger = mock(Logger.class);
603         when(logger.isDebugEnabled()).thenReturn(true);
604         doNothing().when(logger).debug(anyString());
605         when(mojo.getConsoleLogger()).thenReturn(new PluginConsoleLogger(logger));
606 
607         File classesDir = mockFile("classes");
608         File testClassesDir = mockFile("test-classes");
609         TestClassPath testClassPath =
610                 new TestClassPath(new ArrayList<>(), classesDir, testClassesDir, Collections.emptyList());
611 
612         Artifact common = new DefaultArtifact(
613                 "org.apache.maven.surefire",
614                 "maven-surefire-common",
615                 createFromVersion("1"),
616                 "runtime",
617                 "jar",
618                 "",
619                 handler);
620         common.setFile(mockFile("maven-surefire-common.jar"));
621 
622         Artifact ext = new DefaultArtifact(
623                 "org.apache.maven.surefire",
624                 "surefire-extensions-api",
625                 createFromVersion("1"),
626                 "runtime",
627                 "jar",
628                 "",
629                 handler);
630         ext.setFile(mockFile("surefire-extensions-api.jar"));
631 
632         Artifact api = new DefaultArtifact(
633                 "org.apache.maven.surefire", "surefire-api", createFromVersion("1"), "runtime", "jar", "", handler);
634         api.setFile(mockFile("surefire-api.jar"));
635 
636         Artifact loggerApi = new DefaultArtifact(
637                 "org.apache.maven.surefire",
638                 "surefire-logger-api",
639                 createFromVersion("1"),
640                 "runtime",
641                 "jar",
642                 "",
643                 handler);
644         loggerApi.setFile(mockFile("surefire-logger-api.jar"));
645 
646         Artifact spi = new DefaultArtifact(
647                 "org.apache.maven.surefire",
648                 "surefire-extensions-spi",
649                 createFromVersion("1"),
650                 "runtime",
651                 "jar",
652                 "",
653                 handler);
654         spi.setFile(mockFile("surefire-extensions-spi.jar"));
655 
656         Artifact booter = new DefaultArtifact(
657                 "org.apache.maven.surefire", "surefire-booter", createFromVersion("1"), "runtime", "jar", "", handler);
658         booter.setFile(mockFile("surefire-booter.jar"));
659 
660         Artifact utils = new DefaultArtifact(
661                 "org.apache.maven.surefire",
662                 "surefire-shared-utils",
663                 createFromVersion("1"),
664                 "runtime",
665                 "jar",
666                 "",
667                 handler);
668         utils.setFile(mockFile("surefire-shared-utils.jar"));
669 
670         Map<String, Artifact> providerArtifactsMap = new HashMap<>();
671         providerArtifactsMap.put("org.apache.maven.surefire:maven-surefire-common", common);
672         providerArtifactsMap.put("org.apache.maven.surefire:surefire-extensions-api", ext);
673         providerArtifactsMap.put("org.apache.maven.surefire:surefire-api", api);
674         providerArtifactsMap.put("org.apache.maven.surefire:surefire-logger-api", loggerApi);
675         providerArtifactsMap.put("org.apache.maven.surefire:surefire-extensions-spi", spi);
676         providerArtifactsMap.put("org.apache.maven.surefire:surefire-booter", booter);
677         providerArtifactsMap.put("org.apache.maven.surefire:surefire-shared-utils", utils);
678 
679         when(mojo.getPluginArtifactMap()).thenReturn(providerArtifactsMap);
680 
681         doReturn(1).when(mojo).getEffectiveForkCount();
682 
683         return invokeMethod(
684                 mojo, "createStartupConfiguration", providerInfo, false, null, null, testClassPath, null, null);
685     }
686 
687     @Test
688     public void shouldCreateStartupConfigWithModularPath() throws Exception {
689         String baseDir = System.getProperty("user.dir");
690 
691         Mojo mojo = new Mojo();
692 
693         // ### BEGIN
694         // we cannot mock private method newStartupConfigWithModularPath() - mocking the data to prevent from errors
695         LocationManager locationManager = mock(LocationManager.class);
696         ResolvePathsResult resolvePathsResult = mock(ResolvePathsResult.class);
697         when(locationManager.resolvePaths(any(ResolvePathsRequest.class))).thenReturn(resolvePathsResult);
698         when(resolvePathsResult.getPathExceptions()).thenReturn(emptyMap());
699         when(resolvePathsResult.getClasspathElements()).thenReturn(emptyList());
700         when(resolvePathsResult.getModulepathElements()).thenReturn(emptyMap());
701 
702         mojo.setLogger(mock(Logger.class));
703         mojo.setUseModulePath(true);
704         setInternalState(mojo, "locationManager", locationManager);
705 
706         File jdkHome = new File(System.getProperty("java.home"));
707         File jvmExecutable = new File(jdkHome, IS_OS_WINDOWS ? "bin\\java.exe" : "bin/java");
708         JdkAttributes jdkAttributes = new JdkAttributes(jvmExecutable, jdkHome, true);
709         Platform platform = new Platform().withJdkExecAttributesForTests(jdkAttributes);
710 
711         File classesDirectory = new File(baseDir, "mock-dir");
712         File testClassesDirectory = new File(baseDir, "mock-dir");
713         mojo.setTestClassesDirectory(testClassesDirectory);
714         TestClassPath testClassPath = new TestClassPath(
715                 Collections.emptySet(), classesDirectory, testClassesDirectory, Collections.emptyList());
716 
717         ProviderInfo providerInfo = mock(ProviderInfo.class);
718         when(providerInfo.getProviderName()).thenReturn("provider mock");
719         when(providerInfo.getProviderClasspath()).thenReturn(Collections.emptySet());
720 
721         DefaultScanResult defaultScanResult = mock(DefaultScanResult.class);
722         when(defaultScanResult.getClasses()).thenReturn(Collections.emptyList());
723 
724         Path pathToModularDescriptor =
725                 Paths.get(baseDir, "src", "test", "resources", "org", "apache", "maven", "plugin", "surefire");
726         mojo.setMainBuildPath(pathToModularDescriptor.toFile());
727 
728         Map<String, Artifact> artifacts = new HashMap<>();
729         Artifact dummyArtifact = mock(Artifact.class);
730         when(dummyArtifact.getFile()).thenReturn(new File(baseDir, "mock-file"));
731         artifacts.put("org.apache.maven.surefire:maven-surefire-common", dummyArtifact);
732         artifacts.put("org.apache.maven.surefire:surefire-extensions-api", dummyArtifact);
733         artifacts.put("org.apache.maven.surefire:surefire-api", dummyArtifact);
734         artifacts.put("org.apache.maven.surefire:surefire-logger-api", dummyArtifact);
735         artifacts.put("org.apache.maven.surefire:surefire-extensions-spi", dummyArtifact);
736         artifacts.put("org.apache.maven.surefire:surefire-booter", dummyArtifact);
737         artifacts.put("org.apache.maven.surefire:surefire-shared-utils", dummyArtifact);
738         mojo.setPluginArtifactMap(artifacts);
739 
740         ResolvePathResult resolvePathResult = mock(ResolvePathResult.class);
741         JavaModuleDescriptor desc = mock(JavaModuleDescriptor.class);
742         when(desc.name()).thenReturn("");
743         when(resolvePathResult.getModuleDescriptor()).thenReturn(desc);
744         ResolvePathResultWrapper wrapper = new ResolvePathResultWrapper(resolvePathResult, true);
745         // ### END
746 
747         StartupConfiguration actualConfig = invokeMethod(
748                 mojo,
749                 "createStartupConfiguration",
750                 new Class[] {
751                     ProviderInfo.class,
752                     boolean.class,
753                     ClassLoaderConfiguration.class,
754                     DefaultScanResult.class,
755                     TestClassPath.class,
756                     Platform.class,
757                     ResolvePathResultWrapper.class
758                 },
759                 providerInfo,
760                 true,
761                 mock(ClassLoaderConfiguration.class),
762                 defaultScanResult,
763                 testClassPath,
764                 platform,
765                 wrapper);
766 
767         assertThat(actualConfig).isNotNull();
768 
769         assertThat(actualConfig.getClasspathConfiguration()).isInstanceOf(ModularClasspathConfiguration.class);
770     }
771 
772     @Test
773     public void shouldExistTmpDirectory() throws IOException {
774         String systemTmpDir = System.getProperty("java.io.tmpdir");
775         String usrDir = new File(System.getProperty("user.dir")).getCanonicalPath();
776 
777         String tmpDir = "surefireX" + System.currentTimeMillis();
778 
779         //noinspection ResultOfMethodCallIgnored
780         new File(systemTmpDir, tmpDir).delete();
781 
782         File targetDir = new File(usrDir, "target");
783         //noinspection ResultOfMethodCallIgnored
784         new File(targetDir, tmpDir).delete();
785 
786         AbstractSurefireMojo mojo = mock(AbstractSurefireMojo.class);
787         Logger logger = mock(Logger.class);
788         when(logger.isDebugEnabled()).thenReturn(false);
789         when(logger.isErrorEnabled()).thenReturn(false);
790         doNothing().when(logger).debug(anyString());
791         doNothing().when(logger).error(anyString(), any(Throwable.class));
792         when(mojo.getConsoleLogger()).thenReturn(new PluginConsoleLogger(logger));
793         when(mojo.getTempDir()).thenReturn(tmpDir);
794         when(mojo.getProjectBuildDirectory()).thenReturn(targetDir);
795         when(mojo.createSurefireBootDirectoryInTemp()).thenCallRealMethod();
796         when(mojo.createSurefireBootDirectoryInBuild()).thenCallRealMethod();
797         when(mojo.getSurefireTempDir()).thenCallRealMethod();
798 
799         File bootDir = mojo.createSurefireBootDirectoryInTemp();
800         assertThat(bootDir).isNotNull();
801         assertThat(bootDir).isDirectory();
802 
803         assertThat(new File(systemTmpDir, bootDir.getName())).isDirectory();
804         assertThat(bootDir.getName()).startsWith(tmpDir);
805 
806         File buildTmp = mojo.createSurefireBootDirectoryInBuild();
807         assertThat(buildTmp).isNotNull();
808         assertThat(buildTmp).isDirectory();
809         assertThat(buildTmp.getParentFile().getCanonicalFile().getParent()).isEqualTo(usrDir);
810         assertThat(buildTmp.getName()).isEqualTo(tmpDir);
811 
812         File tmp = mojo.getSurefireTempDir();
813         assertThat(tmp).isNotNull();
814         assertThat(tmp).isDirectory();
815         assertThat(IS_OS_WINDOWS ? new File(systemTmpDir, bootDir.getName()) : new File(targetDir, tmpDir))
816                 .isDirectory();
817     }
818 
819     @Test
820     public void shouldSmartlyResolveJUnit5ProviderWithJUnit4() throws Exception {
821         MavenProject mavenProject = new MavenProject();
822         mavenProject.setArtifact(new DefaultArtifact(
823                 "dummy", "pom", createFromVersion("1.0.0"), null, "jar", null, mock(ArtifactHandler.class)));
824         mojo.setProject(mavenProject);
825 
826         final VersionRange surefireVersion = createFromVersion("1");
827 
828         Artifact testClasspathJUnit = new DefaultArtifact(
829                 "junit", "junit", createFromVersion("4.12"), null, "jar", null, mock(ArtifactHandler.class));
830 
831         Artifact testClasspathHamcrest = new DefaultArtifact(
832                 "org.hamcrest",
833                 "hamcrest-core",
834                 createFromVersion("1.3"),
835                 null,
836                 "jar",
837                 null,
838                 mock(ArtifactHandler.class));
839 
840         setProjectDepedenciesToMojo(testClasspathJUnit, testClasspathHamcrest);
841 
842         Collection<Artifact> testArtifacts = new ArrayList<>();
843         testArtifacts.add(testClasspathJUnit);
844         testArtifacts.add(testClasspathHamcrest);
845 
846         File classesDirectory = new File("target/classes");
847 
848         File testClassesDirectory = new File("target/test-classes");
849 
850         TestClassPath testClasspathWrapper =
851                 new TestClassPath(testArtifacts, classesDirectory, testClassesDirectory, null);
852 
853         SurefireDependencyResolver dependencyResolver = mock(SurefireDependencyResolver.class);
854         mojo.setSurefireDependencyResolver(dependencyResolver);
855 
856         when(dependencyResolver.getProviderClasspathAsMap(any(), any(), anyString(), anyString()))
857                 .thenReturn(artifactMapByVersionlessId(createSurefireProviderResolutionResult(surefireVersion)));
858 
859         when(dependencyResolver.resolveArtifacts(any(), any(), any(Artifact.class)))
860                 .thenReturn(createExpectedJUnitPlatformLauncherResolutionResult());
861 
862         final Artifact pluginDep1 = new DefaultArtifact(
863                 "org.junit.vintage", "junit-vintage-engine", createFromVersion("5.4.0"), null, "jar", "", null);
864 
865         final Artifact pluginDep2 = new DefaultArtifact(
866                 "org.apiguardian", "apiguardian-api", createFromVersion("1.0.0"), null, "jar", "", null);
867 
868         final Artifact pluginDep3 = new DefaultArtifact(
869                 "org.junit.platform",
870                 "junit-platform-engine",
871                 createFromVersion("1.4.0"),
872                 null,
873                 "jar",
874                 null,
875                 mock(ArtifactHandler.class));
876 
877         final Artifact pluginDep4 = new DefaultArtifact(
878                 "junit", "junit", createFromVersion("4.12"), null, "jar", null, mock(ArtifactHandler.class));
879 
880         final Artifact pluginDep5 = new DefaultArtifact(
881                 "org.hamcrest",
882                 "hamcrest-core",
883                 createFromVersion("1.3"),
884                 null,
885                 "jar",
886                 null,
887                 mock(ArtifactHandler.class));
888 
889         final Artifact pluginDep6 = new DefaultArtifact(
890                 "org.opentest4j",
891                 "opentest4j",
892                 createFromVersion("1.1.1"),
893                 null,
894                 "jar",
895                 null,
896                 mock(ArtifactHandler.class));
897 
898         final Artifact pluginDep7 = new DefaultArtifact(
899                 "org.junit.platform",
900                 "junit-platform-commons",
901                 createFromVersion("1.4.0"),
902                 null,
903                 "jar",
904                 null,
905                 mock(ArtifactHandler.class));
906 
907         addPluginDependencies(pluginDep1, pluginDep2, pluginDep3, pluginDep4, pluginDep5, pluginDep6, pluginDep7);
908 
909         mojo.setLogger(mock(Logger.class));
910 
911         Set<Artifact> pluginDependencyArtifacts = new HashSet<>();
912         pluginDependencyArtifacts.add(pluginDep1);
913         pluginDependencyArtifacts.add(pluginDep2);
914         pluginDependencyArtifacts.add(pluginDep3);
915         pluginDependencyArtifacts.add(pluginDep4);
916         pluginDependencyArtifacts.add(pluginDep5);
917         pluginDependencyArtifacts.add(pluginDep6);
918         pluginDependencyArtifacts.add(pluginDep7);
919 
920         when(dependencyResolver.resolvePluginDependencies(any(), any(), any(), any()))
921                 .thenReturn(artifactMapByVersionlessId(pluginDependencyArtifacts));
922 
923         PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
924         mojo.setPluginDescriptor(pluginDescriptor);
925         Plugin p = mock(Plugin.class);
926         when(pluginDescriptor.getPlugin()).thenReturn(p);
927 
928         Artifact junitPlatformArtifact = invokeMethod(mojo, "getJUnit5Artifact");
929         assertThat(junitPlatformArtifact.getGroupId()).isEqualTo("org.junit.platform");
930         assertThat(junitPlatformArtifact.getArtifactId()).isEqualTo("junit-platform-engine");
931         assertThat(junitPlatformArtifact.getVersion()).isEqualTo("1.4.0");
932 
933         AbstractSurefireMojo.JUnitPlatformProviderInfo prov =
934                 mojo.createJUnitPlatformProviderInfo(junitPlatformArtifact, testClasspathWrapper);
935 
936         assertThat(prov.isApplicable()).isTrue();
937 
938         Artifact expectedProvider = new DefaultArtifact(
939                 "org.apache.maven.surefire", "surefire-junit-platform", surefireVersion, null, "jar", "", null);
940         Artifact expectedCommonJava5 = new DefaultArtifact(
941                 "org.apache.maven.surefire", "common-java5", surefireVersion, null, "jar", "", null);
942         Artifact expectedLauncher = new DefaultArtifact(
943                 "org.junit.platform", "junit-platform-launcher", createFromVersion("1.4.0"), null, "jar", "", null);
944         Artifact expectedApiguardian = new DefaultArtifact(
945                 "org.apiguardian", "apiguardian-api", createFromVersion("1.0.0"), null, "jar", "", null);
946         Artifact expectedJUnit5Engine = new DefaultArtifact(
947                 "org.junit.platform", "junit-platform-engine", createFromVersion("1.4.0"), null, "jar", "", null);
948         Artifact expectedOpentest4j =
949                 new DefaultArtifact("org.opentest4j", "opentest4j", createFromVersion("1.1.1"), null, "jar", "", null);
950         Artifact expectedPlatformCommons = new DefaultArtifact(
951                 "org.junit.platform", "junit-platform-commons", createFromVersion("1.4.0"), null, "jar", "", null);
952         Artifact expectedEngine = new DefaultArtifact(
953                 "org.junit.vintage", "junit-vintage-engine", createFromVersion("5.4.0"), null, "jar", "", null);
954 
955         assertThat(prov.getProviderClasspath())
956                 .hasSize(8)
957                 .containsOnly(
958                         expectedProvider,
959                         expectedCommonJava5,
960                         expectedLauncher,
961                         expectedApiguardian,
962                         expectedJUnit5Engine,
963                         expectedOpentest4j,
964                         expectedPlatformCommons,
965                         expectedEngine);
966 
967         assertThat(testClasspathWrapper.getTestDependencies())
968                 .hasSize(2)
969                 .containsEntry("junit:junit", testClasspathJUnit)
970                 .containsEntry("org.hamcrest:hamcrest-core", testClasspathHamcrest);
971     }
972 
973     @Test
974     public void shouldSmartlyResolveJUnit5ProviderWithVintage() throws Exception {
975         MavenProject mavenProject = new MavenProject();
976         mavenProject.setArtifact(new DefaultArtifact(
977                 "dummy", "pom", createFromVersion("1.0.0"), null, "jar", null, mock(ArtifactHandler.class)));
978         mojo.setProject(mavenProject);
979 
980         VersionRange surefireVersion = createFromVersion("1");
981 
982         Artifact testClasspathSomeTestArtifact = new DefaultArtifact(
983                 "third.party", "artifact", createFromVersion("1.0"), null, "jar", null, mock(ArtifactHandler.class));
984 
985         Artifact testClasspathVintage = new DefaultArtifact(
986                 "org.junit.vintage",
987                 "junit-vintage-engine",
988                 createFromVersion("5.4.0"),
989                 null,
990                 "jar",
991                 null,
992                 mock(ArtifactHandler.class));
993 
994         Artifact testClasspathApiguardian = new DefaultArtifact(
995                 "org.apiguardian",
996                 "apiguardian-api",
997                 createFromVersion("1.0.0"),
998                 null,
999                 "jar",
1000                 null,
1001                 mock(ArtifactHandler.class));
1002 
1003         Artifact testClasspathPlatformEng = new DefaultArtifact(
1004                 "org.junit.platform",
1005                 "junit-platform-engine",
1006                 createFromVersion("1.4.0"),
1007                 null,
1008                 "jar",
1009                 null,
1010                 mock(ArtifactHandler.class));
1011 
1012         Artifact testClasspathJUnit4 = new DefaultArtifact(
1013                 "junit", "junit", createFromVersion("4.12"), null, "jar", null, mock(ArtifactHandler.class));
1014 
1015         Artifact testClasspathHamcrest = new DefaultArtifact(
1016                 "org.hamcrest",
1017                 "hamcrest-core",
1018                 createFromVersion("1.3"),
1019                 null,
1020                 "jar",
1021                 null,
1022                 mock(ArtifactHandler.class));
1023 
1024         Artifact testClasspathOpentest4j = new DefaultArtifact(
1025                 "org.opentest4j",
1026                 "opentest4j",
1027                 createFromVersion("1.1.1"),
1028                 null,
1029                 "jar",
1030                 null,
1031                 mock(ArtifactHandler.class));
1032 
1033         Artifact testClasspathCommons = new DefaultArtifact(
1034                 "org.junit.platform",
1035                 "junit-platform-commons",
1036                 createFromVersion("1.4.0"),
1037                 null,
1038                 "jar",
1039                 null,
1040                 mock(ArtifactHandler.class));
1041 
1042         Collection<Artifact> testArtifacts = asList(
1043                 testClasspathSomeTestArtifact,
1044                 testClasspathVintage,
1045                 testClasspathApiguardian,
1046                 testClasspathPlatformEng,
1047                 testClasspathJUnit4,
1048                 testClasspathHamcrest,
1049                 testClasspathOpentest4j,
1050                 testClasspathCommons);
1051 
1052         setProjectDepedenciesToMojo(testArtifacts.toArray(new Artifact[0]));
1053 
1054         File classesDirectory = new File("target/classes");
1055 
1056         File testClassesDirectory = new File("target/test-classes");
1057 
1058         TestClassPath testClasspathWrapper =
1059                 new TestClassPath(testArtifacts, classesDirectory, testClassesDirectory, null);
1060 
1061         SurefireDependencyResolver dependencyResolver = mock(SurefireDependencyResolver.class);
1062         mojo.setSurefireDependencyResolver(dependencyResolver);
1063 
1064         when(dependencyResolver.getProviderClasspathAsMap(any(), any(), anyString(), anyString()))
1065                 .thenReturn(artifactMapByVersionlessId(createSurefireProviderResolutionResult(surefireVersion)));
1066 
1067         when(dependencyResolver.resolveArtifacts(any(), any(), any(Artifact.class)))
1068                 .thenReturn(createExpectedJUnitPlatformLauncherResolutionResult());
1069 
1070         mojo.setLogger(mock(Logger.class));
1071 
1072         PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
1073         mojo.setPluginDescriptor(pluginDescriptor);
1074         Plugin p = mock(Plugin.class);
1075         when(pluginDescriptor.getPlugin()).thenReturn(p);
1076         when(p.getDependencies()).thenReturn(Collections.emptyList());
1077 
1078         Artifact junitPlatformArtifact = invokeMethod(mojo, "getJUnit5Artifact");
1079         assertThat(junitPlatformArtifact.getGroupId()).isEqualTo("org.junit.platform");
1080         assertThat(junitPlatformArtifact.getArtifactId()).isEqualTo("junit-platform-commons");
1081         assertThat(junitPlatformArtifact.getVersion()).isEqualTo("1.4.0");
1082 
1083         AbstractSurefireMojo.JUnitPlatformProviderInfo prov =
1084                 mojo.createJUnitPlatformProviderInfo(junitPlatformArtifact, testClasspathWrapper);
1085 
1086         assertThat(prov.isApplicable()).isTrue();
1087 
1088         Artifact expectedProvider = new DefaultArtifact(
1089                 "org.apache.maven.surefire", "surefire-junit-platform", surefireVersion, null, "jar", "", null);
1090         Artifact expectedCommonJava5 = new DefaultArtifact(
1091                 "org.apache.maven.surefire", "common-java5", surefireVersion, null, "jar", "", null);
1092         Artifact expectedLauncher = new DefaultArtifact(
1093                 "org.junit.platform", "junit-platform-launcher", createFromVersion("1.4.0"), null, "jar", "", null);
1094         assertThat(prov.getProviderClasspath())
1095                 .hasSize(3)
1096                 .containsOnly(expectedProvider, expectedCommonJava5, expectedLauncher);
1097 
1098         assertThat(testClasspathWrapper.getTestDependencies())
1099                 .hasSize(8)
1100                 .containsEntry("third.party:artifact", testClasspathSomeTestArtifact)
1101                 .containsEntry("org.junit.vintage:junit-vintage-engine", testClasspathVintage)
1102                 .containsEntry("org.apiguardian:apiguardian-api", testClasspathApiguardian)
1103                 .containsEntry("org.junit.platform:junit-platform-engine", testClasspathPlatformEng)
1104                 .containsEntry("junit:junit", testClasspathJUnit4)
1105                 .containsEntry("org.hamcrest:hamcrest-core", testClasspathHamcrest)
1106                 .containsEntry("org.opentest4j:opentest4j", testClasspathOpentest4j)
1107                 .containsEntry("org.junit.platform:junit-platform-commons", testClasspathCommons);
1108     }
1109 
1110     @Test
1111     public void shouldSmartlyResolveJUnit5ProviderWithJUnit5Commons() throws Exception {
1112         MavenProject mavenProject = new MavenProject();
1113         mavenProject.setArtifact(new DefaultArtifact(
1114                 "dummy", "pom", createFromVersion("1.0.0"), null, "jar", null, mock(ArtifactHandler.class)));
1115         mojo.setProject(mavenProject);
1116 
1117         final VersionRange surefireVersion = createFromVersion("1");
1118 
1119         Artifact testClasspathSomeTestArtifact = new DefaultArtifact(
1120                 "third.party", "artifact", createFromVersion("1.0"), null, "jar", null, mock(ArtifactHandler.class));
1121 
1122         Artifact testClasspathCommons = new DefaultArtifact(
1123                 "org.junit.platform",
1124                 "junit-platform-commons",
1125                 createFromVersion("1.4.0"),
1126                 null,
1127                 "jar",
1128                 null,
1129                 mock(ArtifactHandler.class));
1130 
1131         Artifact testClasspathApiguardian = new DefaultArtifact(
1132                 "org.apiguardian",
1133                 "apiguardian-api",
1134                 createFromVersion("1.0.0"),
1135                 null,
1136                 "jar",
1137                 null,
1138                 mock(ArtifactHandler.class));
1139 
1140         Collection<Artifact> testArtifacts =
1141                 asList(testClasspathSomeTestArtifact, testClasspathApiguardian, testClasspathCommons);
1142 
1143         setProjectDepedenciesToMojo(testArtifacts.toArray(new Artifact[0]));
1144 
1145         File classesDirectory = new File("target/classes");
1146 
1147         File testClassesDirectory = new File("target/test-classes");
1148 
1149         TestClassPath testClasspathWrapper =
1150                 new TestClassPath(testArtifacts, classesDirectory, testClassesDirectory, null);
1151 
1152         SurefireDependencyResolver dependencyResolver = mock(SurefireDependencyResolver.class);
1153         mojo.setSurefireDependencyResolver(dependencyResolver);
1154 
1155         when(dependencyResolver.getProviderClasspathAsMap(any(), any(), anyString(), anyString()))
1156                 .thenReturn(artifactMapByVersionlessId(createSurefireProviderResolutionResult(surefireVersion)));
1157 
1158         when(dependencyResolver.resolveArtifacts(any(), any(), any(Artifact.class)))
1159                 .thenReturn(createExpectedJUnitPlatformLauncherResolutionResult());
1160 
1161         mojo.setLogger(mock(Logger.class));
1162 
1163         invokeMethod(mojo, "setupStuff");
1164 
1165         PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
1166         mojo.setPluginDescriptor(pluginDescriptor);
1167         Plugin p = mock(Plugin.class);
1168         when(pluginDescriptor.getPlugin()).thenReturn(p);
1169         when(p.getDependencies()).thenReturn(Collections.emptyList());
1170 
1171         Artifact junitPlatformArtifact = invokeMethod(mojo, "getJUnit5Artifact");
1172         assertThat(junitPlatformArtifact.getGroupId()).isEqualTo("org.junit.platform");
1173         assertThat(junitPlatformArtifact.getArtifactId()).isEqualTo("junit-platform-commons");
1174         assertThat(junitPlatformArtifact.getVersion()).isEqualTo("1.4.0");
1175 
1176         AbstractSurefireMojo.JUnitPlatformProviderInfo prov =
1177                 mojo.createJUnitPlatformProviderInfo(junitPlatformArtifact, testClasspathWrapper);
1178 
1179         assertThat(prov.isApplicable()).isTrue();
1180 
1181         Set<Artifact> resolvedProviderArtifacts = prov.getProviderClasspath();
1182 
1183         Artifact provider = new DefaultArtifact(
1184                 "org.apache.maven.surefire", "surefire-junit-platform", surefireVersion, null, "jar", "", null);
1185         Artifact java5 = new DefaultArtifact(
1186                 "org.apache.maven.surefire", "common-java5", surefireVersion, null, "jar", "", null);
1187         Artifact launcher = new DefaultArtifact(
1188                 "org.junit.platform", "junit-platform-launcher", createFromVersion("1.4.0"), null, "jar", "", null);
1189         Artifact engine = new DefaultArtifact(
1190                 "org.junit.platform", "junit-platform-engine", createFromVersion("1.4.0"), null, "jar", "", null);
1191         Artifact opentest4j =
1192                 new DefaultArtifact("org.opentest4j", "opentest4j", createFromVersion("1.1.1"), null, "jar", "", null);
1193         assertThat(resolvedProviderArtifacts).hasSize(5).containsOnly(provider, java5, launcher, engine, opentest4j);
1194 
1195         assertThat(testClasspathWrapper.getTestDependencies())
1196                 .hasSize(3)
1197                 .containsEntry("third.party:artifact", testClasspathSomeTestArtifact)
1198                 .containsEntry("org.junit.platform:junit-platform-commons", testClasspathCommons)
1199                 .containsEntry("org.apiguardian:apiguardian-api", testClasspathApiguardian);
1200     }
1201 
1202     @Test
1203     public void shouldSmartlyResolveJUnit5ProviderWithJUnit5Engine() throws Exception {
1204         MavenProject mavenProject = new MavenProject();
1205         mavenProject.setArtifact(new DefaultArtifact(
1206                 "dummy", "pom", createFromVersion("1.0.0"), null, "jar", null, mock(ArtifactHandler.class)));
1207         mojo.setProject(mavenProject);
1208 
1209         final VersionRange surefireVersion = createFromVersion("1");
1210 
1211         final Artifact testClasspathSomeTestArtifact = new DefaultArtifact(
1212                 "third.party", "artifact", createFromVersion("1.0"), null, "jar", null, mock(ArtifactHandler.class));
1213 
1214         final Artifact testClasspathJUnit5 = new DefaultArtifact(
1215                 "org.junit.platform",
1216                 "junit-platform-engine",
1217                 createFromVersion("1.4.0"),
1218                 null,
1219                 "jar",
1220                 null,
1221                 mock(ArtifactHandler.class));
1222 
1223         final Artifact testClasspathApiguardian = new DefaultArtifact(
1224                 "org.apiguardian",
1225                 "apiguardian-api",
1226                 createFromVersion("1.0.0"),
1227                 null,
1228                 "jar",
1229                 null,
1230                 mock(ArtifactHandler.class));
1231 
1232         final Artifact testClasspathCommons = new DefaultArtifact(
1233                 "org.junit.platform",
1234                 "junit-platform-commons",
1235                 createFromVersion("1.4.0"),
1236                 null,
1237                 "jar",
1238                 null,
1239                 mock(ArtifactHandler.class));
1240 
1241         final Artifact testClasspathOpentest4j = new DefaultArtifact(
1242                 "org.opentest4j",
1243                 "opentest4j",
1244                 createFromVersion("1.1.1"),
1245                 null,
1246                 "jar",
1247                 null,
1248                 mock(ArtifactHandler.class));
1249 
1250         Collection<Artifact> testArtifacts = asList(
1251                 testClasspathSomeTestArtifact,
1252                 testClasspathJUnit5,
1253                 testClasspathApiguardian,
1254                 testClasspathCommons,
1255                 testClasspathOpentest4j);
1256 
1257         setProjectDepedenciesToMojo(testArtifacts.toArray(new Artifact[0]));
1258 
1259         File classesDirectory = new File("target/classes");
1260 
1261         File testClassesDirectory = new File("target/test-classes");
1262 
1263         TestClassPath testClasspathWrapper =
1264                 new TestClassPath(testArtifacts, classesDirectory, testClassesDirectory, null);
1265 
1266         SurefireDependencyResolver dependencyResolver = mock(SurefireDependencyResolver.class);
1267         mojo.setSurefireDependencyResolver(dependencyResolver);
1268 
1269         when(dependencyResolver.getProviderClasspathAsMap(any(), any(), anyString(), anyString()))
1270                 .thenReturn(artifactMapByVersionlessId(createSurefireProviderResolutionResult(surefireVersion)));
1271 
1272         when(dependencyResolver.resolveArtifacts(any(), any(), any(Artifact.class)))
1273                 .thenReturn(createExpectedJUnitPlatformLauncherResolutionResult());
1274 
1275         mojo.setLogger(mock(Logger.class));
1276 
1277         invokeMethod(mojo, "setupStuff");
1278 
1279         Artifact junitPlatformArtifact = invokeMethod(mojo, "getJUnit5Artifact");
1280         assertThat(junitPlatformArtifact.getGroupId()).isEqualTo("org.junit.platform");
1281         assertThat(junitPlatformArtifact.getArtifactId()).isEqualTo("junit-platform-commons");
1282         assertThat(junitPlatformArtifact.getVersion()).isEqualTo("1.4.0");
1283 
1284         AbstractSurefireMojo.JUnitPlatformProviderInfo prov =
1285                 mojo.createJUnitPlatformProviderInfo(junitPlatformArtifact, testClasspathWrapper);
1286 
1287         assertThat(prov.isApplicable()).isTrue();
1288 
1289         Artifact surefireProvider = new DefaultArtifact(
1290                 "org.apache.maven.surefire", "surefire-junit-platform", surefireVersion, null, "jar", "", null);
1291 
1292         Artifact java5 = new DefaultArtifact(
1293                 "org.apache.maven.surefire", "common-java5", surefireVersion, null, "jar", "", null);
1294         Artifact launcher = new DefaultArtifact(
1295                 "org.junit.platform", "junit-platform-launcher", createFromVersion("1.4.0"), null, "jar", "", null);
1296 
1297         Set<Artifact> resolvedProviderArtifacts = prov.getProviderClasspath();
1298 
1299         assertThat(resolvedProviderArtifacts).hasSize(3).containsOnly(surefireProvider, java5, launcher);
1300 
1301         assertThat(testClasspathWrapper.getTestDependencies())
1302                 .hasSize(5)
1303                 .containsEntry("third.party:artifact", testClasspathSomeTestArtifact)
1304                 .containsEntry("org.junit.platform:junit-platform-engine", testClasspathJUnit5)
1305                 .containsEntry("org.apiguardian:apiguardian-api", testClasspathApiguardian)
1306                 .containsEntry("org.junit.platform:junit-platform-commons", testClasspathCommons)
1307                 .containsEntry("org.opentest4j:opentest4j", testClasspathOpentest4j);
1308     }
1309 
1310     @Test
1311     public void shouldSmartlyResolveJUnit5ProviderWithJupiterApi() throws Exception {
1312         MavenProject mavenProject = new MavenProject();
1313         mavenProject.setArtifact(new DefaultArtifact(
1314                 "dummy", "pom", createFromVersion("1.0.0"), null, "jar", null, mock(ArtifactHandler.class)));
1315         mojo.setProject(mavenProject);
1316 
1317         final VersionRange surefireVersion = createFromVersion("1");
1318 
1319         final Artifact testClasspathSomeTestArtifact = new DefaultArtifact(
1320                 "third.party", "artifact", createFromVersion("1.0"), null, "jar", null, mock(ArtifactHandler.class));
1321 
1322         final Artifact testClasspathJupiterApi = new DefaultArtifact(
1323                 "org.junit.jupiter",
1324                 "junit-jupiter-api",
1325                 createFromVersion("5.4.0"),
1326                 null,
1327                 "jar",
1328                 null,
1329                 mock(ArtifactHandler.class));
1330 
1331         final Artifact testClasspathApiguardian = new DefaultArtifact(
1332                 "org.apiguardian",
1333                 "apiguardian-api",
1334                 createFromVersion("1.0.0"),
1335                 null,
1336                 "jar",
1337                 null,
1338                 mock(ArtifactHandler.class));
1339 
1340         final Artifact testClasspathCommons = new DefaultArtifact(
1341                 "org.junit.platform",
1342                 "junit-platform-commons",
1343                 createFromVersion("1.4.0"),
1344                 null,
1345                 "jar",
1346                 null,
1347                 mock(ArtifactHandler.class));
1348 
1349         final Artifact testClasspathOpentest4j = new DefaultArtifact(
1350                 "org.opentest4j",
1351                 "opentest4j",
1352                 createFromVersion("1.1.1"),
1353                 null,
1354                 "jar",
1355                 null,
1356                 mock(ArtifactHandler.class));
1357 
1358         Collection<Artifact> testArtifacts = asList(
1359                 testClasspathSomeTestArtifact,
1360                 testClasspathJupiterApi,
1361                 testClasspathApiguardian,
1362                 testClasspathCommons,
1363                 testClasspathOpentest4j);
1364 
1365         setProjectDepedenciesToMojo(testArtifacts.toArray(new Artifact[0]));
1366 
1367         File classesDirectory = new File("target/classes");
1368 
1369         File testClassesDirectory = new File("target/test-classes");
1370 
1371         TestClassPath testClasspathWrapper =
1372                 new TestClassPath(testArtifacts, classesDirectory, testClassesDirectory, null);
1373 
1374         SurefireDependencyResolver dependencyResolver = mock(SurefireDependencyResolver.class);
1375         mojo.setSurefireDependencyResolver(dependencyResolver);
1376 
1377         when(dependencyResolver.getProviderClasspathAsMap(any(), any(), anyString(), anyString()))
1378                 .thenReturn(artifactMapByVersionlessId(createSurefireProviderResolutionResult(surefireVersion)));
1379 
1380         Artifact jUnitPlatformLauncherArtifact = new DefaultArtifact(
1381                 "org.junit.platform",
1382                 "junit-platform-launcher",
1383                 createFromVersion("1.4.0"),
1384                 null,
1385                 "jar",
1386                 null,
1387                 mock(ArtifactHandler.class));
1388 
1389         when(dependencyResolver.resolveArtifacts(any(), any(), eq(jUnitPlatformLauncherArtifact)))
1390                 .thenReturn(createExpectedJUnitPlatformLauncherResolutionResult());
1391 
1392         Artifact jupiterEngineArtifact = new DefaultArtifact(
1393                 "org.junit.jupiter",
1394                 "junit-jupiter-engine",
1395                 createFromVersion("5.4.0"),
1396                 null,
1397                 "jar",
1398                 null,
1399                 mock(ArtifactHandler.class));
1400 
1401         when(dependencyResolver.resolveArtifacts(any(), any(), eq(jupiterEngineArtifact)))
1402                 .thenReturn(createJupiterEngineResolutionResult());
1403 
1404         mojo.setLogger(mock(Logger.class));
1405 
1406         PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
1407         mojo.setPluginDescriptor(pluginDescriptor);
1408         Plugin p = mock(Plugin.class);
1409         when(pluginDescriptor.getPlugin()).thenReturn(p);
1410         when(p.getDependencies()).thenReturn(Collections.emptyList());
1411 
1412         Artifact junitPlatformArtifact = invokeMethod(mojo, "getJUnit5Artifact");
1413         assertThat(junitPlatformArtifact.getGroupId()).isEqualTo("org.junit.platform");
1414         assertThat(junitPlatformArtifact.getArtifactId()).isEqualTo("junit-platform-commons");
1415         assertThat(junitPlatformArtifact.getVersion()).isEqualTo("1.4.0");
1416 
1417         AbstractSurefireMojo.JUnitPlatformProviderInfo prov =
1418                 mojo.createJUnitPlatformProviderInfo(junitPlatformArtifact, testClasspathWrapper);
1419 
1420         assertThat(prov.isApplicable()).isTrue();
1421 
1422         final Artifact surefireProvider = new DefaultArtifact(
1423                 "org.apache.maven.surefire", "surefire-junit-platform", surefireVersion, null, "jar", "", null);
1424 
1425         Artifact java5 = new DefaultArtifact(
1426                 "org.apache.maven.surefire", "common-java5", surefireVersion, null, "jar", "", null);
1427         Artifact launcher = new DefaultArtifact(
1428                 "org.junit.platform", "junit-platform-launcher", createFromVersion("1.4.0"), null, "jar", "", null);
1429         Artifact jupiterEngine = new DefaultArtifact(
1430                 "org.junit.jupiter",
1431                 "junit-jupiter-engine", ///// <------
1432                 createFromVersion("5.4.0"),
1433                 null,
1434                 "jar",
1435                 "",
1436                 null);
1437         Artifact platformEngine = new DefaultArtifact(
1438                 "org.junit.platform", "junit-platform-engine", createFromVersion("1.4.0"), null, "jar", "", null);
1439 
1440         Set<Artifact> resolvedProviderArtifacts = prov.getProviderClasspath();
1441 
1442         assertThat(resolvedProviderArtifacts)
1443                 .hasSize(5)
1444                 .containsOnly(surefireProvider, java5, launcher, jupiterEngine, platformEngine);
1445 
1446         assertThat(testClasspathWrapper.getTestDependencies())
1447                 .hasSize(5)
1448                 .containsEntry("third.party:artifact", testClasspathSomeTestArtifact)
1449                 .containsEntry("org.junit.jupiter:junit-jupiter-api", testClasspathJupiterApi)
1450                 .containsEntry("org.apiguardian:apiguardian-api", testClasspathApiguardian)
1451                 .containsEntry("org.junit.platform:junit-platform-commons", testClasspathCommons)
1452                 .containsEntry("org.opentest4j:opentest4j", testClasspathOpentest4j);
1453     }
1454 
1455     @Test
1456     public void shouldSmartlyResolveJUnit5ProviderWithJupiterEngine() throws Exception {
1457         MavenProject mavenProject = new MavenProject();
1458         mavenProject.setArtifact(new DefaultArtifact(
1459                 "dummy", "pom", createFromVersion("1.0.0"), null, "jar", null, mock(ArtifactHandler.class)));
1460         mojo.setProject(mavenProject);
1461 
1462         final VersionRange surefireVersion = createFromVersion("1");
1463 
1464         final Artifact testClasspathSomeTestArtifact = new DefaultArtifact(
1465                 "third.party", "artifact", createFromVersion("1.0"), null, "jar", null, mock(ArtifactHandler.class));
1466 
1467         final Artifact testClasspathJupiterEngine = new DefaultArtifact(
1468                 "org.junit.jupiter",
1469                 "junit-jupiter-engine",
1470                 createFromVersion("5.4.0"),
1471                 null,
1472                 "jar",
1473                 null,
1474                 mock(ArtifactHandler.class));
1475 
1476         final Artifact testClasspathPlatformEngine = new DefaultArtifact(
1477                 "org.junit.platform",
1478                 "junit-platform-engine",
1479                 createFromVersion("1.4.0"),
1480                 null,
1481                 "jar",
1482                 null,
1483                 mock(ArtifactHandler.class));
1484 
1485         final Artifact testClasspathJupiterApi = new DefaultArtifact(
1486                 "org.junit.jupiter",
1487                 "junit-jupiter-api",
1488                 createFromVersion("5.4.0"),
1489                 null,
1490                 "jar",
1491                 null,
1492                 mock(ArtifactHandler.class));
1493 
1494         final Artifact testClasspathApiguardian = new DefaultArtifact(
1495                 "org.apiguardian",
1496                 "apiguardian-api",
1497                 createFromVersion("1.0.0"),
1498                 null,
1499                 "jar",
1500                 null,
1501                 mock(ArtifactHandler.class));
1502 
1503         final Artifact testClasspathCommons = new DefaultArtifact(
1504                 "org.junit.platform",
1505                 "junit-platform-commons",
1506                 createFromVersion("1.4.0"),
1507                 null,
1508                 "jar",
1509                 null,
1510                 mock(ArtifactHandler.class));
1511 
1512         final Artifact testClasspathOpentest4j = new DefaultArtifact(
1513                 "org.opentest4j",
1514                 "opentest4j",
1515                 createFromVersion("1.1.1"),
1516                 null,
1517                 "jar",
1518                 null,
1519                 mock(ArtifactHandler.class));
1520 
1521         Collection<Artifact> testArtifacts = asList(
1522                 testClasspathSomeTestArtifact,
1523                 testClasspathJupiterEngine,
1524                 testClasspathPlatformEngine,
1525                 testClasspathJupiterApi,
1526                 testClasspathApiguardian,
1527                 testClasspathCommons,
1528                 testClasspathOpentest4j);
1529 
1530         setProjectDepedenciesToMojo(testArtifacts.toArray(new Artifact[0]));
1531 
1532         File classesDirectory = new File("target/classes");
1533 
1534         File testClassesDirectory = new File("target/test-classes");
1535 
1536         TestClassPath testClasspathWrapper =
1537                 new TestClassPath(testArtifacts, classesDirectory, testClassesDirectory, null);
1538 
1539         SurefireDependencyResolver dependencyResolver = mock(SurefireDependencyResolver.class);
1540         mojo.setSurefireDependencyResolver(dependencyResolver);
1541 
1542         when(dependencyResolver.getProviderClasspathAsMap(any(), any(), anyString(), anyString()))
1543                 .thenReturn(artifactMapByVersionlessId(createSurefireProviderResolutionResult(surefireVersion)));
1544 
1545         when(dependencyResolver.resolveArtifacts(any(), any(), any(Artifact.class)))
1546                 .thenReturn(createExpectedJUnitPlatformLauncherResolutionResult());
1547 
1548         mojo.setLogger(mock(Logger.class));
1549 
1550         Artifact junitPlatformArtifact = invokeMethod(mojo, "getJUnit5Artifact");
1551         assertThat(junitPlatformArtifact.getGroupId()).isEqualTo("org.junit.platform");
1552         assertThat(junitPlatformArtifact.getArtifactId()).isEqualTo("junit-platform-commons");
1553         assertThat(junitPlatformArtifact.getVersion()).isEqualTo("1.4.0");
1554 
1555         AbstractSurefireMojo.JUnitPlatformProviderInfo prov =
1556                 mojo.createJUnitPlatformProviderInfo(junitPlatformArtifact, testClasspathWrapper);
1557 
1558         assertThat(prov.isApplicable()).isTrue();
1559 
1560         Artifact surefireProvider = new DefaultArtifact(
1561                 "org.apache.maven.surefire", "surefire-junit-platform", surefireVersion, null, "jar", "", null);
1562         Artifact java5 = new DefaultArtifact(
1563                 "org.apache.maven.surefire", "common-java5", surefireVersion, null, "jar", "", null);
1564         Artifact launcher = new DefaultArtifact(
1565                 "org.junit.platform", "junit-platform-launcher", createFromVersion("1.4.0"), null, "jar", "", null);
1566 
1567         Set<Artifact> resolvedProviderArtifacts = prov.getProviderClasspath();
1568 
1569         assertThat(resolvedProviderArtifacts).hasSize(3).containsOnly(surefireProvider, java5, launcher);
1570 
1571         assertThat(testClasspathWrapper.getTestDependencies())
1572                 .hasSize(7)
1573                 .containsEntry("third.party:artifact", testClasspathSomeTestArtifact)
1574                 .containsEntry("org.junit.jupiter:junit-jupiter-engine", testClasspathJupiterEngine)
1575                 .containsEntry("org.junit.platform:junit-platform-engine", testClasspathPlatformEngine)
1576                 .containsEntry("org.junit.jupiter:junit-jupiter-api", testClasspathJupiterApi)
1577                 .containsEntry("org.apiguardian:apiguardian-api", testClasspathApiguardian)
1578                 .containsEntry("org.junit.platform:junit-platform-commons", testClasspathCommons)
1579                 .containsEntry("org.opentest4j:opentest4j", testClasspathOpentest4j);
1580     }
1581 
1582     @Test
1583     public void shouldSmartlyResolveJUnit5ProviderWithJupiterEngineInPluginDependencies() throws Exception {
1584         final VersionRange surefireVersion = createFromVersion("1");
1585 
1586         final Artifact plugin = new DefaultArtifact(
1587                 "org.apache.maven.surefire",
1588                 "maven-surefire-plugin",
1589                 surefireVersion,
1590                 null,
1591                 "jar",
1592                 null,
1593                 mock(ArtifactHandler.class));
1594 
1595         final Artifact forkedBooter = new DefaultArtifact(
1596                 "org.apache.maven.surefire",
1597                 "surefire-booter",
1598                 surefireVersion,
1599                 null,
1600                 "jar",
1601                 null,
1602                 mock(ArtifactHandler.class));
1603 
1604         final Artifact pluginDepJupiterEngine = new DefaultArtifact(
1605                 "org.junit.jupiter", "junit-jupiter-engine", createFromVersion("5.4.0"), null, "jar", "", null);
1606 
1607         final Artifact pluginDepPlatformEngine = new DefaultArtifact(
1608                 "org.junit.platform",
1609                 "junit-platform-engine",
1610                 createFromVersion("1.4.0"),
1611                 null,
1612                 "jar",
1613                 null,
1614                 mock(ArtifactHandler.class));
1615 
1616         final Artifact pluginDepJupiterApi = new DefaultArtifact(
1617                 "org.junit.jupiter",
1618                 "junit-jupiter-api",
1619                 createFromVersion("5.4.0"),
1620                 null,
1621                 "jar",
1622                 null,
1623                 mock(ArtifactHandler.class));
1624 
1625         final Artifact pluginDepApiguardian = new DefaultArtifact(
1626                 "org.apiguardian",
1627                 "apiguardian-api",
1628                 createFromVersion("1.0.0"),
1629                 null,
1630                 "jar",
1631                 null,
1632                 mock(ArtifactHandler.class));
1633 
1634         final Artifact pluginDepCommons = new DefaultArtifact(
1635                 "org.junit.platform",
1636                 "junit-platform-commons",
1637                 createFromVersion("1.4.0"),
1638                 null,
1639                 "jar",
1640                 null,
1641                 mock(ArtifactHandler.class));
1642 
1643         final Artifact pluginDepOpentest4j = new DefaultArtifact(
1644                 "org.opentest4j",
1645                 "opentest4j",
1646                 createFromVersion("1.1.1"),
1647                 null,
1648                 "jar",
1649                 null,
1650                 mock(ArtifactHandler.class));
1651 
1652         addPluginDependencies(
1653                 plugin,
1654                 forkedBooter,
1655                 pluginDepJupiterEngine,
1656                 pluginDepPlatformEngine,
1657                 pluginDepJupiterApi,
1658                 pluginDepApiguardian,
1659                 pluginDepCommons,
1660                 pluginDepOpentest4j);
1661 
1662         MavenProject mavenProject = new MavenProject();
1663         mavenProject.setArtifact(new DefaultArtifact(
1664                 "dummy", "pom", createFromVersion("1.0.0"), null, "jar", null, mock(ArtifactHandler.class)));
1665         mojo.setProject(mavenProject);
1666 
1667         final Artifact testClasspathSomeTestArtifact = new DefaultArtifact(
1668                 "third.party", "artifact", createFromVersion("1.0"), null, "jar", null, mock(ArtifactHandler.class));
1669 
1670         final Artifact testClasspathJupiterApi = new DefaultArtifact(
1671                 "org.junit.jupiter",
1672                 "junit-jupiter-api",
1673                 createFromVersion("5.3.0"),
1674                 null,
1675                 "jar",
1676                 null,
1677                 mock(ArtifactHandler.class));
1678 
1679         final Artifact testClasspathApiguardian = new DefaultArtifact(
1680                 "org.apiguardian",
1681                 "apiguardian-api",
1682                 createFromVersion("1.0.0"),
1683                 null,
1684                 "jar",
1685                 null,
1686                 mock(ArtifactHandler.class));
1687 
1688         final Artifact testClasspathCommons = new DefaultArtifact(
1689                 "org.junit.platform",
1690                 "junit-platform-commons",
1691                 createFromVersion("1.4.0"),
1692                 null,
1693                 "jar",
1694                 null,
1695                 mock(ArtifactHandler.class));
1696 
1697         final Artifact testClasspathOpentest4j = new DefaultArtifact(
1698                 "org.opentest4j",
1699                 "opentest4j",
1700                 createFromVersion("1.1.1"),
1701                 null,
1702                 "jar",
1703                 null,
1704                 mock(ArtifactHandler.class));
1705 
1706         Collection<Artifact> testArtifacts = asList(
1707                 testClasspathSomeTestArtifact,
1708                 testClasspathJupiterApi,
1709                 testClasspathApiguardian,
1710                 testClasspathCommons,
1711                 testClasspathOpentest4j);
1712 
1713         setProjectDepedenciesToMojo(testArtifacts.toArray(new Artifact[0]));
1714 
1715         File classesDirectory = new File("target/classes");
1716 
1717         File testClassesDirectory = new File("target/test-classes");
1718 
1719         TestClassPath testClasspathWrapper =
1720                 new TestClassPath(testArtifacts, classesDirectory, testClassesDirectory, null);
1721 
1722         SurefireDependencyResolver dependencyResolver = mock(SurefireDependencyResolver.class);
1723         mojo.setSurefireDependencyResolver(dependencyResolver);
1724 
1725         when(dependencyResolver.getProviderClasspathAsMap(any(), any(), anyString(), anyString()))
1726                 .thenReturn(artifactMapByVersionlessId(createSurefireProviderResolutionResult(surefireVersion)));
1727 
1728         when(dependencyResolver.resolveArtifacts(any(), any(), any(Artifact.class)))
1729                 .thenReturn(createExpectedJUnitPlatformLauncherResolutionResult());
1730 
1731         mojo.setLogger(mock(Logger.class));
1732 
1733         Set<Artifact> pluginDepJupiterEngineArtifacts = new HashSet<>();
1734         pluginDepJupiterEngineArtifacts.add(pluginDepJupiterEngine);
1735         pluginDepJupiterEngineArtifacts.add(pluginDepPlatformEngine);
1736         pluginDepJupiterEngineArtifacts.add(pluginDepJupiterApi);
1737         pluginDepJupiterEngineArtifacts.add(pluginDepApiguardian);
1738         pluginDepJupiterEngineArtifacts.add(pluginDepCommons);
1739         pluginDepJupiterEngineArtifacts.add(pluginDepOpentest4j);
1740 
1741         when(dependencyResolver.resolvePluginDependencies(any(), any(), any(), any()))
1742                 .thenReturn(artifactMapByVersionlessId(pluginDepJupiterEngineArtifacts));
1743 
1744         Artifact junitPlatformArtifact = invokeMethod(mojo, "getJUnit5Artifact");
1745         assertThat(junitPlatformArtifact.getGroupId()).isEqualTo("org.junit.platform");
1746         assertThat(junitPlatformArtifact.getArtifactId()).isEqualTo("junit-platform-engine");
1747         assertThat(junitPlatformArtifact.getVersion()).isEqualTo("1.4.0");
1748 
1749         PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
1750         mojo.setPluginDescriptor(pluginDescriptor);
1751         Plugin p = mock(Plugin.class);
1752         when(pluginDescriptor.getPlugin()).thenReturn(p);
1753         List<Dependency> directPluginDependencies = toDependencies(pluginDepJupiterEngine);
1754         when(p.getDependencies()).thenReturn(directPluginDependencies);
1755 
1756         AbstractSurefireMojo.JUnitPlatformProviderInfo prov =
1757                 mojo.createJUnitPlatformProviderInfo(junitPlatformArtifact, testClasspathWrapper);
1758 
1759         assertThat(prov.isApplicable()).isTrue();
1760 
1761         Artifact surefireProvider = new DefaultArtifact(
1762                 "org.apache.maven.surefire", "surefire-junit-platform", surefireVersion, null, "jar", "", null);
1763         Artifact java5 = new DefaultArtifact(
1764                 "org.apache.maven.surefire", "common-java5", surefireVersion, null, "jar", "", null);
1765         Artifact launcher = new DefaultArtifact(
1766                 "org.junit.platform", "junit-platform-launcher", createFromVersion("1.4.0"), null, "jar", "", null);
1767         Artifact jupiterEngine = new DefaultArtifact(
1768                 "org.junit.jupiter", "junit-jupiter-engine", createFromVersion("5.4.0"), null, "jar", "", null);
1769         Artifact platformEngine = new DefaultArtifact(
1770                 "org.junit.platform", "junit-platform-engine", createFromVersion("1.4.0"), null, "jar", "", null);
1771 
1772         Set<Artifact> resolvedProviderArtifacts = prov.getProviderClasspath();
1773 
1774         assertThat(resolvedProviderArtifacts)
1775                 .hasSize(5)
1776                 .containsOnly(surefireProvider, java5, launcher, jupiterEngine, platformEngine);
1777 
1778         assertThat(testClasspathWrapper.getTestDependencies())
1779                 .hasSize(5)
1780                 .containsEntry("third.party:artifact", testClasspathSomeTestArtifact)
1781                 .containsEntry("org.junit.jupiter:junit-jupiter-api", testClasspathJupiterApi)
1782                 .containsEntry("org.apiguardian:apiguardian-api", testClasspathApiguardian)
1783                 .containsEntry("org.junit.platform:junit-platform-commons", testClasspathCommons)
1784                 .containsEntry("org.opentest4j:opentest4j", testClasspathOpentest4j);
1785     }
1786 
1787     @Test
1788     public void shouldConvertJunitEngineParameters() throws Exception {
1789         Properties properties = new Properties();
1790         setInternalState(mojo, "properties", properties);
1791 
1792         invokeMethod(mojo, "convertJunitEngineParameters");
1793         assertThat(properties).isEmpty();
1794 
1795         mojo.setIncludeJUnit5Engines(new String[0]);
1796         mojo.setExcludeJUnit5Engines(new String[0]);
1797         invokeMethod(mojo, "convertJunitEngineParameters");
1798         assertThat(properties).isEmpty();
1799 
1800         mojo.setIncludeJUnit5Engines(new String[] {"e1", "e2"});
1801         invokeMethod(mojo, "convertJunitEngineParameters");
1802         assertThat(properties).containsEntry("includejunit5engines", "e1,e2");
1803 
1804         mojo.setExcludeJUnit5Engines(new String[] {"e1", "e2"});
1805         invokeMethod(mojo, "convertJunitEngineParameters");
1806         assertThat(properties).containsEntry("excludejunit5engines", "e1,e2");
1807     }
1808 
1809     private static Set<Artifact> createJUnitPlatformLauncherResolutionResult(
1810             Artifact junit5Engine, Artifact apiguardian, Artifact commons, Artifact opentest4j) {
1811         Set<Artifact> resolvedLauncherArtifacts = new HashSet<>();
1812         Artifact launcher = new DefaultArtifact(
1813                 "org.junit.platform", "junit-platform-launcher", commons.getVersionRange(), null, "jar", "", null);
1814         resolvedLauncherArtifacts.add(launcher);
1815         resolvedLauncherArtifacts.add(apiguardian);
1816         resolvedLauncherArtifacts.add(junit5Engine);
1817         resolvedLauncherArtifacts.add(commons);
1818         resolvedLauncherArtifacts.add(opentest4j);
1819         resolvedLauncherArtifacts.remove(null);
1820         return resolvedLauncherArtifacts;
1821     }
1822 
1823     private static Set<Artifact> createJupiterEngineResolutionResult() {
1824         Set<Artifact> resolvedLauncherArtifacts = new HashSet<>();
1825         resolvedLauncherArtifacts.add(new DefaultArtifact(
1826                 "org.junit.jupiter", "junit-jupiter-engine", createFromVersion("5.4.0"), null, "jar", "", null));
1827         resolvedLauncherArtifacts.add(new DefaultArtifact(
1828                 "org.junit.jupiter", "junit-jupiter-api", createFromVersion("5.4.0"), null, "jar", "", null));
1829         resolvedLauncherArtifacts.add(new DefaultArtifact(
1830                 "org.junit.platform", "junit-platform-engine", createFromVersion("1.4.0"), null, "jar", "", null));
1831         resolvedLauncherArtifacts.add(new DefaultArtifact(
1832                 "org.apiguardian", "apiguardian-api", createFromVersion("1.0.0"), null, "jar", "", null));
1833         resolvedLauncherArtifacts.add(
1834                 new DefaultArtifact("org.opentest4j", "opentest4j", createFromVersion("1.1.1"), null, "jar", "", null));
1835         resolvedLauncherArtifacts.add(new DefaultArtifact(
1836                 "org.junit.platform", "junit-platform-commons", createFromVersion("1.4.0"), null, "jar", "", null));
1837         return resolvedLauncherArtifacts;
1838     }
1839 
1840     private static Set<Artifact> createExpectedJUnitPlatformLauncherResolutionResult() {
1841         Artifact engine = new DefaultArtifact(
1842                 "org.junit.platform", "junit-platform-engine", createFromVersion("1.4.0"), null, "jar", "", null);
1843         Artifact commons = new DefaultArtifact(
1844                 "org.junit.platform", "junit-platform-commons", createFromVersion("1.4.0"), null, "jar", "", null);
1845         Artifact apiguardian = new DefaultArtifact(
1846                 "org.apiguardian", "apiguardian-api", createFromVersion("1.0.0"), null, "jar", "", null);
1847         Artifact opentest4j =
1848                 new DefaultArtifact("org.opentest4j", "opentest4j", createFromVersion("1.1.1"), null, "jar", "", null);
1849         return createJUnitPlatformLauncherResolutionResult(engine, apiguardian, commons, opentest4j);
1850     }
1851 
1852     private static Set<Artifact> createSurefireProviderResolutionResult(VersionRange surefireVersion) {
1853 
1854         Artifact provider = new DefaultArtifact(
1855                 "org.apache.maven.surefire", "surefire-junit-platform", surefireVersion, null, "jar", "", null);
1856         Artifact java5 = new DefaultArtifact(
1857                 "org.apache.maven.surefire", "common-java5", surefireVersion, null, "jar", "", null);
1858         Artifact launcher = new DefaultArtifact(
1859                 "org.junit.platform", "junit-platform-launcher", createFromVersion("1.3.2"), null, "jar", "", null);
1860         Artifact apiguardian = new DefaultArtifact(
1861                 "org.apiguardian", "apiguardian-api", createFromVersion("1.0.0"), null, "jar", "", null);
1862         Artifact engine = new DefaultArtifact(
1863                 "org.junit.platform", "junit-platform-engine", createFromVersion("1.3.2"), null, "jar", "", null);
1864         Artifact commons = new DefaultArtifact(
1865                 "org.junit.platform", "junit-platform-commons", createFromVersion("1.3.2"), null, "jar", "", null);
1866         Artifact opentest4j =
1867                 new DefaultArtifact("org.opentest4j", "opentest4j", createFromVersion("1.1.1"), null, "jar", "", null);
1868 
1869         Set<Artifact> providerArtifacts = new HashSet<>();
1870         providerArtifacts.add(provider);
1871         providerArtifacts.add(java5);
1872         providerArtifacts.add(launcher);
1873         providerArtifacts.add(apiguardian);
1874         providerArtifacts.add(engine);
1875         providerArtifacts.add(commons);
1876         providerArtifacts.add(opentest4j);
1877 
1878         return providerArtifacts;
1879     }
1880 
1881     @Test
1882     public void shouldVerifyConfigParameters() throws Exception {
1883 
1884         Mojo mojo = new Mojo() {
1885             @Override
1886             public File getTestClassesDirectory() {
1887                 return new File(System.getProperty("user.dir"), "target/test-classes");
1888             }
1889 
1890             @Override
1891             protected String getEnableProcessChecker() {
1892                 return "fake";
1893             }
1894         };
1895 
1896         MojoFailureException m = assertThrows(MojoFailureException.class, mojo::verifyParameters);
1897         assertThat(m.getMessage())
1898                 .isEqualTo("Unexpected value 'fake' in the configuration parameter 'enableProcessChecker'.");
1899     }
1900 
1901     private void setProjectDepedenciesToMojo(Artifact... deps) {
1902         for (Artifact dep : deps) {
1903             mojo.getProjectArtifactMap().put(dep.getGroupId() + ":" + dep.getArtifactId(), dep);
1904         }
1905     }
1906 
1907     private void addPluginDependencies(Artifact... deps) {
1908         for (Artifact dep : deps) {
1909             mojo.getPluginArtifactMap().put(dep.getGroupId() + ":" + dep.getArtifactId(), dep);
1910         }
1911     }
1912 
1913     /**
1914      *
1915      */
1916     public static class Mojo extends AbstractSurefireMojo implements SurefireReportParameters {
1917         private File mainBuildPath;
1918 
1919         private File testClassesDirectory;
1920 
1921         private boolean useModulePath;
1922 
1923         private int failOnFlakeCount;
1924 
1925         private String[] includeJUnit5Engines;
1926 
1927         private String[] excludeJUnit5Engines;
1928 
1929         private List<Artifact> projectTestArtifacts;
1930 
1931         private File includesFile;
1932 
1933         private File excludesFile;
1934 
1935         private List<String> includes;
1936 
1937         private List<String> excludes;
1938 
1939         private String test;
1940 
1941         private boolean testFailureIgnore;
1942 
1943         private JUnitPlatformProviderInfo createJUnitPlatformProviderInfo(
1944                 Artifact junitPlatformArtifact, TestClassPath testClasspathWrapper) {
1945             return new JUnitPlatformProviderInfo(
1946                     null,
1947                     junitPlatformArtifact,
1948                     testClasspathWrapper,
1949                     null,
1950                     getBooterArtifact(),
1951                     getSurefireDependencyResolver(),
1952                     mock(MavenSession.class),
1953                     mock(MavenProject.class),
1954                     getPluginDescriptor(),
1955                     getPluginArtifactMap(),
1956                     getConsoleLogger(),
1957                     null);
1958         }
1959 
1960         void setProjectTestArtifacts(List<Artifact> projectTestArtifacts) {
1961             this.projectTestArtifacts = projectTestArtifacts;
1962         }
1963 
1964         @Override
1965         List<Artifact> getProjectTestArtifacts() {
1966             return projectTestArtifacts;
1967         }
1968 
1969         @Override
1970         protected void logDebugOrCliShowErrors(String s) {
1971             // do nothing
1972         }
1973 
1974         @Override
1975         protected String getPluginName() {
1976             return null;
1977         }
1978 
1979         @Override
1980         protected int getRerunFailingTestsCount() {
1981             return 0;
1982         }
1983 
1984         @Override
1985         public boolean isSkipTests() {
1986             return false;
1987         }
1988 
1989         @Override
1990         public void setSkipTests(boolean skipTests) {}
1991 
1992         @Override
1993         public boolean isSkipExec() {
1994             return false;
1995         }
1996 
1997         @Override
1998         public void setSkipExec(boolean skipExec) {}
1999 
2000         @Override
2001         public boolean isSkip() {
2002             return false;
2003         }
2004 
2005         @Override
2006         public void setSkip(boolean skip) {}
2007 
2008         @Override
2009         public boolean isTestFailureIgnore() {
2010             return testFailureIgnore;
2011         }
2012 
2013         @Override
2014         public void setTestFailureIgnore(boolean testFailureIgnore) {
2015             this.testFailureIgnore = testFailureIgnore;
2016         }
2017 
2018         @Override
2019         public File getBasedir() {
2020             return null;
2021         }
2022 
2023         @Override
2024         public void setBasedir(File basedir) {}
2025 
2026         @Override
2027         public File getTestClassesDirectory() {
2028             return testClassesDirectory;
2029         }
2030 
2031         @Override
2032         public void setTestClassesDirectory(File testClassesDirectory) {
2033             this.testClassesDirectory = testClassesDirectory;
2034         }
2035 
2036         @Override
2037         public File getMainBuildPath() {
2038             return mainBuildPath;
2039         }
2040 
2041         @Override
2042         public void setMainBuildPath(File mainBuildPath) {
2043             this.mainBuildPath = mainBuildPath;
2044         }
2045 
2046         @Override
2047         public File getReportsDirectory() {
2048             return null;
2049         }
2050 
2051         @Override
2052         public void setReportsDirectory(File reportsDirectory) {}
2053 
2054         @Override
2055         public String getTest() {
2056             return test;
2057         }
2058 
2059         @Override
2060         public void setTest(String test) {
2061             this.test = test;
2062         }
2063 
2064         @Override
2065         public List<String> getIncludes() {
2066             return includes;
2067         }
2068 
2069         @Override
2070         public void setIncludes(List<String> includes) {
2071             this.includes = includes;
2072         }
2073 
2074         void setIncludesFile(File includesFile) {
2075             this.includesFile = includesFile;
2076         }
2077 
2078         @Override
2079         public File getIncludesFile() {
2080             return includesFile;
2081         }
2082 
2083         @Override
2084         public List<String> getExcludes() {
2085             return excludes;
2086         }
2087 
2088         @Override
2089         public void setExcludes(List<String> excludes) {
2090             this.excludes = excludes;
2091         }
2092 
2093         @Override
2094         public boolean isPrintSummary() {
2095             return false;
2096         }
2097 
2098         @Override
2099         public void setPrintSummary(boolean printSummary) {}
2100 
2101         @Override
2102         public String getReportFormat() {
2103             return null;
2104         }
2105 
2106         @Override
2107         public void setReportFormat(String reportFormat) {}
2108 
2109         @Override
2110         public boolean isUseFile() {
2111             return false;
2112         }
2113 
2114         @Override
2115         public void setUseFile(boolean useFile) {}
2116 
2117         @Override
2118         public String getDebugForkedProcess() {
2119             return null;
2120         }
2121 
2122         @Override
2123         public void setDebugForkedProcess(String debugForkedProcess) {}
2124 
2125         @Override
2126         public int getForkedProcessTimeoutInSeconds() {
2127             return 0;
2128         }
2129 
2130         @Override
2131         public void setForkedProcessTimeoutInSeconds(int forkedProcessTimeoutInSeconds) {}
2132 
2133         @Override
2134         public int getForkedProcessExitTimeoutInSeconds() {
2135             return 0;
2136         }
2137 
2138         @Override
2139         public void setForkedProcessExitTimeoutInSeconds(int forkedProcessTerminationTimeoutInSeconds) {}
2140 
2141         @Override
2142         public double getParallelTestsTimeoutInSeconds() {
2143             return 0;
2144         }
2145 
2146         @Override
2147         public void setParallelTestsTimeoutInSeconds(double parallelTestsTimeoutInSeconds) {}
2148 
2149         @Override
2150         public double getParallelTestsTimeoutForcedInSeconds() {
2151             return 0;
2152         }
2153 
2154         @Override
2155         public void setParallelTestsTimeoutForcedInSeconds(double parallelTestsTimeoutForcedInSeconds) {}
2156 
2157         @Override
2158         public boolean isUseSystemClassLoader() {
2159             return false;
2160         }
2161 
2162         @Override
2163         public void setUseSystemClassLoader(boolean useSystemClassLoader) {}
2164 
2165         @Override
2166         public boolean isUseManifestOnlyJar() {
2167             return false;
2168         }
2169 
2170         @Override
2171         public void setUseManifestOnlyJar(boolean useManifestOnlyJar) {}
2172 
2173         @Override
2174         public String getEncoding() {
2175             return null;
2176         }
2177 
2178         @Override
2179         public void setEncoding(String encoding) {}
2180 
2181         @Override
2182         public boolean getFailIfNoSpecifiedTests() {
2183             return false;
2184         }
2185 
2186         @Override
2187         public void setFailIfNoSpecifiedTests(boolean failIfNoSpecifiedTests) {}
2188 
2189         @Override
2190         public int getSkipAfterFailureCount() {
2191             return 0;
2192         }
2193 
2194         @Override
2195         public String getShutdown() {
2196             return null;
2197         }
2198 
2199         void setExcludesFile(File excludesFile) {
2200             this.excludesFile = excludesFile;
2201         }
2202 
2203         @Override
2204         public File getExcludesFile() {
2205             return excludesFile;
2206         }
2207 
2208         @Override
2209         protected String[] getExcludedEnvironmentVariables() {
2210             return new String[0];
2211         }
2212 
2213         @Override
2214         public String getRunOrder() {
2215             return null;
2216         }
2217 
2218         @Override
2219         public void setRunOrder(String runOrder) {}
2220 
2221         @Override
2222         public Long getRunOrderRandomSeed() {
2223             return null;
2224         }
2225 
2226         @Override
2227         public void setRunOrderRandomSeed(Long runOrderRandomSeed) {}
2228 
2229         @Override
2230         public String getRunOrderStatisticsFileChecksum() {
2231             return null;
2232         }
2233 
2234         @Override
2235         public void setRunOrderStatisticsFileChecksum(String runOrderStatisticsFileChecksum) {}
2236 
2237         @Override
2238         protected void handleSummary(RunResult summary, Exception firstForkException) {}
2239 
2240         @Override
2241         protected boolean isSkipExecution() {
2242             return false;
2243         }
2244 
2245         @Override
2246         protected String[] getDefaultIncludes() {
2247             return new String[0];
2248         }
2249 
2250         @Override
2251         protected String getReportSchemaLocation() {
2252             return null;
2253         }
2254 
2255         @Override
2256         protected boolean useModulePath() {
2257             return useModulePath;
2258         }
2259 
2260         @Override
2261         protected void setUseModulePath(boolean useModulePath) {
2262             this.useModulePath = useModulePath;
2263         }
2264 
2265         @Override
2266         protected String getEnableProcessChecker() {
2267             return null;
2268         }
2269 
2270         @Override
2271         protected ForkNodeFactory getForkNode() {
2272             return null;
2273         }
2274 
2275         @Override
2276         protected Artifact getMojoArtifact() {
2277             return new DefaultArtifact(
2278                     "org.apache.maven.surefire",
2279                     "maven-surefire-plugin",
2280                     createFromVersion("1"),
2281                     null,
2282                     "jar",
2283                     null,
2284                     mock(ArtifactHandler.class));
2285         }
2286 
2287         @Override
2288         public File getSystemPropertiesFile() {
2289             return null;
2290         }
2291 
2292         @Override
2293         public void setSystemPropertiesFile(File systemPropertiesFile) {}
2294 
2295         public void setToolchain(Toolchain toolchain) {
2296             setInternalState(this, "toolchain", toolchain);
2297         }
2298 
2299         public void setJvm(String jvm) {
2300             setInternalState(this, "jvm", jvm);
2301         }
2302 
2303         @Override
2304         public int getFailOnFlakeCount() {
2305             return failOnFlakeCount;
2306         }
2307 
2308         @Override
2309         public void setFailOnFlakeCount(int failOnFlakeCount) {
2310             this.failOnFlakeCount = failOnFlakeCount;
2311         }
2312 
2313         @Override
2314         public String[] getIncludeJUnit5Engines() {
2315             return includeJUnit5Engines;
2316         }
2317 
2318         @Override
2319         public void setIncludeJUnit5Engines(String[] includeJUnit5Engines) {
2320             this.includeJUnit5Engines = includeJUnit5Engines;
2321         }
2322 
2323         @Override
2324         public String[] getExcludeJUnit5Engines() {
2325             return excludeJUnit5Engines;
2326         }
2327 
2328         @Override
2329         public void setExcludeJUnit5Engines(String[] excludeJUnit5Engines) {
2330             this.excludeJUnit5Engines = excludeJUnit5Engines;
2331         }
2332     }
2333 
2334     @Test
2335     public void shouldNotPerformMethodFilteringOnIncludes() throws Exception {
2336         Mojo plugin = new Mojo();
2337 
2338         File includesExcludes = SureFireFileManager.createTempFile("surefire", "includes");
2339         FileUtils.write(includesExcludes, "AnotherTest#method", UTF_8);
2340         plugin.setIncludesFile(includesExcludes);
2341 
2342         List<String> includes = new LinkedList<>();
2343         includes.add("AnotherTest#method ");
2344         plugin.setIncludes(includes);
2345 
2346         VersionRange version = VersionRange.createFromVersion("1.0");
2347         ArtifactHandler handler = new DefaultArtifactHandler();
2348         Artifact testDeps = new DefaultArtifact("g", "a", version, "compile", "jar", null, handler);
2349         File artifactFile = SureFireFileManager.createTempFile("surefire", ".jar");
2350         artifactFile.deleteOnExit();
2351         testDeps.setFile(artifactFile);
2352         plugin.setProjectTestArtifacts(singletonList(testDeps));
2353         plugin.setDependenciesToScan(new String[] {"g:a"});
2354 
2355         Exception e = assertThrows(Exception.class, plugin::scanDependencies);
2356         assertThat(e.getMessage())
2357                 .isEqualTo("Method filter prohibited in includes|excludes parameter: AnotherTest#method ");
2358     }
2359 
2360     @Test
2361     public void shouldFilterTestsOnIncludesFile() throws Exception {
2362         Mojo plugin = new Mojo();
2363 
2364         plugin.setLogger(mock(Logger.class));
2365 
2366         File includes = SureFireFileManager.createTempFile("surefire", "includes");
2367         FileUtils.write(includes, "AnotherTest#method", UTF_8);
2368         plugin.setIncludesFile(includes);
2369 
2370         VersionRange version = VersionRange.createFromVersion("1.0");
2371         ArtifactHandler handler = new DefaultArtifactHandler();
2372         Artifact testDeps = new DefaultArtifact("g", "a", version, "compile", "test-jar", null, handler);
2373         File artifactFile = SureFireFileManager.createTempFile("surefire", "classes");
2374         String classDir = artifactFile.getCanonicalPath();
2375         assertThat(artifactFile.delete()).isTrue();
2376         File classes = new File(classDir);
2377         assertThat(classes.mkdir()).isTrue();
2378         testDeps.setFile(classes);
2379         assertThat(new File(classes, "AnotherTest.class").createNewFile()).isTrue();
2380         plugin.setProjectTestArtifacts(singletonList(testDeps));
2381         plugin.setDependenciesToScan(new String[] {"g:a"});
2382 
2383         DefaultScanResult result = plugin.scanDependencies();
2384         assertThat(result.getClasses()).hasSize(1);
2385         assertThat(result.getClasses().iterator().next()).isEqualTo("AnotherTest");
2386     }
2387 
2388     @Test
2389     public void shouldFilterTestsOnExcludesFile() throws Exception {
2390         Mojo plugin = new Mojo();
2391 
2392         plugin.setLogger(mock(Logger.class));
2393 
2394         File excludes = SureFireFileManager.createTempFile("surefire", "-excludes");
2395         FileUtils.write(excludes, "AnotherTest", UTF_8);
2396         plugin.setExcludesFile(excludes);
2397 
2398         VersionRange version = VersionRange.createFromVersion("1.0");
2399         ArtifactHandler handler = new DefaultArtifactHandler();
2400         Artifact testDeps = new DefaultArtifact("g", "a", version, "compile", "test-jar", null, handler);
2401         File artifactFile = SureFireFileManager.createTempFile("surefire", "-classes");
2402         String classDir = artifactFile.getCanonicalPath();
2403         assertThat(artifactFile.delete()).isTrue();
2404         File classes = new File(classDir);
2405         assertThat(classes.mkdir()).isTrue();
2406         testDeps.setFile(classes);
2407         assertThat(new File(classes, "AnotherTest.class").createNewFile()).isTrue();
2408         plugin.setProjectTestArtifacts(singletonList(testDeps));
2409         plugin.setDependenciesToScan(new String[] {"g:a"});
2410 
2411         DefaultScanResult result = plugin.scanDependencies();
2412         assertThat(result.getClasses()).isEmpty();
2413     }
2414 
2415     @Test
2416     public void shouldFilterTestsOnExcludes() throws Exception {
2417         Mojo plugin = new Mojo();
2418 
2419         plugin.setLogger(mock(Logger.class));
2420 
2421         plugin.setExcludes(singletonList("AnotherTest"));
2422 
2423         VersionRange version = VersionRange.createFromVersion("1.0");
2424         ArtifactHandler handler = new DefaultArtifactHandler();
2425         Artifact testDeps = new DefaultArtifact("g", "a", version, "compile", "jar", null, handler);
2426         File artifactFile = SureFireFileManager.createTempFile("surefire", "-classes");
2427         String classDir = artifactFile.getCanonicalPath();
2428         assertThat(artifactFile.delete()).isTrue();
2429         File classes = new File(classDir);
2430         assertThat(classes.mkdir()).isTrue();
2431         testDeps.setFile(classes);
2432         assertThat(new File(classes, "AnotherTest.class").createNewFile()).isTrue();
2433         plugin.setProjectTestArtifacts(singletonList(testDeps));
2434         plugin.setDependenciesToScan(new String[] {"g:a"});
2435 
2436         DefaultScanResult result = plugin.scanDependencies();
2437         assertThat(result.getClasses()).isEmpty();
2438     }
2439 
2440     @Test
2441     public void shouldUseOnlySpecificTests() throws Exception {
2442         Mojo plugin = new Mojo();
2443 
2444         plugin.setLogger(mock(Logger.class));
2445 
2446         File includes = SureFireFileManager.createTempFile("surefire", "-includes");
2447         FileUtils.write(includes, "AnotherTest", UTF_8);
2448         plugin.setIncludesFile(includes);
2449         plugin.setTest("DifferentTest");
2450 
2451         VersionRange version = VersionRange.createFromVersion("1.0");
2452         ArtifactHandler handler = new DefaultArtifactHandler();
2453         Artifact testDeps = new DefaultArtifact("g", "a", version, "compile", "test-jar", null, handler);
2454         File artifactFile = SureFireFileManager.createTempFile("surefire", "-classes");
2455         String classDir = artifactFile.getCanonicalPath();
2456         assertThat(artifactFile.delete()).isTrue();
2457         File classes = new File(classDir);
2458         assertThat(classes.mkdir()).isTrue();
2459         testDeps.setFile(classes);
2460         assertThat(new File(classes, "AnotherTest.class").createNewFile()).isTrue();
2461         plugin.setProjectTestArtifacts(singletonList(testDeps));
2462         plugin.setDependenciesToScan(new String[] {"g:a"});
2463 
2464         DefaultScanResult result = plugin.scanDependencies();
2465         assertThat(result.getClasses()).isEmpty();
2466     }
2467 
2468     @Test
2469     public void testSetupProperties() {
2470         Mojo plugin = new Mojo() {
2471 
2472             @Override
2473             Properties getUserProperties() {
2474                 Properties properties = new Properties();
2475                 properties.put("userProperties1", "source4");
2476                 return properties;
2477             }
2478 
2479             @Override
2480             public File getBasedir() {
2481                 return new File("target");
2482             }
2483 
2484             @Override
2485             public String getLocalRepositoryPath() {
2486                 return "local/repository/path";
2487             }
2488 
2489             @Override
2490             public File getSystemPropertiesFile() {
2491                 Properties systemProperties = new Properties();
2492                 systemProperties.put("systemProperties2", "source2");
2493                 systemProperties.put("systemProperties3", "source2");
2494                 systemProperties.put("userProperties1", "source2");
2495                 try {
2496                     File propertiesFile =
2497                             Files.createTempFile(tempFolder, "test", ".tmp").toFile();
2498                     try (OutputStream outputStream = Files.newOutputStream(propertiesFile.toPath())) {
2499                         systemProperties.store(outputStream, "comments");
2500                     }
2501                     return propertiesFile;
2502                 } catch (IOException e) {
2503                     throw new UncheckedIOException(e);
2504                 }
2505             }
2506         };
2507 
2508         plugin.setLogger(mock(Logger.class));
2509         /* expected order of precedence:
2510          * 1. systemProperties
2511          * 2. getSystemPropertiesFile()
2512          * 3. systemPropertyVariables
2513          * 4. getUserProperties()
2514          */
2515         plugin.forkCount = "1";
2516         plugin.promoteUserPropertiesToSystemProperties = true;
2517         Properties systemProperties = new Properties();
2518         systemProperties.put("systemProperties1", "source1");
2519         systemProperties.put("systemProperties2", "source1");
2520         systemProperties.put("systemProperties3", "source1");
2521         systemProperties.put("userProperties1", "source1");
2522         plugin.systemProperties = systemProperties;
2523         Map<String, String> systemPropertyVariables = new HashMap<>();
2524         systemPropertyVariables.put("systemProperties3", "source3");
2525         systemPropertyVariables.put("userProperties1", "source3");
2526         plugin.systemPropertyVariables = systemPropertyVariables;
2527         SurefireProperties properties = plugin.setupProperties();
2528         assertThat(properties)
2529                 .containsOnly(
2530                         Assertions.entry("systemProperties1", "source1"),
2531                         Assertions.entry("systemProperties2", "source2"),
2532                         Assertions.entry("systemProperties3", "source3"),
2533                         Assertions.entry("userProperties1", "source4"),
2534                         Assertions.entry("localRepository", "local/repository/path"),
2535                         Assertions.entry("basedir", new File("target").getAbsolutePath()));
2536 
2537         // and without user properties
2538         plugin.promoteUserPropertiesToSystemProperties = false;
2539         properties = plugin.setupProperties();
2540         assertThat(properties)
2541                 .containsOnly(
2542                         Assertions.entry("systemProperties1", "source1"),
2543                         Assertions.entry("systemProperties2", "source2"),
2544                         Assertions.entry("systemProperties3", "source3"),
2545                         Assertions.entry("userProperties1", "source3"),
2546                         Assertions.entry("localRepository", "local/repository/path"),
2547                         Assertions.entry("basedir", new File("target").getAbsolutePath()));
2548     }
2549 
2550     @SuppressWarnings("unchecked")
2551     private static <T> T invokeMethod(Object target, String methodName, Object... args) throws Exception {
2552         Class<?> clazz = target instanceof Class ? (Class<?>) target : target.getClass();
2553         while (clazz != null) {
2554             for (Method method : clazz.getDeclaredMethods()) {
2555                 if (method.getName().equals(methodName)) {
2556                     int paramCount = method.getParameterCount();
2557                     if (paramCount == args.length || (method.isVarArgs() && args.length >= paramCount - 1)) {
2558                         method.setAccessible(true);
2559                         Object instance = target instanceof Class ? null : target;
2560                         if (method.isVarArgs() && args.length < paramCount) {
2561                             // Fill missing varargs with empty array
2562                             Object[] fullArgs = new Object[paramCount];
2563                             System.arraycopy(args, 0, fullArgs, 0, args.length);
2564                             Class<?> varArgType = method.getParameterTypes()[paramCount - 1].getComponentType();
2565                             fullArgs[paramCount - 1] = java.lang.reflect.Array.newInstance(varArgType, 0);
2566                             return (T) method.invoke(instance, fullArgs);
2567                         }
2568                         return (T) method.invoke(instance, args);
2569                     }
2570                 }
2571             }
2572             clazz = clazz.getSuperclass();
2573         }
2574         throw new NoSuchMethodException(methodName);
2575     }
2576 
2577     @SuppressWarnings("unchecked")
2578     private static <T> T invokeMethod(Object target, String methodName, Class<?>[] paramTypes, Object... args)
2579             throws Exception {
2580         Class<?> clazz = target instanceof Class ? (Class<?>) target : target.getClass();
2581         while (clazz != null) {
2582             try {
2583                 Method method = clazz.getDeclaredMethod(methodName, paramTypes);
2584                 method.setAccessible(true);
2585                 return (T) method.invoke(target instanceof Class ? null : target, args);
2586             } catch (NoSuchMethodException e) {
2587                 clazz = clazz.getSuperclass();
2588             }
2589         }
2590         throw new NoSuchMethodException(methodName);
2591     }
2592 
2593     private static void setInternalState(Object target, String fieldName, Object value) {
2594         try {
2595             Class<?> clazz = target.getClass();
2596             while (clazz != null) {
2597                 try {
2598                     Field field = clazz.getDeclaredField(fieldName);
2599                     field.setAccessible(true);
2600                     field.set(target, value);
2601                     return;
2602                 } catch (NoSuchFieldException e) {
2603                     clazz = clazz.getSuperclass();
2604                 }
2605             }
2606             throw new NoSuchFieldException(fieldName);
2607         } catch (NoSuchFieldException | IllegalAccessException e) {
2608             throw new RuntimeException(e);
2609         }
2610     }
2611 
2612     private static File mockFile(String absolutePath) {
2613         File f = mock(File.class);
2614         when(f.getAbsolutePath()).thenReturn(absolutePath);
2615         return f;
2616     }
2617 
2618     private static Dependency toDependency(Artifact artifact) {
2619         Dependency dependency = new Dependency();
2620         dependency.setGroupId(artifact.getGroupId());
2621         dependency.setArtifactId(artifact.getArtifactId());
2622         dependency.setVersion(artifact.getBaseVersion());
2623         dependency.setType("jar");
2624         return dependency;
2625     }
2626 
2627     private static List<Dependency> toDependencies(Artifact... artifacts) {
2628         List<Dependency> dependencies = new ArrayList<>();
2629         for (Artifact artifact : artifacts) {
2630             dependencies.add(toDependency(artifact));
2631         }
2632         return dependencies;
2633     }
2634 }