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