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