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