1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.surefire;
20
21 import javax.annotation.Nonnull;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.lang.reflect.Method;
26 import java.math.BigDecimal;
27 import java.nio.file.Files;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Enumeration;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.LinkedHashSet;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.Optional;
39 import java.util.Properties;
40 import java.util.Set;
41 import java.util.SortedSet;
42 import java.util.TreeSet;
43 import java.util.concurrent.ConcurrentHashMap;
44 import java.util.zip.ZipFile;
45
46 import org.apache.maven.artifact.Artifact;
47 import org.apache.maven.artifact.DefaultArtifact;
48 import org.apache.maven.artifact.handler.ArtifactHandler;
49 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
50 import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
51 import org.apache.maven.artifact.versioning.ArtifactVersion;
52 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
53 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
54 import org.apache.maven.artifact.versioning.VersionRange;
55 import org.apache.maven.execution.MavenSession;
56 import org.apache.maven.model.Plugin;
57 import org.apache.maven.plugin.AbstractMojo;
58 import org.apache.maven.plugin.MojoExecutionException;
59 import org.apache.maven.plugin.MojoFailureException;
60 import org.apache.maven.plugin.descriptor.PluginDescriptor;
61 import org.apache.maven.plugin.surefire.booterclient.ChecksumCalculator;
62 import org.apache.maven.plugin.surefire.booterclient.ClasspathForkConfiguration;
63 import org.apache.maven.plugin.surefire.booterclient.ForkConfiguration;
64 import org.apache.maven.plugin.surefire.booterclient.ForkStarter;
65 import org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration;
66 import org.apache.maven.plugin.surefire.booterclient.ModularClasspathForkConfiguration;
67 import org.apache.maven.plugin.surefire.booterclient.Platform;
68 import org.apache.maven.plugin.surefire.extensions.LegacyForkNodeFactory;
69 import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter;
70 import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter;
71 import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter;
72 import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
73 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
74 import org.apache.maven.plugin.surefire.util.DependencyScanner;
75 import org.apache.maven.plugin.surefire.util.DirectoryScanner;
76 import org.apache.maven.plugins.annotations.Component;
77 import org.apache.maven.plugins.annotations.Parameter;
78 import org.apache.maven.project.MavenProject;
79 import org.apache.maven.shared.artifact.filter.PatternIncludesArtifactFilter;
80 import org.apache.maven.surefire.api.booter.ProviderParameterNames;
81 import org.apache.maven.surefire.api.booter.Shutdown;
82 import org.apache.maven.surefire.api.cli.CommandLineOption;
83 import org.apache.maven.surefire.api.report.ReporterConfiguration;
84 import org.apache.maven.surefire.api.suite.RunResult;
85 import org.apache.maven.surefire.api.testset.DirectoryScannerParameters;
86 import org.apache.maven.surefire.api.testset.RunOrderParameters;
87 import org.apache.maven.surefire.api.testset.TestArtifactInfo;
88 import org.apache.maven.surefire.api.testset.TestListResolver;
89 import org.apache.maven.surefire.api.testset.TestRequest;
90 import org.apache.maven.surefire.api.testset.TestSetFailedException;
91 import org.apache.maven.surefire.api.util.DefaultScanResult;
92 import org.apache.maven.surefire.api.util.RunOrder;
93 import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
94 import org.apache.maven.surefire.booter.Classpath;
95 import org.apache.maven.surefire.booter.ClasspathConfiguration;
96 import org.apache.maven.surefire.booter.KeyValueSource;
97 import org.apache.maven.surefire.booter.ModularClasspath;
98 import org.apache.maven.surefire.booter.ModularClasspathConfiguration;
99 import org.apache.maven.surefire.booter.ProcessCheckerType;
100 import org.apache.maven.surefire.booter.ProviderConfiguration;
101 import org.apache.maven.surefire.booter.StartupConfiguration;
102 import org.apache.maven.surefire.booter.SurefireBooterForkException;
103 import org.apache.maven.surefire.booter.SurefireExecutionException;
104 import org.apache.maven.surefire.extensions.ForkNodeFactory;
105 import org.apache.maven.surefire.providerapi.ConfigurableProviderInfo;
106 import org.apache.maven.surefire.providerapi.ProviderDetector;
107 import org.apache.maven.surefire.providerapi.ProviderInfo;
108 import org.apache.maven.surefire.providerapi.ProviderRequirements;
109 import org.apache.maven.surefire.shared.utils.io.FileUtils;
110 import org.apache.maven.toolchain.DefaultToolchain;
111 import org.apache.maven.toolchain.Toolchain;
112 import org.apache.maven.toolchain.ToolchainManager;
113 import org.apache.maven.toolchain.java.DefaultJavaToolChain;
114 import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
115 import org.codehaus.plexus.languages.java.jpms.LocationManager;
116 import org.codehaus.plexus.languages.java.jpms.ResolvePathRequest;
117 import org.codehaus.plexus.languages.java.jpms.ResolvePathResult;
118 import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest;
119 import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult;
120 import org.codehaus.plexus.logging.Logger;
121
122 import static java.lang.Integer.parseInt;
123 import static java.util.Arrays.asList;
124 import static java.util.Collections.addAll;
125 import static java.util.Collections.emptyList;
126 import static java.util.Collections.singletonList;
127 import static java.util.Collections.singletonMap;
128 import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.PluginFailureReason.COULD_NOT_RUN_DEFAULT_TESTS;
129 import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.PluginFailureReason.COULD_NOT_RUN_SPECIFIED_TESTS;
130 import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.PluginFailureReason.NONE;
131 import static org.apache.maven.plugin.surefire.SurefireDependencyResolver.isWithinVersionSpec;
132 import static org.apache.maven.plugin.surefire.SurefireHelper.replaceThreadNumberPlaceholders;
133 import static org.apache.maven.plugin.surefire.util.DependencyScanner.filter;
134 import static org.apache.maven.surefire.api.booter.ProviderParameterNames.EXCLUDE_JUNIT5_ENGINES_PROP;
135 import static org.apache.maven.surefire.api.booter.ProviderParameterNames.INCLUDE_JUNIT5_ENGINES_PROP;
136 import static org.apache.maven.surefire.api.suite.RunResult.failure;
137 import static org.apache.maven.surefire.api.suite.RunResult.noTestsRun;
138 import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
139 import static org.apache.maven.surefire.api.util.ReflectionUtils.tryGetMethod;
140 import static org.apache.maven.surefire.booter.Classpath.emptyClasspath;
141 import static org.apache.maven.surefire.booter.SystemUtils.endsWithJavaPath;
142 import static org.apache.maven.surefire.booter.SystemUtils.isBuiltInJava9AtLeast;
143 import static org.apache.maven.surefire.booter.SystemUtils.isJava9AtLeast;
144 import static org.apache.maven.surefire.booter.SystemUtils.toJdkHomeFromJvmExec;
145 import static org.apache.maven.surefire.booter.SystemUtils.toJdkVersionFromReleaseFile;
146 import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_RECENT;
147 import static org.apache.maven.surefire.shared.lang3.StringUtils.substringBeforeLast;
148 import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
149 import static org.apache.maven.surefire.shared.utils.StringUtils.capitalizeFirstLetter;
150 import static org.apache.maven.surefire.shared.utils.StringUtils.isEmpty;
151 import static org.apache.maven.surefire.shared.utils.StringUtils.isNotBlank;
152 import static org.apache.maven.surefire.shared.utils.StringUtils.isNotEmpty;
153 import static org.apache.maven.surefire.shared.utils.StringUtils.split;
154 import static org.apache.maven.surefire.shared.utils.cli.ShutdownHookUtils.addShutDownHook;
155 import static org.apache.maven.surefire.shared.utils.cli.ShutdownHookUtils.removeShutdownHook;
156
157
158
159
160
161
162
163 public abstract class AbstractSurefireMojo extends AbstractMojo implements SurefireExecutionParameters {
164 private static final Map<String, String> JAVA_9_MATCHER_OLD_NOTATION = singletonMap("version", "[1.9,)");
165 private static final Map<String, String> JAVA_9_MATCHER = singletonMap("version", "[9,)");
166 private static final Platform PLATFORM = new Platform();
167
168 private final ClasspathCache classpathCache = new ClasspathCache();
169
170
171
172
173 @Parameter
174 private SurefireStatelessReporter statelessTestsetReporter;
175
176 @Parameter
177 private SurefireConsoleOutputReporter consoleOutputReporter;
178
179 @Parameter
180 private SurefireStatelessTestsetInfoReporter statelessTestsetInfoReporter;
181
182
183
184
185
186
187
188 @Parameter(defaultValue = "${plugin}", readonly = true, required = true)
189 private PluginDescriptor pluginDescriptor;
190
191
192
193
194
195
196
197
198
199 @Parameter(property = "skipTests", defaultValue = "false")
200 protected boolean skipTests;
201
202
203
204
205
206
207
208 @Deprecated
209 @Parameter(property = "maven.test.skip.exec")
210 protected boolean skipExec;
211
212
213
214
215
216
217 @Parameter(property = "maven.test.skip", defaultValue = "false")
218 protected boolean skip;
219
220
221
222
223 @Parameter(defaultValue = "${project}", required = true, readonly = true)
224 private MavenProject project;
225
226
227
228
229
230 @Parameter(defaultValue = "${basedir}", readonly = true, required = true)
231 protected File basedir;
232
233
234
235
236
237 @Parameter(defaultValue = "${project.build.testOutputDirectory}")
238 protected File testClassesDirectory;
239
240
241
242
243
244
245
246 @Parameter(property = "maven.test.dependency.excludes")
247 private String[] classpathDependencyExcludes;
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263 @Parameter(defaultValue = "")
264 private String classpathDependencyScopeExclude;
265
266
267
268
269
270
271 @Parameter(property = "maven.test.additionalClasspath")
272 private String[] additionalClasspathElements;
273
274
275
276
277
278
279
280 @Parameter(defaultValue = "${project.build.testSourceDirectory}")
281 private File testSourceDirectory;
282
283
284
285
286
287
288 @Deprecated
289 @Parameter
290 private Properties systemProperties;
291
292
293
294
295
296
297 @Parameter
298 private Map<String, String> systemPropertyVariables;
299
300
301
302
303
304
305
306 @Parameter
307 private Properties properties;
308
309
310
311
312 @Parameter(property = "plugin.artifactMap", required = true, readonly = true)
313 private Map<String, Artifact> pluginArtifactMap;
314
315
316
317
318 @Parameter(property = "project.artifactMap", readonly = true, required = true)
319 private Map<String, Artifact> projectArtifactMap;
320
321
322
323
324
325
326
327 @Parameter(property = "surefire.reportNameSuffix", defaultValue = "")
328 private String reportNameSuffix;
329
330
331
332
333
334
335
336 @Parameter(property = "maven.test.redirectTestOutputToFile", defaultValue = "false")
337 private boolean redirectTestOutputToFile;
338
339
340
341
342
343
344 @Parameter(property = "failIfNoTests", defaultValue = "false")
345 private boolean failIfNoTests;
346
347
348
349
350
351
352
353
354
355
356
357
358 @Parameter(property = "tempDir", defaultValue = "surefire")
359 private String tempDir;
360
361
362
363
364
365
366
367
368 @Parameter(property = "jvm")
369 private String jvm;
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387 @Parameter(property = "argLine")
388 private String argLine;
389
390
391
392
393
394
395 @Parameter
396 private Map<String, String> environmentVariables = new HashMap<>();
397
398
399
400
401
402
403 @Parameter(property = "basedir")
404 private File workingDirectory;
405
406
407
408
409
410
411
412
413
414 @Parameter(property = "childDelegation", defaultValue = "false")
415 private boolean childDelegation;
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 @Parameter(property = "groups")
431 private String groups;
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446 @Parameter(property = "excludedGroups")
447 private String excludedGroups;
448
449
450
451
452
453
454 @Parameter(property = "junitArtifactName", defaultValue = "junit:junit")
455 private String junitArtifactName;
456
457
458
459
460
461
462 @Parameter(property = "testNGArtifactName", defaultValue = "org.testng:testng")
463 private String testNGArtifactName;
464
465
466
467
468
469
470
471 @Parameter(property = "threadCount")
472 private int threadCount;
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489 @Parameter(property = "forkCount", defaultValue = "1")
490 private String forkCount;
491
492
493
494
495
496
497
498 @Parameter(property = "reuseForks", defaultValue = "true")
499 private boolean reuseForks;
500
501
502
503
504
505
506
507 @Parameter(property = "perCoreThreadCount", defaultValue = "true")
508 private boolean perCoreThreadCount;
509
510
511
512
513
514
515
516
517 @Parameter(property = "useUnlimitedThreads", defaultValue = "false")
518 private boolean useUnlimitedThreads;
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543 @Parameter(property = "parallel")
544 private String parallel;
545
546
547
548
549
550
551
552
553
554 @Parameter(property = "parallelOptimized", defaultValue = "true")
555 private boolean parallelOptimized;
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573 @Parameter(property = "threadCountSuites", defaultValue = "0")
574 private int threadCountSuites;
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596 @Parameter(property = "threadCountClasses", defaultValue = "0")
597 private int threadCountClasses;
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618 @Parameter(property = "threadCountMethods", defaultValue = "0")
619 private int threadCountMethods;
620
621
622
623
624
625
626 @Parameter(property = "trimStackTrace", defaultValue = "false")
627 private boolean trimStackTrace;
628
629
630
631
632
633
634
635 @Deprecated
636 @Parameter(property = "disableXmlReport", defaultValue = "false")
637 private boolean disableXmlReport;
638
639
640
641
642
643
644
645 @Parameter(property = "enableAssertions", defaultValue = "true")
646 private boolean enableAssertions;
647
648
649
650
651 @Parameter(defaultValue = "${session}", required = true, readonly = true)
652 private MavenSession session;
653
654 @Component
655 private Logger logger;
656
657
658
659
660
661
662 @Parameter(property = "objectFactory")
663 private String objectFactory;
664
665
666
667
668 @Parameter(defaultValue = "${session.parallel}", readonly = true)
669 private Boolean parallelMavenExecution;
670
671
672
673
674
675 @Parameter(defaultValue = "${project.build.directory}", readonly = true, required = true)
676 private File projectBuildDirectory;
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706 @Parameter(property = "dependenciesToScan")
707 private String[] dependenciesToScan;
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742 @Parameter
743 private Map<String, String> jdkToolchain;
744
745
746
747
748 @Component
749 private ToolchainManager toolchainManager;
750
751 @Component
752 private LocationManager locationManager;
753
754 @Component
755 private ProviderDetector providerDetector;
756
757 private Toolchain toolchain;
758
759 private int effectiveForkCount = -1;
760
761 protected abstract String getPluginName();
762
763 protected abstract int getRerunFailingTestsCount();
764
765 @Override
766 public abstract List<String> getIncludes();
767
768 public abstract File getIncludesFile();
769
770 @Override
771 public abstract void setIncludes(List<String> includes);
772
773 public abstract File getExcludesFile();
774
775
776
777
778
779
780
781 protected abstract List<File> suiteXmlFiles();
782
783
784
785
786 protected abstract boolean hasSuiteXmlFiles();
787
788 protected abstract String[] getExcludedEnvironmentVariables();
789
790 public abstract File[] getSuiteXmlFiles();
791
792 public abstract void setSuiteXmlFiles(File[] suiteXmlFiles);
793
794 public abstract String getRunOrder();
795
796 public abstract void setRunOrder(String runOrder);
797
798 public abstract Long getRunOrderRandomSeed();
799
800 public abstract void setRunOrderRandomSeed(Long runOrderRandomSeed);
801
802 protected abstract void handleSummary(RunResult summary, Exception firstForkException)
803 throws MojoExecutionException, MojoFailureException;
804
805 protected abstract boolean isSkipExecution();
806
807 protected abstract String[] getDefaultIncludes();
808
809 protected abstract String getReportSchemaLocation();
810
811 protected abstract boolean useModulePath();
812
813 protected abstract void setUseModulePath(boolean useModulePath);
814
815 protected abstract String getEnableProcessChecker();
816
817 protected abstract ForkNodeFactory getForkNode();
818
819
820
821
822
823
824 protected Artifact getMojoArtifact() {
825 return getPluginDescriptor().getPluginArtifact();
826 }
827
828 private String getDefaultExcludes() {
829 return "**/*$*";
830 }
831
832 @Component(role = SurefireDependencyResolver.class)
833 private SurefireDependencyResolver surefireDependencyResolver;
834
835 private TestListResolver specificTests;
836
837 private TestListResolver includedExcludedTests;
838
839 private List<CommandLineOption> cli;
840
841 private volatile PluginConsoleLogger consoleLogger;
842
843 @Override
844 public void execute() throws MojoExecutionException, MojoFailureException {
845 cli = commandLineOptions();
846
847 setupStuff();
848 Platform platform = PLATFORM.withJdkExecAttributesForTests(getEffectiveJvm());
849 Thread shutdownThread = new Thread(platform::setShutdownState);
850 addShutDownHook(shutdownThread);
851 try {
852 if (verifyParameters() && !hasExecutedBefore()) {
853 DefaultScanResult scan = scanForTestClasses();
854 if (!hasSuiteXmlFiles() && scan.isEmpty()) {
855 switch (getEffectiveFailIfNoTests()) {
856 case COULD_NOT_RUN_DEFAULT_TESTS:
857 throw new MojoFailureException(
858 "No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)");
859 case COULD_NOT_RUN_SPECIFIED_TESTS:
860 throw new MojoFailureException("No tests matching pattern \""
861 + getSpecificTests().toString()
862 + "\" were executed! (Set "
863 + "-D" + getPluginName()
864 + ".failIfNoSpecifiedTests=false to ignore this error.)");
865 default:
866 handleSummary(noTestsRun(), null);
867 return;
868 }
869 }
870 logReportsDirectory();
871 executeAfterPreconditionsChecked(scan, platform);
872 }
873 } finally {
874 platform.clearShutdownState();
875 removeShutdownHook(shutdownThread);
876 }
877 }
878
879 void setLogger(Logger logger) {
880 this.logger = logger;
881 }
882
883 void setSurefireDependencyResolver(SurefireDependencyResolver surefireDependencyResolver) {
884 this.surefireDependencyResolver = surefireDependencyResolver;
885 }
886
887 @Nonnull
888 protected final PluginConsoleLogger getConsoleLogger() {
889 if (consoleLogger == null) {
890 synchronized (this) {
891 if (consoleLogger == null) {
892 consoleLogger = new PluginConsoleLogger(logger);
893 }
894 }
895 }
896 return consoleLogger;
897 }
898
899 private static <T extends ToolchainManager> Toolchain getToolchainMaven33x(
900 Class<T> toolchainManagerType, T toolchainManager, MavenSession session, Map<String, String> toolchainArgs)
901 throws MojoFailureException {
902 Method getToolchainsMethod =
903 tryGetMethod(toolchainManagerType, "getToolchains", MavenSession.class, String.class, Map.class);
904 if (getToolchainsMethod != null) {
905
906 List<Toolchain> tcs =
907 invokeMethodWithArray(toolchainManager, getToolchainsMethod, session, "jdk", toolchainArgs);
908 if (tcs.isEmpty()) {
909 throw new MojoFailureException(
910 "Requested toolchain specification did not match any configured toolchain: " + toolchainArgs);
911 }
912 return tcs.get(0);
913 }
914 return null;
915 }
916
917
918
919 private Toolchain getToolchain() throws MojoFailureException {
920 Toolchain tc = null;
921
922 if (getJdkToolchain() != null) {
923 tc = getToolchainMaven33x(ToolchainManager.class, getToolchainManager(), getSession(), getJdkToolchain());
924 }
925
926 if (tc == null) {
927 tc = getToolchainManager().getToolchainFromBuildContext("jdk", getSession());
928 }
929
930 return tc;
931 }
932
933 private void setupStuff() throws MojoFailureException {
934
935 if (getBooterArtifact() == null) {
936 throw new RuntimeException("Unable to locate surefire-booter in the list of plugin artifacts");
937 }
938
939 if (getToolchainManager() != null) {
940 toolchain = getToolchain();
941 }
942 }
943
944 @Nonnull
945 private DefaultScanResult scanForTestClasses() throws MojoFailureException {
946 DefaultScanResult scan = scanDirectories();
947 DefaultScanResult scanDeps = scanDependencies();
948 return scan.append(scanDeps);
949 }
950
951 private DefaultScanResult scanDirectories() throws MojoFailureException {
952 DirectoryScanner scanner = new DirectoryScanner(getTestClassesDirectory(), getIncludedAndExcludedTests());
953 return scanner.scan();
954 }
955
956 List<Artifact> getProjectTestArtifacts() {
957 return project.getTestArtifacts();
958 }
959
960 DefaultScanResult scanDependencies() throws MojoFailureException {
961 if (getDependenciesToScan() == null) {
962 return null;
963 } else {
964 try {
965 DefaultScanResult result = null;
966
967 List<Artifact> dependenciesToScan = filter(getProjectTestArtifacts(), asList(getDependenciesToScan()));
968
969 for (Artifact artifact : dependenciesToScan) {
970 String type = artifact.getType();
971 File out = artifact.getFile();
972 if (out == null
973 || !out.exists()
974 || !("jar".equals(type)
975 || out.isDirectory()
976 || out.getName().endsWith(".jar"))) {
977 continue;
978 }
979
980 if (out.isFile()) {
981 DependencyScanner scanner =
982 new DependencyScanner(singletonList(out), getIncludedAndExcludedTests());
983 result = result == null ? scanner.scan() : result.append(scanner.scan());
984 } else if (out.isDirectory()) {
985 DirectoryScanner scanner = new DirectoryScanner(out, getIncludedAndExcludedTests());
986 result = result == null ? scanner.scan() : result.append(scanner.scan());
987 }
988 }
989
990 return result;
991 } catch (Exception e) {
992 throw new MojoFailureException(e.getLocalizedMessage(), e);
993 }
994 }
995 }
996
997 boolean verifyParameters() throws MojoFailureException, MojoExecutionException {
998 setProperties(new SurefireProperties(getProperties()));
999 if (isSkipExecution()) {
1000 getConsoleLogger().info("Tests are skipped.");
1001 return false;
1002 }
1003
1004 String jvmToUse = getJvm();
1005 if (toolchain != null) {
1006 getConsoleLogger().info("Toolchain in maven-" + getPluginName() + "-plugin: " + toolchain);
1007 if (jvmToUse != null) {
1008 getConsoleLogger().warning("Toolchains are ignored, 'jvm' parameter is set to " + jvmToUse);
1009 }
1010 }
1011
1012 if (!getTestClassesDirectory().exists()
1013 && (getDependenciesToScan() == null || getDependenciesToScan().length == 0)) {
1014 if (getFailIfNoTests()) {
1015 throw new MojoFailureException("No tests to run!");
1016 }
1017 getConsoleLogger().info("No tests to run.");
1018 } else {
1019 ensureEnableProcessChecker();
1020 ensureWorkingDirectoryExists();
1021 ensureParallelRunningCompatibility();
1022 warnIfUselessUseSystemClassLoaderParameter();
1023 warnIfDefunctGroupsCombinations();
1024 warnIfRerunClashes();
1025 warnIfWrongShutdownValue();
1026 warnIfNotApplicableSkipAfterFailureCount();
1027 warnIfIllegalTempDir();
1028 warnIfForkCountIsZero();
1029 warnIfIllegalFailOnFlakeCount();
1030 printDefaultSeedIfNecessary();
1031 }
1032 return true;
1033 }
1034
1035 private void warnIfForkCountIsZero() {
1036 if ("0".equals(getForkCount())) {
1037 getConsoleLogger()
1038 .warning("The parameter forkCount should likely not be 0. Forking a JVM for tests "
1039 + "improves test accuracy. Ensure to have a <forkCount> >= 1.");
1040 }
1041 }
1042
1043 private void executeAfterPreconditionsChecked(@Nonnull DefaultScanResult scanResult, @Nonnull Platform platform)
1044 throws MojoExecutionException, MojoFailureException {
1045 TestClassPath testClasspath = generateTestClasspath();
1046 List<ProviderInfo> providers = createProviders(testClasspath);
1047 ResolvePathResultWrapper wrapper =
1048 findModuleDescriptor(platform.getJdkExecAttributesForTests().getJdkHome());
1049
1050 RunResult current = noTestsRun();
1051
1052 Exception firstForkException = null;
1053 for (ProviderInfo provider : providers) {
1054 try {
1055 current = current.aggregate(executeProvider(provider, scanResult, testClasspath, platform, wrapper));
1056 } catch (SurefireBooterForkException | SurefireExecutionException | TestSetFailedException e) {
1057 if (firstForkException == null) {
1058 firstForkException = e;
1059 }
1060 }
1061 }
1062
1063 if (firstForkException != null) {
1064 current = failure(current, firstForkException);
1065 }
1066
1067 handleSummary(current, firstForkException);
1068 }
1069
1070 protected List<ProviderInfo> createProviders(TestClassPath testClasspath) throws MojoExecutionException {
1071 Artifact junitDepArtifact = getJunitDepArtifact();
1072 return providerDetector.resolve(
1073 new DynamicProviderInfo(null),
1074 new JUnitPlatformProviderInfo(getJUnitPlatformRunnerArtifact(), getJUnit5Artifact(), testClasspath),
1075 new TestNgProviderInfo(getTestNgArtifact()),
1076 new JUnitCoreProviderInfo(getJunitArtifact(), junitDepArtifact),
1077 new JUnit4ProviderInfo(getJunitArtifact(), junitDepArtifact),
1078 new JUnit3ProviderInfo());
1079 }
1080
1081 private SurefireProperties setupProperties() {
1082 SurefireProperties sysProps = null;
1083 try {
1084 sysProps = SurefireProperties.loadProperties(getSystemPropertiesFile());
1085 } catch (IOException e) {
1086 String msg = "The file '" + getSystemPropertiesFile().getAbsolutePath() + "' can't be read.";
1087 if (getConsoleLogger().isDebugEnabled()) {
1088 getConsoleLogger().debug(msg, e);
1089 } else {
1090 getConsoleLogger().warning(msg);
1091 }
1092 }
1093
1094 SurefireProperties result = SurefireProperties.calculateEffectiveProperties(
1095 getSystemProperties(), getSystemPropertyVariables(), getUserProperties(), sysProps);
1096
1097 result.setProperty("basedir", getBasedir().getAbsolutePath());
1098 result.setProperty("localRepository", getLocalRepositoryPath());
1099 if (isForking()) {
1100 for (Object o : result.propertiesThatCannotBeSetASystemProperties()) {
1101 if (getArgLine() == null || !getArgLine().contains("-D" + o + "=")) {
1102 getConsoleLogger()
1103 .warning(o + " cannot be set as system property, use <argLine>-D" + o
1104 + "=...</argLine> instead");
1105 }
1106 }
1107 for (Object systemPropertyMatchingArgLine : systemPropertiesMatchingArgLine(result)) {
1108 getConsoleLogger()
1109 .warning("The system property "
1110 + systemPropertyMatchingArgLine
1111 + " is configured twice! "
1112 + "The property appears in <argLine/> and any of <systemPropertyVariables/>, "
1113 + "<systemProperties/> or user property.");
1114 }
1115 } else {
1116 result.setProperty("user.dir", getWorkingDirectory().getAbsolutePath());
1117 }
1118
1119 if (getConsoleLogger().isDebugEnabled()) {
1120 showToLog(result, getConsoleLogger());
1121 }
1122
1123 return result;
1124 }
1125
1126 private Set<Object> systemPropertiesMatchingArgLine(SurefireProperties result) {
1127 Set<Object> intersection = new HashSet<>();
1128 if (isNotBlank(getArgLine())) {
1129 for (Object systemProperty : result.getStringKeySet()) {
1130 if (getArgLine().contains("-D" + systemProperty + "=")) {
1131 intersection.add(systemProperty);
1132 }
1133 }
1134
1135 Set<Object> ignored = result.propertiesThatCannotBeSetASystemProperties();
1136 intersection.removeAll(ignored);
1137 }
1138 return intersection;
1139 }
1140
1141 private void showToLog(SurefireProperties props, ConsoleLogger log) {
1142 for (Object key : props.getStringKeySet()) {
1143 String value = props.getProperty((String) key);
1144 log.debug("Setting system property [" + key + "]=[" + value + "]");
1145 }
1146 }
1147
1148 @Nonnull
1149 private RunResult executeProvider(
1150 @Nonnull ProviderInfo provider,
1151 @Nonnull DefaultScanResult scanResult,
1152 @Nonnull TestClassPath testClasspathWrapper,
1153 @Nonnull Platform platform,
1154 @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult)
1155 throws MojoExecutionException, MojoFailureException, SurefireExecutionException,
1156 SurefireBooterForkException, TestSetFailedException {
1157 getConsoleLogger().debug("Using the provider " + provider.getProviderName());
1158 SurefireProperties effectiveProperties = setupProperties();
1159 ClassLoaderConfiguration classLoaderConfiguration = getClassLoaderConfiguration();
1160 provider.addProviderProperties();
1161 RunOrderParameters runOrderParameters =
1162 new RunOrderParameters(getRunOrder(), getStatisticsFile(getConfigChecksum()), getRunOrderRandomSeed());
1163
1164 if (isNotForking()) {
1165 Properties originalSystemProperties =
1166 (Properties) System.getProperties().clone();
1167 try {
1168 createCopyAndReplaceForkNumPlaceholder(effectiveProperties, 1).copyToSystemProperties();
1169
1170 InPluginVMSurefireStarter surefireStarter = createInprocessStarter(
1171 provider,
1172 classLoaderConfiguration,
1173 runOrderParameters,
1174 scanResult,
1175 platform,
1176 testClasspathWrapper);
1177 return surefireStarter.runSuitesInProcess(scanResult);
1178 } finally {
1179 System.setProperties(originalSystemProperties);
1180 }
1181 } else {
1182 ForkConfiguration forkConfiguration = createForkConfiguration(platform, resolvedJavaModularityResult);
1183 if (getConsoleLogger().isDebugEnabled()) {
1184 showMap(getEnvironmentVariables(), "environment variable");
1185 showArray(getExcludedEnvironmentVariables(), "excluded environment variable");
1186 }
1187
1188 Properties originalSystemProperties =
1189 (Properties) System.getProperties().clone();
1190 ForkStarter forkStarter = null;
1191 try {
1192 forkStarter = createForkStarter(
1193 provider,
1194 forkConfiguration,
1195 classLoaderConfiguration,
1196 runOrderParameters,
1197 getConsoleLogger(),
1198 scanResult,
1199 testClasspathWrapper,
1200 platform,
1201 resolvedJavaModularityResult);
1202
1203 return forkStarter.run(effectiveProperties, scanResult);
1204 } catch (SurefireBooterForkException e) {
1205 forkStarter.killOrphanForks();
1206 throw e;
1207 } finally {
1208 System.setProperties(originalSystemProperties);
1209 cleanupForkConfiguration(forkConfiguration);
1210 }
1211 }
1212 }
1213
1214 public static SurefireProperties createCopyAndReplaceForkNumPlaceholder(
1215 SurefireProperties effectiveSystemProperties, int threadNumber) {
1216 SurefireProperties filteredProperties = new SurefireProperties((KeyValueSource) effectiveSystemProperties);
1217 for (Entry<Object, Object> entry : effectiveSystemProperties.entrySet()) {
1218 if (entry.getValue() instanceof String) {
1219 String value = (String) entry.getValue();
1220 filteredProperties.put(entry.getKey(), replaceThreadNumberPlaceholders(value, threadNumber));
1221 }
1222 }
1223 return filteredProperties;
1224 }
1225
1226 protected void cleanupForkConfiguration(ForkConfiguration forkConfiguration) {
1227 if (!getConsoleLogger().isDebugEnabled() && forkConfiguration != null) {
1228 File tempDirectory = forkConfiguration.getTempDirectory();
1229 try {
1230 FileUtils.deleteDirectory(tempDirectory);
1231 } catch (IOException e) {
1232 getConsoleLogger()
1233 .warning("Could not delete temp directory " + tempDirectory + " because " + e.getMessage());
1234 }
1235 }
1236 }
1237
1238 protected void logReportsDirectory() {
1239 logDebugOrCliShowErrors(capitalizeFirstLetter(getPluginName()) + " report directory: " + getReportsDirectory());
1240 }
1241
1242 private boolean existsModuleDescriptor(ResolvePathResultWrapper resolvedJavaModularityResult) {
1243 return resolvedJavaModularityResult.getResolvePathResult() != null;
1244 }
1245
1246 private ResolvePathResultWrapper findModuleDescriptor(File jdkHome) {
1247 ResolvePathResultWrapper test = findModuleDescriptor(jdkHome, getTestClassesDirectory(), false);
1248 return test.getResolvePathResult() == null ? findModuleDescriptor(jdkHome, getMainBuildPath(), true) : test;
1249 }
1250
1251 private ResolvePathResultWrapper findModuleDescriptor(File jdkHome, File buildPath, boolean isMainDescriptor) {
1252 boolean isJpmsModule =
1253 buildPath.isDirectory() ? new File(buildPath, "module-info.class").exists() : isModule(buildPath);
1254
1255 if (!isJpmsModule) {
1256 return new ResolvePathResultWrapper(null, isMainDescriptor);
1257 }
1258
1259 try {
1260 ResolvePathRequest<?> request = ResolvePathRequest.ofFile(buildPath).setJdkHome(jdkHome);
1261 ResolvePathResult result = getLocationManager().resolvePath(request);
1262 boolean isEmpty = result.getModuleNameSource() == null;
1263 return new ResolvePathResultWrapper(isEmpty ? null : result, isMainDescriptor);
1264 } catch (Exception e) {
1265 return new ResolvePathResultWrapper(null, isMainDescriptor);
1266 }
1267 }
1268
1269 private static boolean isModule(File jar) {
1270 try (ZipFile zip = new ZipFile(jar)) {
1271 return zip.getEntry("module-info.class") != null;
1272 } catch (IOException e) {
1273 return false;
1274 }
1275 }
1276
1277 private boolean canExecuteProviderWithModularPath(
1278 @Nonnull Platform platform, @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult) {
1279 return useModulePath()
1280 && platform.getJdkExecAttributesForTests().isJava9AtLeast()
1281 && existsModuleDescriptor(resolvedJavaModularityResult);
1282 }
1283
1284
1285
1286
1287
1288 private void convertTestNGParameters() throws MojoExecutionException {
1289 if (this.getParallel() != null) {
1290 getProperties().setProperty(ProviderParameterNames.PARALLEL_PROP, this.getParallel());
1291 }
1292 convertGroupParameters();
1293
1294 if (this.getThreadCount() > 0) {
1295 getProperties()
1296 .setProperty(ProviderParameterNames.THREADCOUNT_PROP, Integer.toString(this.getThreadCount()));
1297 }
1298 if (this.getObjectFactory() != null) {
1299 getProperties().setProperty("objectfactory", this.getObjectFactory());
1300 }
1301 if (this.getTestClassesDirectory() != null) {
1302 getProperties()
1303 .setProperty(
1304 "testng.test.classpath", getTestClassesDirectory().getAbsolutePath());
1305 }
1306
1307 Artifact testNgArtifact = getTestNgArtifact();
1308 if (testNgArtifact != null) {
1309 DefaultArtifactVersion defaultArtifactVersion = new DefaultArtifactVersion(testNgArtifact.getVersion());
1310 getProperties()
1311 .setProperty(
1312 "testng.configurator", getConfiguratorName(defaultArtifactVersion, getConsoleLogger()));
1313 }
1314 }
1315
1316 private static String getConfiguratorName(ArtifactVersion version, PluginConsoleLogger log)
1317 throws MojoExecutionException {
1318 try {
1319 VersionRange range = VersionRange.createFromVersionSpec("[4.7,5.2)");
1320 if (range.containsVersion(version)) {
1321 return "org.apache.maven.surefire.testng.conf.TestNG4751Configurator";
1322 }
1323 range = VersionRange.createFromVersionSpec("[5.2,5.3)");
1324 if (range.containsVersion(version)) {
1325 return "org.apache.maven.surefire.testng.conf.TestNG52Configurator";
1326 }
1327 range = VersionRange.createFromVersionSpec("[5.3,5.10)");
1328 if (range.containsVersion(version)) {
1329 return "org.apache.maven.surefire.testng.conf.TestNGMapConfigurator";
1330 }
1331 range = VersionRange.createFromVersionSpec("[5.10,5.13)");
1332 if (range.containsVersion(version)) {
1333 return "org.apache.maven.surefire.testng.conf.TestNG510Configurator";
1334 }
1335 range = VersionRange.createFromVersionSpec("[5.13,5.14.1)");
1336 if (range.containsVersion(version)) {
1337 return "org.apache.maven.surefire.testng.conf.TestNG513Configurator";
1338 }
1339 range = VersionRange.createFromVersionSpec("[5.14.1,5.14.3)");
1340 if (range.containsVersion(version)) {
1341 log.warning("The 'reporter' or 'listener' may not work properly in TestNG 5.14.1 and 5.14.2.");
1342 return "org.apache.maven.surefire.testng.conf.TestNG5141Configurator";
1343 }
1344 range = VersionRange.createFromVersionSpec("[5.14.3,6.0)");
1345 if (range.containsVersion(version)) {
1346 if (version.equals(new DefaultArtifactVersion("[5.14.3,5.14.5]"))) {
1347 throw new MojoExecutionException("TestNG 5.14.3-5.14.5 is not supported. "
1348 + "System dependency org.testng:guice missed path.");
1349 }
1350 return "org.apache.maven.surefire.testng.conf.TestNG5143Configurator";
1351 }
1352 range = VersionRange.createFromVersionSpec("[6.0,7.4.0)");
1353 if (range.containsVersion(version)) {
1354 return "org.apache.maven.surefire.testng.conf.TestNG60Configurator";
1355 }
1356 range = VersionRange.createFromVersionSpec("[7.4.0,)");
1357 if (range.containsVersion(version)) {
1358 return "org.apache.maven.surefire.testng.conf.TestNG740Configurator";
1359 }
1360
1361 throw new MojoExecutionException("Unknown TestNG version " + version);
1362 } catch (InvalidVersionSpecificationException invsex) {
1363 throw new MojoExecutionException("Bug in plugin. Please report it with the attached stacktrace", invsex);
1364 }
1365 }
1366
1367 private void convertGroupParameters() {
1368 if (this.getExcludedGroups() != null) {
1369 getProperties().setProperty(ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP, this.getExcludedGroups());
1370 }
1371 if (this.getGroups() != null) {
1372 getProperties().setProperty(ProviderParameterNames.TESTNG_GROUPS_PROP, this.getGroups());
1373 }
1374 }
1375
1376 private void convertJunitEngineParameters() {
1377 if (getIncludeJUnit5Engines() != null && getIncludeJUnit5Engines().length != 0) {
1378 getProperties().setProperty(INCLUDE_JUNIT5_ENGINES_PROP, join(getIncludeJUnit5Engines()));
1379 }
1380
1381 if (getExcludeJUnit5Engines() != null && getExcludeJUnit5Engines().length != 0) {
1382 getProperties().setProperty(EXCLUDE_JUNIT5_ENGINES_PROP, join(getExcludeJUnit5Engines()));
1383 }
1384 }
1385
1386 private static String join(String[] array) {
1387 StringBuilder stringBuilder = new StringBuilder();
1388 for (int i = 0, length = array.length; i < length; i++) {
1389 stringBuilder.append(array[i]);
1390 if (i < length - 1) {
1391 stringBuilder.append(',');
1392 }
1393 }
1394 return stringBuilder.toString();
1395 }
1396
1397 protected boolean isAnyConcurrencySelected() {
1398 return getParallel() != null && !getParallel().trim().isEmpty();
1399 }
1400
1401 protected boolean isAnyGroupsSelected() {
1402 return this.getGroups() != null || this.getExcludedGroups() != null;
1403 }
1404
1405
1406
1407
1408
1409 private void convertJunitCoreParameters() throws MojoExecutionException {
1410 checkThreadCountEntity(getThreadCountSuites(), "suites");
1411 checkThreadCountEntity(getThreadCountClasses(), "classes");
1412 checkThreadCountEntity(getThreadCountMethods(), "methods");
1413
1414 String usedParallel = (getParallel() != null) ? getParallel() : "none";
1415
1416 if (!"none".equals(usedParallel)) {
1417 checkNonForkedThreads(parallel);
1418 }
1419
1420 getProperties().setProperty(ProviderParameterNames.PARALLEL_PROP, usedParallel);
1421 if (this.getThreadCount() > 0) {
1422 getProperties().setProperty(ProviderParameterNames.THREADCOUNT_PROP, Integer.toString(getThreadCount()));
1423 }
1424 getProperties().setProperty("perCoreThreadCount", Boolean.toString(getPerCoreThreadCount()));
1425 getProperties().setProperty("useUnlimitedThreads", Boolean.toString(getUseUnlimitedThreads()));
1426 getProperties()
1427 .setProperty(ProviderParameterNames.THREADCOUNTSUITES_PROP, Integer.toString(getThreadCountSuites()));
1428 getProperties()
1429 .setProperty(ProviderParameterNames.THREADCOUNTCLASSES_PROP, Integer.toString(getThreadCountClasses()));
1430 getProperties()
1431 .setProperty(ProviderParameterNames.THREADCOUNTMETHODS_PROP, Integer.toString(getThreadCountMethods()));
1432 getProperties()
1433 .setProperty(
1434 ProviderParameterNames.PARALLEL_TIMEOUT_PROP,
1435 Double.toString(getParallelTestsTimeoutInSeconds()));
1436 getProperties()
1437 .setProperty(
1438 ProviderParameterNames.PARALLEL_TIMEOUTFORCED_PROP,
1439 Double.toString(getParallelTestsTimeoutForcedInSeconds()));
1440 getProperties()
1441 .setProperty(ProviderParameterNames.PARALLEL_OPTIMIZE_PROP, Boolean.toString(isParallelOptimized()));
1442
1443 String message = "parallel='" + usedParallel + '\''
1444 + ", perCoreThreadCount=" + getPerCoreThreadCount()
1445 + ", threadCount=" + getThreadCount()
1446 + ", useUnlimitedThreads=" + getUseUnlimitedThreads()
1447 + ", threadCountSuites=" + getThreadCountSuites()
1448 + ", threadCountClasses=" + getThreadCountClasses()
1449 + ", threadCountMethods=" + getThreadCountMethods()
1450 + ", parallelOptimized=" + isParallelOptimized();
1451
1452 logDebugOrCliShowErrors(message);
1453 }
1454
1455 private void checkNonForkedThreads(String parallel) throws MojoExecutionException {
1456 if ("suites".equals(parallel)) {
1457 if (!(getUseUnlimitedThreads() || getThreadCount() > 0 ^ getThreadCountSuites() > 0)) {
1458 throw new MojoExecutionException(
1459 "Use threadCount or threadCountSuites > 0 or useUnlimitedThreads=true for parallel='suites'");
1460 }
1461 setThreadCountClasses(0);
1462 setThreadCountMethods(0);
1463 } else if ("classes".equals(parallel)) {
1464 if (!(getUseUnlimitedThreads() || getThreadCount() > 0 ^ getThreadCountClasses() > 0)) {
1465 throw new MojoExecutionException(
1466 "Use threadCount or threadCountClasses > 0 or useUnlimitedThreads=true for parallel='classes'");
1467 }
1468 setThreadCountSuites(0);
1469 setThreadCountMethods(0);
1470 } else if ("methods".equals(parallel)) {
1471 if (!(getUseUnlimitedThreads() || getThreadCount() > 0 ^ getThreadCountMethods() > 0)) {
1472 throw new MojoExecutionException(
1473 "Use threadCount or threadCountMethods > 0 or useUnlimitedThreads=true for parallel='methods'");
1474 }
1475 setThreadCountSuites(0);
1476 setThreadCountClasses(0);
1477 } else if ("suitesAndClasses".equals(parallel)) {
1478 if (!(getUseUnlimitedThreads()
1479 || onlyThreadCount()
1480 || getThreadCountSuites() > 0
1481 && getThreadCountClasses() > 0
1482 && getThreadCount() == 0
1483 && getThreadCountMethods() == 0
1484 || getThreadCount() > 0
1485 && getThreadCountSuites() > 0
1486 && getThreadCountClasses() > 0
1487 && getThreadCountMethods() == 0
1488 || getThreadCount() > 0
1489 && getThreadCountSuites() > 0
1490 && getThreadCount() > getThreadCountSuites()
1491 && getThreadCountClasses() == 0
1492 && getThreadCountMethods() == 0)) {
1493 throw new MojoExecutionException("Use useUnlimitedThreads=true, "
1494 + "or only threadCount > 0, "
1495 + "or (threadCountSuites > 0 and threadCountClasses > 0), "
1496 + "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0) "
1497 + "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) "
1498 + "for parallel='suitesAndClasses' or 'both'");
1499 }
1500 setThreadCountMethods(0);
1501 } else if ("suitesAndMethods".equals(parallel)) {
1502 if (!(getUseUnlimitedThreads()
1503 || onlyThreadCount()
1504 || getThreadCountSuites() > 0
1505 && getThreadCountMethods() > 0
1506 && getThreadCount() == 0
1507 && getThreadCountClasses() == 0
1508 || getThreadCount() > 0
1509 && getThreadCountSuites() > 0
1510 && getThreadCountMethods() > 0
1511 && getThreadCountClasses() == 0
1512 || getThreadCount() > 0
1513 && getThreadCountSuites() > 0
1514 && getThreadCount() > getThreadCountSuites()
1515 && getThreadCountClasses() == 0
1516 && getThreadCountMethods() == 0)) {
1517 throw new MojoExecutionException("Use useUnlimitedThreads=true, "
1518 + "or only threadCount > 0, "
1519 + "or (threadCountSuites > 0 and threadCountMethods > 0), "
1520 + "or (threadCount > 0 and threadCountSuites > 0 and threadCountMethods > 0), "
1521 + "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) "
1522 + "for parallel='suitesAndMethods'");
1523 }
1524 setThreadCountClasses(0);
1525 } else if ("both".equals(parallel) || "classesAndMethods".equals(parallel)) {
1526 if (!(getUseUnlimitedThreads()
1527 || onlyThreadCount()
1528 || getThreadCountClasses() > 0
1529 && getThreadCountMethods() > 0
1530 && getThreadCount() == 0
1531 && getThreadCountSuites() == 0
1532 || getThreadCount() > 0
1533 && getThreadCountClasses() > 0
1534 && getThreadCountMethods() > 0
1535 && getThreadCountSuites() == 0
1536 || getThreadCount() > 0
1537 && getThreadCountClasses() > 0
1538 && getThreadCount() > getThreadCountClasses()
1539 && getThreadCountSuites() == 0
1540 && getThreadCountMethods() == 0)) {
1541 throw new MojoExecutionException("Use useUnlimitedThreads=true, "
1542 + "or only threadCount > 0, "
1543 + "or (threadCountClasses > 0 and threadCountMethods > 0), "
1544 + "or (threadCount > 0 and threadCountClasses > 0 and threadCountMethods > 0), "
1545 + "or (threadCount > 0 and threadCountClasses > 0 and threadCount > threadCountClasses) "
1546 + "for parallel='both' or parallel='classesAndMethods'");
1547 }
1548 setThreadCountSuites(0);
1549 } else if ("all".equals(parallel)) {
1550 if (!(getUseUnlimitedThreads()
1551 || onlyThreadCount()
1552 || getThreadCountSuites() > 0 && getThreadCountClasses() > 0 && getThreadCountMethods() > 0
1553 || getThreadCount() > 0
1554 && getThreadCountSuites() > 0
1555 && getThreadCountClasses() > 0
1556 && getThreadCountMethods() == 0
1557 && getThreadCount() > (getThreadCountSuites() + getThreadCountClasses()))) {
1558 throw new MojoExecutionException("Use useUnlimitedThreads=true, "
1559 + "or only threadCount > 0, "
1560 + "or (threadCountSuites > 0 and threadCountClasses > 0 and threadCountMethods > 0), "
1561 + "or every thread-count is specified, "
1562 + "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0 "
1563 + "and threadCount > threadCountSuites + threadCountClasses) "
1564 + "for parallel='all'");
1565 }
1566 } else {
1567 throw new MojoExecutionException("Illegal parallel='" + parallel + "'");
1568 }
1569 }
1570
1571 private boolean onlyThreadCount() {
1572 return getThreadCount() > 0
1573 && getThreadCountSuites() == 0
1574 && getThreadCountClasses() == 0
1575 && getThreadCountMethods() == 0;
1576 }
1577
1578 private static void checkThreadCountEntity(int count, String entity) throws MojoExecutionException {
1579 if (count < 0) {
1580 throw new MojoExecutionException("parallel maven execution does not allow negative thread-count" + entity);
1581 }
1582 }
1583
1584 private boolean isJunit47Compatible(Artifact artifact) {
1585 return isWithinVersionSpec(artifact, "[4.7,)");
1586 }
1587
1588 private boolean isAnyJunit4(Artifact artifact) {
1589 return isWithinVersionSpec(artifact, "[4.0,)");
1590 }
1591
1592 protected boolean isForking() {
1593 return 0 < getEffectiveForkCount();
1594 }
1595
1596 private List<RunOrder> getRunOrders() {
1597 String runOrderString = getRunOrder();
1598 RunOrder[] runOrder = runOrderString == null ? RunOrder.DEFAULT : RunOrder.valueOfMulti(runOrderString);
1599 return asList(runOrder);
1600 }
1601
1602 private boolean requiresRunHistory() {
1603 final List<RunOrder> runOrders = getRunOrders();
1604 return runOrders.contains(RunOrder.BALANCED) || runOrders.contains(RunOrder.FAILEDFIRST);
1605 }
1606
1607 private PluginFailureReason getEffectiveFailIfNoTests() {
1608 if (isSpecificTestSpecified()) {
1609 return getFailIfNoSpecifiedTests() ? COULD_NOT_RUN_SPECIFIED_TESTS : NONE;
1610 } else {
1611 return getFailIfNoTests() ? COULD_NOT_RUN_DEFAULT_TESTS : NONE;
1612 }
1613 }
1614
1615 private ProviderConfiguration createProviderConfiguration(RunOrderParameters runOrderParameters)
1616 throws MojoExecutionException, MojoFailureException {
1617 final ReporterConfiguration reporterConfiguration =
1618 new ReporterConfiguration(getReportsDirectory(), isTrimStackTrace());
1619
1620 final Artifact testNgArtifact = getTestNgArtifact();
1621 final boolean isTestNg = testNgArtifact != null;
1622 final TestArtifactInfo testNg =
1623 isTestNg ? new TestArtifactInfo(testNgArtifact.getVersion(), testNgArtifact.getClassifier()) : null;
1624 final TestRequest testSuiteDefinition = new TestRequest(
1625 suiteXmlFiles(), getTestSourceDirectory(), getSpecificTests(), getRerunFailingTestsCount());
1626
1627 final boolean actualFailIfNoTests;
1628 DirectoryScannerParameters directoryScannerParameters = null;
1629 if (hasSuiteXmlFiles() && !isSpecificTestSpecified()) {
1630 actualFailIfNoTests = getFailIfNoTests();
1631 if (!isTestNg) {
1632 throw new MojoExecutionException("suiteXmlFiles is configured, but there is no TestNG dependency");
1633 }
1634 } else {
1635
1636
1637
1638
1639 List<String> actualIncludes = getIncludeList();
1640 List<String> actualExcludes = getExcludeList();
1641
1642 List<String> specificTests = Collections.emptyList();
1643
1644 directoryScannerParameters = new DirectoryScannerParameters(
1645 getTestClassesDirectory(), actualIncludes, actualExcludes, specificTests, getRunOrder());
1646 }
1647
1648 Map<String, String> providerProperties = toStringProperties(getProperties());
1649
1650 return new ProviderConfiguration(
1651 directoryScannerParameters,
1652 runOrderParameters,
1653 reporterConfiguration,
1654 testNg,
1655 testSuiteDefinition,
1656 providerProperties,
1657 null,
1658 false,
1659 cli,
1660 getSkipAfterFailureCount(),
1661 Shutdown.parameterOf(getShutdown()),
1662 getForkedProcessExitTimeoutInSeconds());
1663 }
1664
1665 private static Map<String, String> toStringProperties(Properties properties) {
1666 Map<String, String> h = new ConcurrentHashMap<>(properties.size());
1667 for (Enumeration<?> e = properties.keys(); e.hasMoreElements(); ) {
1668 Object k = e.nextElement();
1669 Object v = properties.get(k);
1670 if (k.getClass() == String.class && v.getClass() == String.class) {
1671 h.put((String) k, (String) v);
1672 }
1673 }
1674 return h;
1675 }
1676
1677 private File getStatisticsFile(String configurationHash) {
1678 return new File(getBasedir(), ".surefire-" + configurationHash);
1679 }
1680
1681 private StartupConfiguration createStartupConfiguration(
1682 @Nonnull ProviderInfo provider,
1683 boolean isForking,
1684 @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
1685 @Nonnull DefaultScanResult scanResult,
1686 @Nonnull TestClassPath testClasspathWrapper,
1687 @Nonnull Platform platform,
1688 @Nonnull ResolvePathResultWrapper resolvedJavaModularity)
1689 throws MojoExecutionException {
1690 try {
1691 if (isForking && canExecuteProviderWithModularPath(platform, resolvedJavaModularity)) {
1692 File jdkHome = platform.getJdkExecAttributesForTests().getJdkHome();
1693 return newStartupConfigWithModularPath(
1694 classLoaderConfiguration,
1695 provider,
1696 resolvedJavaModularity,
1697 scanResult,
1698 jdkHome.getAbsolutePath(),
1699 testClasspathWrapper);
1700 } else {
1701 return newStartupConfigWithClasspath(classLoaderConfiguration, provider, testClasspathWrapper);
1702 }
1703 } catch (IOException e) {
1704 throw new MojoExecutionException(e.getMessage(), e);
1705 }
1706 }
1707
1708 private StartupConfiguration newStartupConfigWithClasspath(
1709 @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
1710 @Nonnull ProviderInfo providerInfo,
1711 @Nonnull TestClassPath testClasspathWrapper)
1712 throws MojoExecutionException {
1713 Classpath testClasspath = testClasspathWrapper.toClasspath();
1714 Set<Artifact> providerArtifacts = providerInfo.getProviderClasspath();
1715 String providerName = providerInfo.getProviderName();
1716 Classpath providerClasspath = classpathCache.getCachedClassPath(providerName);
1717 if (providerClasspath == null) {
1718 providerClasspath = classpathCache.setCachedClasspath(providerName, providerArtifacts);
1719 }
1720
1721 getConsoleLogger().debug(testClasspath.getLogMessage("test classpath:"));
1722 getConsoleLogger().debug(providerClasspath.getLogMessage("provider classpath:"));
1723 getConsoleLogger().debug(testClasspath.getCompactLogMessage("test(compact) classpath:"));
1724 getConsoleLogger().debug(providerClasspath.getCompactLogMessage("provider(compact) classpath:"));
1725
1726 Artifact[] additionalInProcArtifacts = {
1727 getCommonArtifact(),
1728 getBooterArtifact(),
1729 getExtensionsArtifact(),
1730 getApiArtifact(),
1731 getSpiArtifact(),
1732 getLoggerApiArtifact(),
1733 getSurefireSharedUtilsArtifact()
1734 };
1735 Set<Artifact> inProcArtifacts = retainInProcArtifactsUnique(providerArtifacts, additionalInProcArtifacts);
1736 Classpath inProcClasspath = createInProcClasspath(providerClasspath, inProcArtifacts);
1737 getConsoleLogger().debug(inProcClasspath.getLogMessage("in-process classpath:"));
1738 getConsoleLogger().debug(inProcClasspath.getCompactLogMessage("in-process(compact) classpath:"));
1739
1740 ClasspathConfiguration classpathConfiguration = new ClasspathConfiguration(
1741 testClasspath, providerClasspath, inProcClasspath, effectiveIsEnableAssertions(), isChildDelegation());
1742 ProviderRequirements forkRequirements = new ProviderRequirements(false, false, false);
1743 return new StartupConfiguration(
1744 providerName,
1745 classpathConfiguration,
1746 classLoaderConfiguration,
1747 ProcessCheckerType.toEnum(getEnableProcessChecker()),
1748 providerInfo.getJpmsArguments(forkRequirements));
1749 }
1750
1751 private static Set<Artifact> retainInProcArtifactsUnique(
1752 Set<Artifact> providerArtifacts, Artifact... inPluginArtifacts) {
1753 Set<Artifact> result = new LinkedHashSet<>();
1754 for (Artifact inPluginArtifact : inPluginArtifacts) {
1755 boolean contains = false;
1756 for (Artifact providerArtifact : providerArtifacts) {
1757 if (hasGroupArtifactId(
1758 providerArtifact.getGroupId(), providerArtifact.getArtifactId(), inPluginArtifact)) {
1759 contains = true;
1760 break;
1761 }
1762 }
1763 if (!contains) {
1764 result.add(inPluginArtifact);
1765 }
1766 }
1767 return result;
1768 }
1769
1770 private static boolean hasGroupArtifactId(String groupId, String artifactId, Artifact artifact) {
1771 return groupId.equals(artifact.getGroupId()) && artifactId.equals(artifact.getArtifactId());
1772 }
1773
1774 private static Classpath createInProcClasspath(Classpath providerClasspath, Set<Artifact> newArtifacts) {
1775 Classpath inprocClasspath = providerClasspath.clone();
1776 for (Artifact newArtifact : newArtifacts) {
1777 inprocClasspath =
1778 inprocClasspath.addClassPathElementUrl(newArtifact.getFile().getAbsolutePath());
1779 }
1780 return inprocClasspath;
1781 }
1782
1783
1784
1785
1786
1787 private LocationManager getLocationManager() {
1788 return locationManager;
1789 }
1790
1791 private StartupConfiguration newStartupConfigWithModularPath(
1792 @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
1793 @Nonnull ProviderInfo providerInfo,
1794 @Nonnull ResolvePathResultWrapper moduleDescriptor,
1795 @Nonnull DefaultScanResult scanResult,
1796 @Nonnull String javaHome,
1797 @Nonnull TestClassPath testClasspathWrapper)
1798 throws MojoExecutionException, IOException {
1799 boolean isMainDescriptor = moduleDescriptor.isMainModuleDescriptor();
1800 JavaModuleDescriptor javaModuleDescriptor =
1801 moduleDescriptor.getResolvePathResult().getModuleDescriptor();
1802 SortedSet<String> packages = new TreeSet<>();
1803
1804 Classpath testClasspath = testClasspathWrapper.toClasspath();
1805 Set<Artifact> providerArtifacts = providerInfo.getProviderClasspath();
1806 String providerName = providerInfo.getProviderName();
1807 Classpath providerClasspath = classpathCache.getCachedClassPath(providerName);
1808 if (providerClasspath == null) {
1809 providerClasspath = classpathCache.setCachedClasspath(providerName, providerArtifacts);
1810 }
1811
1812 final ProviderRequirements providerRequirements;
1813 final Classpath testModulepath;
1814 if (isMainDescriptor) {
1815 providerRequirements = new ProviderRequirements(true, true, false);
1816 ResolvePathsRequest<String> req = ResolvePathsRequest.ofStrings(testClasspath.getClassPath())
1817 .setIncludeAllProviders(true)
1818 .setJdkHome(javaHome)
1819 .setIncludeStatic(true)
1820 .setModuleDescriptor(javaModuleDescriptor);
1821
1822 ResolvePathsResult<String> result = getLocationManager().resolvePaths(req);
1823 for (Entry<String, Exception> entry : result.getPathExceptions().entrySet()) {
1824
1825 getConsoleLogger().warning("Exception for '" + entry.getKey() + "'.", entry.getValue());
1826 }
1827
1828 testClasspath = new Classpath(result.getClasspathElements());
1829 testModulepath = new Classpath(result.getModulepathElements().keySet());
1830
1831 for (String className : scanResult.getClasses()) {
1832 packages.add(substringBeforeLast(className, "."));
1833 }
1834 } else {
1835 providerRequirements = new ProviderRequirements(true, false, true);
1836 testModulepath = testClasspath;
1837 testClasspath = emptyClasspath();
1838 }
1839
1840 getConsoleLogger().debug("main module descriptor name: " + javaModuleDescriptor.name());
1841
1842 ModularClasspath modularClasspath = new ModularClasspath(
1843 javaModuleDescriptor.name(),
1844 testModulepath.getClassPath(),
1845 packages,
1846 isMainDescriptor ? getTestClassesDirectory() : null,
1847 isMainDescriptor);
1848
1849 Artifact[] additionalInProcArtifacts = {
1850 getCommonArtifact(),
1851 getBooterArtifact(),
1852 getExtensionsArtifact(),
1853 getApiArtifact(),
1854 getSpiArtifact(),
1855 getLoggerApiArtifact(),
1856 getSurefireSharedUtilsArtifact()
1857 };
1858 Set<Artifact> inProcArtifacts = retainInProcArtifactsUnique(providerArtifacts, additionalInProcArtifacts);
1859 Classpath inProcClasspath = createInProcClasspath(providerClasspath, inProcArtifacts);
1860
1861 ModularClasspathConfiguration classpathConfiguration = new ModularClasspathConfiguration(
1862 modularClasspath,
1863 testClasspath,
1864 providerClasspath,
1865 inProcClasspath,
1866 effectiveIsEnableAssertions(),
1867 isChildDelegation());
1868
1869 getConsoleLogger().debug(testClasspath.getLogMessage("test classpath:"));
1870 getConsoleLogger().debug(testModulepath.getLogMessage("test modulepath:"));
1871 getConsoleLogger().debug(providerClasspath.getLogMessage("provider classpath:"));
1872 getConsoleLogger().debug(testClasspath.getCompactLogMessage("test(compact) classpath:"));
1873 getConsoleLogger().debug(testModulepath.getCompactLogMessage("test(compact) modulepath:"));
1874 getConsoleLogger().debug(providerClasspath.getCompactLogMessage("provider(compact) classpath:"));
1875 getConsoleLogger().debug(inProcClasspath.getLogMessage("in-process classpath:"));
1876 getConsoleLogger().debug(inProcClasspath.getCompactLogMessage("in-process(compact) classpath:"));
1877
1878 ProcessCheckerType processCheckerType = ProcessCheckerType.toEnum(getEnableProcessChecker());
1879 List<String[]> jpmsArgs = providerInfo.getJpmsArguments(providerRequirements);
1880 return new StartupConfiguration(
1881 providerName, classpathConfiguration, classLoaderConfiguration, processCheckerType, jpmsArgs);
1882 }
1883
1884 private Artifact getCommonArtifact() {
1885 return getPluginArtifactMap().get("org.apache.maven.surefire:maven-surefire-common");
1886 }
1887
1888 private Artifact getExtensionsArtifact() {
1889 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-extensions-api");
1890 }
1891
1892 private Artifact getSpiArtifact() {
1893 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-extensions-spi");
1894 }
1895
1896 private Artifact getApiArtifact() {
1897 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-api");
1898 }
1899
1900 private Artifact getSurefireSharedUtilsArtifact() {
1901 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-shared-utils");
1902 }
1903
1904 private Artifact getLoggerApiArtifact() {
1905 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-logger-api");
1906 }
1907
1908 private Artifact getBooterArtifact() {
1909 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-booter");
1910 }
1911
1912 private Artifact getShadefireArtifact() {
1913 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-shadefire");
1914 }
1915
1916 private StartupReportConfiguration getStartupReportConfiguration(String configChecksum, boolean isForking) {
1917 SurefireStatelessReporter xmlReporter = statelessTestsetReporter == null
1918 ? new SurefireStatelessReporter( isDisableXmlReport(), "3.0")
1919 : statelessTestsetReporter;
1920
1921 xmlReporter.setDisable(isDisableXmlReport());
1922
1923 SurefireConsoleOutputReporter outReporter =
1924 consoleOutputReporter == null ? new SurefireConsoleOutputReporter() : consoleOutputReporter;
1925
1926 SurefireStatelessTestsetInfoReporter testsetReporter = statelessTestsetInfoReporter == null
1927 ? new SurefireStatelessTestsetInfoReporter()
1928 : statelessTestsetInfoReporter;
1929
1930 return new StartupReportConfiguration(
1931 isUseFile(),
1932 isPrintSummary(),
1933 getReportFormat(),
1934 isRedirectTestOutputToFile(),
1935 getReportsDirectory(),
1936 isTrimStackTrace(),
1937 getReportNameSuffix(),
1938 getStatisticsFile(configChecksum),
1939 requiresRunHistory(),
1940 getRerunFailingTestsCount(),
1941 getReportSchemaLocation(),
1942 getEncoding(),
1943 isForking,
1944 xmlReporter,
1945 outReporter,
1946 testsetReporter);
1947 }
1948
1949 private boolean isSpecificTestSpecified() {
1950 return isNotBlank(getTest());
1951 }
1952
1953 @Nonnull
1954 private List<String> readListFromFile(@Nonnull final File file) {
1955 getConsoleLogger().debug("Reading list from: " + file);
1956
1957 if (!file.exists()) {
1958 throw new RuntimeException("Failed to load list from file: " + file);
1959 }
1960
1961 try {
1962 List<String> list = FileUtils.loadFile(file);
1963
1964 if (getConsoleLogger().isDebugEnabled()) {
1965 getConsoleLogger().debug("List contents:");
1966 for (String entry : list) {
1967 getConsoleLogger().debug(" " + entry);
1968 }
1969 }
1970 return list;
1971 } catch (IOException e) {
1972 throw new RuntimeException("Failed to load list from file: " + file, e);
1973 }
1974 }
1975
1976 @Nonnull
1977 private List<String> getExcludedScanList() throws MojoFailureException {
1978 return getExcludeList(true);
1979 }
1980
1981 @Nonnull
1982 private List<String> getExcludeList() throws MojoFailureException {
1983 return getExcludeList(false);
1984 }
1985
1986
1987
1988
1989
1990
1991
1992
1993 @Nonnull
1994 private List<String> getExcludeList(boolean asScanList) throws MojoFailureException {
1995 List<String> excludes;
1996 if (isSpecificTestSpecified()) {
1997 excludes = Collections.emptyList();
1998 } else {
1999 excludes = new ArrayList<>();
2000 if (asScanList) {
2001 if (getExcludes() != null) {
2002 excludes.addAll(getExcludes());
2003 }
2004 checkMethodFilterInIncludesExcludes(excludes);
2005 }
2006
2007 if (getExcludesFile() != null) {
2008 excludes.addAll(readListFromFile(getExcludesFile()));
2009 }
2010
2011 if (asScanList && excludes.isEmpty()) {
2012 excludes = Collections.singletonList(getDefaultExcludes());
2013 }
2014 }
2015 return filterNulls(excludes);
2016 }
2017
2018 @Nonnull
2019 private List<String> getIncludedScanList() throws MojoFailureException {
2020 return getIncludeList(true);
2021 }
2022
2023 @Nonnull
2024 private List<String> getIncludeList() throws MojoFailureException {
2025 return getIncludeList(false);
2026 }
2027
2028
2029
2030
2031
2032
2033
2034
2035 @Nonnull
2036 private List<String> getIncludeList(boolean asScanList) throws MojoFailureException {
2037 final List<String> includes = new ArrayList<>();
2038 if (isSpecificTestSpecified()) {
2039 addAll(includes, split(getTest(), ","));
2040 } else {
2041 if (asScanList) {
2042 if (getIncludes() != null) {
2043 includes.addAll(getIncludes());
2044 }
2045 checkMethodFilterInIncludesExcludes(includes);
2046 }
2047
2048 if (getIncludesFile() != null) {
2049 includes.addAll(readListFromFile(getIncludesFile()));
2050 }
2051
2052 if (asScanList && includes.isEmpty()) {
2053 addAll(includes, getDefaultIncludes());
2054 }
2055 }
2056
2057 return filterNulls(includes);
2058 }
2059
2060 private void checkMethodFilterInIncludesExcludes(Iterable<String> patterns) throws MojoFailureException {
2061 for (String pattern : patterns) {
2062 if (pattern != null && pattern.contains("#")) {
2063 throw new MojoFailureException("Method filter prohibited in includes|excludes parameter: " + pattern);
2064 }
2065 }
2066 }
2067
2068 private TestListResolver getIncludedAndExcludedTests() throws MojoFailureException {
2069 if (includedExcludedTests == null) {
2070 includedExcludedTests = new TestListResolver(getIncludedScanList(), getExcludedScanList());
2071 getConsoleLogger().debug("Resolved included and excluded patterns: " + includedExcludedTests);
2072 }
2073 return includedExcludedTests;
2074 }
2075
2076 public TestListResolver getSpecificTests() throws MojoFailureException {
2077 if (specificTests == null) {
2078 specificTests = new TestListResolver(getIncludeList(), getExcludeList());
2079 }
2080 return specificTests;
2081 }
2082
2083 @Nonnull
2084 private List<String> filterNulls(@Nonnull List<String> toFilter) {
2085 List<String> result = new ArrayList<>(toFilter.size());
2086 for (String item : toFilter) {
2087 if (item != null) {
2088 item = item.trim();
2089 if (!item.isEmpty()) {
2090 result.add(item);
2091 }
2092 }
2093 }
2094
2095 return result;
2096 }
2097
2098 private Artifact getTestNgArtifact() throws MojoExecutionException {
2099 Artifact artifact = getProjectArtifactMap().get(getTestNGArtifactName());
2100 Artifact projectArtifact = project.getArtifact();
2101 String projectArtifactName = projectArtifact.getGroupId() + ":" + projectArtifact.getArtifactId();
2102
2103 if (artifact != null) {
2104 VersionRange range = createVersionRange();
2105 if (!range.containsVersion(new DefaultArtifactVersion(artifact.getVersion()))) {
2106 throw new MojoExecutionException(
2107 "TestNG support requires version 4.7 or above. You have declared version "
2108 + artifact.getVersion());
2109 }
2110 } else if (projectArtifactName.equals(getTestNGArtifactName())) {
2111 artifact = projectArtifact;
2112 }
2113
2114 return artifact;
2115 }
2116
2117 private VersionRange createVersionRange() {
2118 try {
2119 return VersionRange.createFromVersionSpec("[4.7,)");
2120 } catch (InvalidVersionSpecificationException e) {
2121 throw new RuntimeException(e);
2122 }
2123 }
2124
2125 private Artifact getJunitArtifact() {
2126 Artifact artifact = getProjectArtifactMap().get(getJunitArtifactName());
2127 Artifact projectArtifact = project.getArtifact();
2128 String projectArtifactName = projectArtifact.getGroupId() + ":" + projectArtifact.getArtifactId();
2129
2130 if (artifact == null && projectArtifactName.equals(getJunitArtifactName())) {
2131 artifact = projectArtifact;
2132 }
2133
2134 return artifact;
2135 }
2136
2137 private Artifact getJunitDepArtifact() {
2138 return getProjectArtifactMap().get("junit:junit-dep");
2139 }
2140
2141 private Artifact getJUnitPlatformRunnerArtifact() {
2142 return getProjectArtifactMap().get("org.junit.platform:junit-platform-runner");
2143 }
2144
2145 private Artifact getJUnit5Artifact() {
2146 Artifact artifact = getPluginArtifactMap().get("org.junit.platform:junit-platform-engine");
2147 if (artifact == null) {
2148 return getProjectArtifactMap().get("org.junit.platform:junit-platform-commons");
2149 }
2150
2151 return artifact;
2152 }
2153
2154 private ForkStarter createForkStarter(
2155 @Nonnull ProviderInfo provider,
2156 @Nonnull ForkConfiguration forkConfiguration,
2157 @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
2158 @Nonnull RunOrderParameters runOrderParameters,
2159 @Nonnull ConsoleLogger log,
2160 @Nonnull DefaultScanResult scanResult,
2161 @Nonnull TestClassPath testClasspathWrapper,
2162 @Nonnull Platform platform,
2163 @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult)
2164 throws MojoExecutionException, MojoFailureException {
2165 StartupConfiguration startupConfiguration = createStartupConfiguration(
2166 provider,
2167 true,
2168 classLoaderConfiguration,
2169 scanResult,
2170 testClasspathWrapper,
2171 platform,
2172 resolvedJavaModularityResult);
2173 String configChecksum = getConfigChecksum();
2174 StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration(configChecksum, true);
2175 ProviderConfiguration providerConfiguration = createProviderConfiguration(runOrderParameters);
2176 return new ForkStarter(
2177 providerConfiguration,
2178 startupConfiguration,
2179 forkConfiguration,
2180 getForkedProcessTimeoutInSeconds(),
2181 startupReportConfiguration,
2182 log);
2183 }
2184
2185 private InPluginVMSurefireStarter createInprocessStarter(
2186 @Nonnull ProviderInfo provider,
2187 @Nonnull ClassLoaderConfiguration classLoaderConfig,
2188 @Nonnull RunOrderParameters runOrderParameters,
2189 @Nonnull DefaultScanResult scanResult,
2190 @Nonnull Platform platform,
2191 @Nonnull TestClassPath testClasspathWrapper)
2192 throws MojoExecutionException, MojoFailureException {
2193 StartupConfiguration startupConfiguration = createStartupConfiguration(
2194 provider,
2195 false,
2196 classLoaderConfig,
2197 scanResult,
2198 testClasspathWrapper,
2199 platform,
2200 new ResolvePathResultWrapper(null, true));
2201 String configChecksum = getConfigChecksum();
2202 StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration(configChecksum, false);
2203 ProviderConfiguration providerConfiguration = createProviderConfiguration(runOrderParameters);
2204 return new InPluginVMSurefireStarter(
2205 startupConfiguration, providerConfiguration, startupReportConfiguration, getConsoleLogger(), platform);
2206 }
2207
2208
2209 @Nonnull
2210 private ForkNodeFactory getForkNodeFactory() {
2211 ForkNodeFactory forkNode = getForkNode();
2212 return forkNode == null ? new LegacyForkNodeFactory() : forkNode;
2213 }
2214
2215 @Nonnull
2216 private ForkConfiguration createForkConfiguration(
2217 @Nonnull Platform platform, @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult)
2218 throws MojoExecutionException {
2219 File tmpDir = getSurefireTempDir();
2220
2221 Artifact shadeFire = getShadefireArtifact();
2222
2223 Classpath bootClasspath = getArtifactClasspath(shadeFire != null ? shadeFire : getBooterArtifact());
2224
2225 ForkNodeFactory forkNode = getForkNodeFactory();
2226
2227 getConsoleLogger()
2228 .debug("Found implementation of fork node factory: "
2229 + forkNode.getClass().getName());
2230
2231 if (canExecuteProviderWithModularPath(platform, resolvedJavaModularityResult)) {
2232 return new ModularClasspathForkConfiguration(
2233 bootClasspath,
2234 tmpDir,
2235 getEffectiveDebugForkedProcess(),
2236 getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
2237 getProject().getModel().getProperties(),
2238 getArgLine(),
2239 getEnvironmentVariables(),
2240 getExcludedEnvironmentVariables(),
2241 getConsoleLogger().isDebugEnabled(),
2242 getEffectiveForkCount(),
2243 reuseForks,
2244 platform,
2245 getConsoleLogger(),
2246 forkNode);
2247 } else if (getClassLoaderConfiguration().isManifestOnlyJarRequestedAndUsable()) {
2248 return new JarManifestForkConfiguration(
2249 bootClasspath,
2250 tmpDir,
2251 getEffectiveDebugForkedProcess(),
2252 getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
2253 getProject().getModel().getProperties(),
2254 getArgLine(),
2255 getEnvironmentVariables(),
2256 getExcludedEnvironmentVariables(),
2257 getConsoleLogger().isDebugEnabled(),
2258 getEffectiveForkCount(),
2259 reuseForks,
2260 platform,
2261 getConsoleLogger(),
2262 forkNode);
2263 } else {
2264 return new ClasspathForkConfiguration(
2265 bootClasspath,
2266 tmpDir,
2267 getEffectiveDebugForkedProcess(),
2268 getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
2269 getProject().getModel().getProperties(),
2270 getArgLine(),
2271 getEnvironmentVariables(),
2272 getExcludedEnvironmentVariables(),
2273 getConsoleLogger().isDebugEnabled(),
2274 getEffectiveForkCount(),
2275 reuseForks,
2276 platform,
2277 getConsoleLogger(),
2278 forkNode);
2279 }
2280 }
2281
2282 private void ensureEnableProcessChecker() throws MojoFailureException {
2283 if (!ProcessCheckerType.isValid(getEnableProcessChecker())) {
2284 throw new MojoFailureException("Unexpected value '"
2285 + getEnableProcessChecker()
2286 + "' in the configuration parameter 'enableProcessChecker'.");
2287 }
2288 }
2289
2290 @SuppressWarnings("checkstyle:emptyblock")
2291 protected int getEffectiveForkCount() {
2292 if (effectiveForkCount < 0) {
2293 try {
2294 effectiveForkCount = convertWithCoreCount(forkCount);
2295 } catch (NumberFormatException ignored) {
2296 }
2297
2298 if (effectiveForkCount < 0) {
2299 throw new IllegalArgumentException("Fork count " + forkCount.trim() + " is not a legal value.");
2300 }
2301 }
2302
2303 return effectiveForkCount;
2304 }
2305
2306 protected int convertWithCoreCount(String count) {
2307 String trimmed = count.trim();
2308 if (trimmed.endsWith("C")) {
2309 double multiplier = Double.parseDouble(trimmed.substring(0, trimmed.length() - 1));
2310 double calculated = multiplier * ((double) Runtime.getRuntime().availableProcessors());
2311 return calculated > 0d ? Math.max((int) calculated, 1) : 0;
2312 } else {
2313 return parseInt(trimmed);
2314 }
2315 }
2316
2317 private String getEffectiveDebugForkedProcess() {
2318 String debugForkedProcess = getDebugForkedProcess();
2319 if ("true".equals(debugForkedProcess)) {
2320 return "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:5005";
2321 }
2322 return debugForkedProcess;
2323 }
2324
2325 private JdkAttributes getEffectiveJvm() throws MojoFailureException {
2326 if (isNotEmpty(getJvm())) {
2327 File pathToJava = new File(getJvm()).getAbsoluteFile();
2328 if (!endsWithJavaPath(pathToJava.getPath())) {
2329 throw new MojoFailureException(
2330 "Given path does not end with java executor \"" + pathToJava.getPath() + "\".");
2331 }
2332
2333 if (!(pathToJava.isFile()
2334 || "java".equals(pathToJava.getName())
2335 && pathToJava.getParentFile().isDirectory())) {
2336 throw new MojoFailureException(
2337 "Given path to java executor does not exist \"" + pathToJava.getPath() + "\".");
2338 }
2339
2340 File jdkHome = toJdkHomeFromJvmExec(pathToJava.getPath());
2341 if (jdkHome == null) {
2342 getConsoleLogger().warning("Cannot determine JAVA_HOME of jvm exec path " + pathToJava);
2343 } else if (!getEnvironmentVariables().containsKey("JAVA_HOME")) {
2344 getEnvironmentVariables().put("JAVA_HOME", jdkHome.getAbsolutePath());
2345 }
2346 BigDecimal version = jdkHome == null ? null : toJdkVersionFromReleaseFile(jdkHome);
2347 boolean javaVersion9 = version == null ? isJava9AtLeast(pathToJava.getPath()) : isJava9AtLeast(version);
2348 return new JdkAttributes(pathToJava, jdkHome, javaVersion9);
2349 }
2350
2351 if (toolchain != null) {
2352 String jvmToUse = toolchain.findTool("java");
2353 if (isNotEmpty(jvmToUse)) {
2354 boolean javaVersion9 = false;
2355 String jdkHome = null;
2356
2357 if (toolchain instanceof DefaultToolchain) {
2358 DefaultToolchain defaultToolchain = (DefaultToolchain) toolchain;
2359 javaVersion9 = defaultToolchain.matchesRequirements(JAVA_9_MATCHER)
2360 || defaultToolchain.matchesRequirements(JAVA_9_MATCHER_OLD_NOTATION);
2361 }
2362
2363 if (toolchain instanceof DefaultJavaToolChain) {
2364 DefaultJavaToolChain defaultJavaToolChain = (DefaultJavaToolChain) toolchain;
2365 if (!getEnvironmentVariables().containsKey("JAVA_HOME")) {
2366 jdkHome = defaultJavaToolChain.getJavaHome();
2367 getEnvironmentVariables().put("JAVA_HOME", jdkHome);
2368 }
2369 }
2370
2371 if (!javaVersion9) {
2372 javaVersion9 = isJava9AtLeast(jvmToUse);
2373 }
2374
2375 return new JdkAttributes(
2376 new File(jvmToUse),
2377 jdkHome == null ? toJdkHomeFromJvmExec(jvmToUse) : new File(jdkHome),
2378 javaVersion9);
2379 }
2380 }
2381
2382
2383 String jvmToUse = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
2384 getConsoleLogger().debug("Using JVM: " + jvmToUse + " with Java version " + JAVA_RECENT);
2385
2386 return new JdkAttributes(jvmToUse, isBuiltInJava9AtLeast());
2387 }
2388
2389
2390
2391
2392
2393
2394 File getSurefireTempDir() {
2395 File result = IS_OS_WINDOWS ? createSurefireBootDirectoryInTemp() : createSurefireBootDirectoryInBuild();
2396 try {
2397 File canonical = result.getCanonicalFile();
2398 if (!result.equals(canonical)) {
2399 getConsoleLogger().debug("Canonicalized tempDir path '" + result + "' to '" + canonical + "'");
2400 }
2401 return canonical;
2402 } catch (IOException e) {
2403 getConsoleLogger().error("Could not canonicalize tempDir path '" + result + "'", e);
2404 }
2405 return result;
2406 }
2407
2408
2409
2410
2411
2412
2413 private String getConfigChecksum() {
2414 ChecksumCalculator checksum = new ChecksumCalculator();
2415 checksum.add(getPluginName());
2416 checksum.add(isSkipTests());
2417 checksum.add(isSkipExec());
2418 checksum.add(isSkip());
2419 checksum.add(getTestClassesDirectory());
2420 checksum.add(getMainBuildPath());
2421 checksum.add(getClasspathDependencyExcludes());
2422 checksum.add(getClasspathDependencyScopeExclude());
2423 checksum.add(getAdditionalClasspathElements());
2424 checksum.add(getReportsDirectory());
2425 checksum.add(getProjectBuildDirectory());
2426 checksum.add(getTestSourceDirectory());
2427 checksum.add(getTest());
2428 checksum.add(getIncludes());
2429 checksum.add(getSkipAfterFailureCount());
2430 checksum.add(getShutdown());
2431 checksum.add(getExcludes());
2432 checksum.add(getLocalRepositoryPath());
2433 checksum.add(getSystemProperties());
2434 checksum.add(getSystemPropertyVariables());
2435 checksum.add(getSystemPropertiesFile());
2436 checksum.add(getProperties());
2437 checksum.add(isPrintSummary());
2438 checksum.add(getReportFormat());
2439 checksum.add(getReportNameSuffix());
2440 checksum.add(isUseFile());
2441 checksum.add(isRedirectTestOutputToFile());
2442 checksum.add(getForkCount());
2443 checksum.add(isReuseForks());
2444 checksum.add(getJvm());
2445 checksum.add(getArgLine());
2446 checksum.add(getDebugForkedProcess());
2447 checksum.add(getForkedProcessTimeoutInSeconds());
2448 checksum.add(getParallelTestsTimeoutInSeconds());
2449 checksum.add(getParallelTestsTimeoutForcedInSeconds());
2450 checksum.add(getEnvironmentVariables());
2451 checksum.add(getExcludedEnvironmentVariables());
2452 checksum.add(getWorkingDirectory());
2453 checksum.add(isChildDelegation());
2454 checksum.add(getGroups());
2455 checksum.add(getExcludedGroups());
2456 checksum.add(getIncludeJUnit5Engines());
2457 checksum.add(getExcludeJUnit5Engines());
2458 checksum.add(getSuiteXmlFiles());
2459 checksum.add(getJunitArtifact());
2460 checksum.add(getTestNGArtifactName());
2461 checksum.add(getThreadCount());
2462 checksum.add(getThreadCountSuites());
2463 checksum.add(getThreadCountClasses());
2464 checksum.add(getThreadCountMethods());
2465 checksum.add(getPerCoreThreadCount());
2466 checksum.add(getUseUnlimitedThreads());
2467 checksum.add(getParallel());
2468 checksum.add(isParallelOptimized());
2469 checksum.add(isTrimStackTrace());
2470 checksum.add(isDisableXmlReport());
2471 checksum.add(isUseSystemClassLoader());
2472 checksum.add(isUseManifestOnlyJar());
2473 checksum.add(getEncoding());
2474 checksum.add(isEnableAssertions());
2475 checksum.add(getObjectFactory());
2476 checksum.add(getFailIfNoTests());
2477 checksum.add(getRunOrder());
2478 checksum.add(getDependenciesToScan());
2479 checksum.add(getForkedProcessExitTimeoutInSeconds());
2480 checksum.add(getRerunFailingTestsCount());
2481 checksum.add(getTempDir());
2482 checksum.add(useModulePath());
2483 checksum.add(getEnableProcessChecker());
2484 addPluginSpecificChecksumItems(checksum);
2485 return checksum.getSha1();
2486 }
2487
2488 protected void addPluginSpecificChecksumItems(ChecksumCalculator checksum) {}
2489
2490 protected boolean hasExecutedBefore() {
2491
2492 String configChecksum = getConfigChecksum();
2493 @SuppressWarnings("unchecked")
2494 Map<String, String> pluginContext = getPluginContext();
2495 if (pluginContext.containsKey(configChecksum)) {
2496 getConsoleLogger()
2497 .info("Skipping execution of surefire because it has already been run for this configuration");
2498 return true;
2499 }
2500 pluginContext.put(configChecksum, configChecksum);
2501
2502 return false;
2503 }
2504
2505 @Nonnull
2506 protected ClassLoaderConfiguration getClassLoaderConfiguration() {
2507 return isForking()
2508 ? new ClassLoaderConfiguration(isUseSystemClassLoader(), isUseManifestOnlyJar())
2509 : new ClassLoaderConfiguration(false, false);
2510 }
2511
2512
2513
2514
2515
2516
2517 private TestClassPath generateTestClasspath() {
2518 Set<Artifact> classpathArtifacts = getProject().getArtifacts();
2519
2520 if (getClasspathDependencyScopeExclude() != null
2521 && !getClasspathDependencyScopeExclude().isEmpty()) {
2522 ArtifactFilter dependencyFilter = new ScopeArtifactFilter(getClasspathDependencyScopeExclude());
2523 classpathArtifacts = filterArtifacts(classpathArtifacts, dependencyFilter);
2524 }
2525
2526 if (getClasspathDependencyExcludes() != null) {
2527 List<String> excludedDependencies = asList(getClasspathDependencyExcludes());
2528 ArtifactFilter dependencyFilter = new PatternIncludesArtifactFilter(excludedDependencies);
2529 classpathArtifacts = filterArtifacts(classpathArtifacts, dependencyFilter);
2530 }
2531
2532 return new TestClassPath(
2533 classpathArtifacts, getMainBuildPath(), getTestClassesDirectory(), getAdditionalClasspathElements());
2534 }
2535
2536
2537
2538
2539
2540
2541
2542
2543 private static Set<Artifact> filterArtifacts(Set<Artifact> artifacts, ArtifactFilter filter) {
2544 Set<Artifact> filteredArtifacts = new LinkedHashSet<>();
2545
2546 for (Artifact artifact : artifacts) {
2547 if (!filter.include(artifact)) {
2548 filteredArtifacts.add(artifact);
2549 }
2550 }
2551
2552 return filteredArtifacts;
2553 }
2554
2555 private void showMap(Map<?, ?> map, String setting) {
2556 for (Object o : map.keySet()) {
2557 String key = (String) o;
2558 String value = (String) map.get(key);
2559 getConsoleLogger().debug("Setting " + setting + " [" + key + "]=[" + value + "]");
2560 }
2561 }
2562
2563 private <T> void showArray(T[] array, String setting) {
2564 for (T e : array) {
2565 getConsoleLogger().debug("Setting " + setting + " [" + e + "]");
2566 }
2567 }
2568
2569 private Classpath getArtifactClasspath(Artifact surefireArtifact) throws MojoExecutionException {
2570 Classpath existing = classpathCache.getCachedClassPath(surefireArtifact.getArtifactId());
2571 if (existing == null) {
2572 List<String> items = new ArrayList<>();
2573 Set<Artifact> booterArtifacts = surefireDependencyResolver.resolveArtifacts(
2574 session.getRepositorySession(), project.getRemotePluginRepositories(), surefireArtifact);
2575 for (Artifact artifact : booterArtifacts) {
2576 items.add(artifact.getFile().getAbsolutePath());
2577 }
2578 existing = new Classpath(items);
2579 classpathCache.setCachedClasspath(surefireArtifact.getArtifactId(), existing);
2580 }
2581 return existing;
2582 }
2583
2584 private Properties getUserProperties() {
2585 return getSession().getUserProperties();
2586 }
2587
2588 private void ensureWorkingDirectoryExists() throws MojoFailureException {
2589 if (getWorkingDirectory() == null) {
2590 throw new MojoFailureException("workingDirectory cannot be null");
2591 }
2592
2593 if (isForking()) {
2594
2595
2596 return;
2597 }
2598
2599 if (!getWorkingDirectory().exists()) {
2600 if (!getWorkingDirectory().mkdirs()) {
2601 throw new MojoFailureException("Cannot create workingDirectory " + getWorkingDirectory());
2602 }
2603 }
2604
2605 if (!getWorkingDirectory().isDirectory()) {
2606 throw new MojoFailureException(
2607 "workingDirectory " + getWorkingDirectory() + " exists and is not a directory");
2608 }
2609 }
2610
2611 private void ensureParallelRunningCompatibility() throws MojoFailureException {
2612 if (isMavenParallel() && isNotForking()) {
2613 throw new MojoFailureException("parallel maven execution is not compatible with surefire forkCount 0");
2614 }
2615 }
2616
2617 private void warnIfUselessUseSystemClassLoaderParameter() {
2618 if (isUseSystemClassLoader() && isNotForking()) {
2619 getConsoleLogger().warning("useSystemClassLoader setting has no effect when not forking");
2620 }
2621 }
2622
2623 private boolean isNotForking() {
2624 return !isForking();
2625 }
2626
2627 private List<CommandLineOption> commandLineOptions() {
2628 return SurefireHelper.commandLineOptions(getSession(), getConsoleLogger());
2629 }
2630
2631 private void warnIfDefunctGroupsCombinations() throws MojoFailureException, MojoExecutionException {
2632 if (isAnyGroupsSelected()) {
2633 if (getTestNgArtifact() == null) {
2634 Artifact junitArtifact = getJunitArtifact();
2635 boolean junit47Compatible = isJunit47Compatible(junitArtifact);
2636 boolean junit5PlatformCompatible = getJUnit5Artifact() != null;
2637 if (!junit47Compatible && !junit5PlatformCompatible) {
2638 if (junitArtifact != null) {
2639 throw new MojoFailureException("groups/excludedGroups are specified but JUnit version on "
2640 + "classpath is too old to support groups. "
2641 + "Check your dependency:tree to see if your project "
2642 + "is picking up an old junit version");
2643 }
2644 throw new MojoFailureException("groups/excludedGroups require TestNG, JUnit48+ or JUnit 5 "
2645 + "(a specific engine required on classpath) on project test classpath");
2646 }
2647 }
2648 }
2649 }
2650
2651 private void warnIfRerunClashes() throws MojoFailureException {
2652 if (getRerunFailingTestsCount() < 0) {
2653 throw new MojoFailureException("Parameter \"rerunFailingTestsCount\" should not be negative.");
2654 }
2655
2656 if (getSkipAfterFailureCount() < 0) {
2657 throw new MojoFailureException("Parameter \"skipAfterFailureCount\" should not be negative.");
2658 }
2659 }
2660
2661 private void warnIfWrongShutdownValue() throws MojoFailureException {
2662 if (!Shutdown.isKnown(getShutdown())) {
2663 throw new MojoFailureException("Parameter \"shutdown\" should have values " + Shutdown.listParameters());
2664 }
2665 }
2666
2667 private void warnIfNotApplicableSkipAfterFailureCount() throws MojoFailureException {
2668 int skipAfterFailureCount = getSkipAfterFailureCount();
2669
2670 if (skipAfterFailureCount < 0) {
2671 throw new MojoFailureException("Parameter \"skipAfterFailureCount\" should not be negative.");
2672 } else if (skipAfterFailureCount > 0) {
2673 try {
2674 Artifact testng = getTestNgArtifact();
2675 if (testng != null) {
2676 VersionRange range = VersionRange.createFromVersionSpec("[5.10,)");
2677 if (!range.containsVersion(new DefaultArtifactVersion(testng.getVersion()))) {
2678 throw new MojoFailureException(
2679 "Parameter \"skipAfterFailureCount\" expects TestNG Version 5.10 or higher. "
2680 + "java.lang.NoClassDefFoundError: org/testng/IInvokedMethodListener");
2681 }
2682 } else {
2683
2684 Artifact junit = getJunitArtifact();
2685 if (junit != null) {
2686 VersionRange range = VersionRange.createFromVersionSpec("[4.0,)");
2687 if (!range.containsVersion(new DefaultArtifactVersion(junit.getVersion()))) {
2688 throw new MojoFailureException(
2689 "Parameter \"skipAfterFailureCount\" expects JUnit Version 4.0 or higher. "
2690 + "java.lang.NoSuchMethodError: "
2691 + "org.junit.runner.notification.RunNotifier.pleaseStop()V");
2692 }
2693 }
2694 }
2695 } catch (MojoExecutionException e) {
2696 throw new MojoFailureException(e.getLocalizedMessage());
2697 } catch (InvalidVersionSpecificationException e) {
2698 throw new RuntimeException(e);
2699 }
2700 }
2701 }
2702
2703 private void warnIfIllegalTempDir() throws MojoFailureException {
2704 if (isEmpty(getTempDir())) {
2705 throw new MojoFailureException("Parameter 'tempDir' should not be blank string.");
2706 }
2707 }
2708
2709 protected void warnIfIllegalFailOnFlakeCount() throws MojoFailureException {}
2710
2711 private void printDefaultSeedIfNecessary() {
2712 if (getRunOrder().equals(RunOrder.RANDOM.name())) {
2713 if (getRunOrderRandomSeed() == null) {
2714 setRunOrderRandomSeed(System.nanoTime());
2715 }
2716 getConsoleLogger()
2717 .info("Tests will run in random order. To reproduce ordering use flag -D" + getPluginName()
2718 + ".runOrder.random.seed=" + getRunOrderRandomSeed());
2719 }
2720 }
2721
2722 final class TestNgProviderInfo implements ProviderInfo {
2723 private final Artifact testNgArtifact;
2724
2725 TestNgProviderInfo(Artifact testNgArtifact) {
2726 this.testNgArtifact = testNgArtifact;
2727 }
2728
2729 @Override
2730 @Nonnull
2731 public String getProviderName() {
2732 return "org.apache.maven.surefire.testng.TestNGProvider";
2733 }
2734
2735 @Override
2736 public boolean isApplicable() {
2737 return testNgArtifact != null;
2738 }
2739
2740 @Override
2741 public void addProviderProperties() throws MojoExecutionException {
2742 convertTestNGParameters();
2743 }
2744
2745 @Nonnull
2746 @Override
2747 public List<String[]> getJpmsArguments(@Nonnull ProviderRequirements forkRequirements) {
2748 return emptyList();
2749 }
2750
2751 @Override
2752 @Nonnull
2753 public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
2754 Artifact surefireArtifact = getBooterArtifact();
2755 String version = surefireArtifact.getBaseVersion();
2756 return surefireDependencyResolver.getProviderClasspath(
2757 session.getRepositorySession(), project.getRemotePluginRepositories(), "surefire-testng", version);
2758 }
2759 }
2760
2761 final class JUnit3ProviderInfo implements ProviderInfo {
2762 @Override
2763 @Nonnull
2764 public String getProviderName() {
2765 return "org.apache.maven.surefire.junit.JUnit3Provider";
2766 }
2767
2768 @Override
2769 public boolean isApplicable() {
2770 return true;
2771 }
2772
2773 @Override
2774 public void addProviderProperties() {}
2775
2776 @Nonnull
2777 @Override
2778 public List<String[]> getJpmsArguments(@Nonnull ProviderRequirements forkRequirements) {
2779 return emptyList();
2780 }
2781
2782 @Override
2783 @Nonnull
2784 public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
2785
2786
2787 String version = getBooterArtifact().getBaseVersion();
2788 return surefireDependencyResolver.getProviderClasspath(
2789 session.getRepositorySession(), project.getRemotePluginRepositories(), "surefire-junit3", version);
2790 }
2791 }
2792
2793 final class JUnit4ProviderInfo implements ProviderInfo {
2794 private final Artifact junitArtifact;
2795
2796 private final Artifact junitDepArtifact;
2797
2798 JUnit4ProviderInfo(Artifact junitArtifact, Artifact junitDepArtifact) {
2799 this.junitArtifact = junitArtifact;
2800 this.junitDepArtifact = junitDepArtifact;
2801 }
2802
2803 @Override
2804 @Nonnull
2805 public String getProviderName() {
2806 return "org.apache.maven.surefire.junit4.JUnit4Provider";
2807 }
2808
2809 @Override
2810 public boolean isApplicable() {
2811 return junitDepArtifact != null || isAnyJunit4(junitArtifact);
2812 }
2813
2814 @Override
2815 public void addProviderProperties() {}
2816
2817 @Nonnull
2818 @Override
2819 public List<String[]> getJpmsArguments(@Nonnull ProviderRequirements forkRequirements) {
2820 return emptyList();
2821 }
2822
2823 @Override
2824 @Nonnull
2825 public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
2826 String version = getBooterArtifact().getBaseVersion();
2827 return surefireDependencyResolver.getProviderClasspath(
2828 session.getRepositorySession(), project.getRemotePluginRepositories(), "surefire-junit4", version);
2829 }
2830 }
2831
2832 final class JUnitPlatformProviderInfo implements ProviderInfo {
2833 private static final String PROVIDER_DEP_GID = "org.junit.platform";
2834 private static final String PROVIDER_DEP_AID = "junit-platform-launcher";
2835
2836 private final Artifact junitPlatformRunnerArtifact;
2837 private final Artifact junitPlatformArtifact;
2838 private final TestClassPath testClasspath;
2839
2840 JUnitPlatformProviderInfo(
2841 Artifact junitPlatformRunnerArtifact,
2842 Artifact junitPlatformArtifact,
2843 @Nonnull TestClassPath testClasspath) {
2844 this.junitPlatformRunnerArtifact = junitPlatformRunnerArtifact;
2845 this.junitPlatformArtifact = junitPlatformArtifact;
2846 this.testClasspath = testClasspath;
2847 }
2848
2849 @Override
2850 @Nonnull
2851 public String getProviderName() {
2852 return "org.apache.maven.surefire.junitplatform.JUnitPlatformProvider";
2853 }
2854
2855 @Override
2856 public boolean isApplicable() {
2857 return junitPlatformRunnerArtifact == null && junitPlatformArtifact != null;
2858 }
2859
2860 @Override
2861 public void addProviderProperties() {
2862 convertGroupParameters();
2863 convertJunitEngineParameters();
2864 }
2865
2866 @Nonnull
2867 @Override
2868 public List<String[]> getJpmsArguments(@Nonnull ProviderRequirements forkRequirements) {
2869 boolean hasTestDescriptor = forkRequirements.isModularPath() && forkRequirements.hasTestModuleDescriptor();
2870 return hasTestDescriptor ? getJpmsArgs() : Collections.<String[]>emptyList();
2871 }
2872
2873 @Override
2874 @Nonnull
2875 public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
2876 String surefireVersion = getBooterArtifact().getBaseVersion();
2877 Map<String, Artifact> providerArtifacts = surefireDependencyResolver.getProviderClasspathAsMap(
2878 session.getRepositorySession(),
2879 project.getRemotePluginRepositories(),
2880 "surefire-junit-platform",
2881 surefireVersion);
2882 Map<String, Artifact> testDeps = testClasspath.getTestDependencies();
2883
2884 Plugin plugin = getPluginDescriptor().getPlugin();
2885 Map<String, Artifact> pluginDeps = surefireDependencyResolver.resolvePluginDependencies(
2886 session.getRepositorySession(),
2887 project.getRemotePluginRepositories(),
2888 plugin,
2889 getPluginArtifactMap());
2890
2891 if (hasDependencyPlatformEngine(pluginDeps)) {
2892 providerArtifacts.putAll(pluginDeps);
2893 } else {
2894 String engineVersion = null;
2895 if (hasDependencyJupiterAPI(testDeps)
2896 && !testDeps.containsKey("org.junit.jupiter:junit-jupiter-engine")) {
2897 String engineGroupId = "org.junit.jupiter";
2898 String engineArtifactId = "junit-jupiter-engine";
2899 String engineCoordinates = engineGroupId + ":" + engineArtifactId;
2900 String api = "org.junit.jupiter:junit-jupiter-api";
2901 engineVersion = testDeps.get(api).getBaseVersion();
2902 getConsoleLogger()
2903 .debug("Test dependencies contain " + api + ". Resolving " + engineCoordinates + ":"
2904 + engineVersion);
2905 addEngineByApi(engineGroupId, engineArtifactId, engineVersion, providerArtifacts);
2906 }
2907
2908 if ((testDeps.containsKey("junit:junit") || testDeps.containsKey("junit:junit-dep"))
2909 && !testDeps.containsKey("org.junit.vintage:junit-vintage-engine")) {
2910 String engineGroupId = "org.junit.vintage";
2911 String engineArtifactId = "junit-vintage-engine";
2912 String engineCoordinates = engineGroupId + ":" + engineArtifactId;
2913
2914 if (engineVersion != null) {
2915 getConsoleLogger()
2916 .debug("Test dependencies contain JUnit4. Resolving " + engineCoordinates + ":"
2917 + engineVersion);
2918 addEngineByApi(engineGroupId, engineArtifactId, engineVersion, providerArtifacts);
2919 }
2920 }
2921 }
2922
2923 narrowDependencies(providerArtifacts, testDeps);
2924 alignProviderVersions(providerArtifacts);
2925
2926 return new LinkedHashSet<>(providerArtifacts.values());
2927 }
2928
2929 private List<String[]> getJpmsArgs() {
2930 List<String[]> args = new ArrayList<>();
2931
2932 args.add(new String[] {
2933 "--add-opens", "org.junit.platform.commons/org.junit.platform.commons.util=ALL-UNNAMED"
2934 });
2935
2936 args.add(new String[] {
2937 "--add-opens", "org.junit.platform.commons/org.junit.platform.commons.logging=ALL-UNNAMED"
2938 });
2939
2940 return args;
2941 }
2942
2943 private void addEngineByApi(
2944 String engineGroupId,
2945 String engineArtifactId,
2946 String engineVersion,
2947 Map<String, Artifact> providerArtifacts)
2948 throws MojoExecutionException {
2949 for (Artifact dep : resolve(engineGroupId, engineArtifactId, engineVersion, null, "jar")) {
2950 String key = dep.getGroupId() + ":" + dep.getArtifactId();
2951 providerArtifacts.put(key, dep);
2952 }
2953 }
2954
2955 private void narrowDependencies(
2956 Map<String, Artifact> providerArtifacts, Map<String, Artifact> testDependencies) {
2957 providerArtifacts.keySet().removeAll(testDependencies.keySet());
2958 }
2959
2960 private void alignProviderVersions(Map<String, Artifact> providerArtifacts) throws MojoExecutionException {
2961 String version = junitPlatformArtifact.getBaseVersion();
2962 for (Artifact launcherArtifact : resolve(PROVIDER_DEP_GID, PROVIDER_DEP_AID, version, null, "jar")) {
2963 String key = launcherArtifact.getGroupId() + ":" + launcherArtifact.getArtifactId();
2964 if (providerArtifacts.containsKey(key)) {
2965 providerArtifacts.put(key, launcherArtifact);
2966 }
2967 }
2968 }
2969
2970 private Set<Artifact> resolve(String g, String a, String v, String c, String t) throws MojoExecutionException {
2971 ArtifactHandler handler = junitPlatformArtifact.getArtifactHandler();
2972 Artifact artifact = new DefaultArtifact(g, a, v, null, t, c, handler);
2973 getConsoleLogger().debug("Resolving artifact " + g + ":" + a + ":" + v);
2974 Set<Artifact> r = surefireDependencyResolver.resolveArtifacts(
2975 session.getRepositorySession(), project.getRemoteProjectRepositories(), artifact);
2976 getConsoleLogger().debug("Resolved artifact " + g + ":" + a + ":" + v + " to " + r);
2977 return r;
2978 }
2979
2980 private boolean hasDependencyJupiterAPI(Map<String, Artifact> dependencies) {
2981 return dependencies.containsKey("org.junit.jupiter:junit-jupiter-api");
2982 }
2983
2984 private boolean hasDependencyPlatformEngine(Map<String, Artifact> dependencies) {
2985 for (Entry<String, Artifact> dependency : dependencies.entrySet()) {
2986 if (dependency.getKey().equals("org.junit.platform:junit-platform-engine")) {
2987 return true;
2988 }
2989 }
2990
2991 return false;
2992 }
2993 }
2994
2995 final class JUnitCoreProviderInfo implements ProviderInfo {
2996 private final Artifact junitArtifact;
2997
2998 private final Artifact junitDepArtifact;
2999
3000 JUnitCoreProviderInfo(Artifact junitArtifact, Artifact junitDepArtifact) {
3001 this.junitArtifact = junitArtifact;
3002 this.junitDepArtifact = junitDepArtifact;
3003 }
3004
3005 @Override
3006 @Nonnull
3007 public String getProviderName() {
3008 return "org.apache.maven.surefire.junitcore.JUnitCoreProvider";
3009 }
3010
3011 private boolean is47CompatibleJunitDep() {
3012 return isJunit47Compatible(junitDepArtifact);
3013 }
3014
3015 @Override
3016 public boolean isApplicable() {
3017 final boolean isJunitArtifact47 = isAnyJunit4(junitArtifact) && isJunit47Compatible(junitArtifact);
3018 final boolean isAny47ProvidersForces = isAnyConcurrencySelected() || isAnyGroupsSelected();
3019 return isAny47ProvidersForces && (isJunitArtifact47 || is47CompatibleJunitDep());
3020 }
3021
3022 @Override
3023 public void addProviderProperties() throws MojoExecutionException {
3024 convertJunitCoreParameters();
3025 convertGroupParameters();
3026 convertJunitEngineParameters();
3027 }
3028
3029 @Nonnull
3030 @Override
3031 public List<String[]> getJpmsArguments(@Nonnull ProviderRequirements forkRequirements) {
3032 return emptyList();
3033 }
3034
3035 @Override
3036 @Nonnull
3037 public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
3038 String version = getBooterArtifact().getBaseVersion();
3039 return surefireDependencyResolver.getProviderClasspath(
3040 session.getRepositorySession(), project.getRemotePluginRepositories(), "surefire-junit47", version);
3041 }
3042 }
3043
3044
3045
3046
3047 final class DynamicProviderInfo implements ConfigurableProviderInfo {
3048 final String providerName;
3049
3050 DynamicProviderInfo(String providerName) {
3051 this.providerName = providerName;
3052 }
3053
3054 @Override
3055 public ProviderInfo instantiate(String providerName) {
3056 return new DynamicProviderInfo(providerName);
3057 }
3058
3059 @Override
3060 @Nonnull
3061 public String getProviderName() {
3062 return providerName;
3063 }
3064
3065 @Override
3066 public boolean isApplicable() {
3067 return true;
3068 }
3069
3070 @Override
3071 public void addProviderProperties() throws MojoExecutionException {
3072
3073 convertJunitCoreParameters();
3074 convertTestNGParameters();
3075 }
3076
3077 @Nonnull
3078 @Override
3079 public List<String[]> getJpmsArguments(@Nonnull ProviderRequirements forkRequirements) {
3080 return emptyList();
3081 }
3082
3083 @Override
3084 @Nonnull
3085 public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
3086 Plugin plugin = getPluginDescriptor().getPlugin();
3087 Map<String, Artifact> providerArtifacts = surefireDependencyResolver.resolvePluginDependencies(
3088 session.getRepositorySession(),
3089 project.getRemotePluginRepositories(),
3090 plugin,
3091 getPluginArtifactMap());
3092 return new LinkedHashSet<>(providerArtifacts.values());
3093 }
3094 }
3095
3096 File createSurefireBootDirectoryInBuild() {
3097 File tmp = new File(getProjectBuildDirectory(), getTempDir());
3098
3099 tmp.mkdirs();
3100 return tmp;
3101 }
3102
3103 File createSurefireBootDirectoryInTemp() {
3104 try {
3105 return Files.createTempDirectory(getTempDir()).toFile();
3106 } catch (IOException e) {
3107 return createSurefireBootDirectoryInBuild();
3108 }
3109 }
3110
3111 @Override
3112 public String getLocalRepositoryPath() {
3113 return Optional.ofNullable(
3114 session.getRepositorySession().getLocalRepository().getBasedir())
3115 .map(File::getAbsolutePath)
3116 .orElse(".");
3117 }
3118
3119 public Properties getSystemProperties() {
3120 return systemProperties;
3121 }
3122
3123 @SuppressWarnings("UnusedDeclaration")
3124 public void setSystemProperties(Properties systemProperties) {
3125 this.systemProperties = systemProperties;
3126 }
3127
3128 public Map<String, String> getSystemPropertyVariables() {
3129 return systemPropertyVariables;
3130 }
3131
3132 @SuppressWarnings("UnusedDeclaration")
3133 public void setSystemPropertyVariables(Map<String, String> systemPropertyVariables) {
3134 this.systemPropertyVariables = systemPropertyVariables;
3135 }
3136
3137
3138
3139
3140
3141
3142 public abstract File getSystemPropertiesFile();
3143
3144 @SuppressWarnings("UnusedDeclaration")
3145 public abstract void setSystemPropertiesFile(File systemPropertiesFile);
3146
3147 private Properties getProperties() {
3148 return properties;
3149 }
3150
3151 public void setProperties(Properties properties) {
3152 this.properties = properties;
3153 }
3154
3155 public Map<String, Artifact> getPluginArtifactMap() {
3156 return pluginArtifactMap;
3157 }
3158
3159 @SuppressWarnings("UnusedDeclaration")
3160 public void setPluginArtifactMap(Map<String, Artifact> pluginArtifactMap) {
3161 this.pluginArtifactMap = pluginArtifactMap;
3162 }
3163
3164 public Map<String, Artifact> getProjectArtifactMap() {
3165 return projectArtifactMap;
3166 }
3167
3168 @SuppressWarnings("UnusedDeclaration")
3169 public void setProjectArtifactMap(Map<String, Artifact> projectArtifactMap) {
3170 this.projectArtifactMap = projectArtifactMap;
3171 }
3172
3173 public String getReportNameSuffix() {
3174 return reportNameSuffix;
3175 }
3176
3177 @SuppressWarnings("UnusedDeclaration")
3178 public void setReportNameSuffix(String reportNameSuffix) {
3179 this.reportNameSuffix = reportNameSuffix;
3180 }
3181
3182 public boolean isRedirectTestOutputToFile() {
3183 return redirectTestOutputToFile;
3184 }
3185
3186 @SuppressWarnings("UnusedDeclaration")
3187 public void setRedirectTestOutputToFile(boolean redirectTestOutputToFile) {
3188 this.redirectTestOutputToFile = redirectTestOutputToFile;
3189 }
3190
3191 public boolean getFailIfNoTests() {
3192 return failIfNoTests;
3193 }
3194
3195 public void setFailIfNoTests(boolean failIfNoTests) {
3196 this.failIfNoTests = failIfNoTests;
3197 }
3198
3199 public String getJvm() {
3200 return jvm;
3201 }
3202
3203 public String getArgLine() {
3204 return argLine;
3205 }
3206
3207 @SuppressWarnings("UnusedDeclaration")
3208 public void setArgLine(String argLine) {
3209 this.argLine = argLine;
3210 }
3211
3212 public Map<String, String> getEnvironmentVariables() {
3213 return environmentVariables;
3214 }
3215
3216 @SuppressWarnings("UnusedDeclaration")
3217 public void setEnvironmentVariables(Map<String, String> environmentVariables) {
3218 this.environmentVariables = environmentVariables;
3219 }
3220
3221 public File getWorkingDirectory() {
3222 return workingDirectory;
3223 }
3224
3225 @SuppressWarnings("UnusedDeclaration")
3226 public void setWorkingDirectory(File workingDirectory) {
3227 this.workingDirectory = workingDirectory;
3228 }
3229
3230 public boolean isChildDelegation() {
3231 return childDelegation;
3232 }
3233
3234 @SuppressWarnings("UnusedDeclaration")
3235 public void setChildDelegation(boolean childDelegation) {
3236 this.childDelegation = childDelegation;
3237 }
3238
3239 public String getGroups() {
3240 return groups;
3241 }
3242
3243 @SuppressWarnings("UnusedDeclaration")
3244 public void setGroups(String groups) {
3245 this.groups = groups;
3246 }
3247
3248 public String getExcludedGroups() {
3249 return excludedGroups;
3250 }
3251
3252 @SuppressWarnings("UnusedDeclaration")
3253 public void setExcludedGroups(String excludedGroups) {
3254 this.excludedGroups = excludedGroups;
3255 }
3256
3257 public String getJunitArtifactName() {
3258 return junitArtifactName;
3259 }
3260
3261 @SuppressWarnings("UnusedDeclaration")
3262 public void setJunitArtifactName(String junitArtifactName) {
3263 this.junitArtifactName = junitArtifactName;
3264 }
3265
3266 public String getTestNGArtifactName() {
3267 return testNGArtifactName;
3268 }
3269
3270 @SuppressWarnings("UnusedDeclaration")
3271 public void setTestNGArtifactName(String testNGArtifactName) {
3272 this.testNGArtifactName = testNGArtifactName;
3273 }
3274
3275 public int getThreadCount() {
3276 return threadCount;
3277 }
3278
3279 @SuppressWarnings("UnusedDeclaration")
3280 public void setThreadCount(int threadCount) {
3281 this.threadCount = threadCount;
3282 }
3283
3284 public boolean getPerCoreThreadCount() {
3285 return perCoreThreadCount;
3286 }
3287
3288 @SuppressWarnings("UnusedDeclaration")
3289 public void setPerCoreThreadCount(boolean perCoreThreadCount) {
3290 this.perCoreThreadCount = perCoreThreadCount;
3291 }
3292
3293 public boolean getUseUnlimitedThreads() {
3294 return useUnlimitedThreads;
3295 }
3296
3297 @SuppressWarnings("UnusedDeclaration")
3298 public void setUseUnlimitedThreads(boolean useUnlimitedThreads) {
3299 this.useUnlimitedThreads = useUnlimitedThreads;
3300 }
3301
3302 public String getParallel() {
3303 return parallel;
3304 }
3305
3306 @SuppressWarnings("UnusedDeclaration")
3307 public void setParallel(String parallel) {
3308 this.parallel = parallel;
3309 }
3310
3311 public boolean isParallelOptimized() {
3312 return parallelOptimized;
3313 }
3314
3315 @SuppressWarnings("UnusedDeclaration")
3316 public void setParallelOptimized(boolean parallelOptimized) {
3317 this.parallelOptimized = parallelOptimized;
3318 }
3319
3320 public int getThreadCountSuites() {
3321 return threadCountSuites;
3322 }
3323
3324 public void setThreadCountSuites(int threadCountSuites) {
3325 this.threadCountSuites = threadCountSuites;
3326 }
3327
3328 public int getThreadCountClasses() {
3329 return threadCountClasses;
3330 }
3331
3332 public void setThreadCountClasses(int threadCountClasses) {
3333 this.threadCountClasses = threadCountClasses;
3334 }
3335
3336 public int getThreadCountMethods() {
3337 return threadCountMethods;
3338 }
3339
3340 public void setThreadCountMethods(int threadCountMethods) {
3341 this.threadCountMethods = threadCountMethods;
3342 }
3343
3344 public boolean isTrimStackTrace() {
3345 return trimStackTrace;
3346 }
3347
3348 @SuppressWarnings("UnusedDeclaration")
3349 public void setTrimStackTrace(boolean trimStackTrace) {
3350 this.trimStackTrace = trimStackTrace;
3351 }
3352
3353 public boolean isDisableXmlReport() {
3354 return disableXmlReport;
3355 }
3356
3357 @SuppressWarnings("UnusedDeclaration")
3358 public void setDisableXmlReport(boolean disableXmlReport) {
3359 this.disableXmlReport = disableXmlReport;
3360 }
3361
3362 public boolean isEnableAssertions() {
3363 return enableAssertions;
3364 }
3365
3366 public boolean effectiveIsEnableAssertions() {
3367 if (getArgLine() != null) {
3368 List<String> args = asList(getArgLine().split(" "));
3369 if (args.contains("-da") || args.contains("-disableassertions")) {
3370 return false;
3371 }
3372 }
3373 return isEnableAssertions();
3374 }
3375
3376 @SuppressWarnings("UnusedDeclaration")
3377 public void setEnableAssertions(boolean enableAssertions) {
3378 this.enableAssertions = enableAssertions;
3379 }
3380
3381 public MavenSession getSession() {
3382 return session;
3383 }
3384
3385 @SuppressWarnings("UnusedDeclaration")
3386 public void setSession(MavenSession session) {
3387 this.session = session;
3388 }
3389
3390 public String getObjectFactory() {
3391 return objectFactory;
3392 }
3393
3394 @SuppressWarnings("UnusedDeclaration")
3395 public void setObjectFactory(String objectFactory) {
3396 this.objectFactory = objectFactory;
3397 }
3398
3399 public ToolchainManager getToolchainManager() {
3400 return toolchainManager;
3401 }
3402
3403 @SuppressWarnings("UnusedDeclaration")
3404 public void setToolchainManager(ToolchainManager toolchainManager) {
3405 this.toolchainManager = toolchainManager;
3406 }
3407
3408 public boolean isMavenParallel() {
3409 return parallelMavenExecution != null && parallelMavenExecution;
3410 }
3411
3412 public String[] getDependenciesToScan() {
3413 return dependenciesToScan;
3414 }
3415
3416 public void setDependenciesToScan(String[] dependenciesToScan) {
3417 this.dependenciesToScan = dependenciesToScan;
3418 }
3419
3420 @SuppressWarnings("UnusedDeclaration")
3421 void setPluginDescriptor(PluginDescriptor pluginDescriptor) {
3422 this.pluginDescriptor = pluginDescriptor;
3423 }
3424
3425 public PluginDescriptor getPluginDescriptor() {
3426 return pluginDescriptor;
3427 }
3428
3429 public MavenProject getProject() {
3430 return project;
3431 }
3432
3433 @SuppressWarnings("UnusedDeclaration")
3434 public void setProject(MavenProject project) {
3435 this.project = project;
3436 }
3437
3438 @Override
3439 public File getTestSourceDirectory() {
3440 return testSourceDirectory;
3441 }
3442
3443 @Override
3444 public void setTestSourceDirectory(File testSourceDirectory) {
3445 this.testSourceDirectory = testSourceDirectory;
3446 }
3447
3448 public String getForkCount() {
3449 return forkCount;
3450 }
3451
3452 public boolean isReuseForks() {
3453 return reuseForks;
3454 }
3455
3456 public String[] getAdditionalClasspathElements() {
3457 return additionalClasspathElements;
3458 }
3459
3460 public void setAdditionalClasspathElements(String[] additionalClasspathElements) {
3461 this.additionalClasspathElements = additionalClasspathElements;
3462 }
3463
3464 public String[] getClasspathDependencyExcludes() {
3465 return classpathDependencyExcludes;
3466 }
3467
3468 public void setClasspathDependencyExcludes(String[] classpathDependencyExcludes) {
3469 this.classpathDependencyExcludes = classpathDependencyExcludes;
3470 }
3471
3472 public String getClasspathDependencyScopeExclude() {
3473 return classpathDependencyScopeExclude;
3474 }
3475
3476 public void setClasspathDependencyScopeExclude(String classpathDependencyScopeExclude) {
3477 this.classpathDependencyScopeExclude = classpathDependencyScopeExclude;
3478 }
3479
3480 public File getProjectBuildDirectory() {
3481 return projectBuildDirectory;
3482 }
3483
3484 public void setProjectBuildDirectory(File projectBuildDirectory) {
3485 this.projectBuildDirectory = projectBuildDirectory;
3486 }
3487
3488 protected void logDebugOrCliShowErrors(String s) {
3489 SurefireHelper.logDebugOrCliShowErrors(s, getConsoleLogger(), cli);
3490 }
3491
3492 public Map<String, String> getJdkToolchain() {
3493 return jdkToolchain;
3494 }
3495
3496 public void setJdkToolchain(Map<String, String> jdkToolchain) {
3497 this.jdkToolchain = jdkToolchain;
3498 }
3499
3500 public String getTempDir() {
3501 return tempDir;
3502 }
3503
3504 public void setTempDir(String tempDir) {
3505 this.tempDir = tempDir;
3506 }
3507
3508 private static final class ClasspathCache {
3509 private final Map<String, Classpath> classpaths = new HashMap<>(4);
3510
3511 private Classpath getCachedClassPath(@Nonnull String artifactId) {
3512 return classpaths.get(artifactId);
3513 }
3514
3515 private void setCachedClasspath(@Nonnull String key, @Nonnull Classpath classpath) {
3516 classpaths.put(key, classpath);
3517 }
3518
3519 private Classpath setCachedClasspath(@Nonnull String key, @Nonnull Set<Artifact> artifacts) {
3520 Collection<String> files = new ArrayList<>();
3521 for (Artifact artifact : artifacts) {
3522 files.add(artifact.getFile().getAbsolutePath());
3523 }
3524 Classpath classpath = new Classpath(files);
3525 setCachedClasspath(key, classpath);
3526 return classpath;
3527 }
3528 }
3529
3530
3531
3532
3533 enum PluginFailureReason {
3534 NONE,
3535 COULD_NOT_RUN_SPECIFIED_TESTS,
3536 COULD_NOT_RUN_DEFAULT_TESTS,
3537 }
3538 }