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
3164 String junitSupportGroupId = "org.junit.support";
3165 String testNgEngineArtifactId = "testng-engine";
3166 String testNgEngineCoordinates = junitSupportGroupId + ":" + testNgEngineArtifactId;
3167
3168
3169 String version = "1.0.6";
3170 consoleLogger.debug("TestNG is present. Resolving " + testNgEngineCoordinates + ":" + version);
3171 if (!testDeps.containsKey(testNgEngineCoordinates)
3172 && !pluginDeps.containsKey(testNgEngineCoordinates)) {
3173 addEngineByApi(junitSupportGroupId, testNgEngineArtifactId, version, providerArtifacts);
3174 }
3175 }
3176
3177 if (!hasDependencyPlatformEngine(providerArtifacts)) {
3178 addEngineByApi(engineGroupId, engineArtifactId, engineVersion, providerArtifacts);
3179 }
3180
3181 if (!hasDependencyPlatformEngine(providerArtifacts)) {
3182 addEngineByApi(engineGroupId, engineArtifactId, engineVersion, providerArtifacts);
3183 }
3184
3185 narrowDependencies(providerArtifacts, testDeps);
3186 alignProviderVersions(providerArtifacts, engineVersion, testDeps.get(api));
3187
3188 return new LinkedHashSet<>(providerArtifacts.values());
3189 }
3190
3191 private List<String[]> getJpmsArgs() {
3192 List<String[]> args = new ArrayList<>();
3193
3194 args.add(new String[] {
3195 "--add-opens", "org.junit.platform.commons/org.junit.platform.commons.util=ALL-UNNAMED"
3196 });
3197
3198 args.add(new String[] {
3199 "--add-opens", "org.junit.platform.commons/org.junit.platform.commons.logging=ALL-UNNAMED"
3200 });
3201
3202 return args;
3203 }
3204
3205 private void addEngineByApi(
3206 String engineGroupId,
3207 String engineArtifactId,
3208 String engineVersion,
3209 Map<String, Artifact> providerArtifacts)
3210 throws MojoExecutionException {
3211 for (Artifact dep : resolve(engineGroupId, engineArtifactId, engineVersion, null, "jar")) {
3212 String key = dep.getGroupId() + ":" + dep.getArtifactId();
3213 Artifact removed = providerArtifacts.put(key, dep);
3214 if (removed != null) {
3215 consoleLogger.debug("Replaced provider dependency " + key + " " + removed + " with " + dep);
3216 ComparableVersion removedVersion = new ComparableVersion(removed.getVersion());
3217 ComparableVersion depVersion = new ComparableVersion(dep.getVersion());
3218
3219 if (removedVersion.compareTo(depVersion) > 0) {
3220 providerArtifacts.put(key, removed);
3221 consoleLogger.debug("Kept higher version " + key + " " + removed);
3222 }
3223 }
3224 }
3225 }
3226
3227 private String getDefaultJunitVersion() {
3228 try (InputStream inputStream = Thread.currentThread()
3229 .getContextClassLoader()
3230 .getResourceAsStream("surefire.junit.version.properties")) {
3231 Properties junitProperties = new Properties();
3232 junitProperties.load(inputStream);
3233 return junitProperties.getProperty("junit.version");
3234 } catch (Exception e) {
3235 consoleLogger.warning(
3236 "Could not load default JUnit version from junit.version.properties use default 5.14.1");
3237 return "5.14.1";
3238 }
3239 }
3240
3241 private void narrowDependencies(
3242 Map<String, Artifact> providerArtifacts, Map<String, Artifact> testDependencies) {
3243 providerArtifacts.keySet().removeAll(testDependencies.keySet());
3244 }
3245
3246 protected void alignProviderVersions(
3247 Map<String, Artifact> providerArtifacts, String engineVersion, Artifact engineApi)
3248 throws MojoExecutionException {
3249 if (junitPlatformArtifact == null) {
3250 return;
3251 }
3252
3253 String version = junitPlatformArtifact.getBaseVersion();
3254
3255 boolean is6x = false;
3256 if (engineApi != null) {
3257 is6x = isWithinVersionSpec(engineApi, "[6.0.0,)");
3258 }
3259
3260 if (!version.equals(engineVersion) && is6x) {
3261 version = engineVersion;
3262 }
3263 for (Artifact launcherArtifact : resolve(PROVIDER_DEP_GID, PROVIDER_DEP_AID, version, null, "jar")) {
3264 String key = launcherArtifact.getGroupId() + ":" + launcherArtifact.getArtifactId();
3265 if (providerArtifacts.containsKey(key)) {
3266 providerArtifacts.put(key, launcherArtifact);
3267 }
3268 }
3269 }
3270
3271 private Set<Artifact> resolve(String groupId, String artifactId, String version, String classifier, String type)
3272 throws MojoExecutionException {
3273
3274 ArtifactHandler handler = junitPlatformArtifact != null
3275 ? junitPlatformArtifact.getArtifactHandler()
3276 : junitArtifact != null
3277 ? junitArtifact.getArtifactHandler()
3278 : testNgArtifact != null ? testNgArtifact.getArtifactHandler() : null;
3279 Artifact artifact = new DefaultArtifact(groupId, artifactId, version, null, type, classifier, handler);
3280 consoleLogger.debug("Resolving artifact " + groupId + ":" + artifactId + ":" + version);
3281 Set<Artifact> r = surefireDependencyResolver.resolveArtifacts(
3282 session.getRepositorySession(), project.getRemoteProjectRepositories(), artifact);
3283 consoleLogger.debug("Resolved artifact " + groupId + ":" + artifactId + ":" + version + " to " + r);
3284 return r;
3285 }
3286
3287 private boolean hasDependencyJupiterAPI(Map<String, Artifact> dependencies) {
3288 return dependencies.containsKey("org.junit.jupiter:junit-jupiter-api");
3289 }
3290
3291 private boolean hasDependencyPlatformEngine(Map<String, Artifact> dependencies) {
3292 return dependencies.entrySet().stream()
3293 .anyMatch(stringArtifactEntry ->
3294 stringArtifactEntry.getKey().equals("org.junit.platform:junit-platform-engine"));
3295 }
3296 }
3297
3298
3299 @SuppressWarnings("checkstyle:parameternumber")
3300 final class JUnitPlatformProviderShadefireInfo extends JUnitPlatformProviderInfo {
3301
3302 JUnitPlatformProviderShadefireInfo(
3303 Artifact junitPlatformRunnerArtifact,
3304 Artifact junitPlatformArtifact,
3305 @Nonnull TestClassPath testClasspath,
3306 Artifact junitArtifact,
3307 Artifact booterArtifact,
3308 SurefireDependencyResolver surefireDependencyResolver,
3309 MavenSession session,
3310 MavenProject project,
3311 PluginDescriptor pluginDescriptor,
3312 Map<String, Artifact> pluginArtifactMap,
3313 ConsoleLogger consoleLogger,
3314 Artifact testNgArtifact) {
3315 super(
3316 junitPlatformRunnerArtifact,
3317 junitPlatformArtifact,
3318 testClasspath,
3319 junitArtifact,
3320 booterArtifact,
3321 surefireDependencyResolver,
3322 session,
3323 project,
3324 pluginDescriptor,
3325 pluginArtifactMap,
3326 consoleLogger,
3327 testNgArtifact);
3328 }
3329
3330 @Override
3331 public boolean isApplicable() {
3332
3333 return false;
3334 }
3335
3336 @Override
3337 @Nonnull
3338 public String getProviderName() {
3339 return "org.apache.maven.shadefire.surefire.junitplatform.JUnitPlatformProvider";
3340 }
3341
3342 @Override
3343 protected String getProviderArtifactName() {
3344 return "surefire-shadefire";
3345 }
3346
3347 @Override
3348 protected void alignProviderVersions(
3349 Map<String, Artifact> providerArtifacts, String engineVersion, Artifact engineApi)
3350 throws MojoExecutionException {
3351
3352
3353 providerArtifacts.put("org.junit.platform:junit-platform-launcher", null);
3354 super.alignProviderVersions(providerArtifacts, engineVersion, engineApi);
3355 }
3356 }
3357
3358 File createSurefireBootDirectoryInBuild() {
3359 File tmp = new File(getProjectBuildDirectory(), getTempDir());
3360
3361 tmp.mkdirs();
3362 return tmp;
3363 }
3364
3365 File createSurefireBootDirectoryInTemp() {
3366 try {
3367 return Files.createTempDirectory(getTempDir()).toFile();
3368 } catch (IOException e) {
3369 return createSurefireBootDirectoryInBuild();
3370 }
3371 }
3372
3373 @Override
3374 public String getLocalRepositoryPath() {
3375 return Optional.ofNullable(
3376 session.getRepositorySession().getLocalRepository().getBasedir())
3377 .map(File::getAbsolutePath)
3378 .orElse(".");
3379 }
3380
3381 public Properties getSystemProperties() {
3382 return systemProperties;
3383 }
3384
3385 @SuppressWarnings("UnusedDeclaration")
3386 public void setSystemProperties(Properties systemProperties) {
3387 this.systemProperties = systemProperties;
3388 }
3389
3390 public Map<String, String> getSystemPropertyVariables() {
3391 return systemPropertyVariables;
3392 }
3393
3394 @SuppressWarnings("UnusedDeclaration")
3395 public void setSystemPropertyVariables(Map<String, String> systemPropertyVariables) {
3396 this.systemPropertyVariables = systemPropertyVariables;
3397 }
3398
3399
3400
3401
3402
3403
3404 public abstract File getSystemPropertiesFile();
3405
3406 @SuppressWarnings("UnusedDeclaration")
3407 public abstract void setSystemPropertiesFile(File systemPropertiesFile);
3408
3409 private Properties getProperties() {
3410 return properties;
3411 }
3412
3413 public void setProperties(Properties properties) {
3414 this.properties = properties;
3415 }
3416
3417 public Map<String, Artifact> getPluginArtifactMap() {
3418 return pluginArtifactMap;
3419 }
3420
3421 @SuppressWarnings("UnusedDeclaration")
3422 public void setPluginArtifactMap(Map<String, Artifact> pluginArtifactMap) {
3423 this.pluginArtifactMap = pluginArtifactMap;
3424 }
3425
3426 public Map<String, Artifact> getProjectArtifactMap() {
3427 return projectArtifactMap;
3428 }
3429
3430 @SuppressWarnings("UnusedDeclaration")
3431 public void setProjectArtifactMap(Map<String, Artifact> projectArtifactMap) {
3432 this.projectArtifactMap = projectArtifactMap;
3433 }
3434
3435 public String getReportNameSuffix() {
3436 return reportNameSuffix;
3437 }
3438
3439 @SuppressWarnings("UnusedDeclaration")
3440 public void setReportNameSuffix(String reportNameSuffix) {
3441 this.reportNameSuffix = reportNameSuffix;
3442 }
3443
3444 public boolean isRedirectTestOutputToFile() {
3445 return redirectTestOutputToFile;
3446 }
3447
3448 @SuppressWarnings("UnusedDeclaration")
3449 public void setRedirectTestOutputToFile(boolean redirectTestOutputToFile) {
3450 this.redirectTestOutputToFile = redirectTestOutputToFile;
3451 }
3452
3453 public boolean getFailIfNoTests() {
3454 return failIfNoTests;
3455 }
3456
3457 public void setFailIfNoTests(boolean failIfNoTests) {
3458 this.failIfNoTests = failIfNoTests;
3459 }
3460
3461 public String getJvm() {
3462 return jvm;
3463 }
3464
3465 public String getArgLine() {
3466 return argLine;
3467 }
3468
3469 @SuppressWarnings("UnusedDeclaration")
3470 public void setArgLine(String argLine) {
3471 this.argLine = argLine;
3472 }
3473
3474 public Map<String, String> getEnvironmentVariables() {
3475 return environmentVariables;
3476 }
3477
3478 @SuppressWarnings("UnusedDeclaration")
3479 public void setEnvironmentVariables(Map<String, String> environmentVariables) {
3480 this.environmentVariables = environmentVariables;
3481 }
3482
3483 public File getWorkingDirectory() {
3484 return workingDirectory;
3485 }
3486
3487 @SuppressWarnings("UnusedDeclaration")
3488 public void setWorkingDirectory(File workingDirectory) {
3489 this.workingDirectory = workingDirectory;
3490 }
3491
3492 public boolean isChildDelegation() {
3493 return childDelegation;
3494 }
3495
3496 @SuppressWarnings("UnusedDeclaration")
3497 public void setChildDelegation(boolean childDelegation) {
3498 this.childDelegation = childDelegation;
3499 }
3500
3501 public String getGroups() {
3502 return groups;
3503 }
3504
3505 @SuppressWarnings("UnusedDeclaration")
3506 public void setGroups(String groups) {
3507 this.groups = groups;
3508 }
3509
3510 public String getExcludedGroups() {
3511 return excludedGroups;
3512 }
3513
3514 @SuppressWarnings("UnusedDeclaration")
3515 public void setExcludedGroups(String excludedGroups) {
3516 this.excludedGroups = excludedGroups;
3517 }
3518
3519 public String getJunitArtifactName() {
3520 return junitArtifactName;
3521 }
3522
3523 @SuppressWarnings("UnusedDeclaration")
3524 public void setJunitArtifactName(String junitArtifactName) {
3525 this.junitArtifactName = junitArtifactName;
3526 }
3527
3528 public String getTestNGArtifactName() {
3529 return testNGArtifactName;
3530 }
3531
3532 @SuppressWarnings("UnusedDeclaration")
3533 public void setTestNGArtifactName(String testNGArtifactName) {
3534 this.testNGArtifactName = testNGArtifactName;
3535 }
3536
3537 public int getThreadCount() {
3538 return threadCount;
3539 }
3540
3541 @SuppressWarnings("UnusedDeclaration")
3542 public void setThreadCount(int threadCount) {
3543 this.threadCount = threadCount;
3544 }
3545
3546 public boolean getPerCoreThreadCount() {
3547 return perCoreThreadCount;
3548 }
3549
3550 @SuppressWarnings("UnusedDeclaration")
3551 public void setPerCoreThreadCount(boolean perCoreThreadCount) {
3552 this.perCoreThreadCount = perCoreThreadCount;
3553 }
3554
3555 public boolean getUseUnlimitedThreads() {
3556 return useUnlimitedThreads;
3557 }
3558
3559 @SuppressWarnings("UnusedDeclaration")
3560 public void setUseUnlimitedThreads(boolean useUnlimitedThreads) {
3561 this.useUnlimitedThreads = useUnlimitedThreads;
3562 }
3563
3564 public String getParallel() {
3565 return parallel;
3566 }
3567
3568 @SuppressWarnings("UnusedDeclaration")
3569 public void setParallel(String parallel) {
3570 this.parallel = parallel;
3571 }
3572
3573 public boolean isParallelOptimized() {
3574 return parallelOptimized;
3575 }
3576
3577 @SuppressWarnings("UnusedDeclaration")
3578 public void setParallelOptimized(boolean parallelOptimized) {
3579 this.parallelOptimized = parallelOptimized;
3580 }
3581
3582 public int getThreadCountSuites() {
3583 return threadCountSuites;
3584 }
3585
3586 public void setThreadCountSuites(int threadCountSuites) {
3587 this.threadCountSuites = threadCountSuites;
3588 }
3589
3590 public int getThreadCountClasses() {
3591 return threadCountClasses;
3592 }
3593
3594 public void setThreadCountClasses(int threadCountClasses) {
3595 this.threadCountClasses = threadCountClasses;
3596 }
3597
3598 public int getThreadCountMethods() {
3599 return threadCountMethods;
3600 }
3601
3602 public void setThreadCountMethods(int threadCountMethods) {
3603 this.threadCountMethods = threadCountMethods;
3604 }
3605
3606 public boolean isTrimStackTrace() {
3607 return trimStackTrace;
3608 }
3609
3610 @SuppressWarnings("UnusedDeclaration")
3611 public void setTrimStackTrace(boolean trimStackTrace) {
3612 this.trimStackTrace = trimStackTrace;
3613 }
3614
3615 public boolean isEnableAssertions() {
3616 return enableAssertions;
3617 }
3618
3619 public boolean effectiveIsEnableAssertions() {
3620 if (getArgLine() != null) {
3621 List<String> args = asList(getArgLine().split(" "));
3622 if (args.contains("-da") || args.contains("-disableassertions")) {
3623 return false;
3624 }
3625 }
3626 return isEnableAssertions();
3627 }
3628
3629 @SuppressWarnings("UnusedDeclaration")
3630 public void setEnableAssertions(boolean enableAssertions) {
3631 this.enableAssertions = enableAssertions;
3632 }
3633
3634 public boolean isEnableOutErrElements() {
3635 return enableOutErrElements;
3636 }
3637
3638 @SuppressWarnings("UnusedDeclaration")
3639 public void setEnableOutErrElements(boolean enableOutErrElements) {
3640 this.enableOutErrElements = enableOutErrElements;
3641 }
3642
3643 public boolean isEnablePropertiesElement() {
3644 return enablePropertiesElement;
3645 }
3646
3647 public boolean isReportTestTimestamp() {
3648 return reportTestTimestamp;
3649 }
3650
3651 @SuppressWarnings("UnusedDeclaration")
3652 public void setEnablePropertiesElement(boolean enablePropertiesElement) {
3653 this.enablePropertiesElement = enablePropertiesElement;
3654 }
3655
3656 public MavenSession getSession() {
3657 return session;
3658 }
3659
3660 @SuppressWarnings("UnusedDeclaration")
3661 public void setSession(MavenSession session) {
3662 this.session = session;
3663 }
3664
3665 public String getObjectFactory() {
3666 return objectFactory;
3667 }
3668
3669 @SuppressWarnings("UnusedDeclaration")
3670 public void setObjectFactory(String objectFactory) {
3671 this.objectFactory = objectFactory;
3672 }
3673
3674 public ToolchainManager getToolchainManager() {
3675 return toolchainManager;
3676 }
3677
3678 @SuppressWarnings("UnusedDeclaration")
3679 public void setToolchainManager(ToolchainManager toolchainManager) {
3680 this.toolchainManager = toolchainManager;
3681 }
3682
3683 public boolean isMavenParallel() {
3684 return parallelMavenExecution != null && parallelMavenExecution;
3685 }
3686
3687 public String[] getDependenciesToScan() {
3688 return dependenciesToScan;
3689 }
3690
3691 public void setDependenciesToScan(String[] dependenciesToScan) {
3692 this.dependenciesToScan = dependenciesToScan;
3693 }
3694
3695 @SuppressWarnings("UnusedDeclaration")
3696 void setPluginDescriptor(PluginDescriptor pluginDescriptor) {
3697 this.pluginDescriptor = pluginDescriptor;
3698 }
3699
3700 public PluginDescriptor getPluginDescriptor() {
3701 return pluginDescriptor;
3702 }
3703
3704 public MavenProject getProject() {
3705 return project;
3706 }
3707
3708 @SuppressWarnings("UnusedDeclaration")
3709 public void setProject(MavenProject project) {
3710 this.project = project;
3711 }
3712
3713 @Override
3714 public File getTestSourceDirectory() {
3715 return testSourceDirectory;
3716 }
3717
3718 @Override
3719 public void setTestSourceDirectory(File testSourceDirectory) {
3720 this.testSourceDirectory = testSourceDirectory;
3721 }
3722
3723 public String getForkCount() {
3724 return forkCount;
3725 }
3726
3727 public boolean isReuseForks() {
3728 return reuseForks;
3729 }
3730
3731 public String[] getAdditionalClasspathElements() {
3732 return additionalClasspathElements;
3733 }
3734
3735 public void setAdditionalClasspathElements(String[] additionalClasspathElements) {
3736 this.additionalClasspathElements = additionalClasspathElements;
3737 }
3738
3739 public String[] getClasspathDependencyExcludes() {
3740 return classpathDependencyExcludes;
3741 }
3742
3743 public void setClasspathDependencyExcludes(String[] classpathDependencyExcludes) {
3744 this.classpathDependencyExcludes = classpathDependencyExcludes;
3745 }
3746
3747 public String getClasspathDependencyScopeExclude() {
3748 return classpathDependencyScopeExclude;
3749 }
3750
3751 public void setClasspathDependencyScopeExclude(String classpathDependencyScopeExclude) {
3752 this.classpathDependencyScopeExclude = classpathDependencyScopeExclude;
3753 }
3754
3755 public File getProjectBuildDirectory() {
3756 return projectBuildDirectory;
3757 }
3758
3759 public void setProjectBuildDirectory(File projectBuildDirectory) {
3760 this.projectBuildDirectory = projectBuildDirectory;
3761 }
3762
3763 protected void logDebugOrCliShowErrors(String s) {
3764 SurefireHelper.logDebugOrCliShowErrors(s, getConsoleLogger(), cli);
3765 }
3766
3767 public Map<String, String> getJdkToolchain() {
3768 return jdkToolchain;
3769 }
3770
3771 public void setJdkToolchain(Map<String, String> jdkToolchain) {
3772 this.jdkToolchain = jdkToolchain;
3773 }
3774
3775 public String getTempDir() {
3776 return tempDir;
3777 }
3778
3779 public void setTempDir(String tempDir) {
3780 this.tempDir = tempDir;
3781 }
3782
3783 private static final class ClasspathCache {
3784 private final Map<String, Classpath> classpaths = new HashMap<>(4);
3785
3786 private Classpath getCachedClassPath(@Nonnull String artifactId) {
3787 return classpaths.get(artifactId);
3788 }
3789
3790 private void setCachedClasspath(@Nonnull String key, @Nonnull Classpath classpath) {
3791 classpaths.put(key, classpath);
3792 }
3793
3794 private Classpath setCachedClasspath(@Nonnull String key, @Nonnull Set<Artifact> artifacts) {
3795 Collection<String> files = new ArrayList<>();
3796 for (Artifact artifact : artifacts) {
3797 files.add(artifact.getFile().getAbsolutePath());
3798 }
3799 Classpath classpath = new Classpath(files);
3800 setCachedClasspath(key, classpath);
3801 return classpath;
3802 }
3803 }
3804
3805
3806
3807
3808 enum PluginFailureReason {
3809 NONE,
3810 COULD_NOT_RUN_SPECIFIED_TESTS,
3811 COULD_NOT_RUN_DEFAULT_TESTS,
3812 }
3813 }