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