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