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