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