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