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