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
172
173
174 @Parameter
175 private SurefireStatelessReporter statelessTestsetReporter;
176
177 @Parameter
178 private SurefireConsoleOutputReporter consoleOutputReporter;
179
180 @Parameter
181 private SurefireStatelessTestsetInfoReporter statelessTestsetInfoReporter;
182
183
184
185
186
187
188
189 @Parameter(defaultValue = "${plugin}", readonly = true, required = true)
190 private PluginDescriptor pluginDescriptor;
191
192
193
194
195
196
197
198
199
200 @Parameter(property = "skipTests", defaultValue = "false")
201 protected boolean skipTests;
202
203
204
205
206
207
208
209 @Deprecated
210 @Parameter(property = "maven.test.skip.exec")
211 protected boolean skipExec;
212
213
214
215
216
217
218 @Parameter(property = "maven.test.skip", defaultValue = "false")
219 protected boolean skip;
220
221
222
223
224 @Parameter(defaultValue = "${project}", required = true, readonly = true)
225 private MavenProject project;
226
227
228
229
230
231 @Parameter(defaultValue = "${basedir}", readonly = true, required = true)
232 protected File basedir;
233
234
235
236
237
238 @Parameter(defaultValue = "${project.build.testOutputDirectory}")
239 protected File testClassesDirectory;
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 @Parameter(property = "maven.test.dependency.excludes")
256 private String[] classpathDependencyExcludes;
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272 @Parameter(defaultValue = "")
273 private String classpathDependencyScopeExclude;
274
275
276
277
278
279
280
281
282 @Parameter(property = "maven.test.additionalClasspath")
283 private String[] additionalClasspathElements;
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302 @Parameter(property = "maven.test.additionalClasspathDependencies")
303 private List<Dependency> additionalClasspathDependencies;
304
305
306
307
308
309
310
311 @Parameter(defaultValue = "${project.build.testSourceDirectory}")
312 private File testSourceDirectory;
313
314
315
316
317
318
319
320 @Deprecated
321 @Parameter
322 Properties systemProperties;
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 @Parameter
350 Map<String, String> systemPropertyVariables;
351
352
353
354
355
356
357
358
359 @Parameter(defaultValue = "true")
360 boolean promoteUserPropertiesToSystemProperties;
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382 @Parameter
383 private Properties properties;
384
385
386
387
388 @Parameter(property = "plugin.artifactMap", required = true, readonly = true)
389 private Map<String, Artifact> pluginArtifactMap;
390
391
392
393
394 @Parameter(property = "project.artifactMap", readonly = true, required = true)
395 private Map<String, Artifact> projectArtifactMap;
396
397
398
399
400
401
402
403 @Parameter(property = "surefire.reportNameSuffix", defaultValue = "")
404 private String reportNameSuffix;
405
406
407
408
409
410
411
412 @Parameter(property = "maven.test.redirectTestOutputToFile", defaultValue = "false")
413 private boolean redirectTestOutputToFile;
414
415
416
417
418
419
420 @Parameter(property = "failIfNoTests", defaultValue = "false")
421 private boolean failIfNoTests;
422
423
424
425
426
427
428
429
430
431
432
433
434 @Parameter(property = "tempDir", defaultValue = "surefire")
435 private String tempDir;
436
437
438
439
440
441
442
443
444 @Parameter(property = "jvm")
445 private String jvm;
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464 @Parameter(property = "argLine")
465 private String argLine;
466
467
468
469
470
471
472 @Parameter
473 private Map<String, String> environmentVariables = new HashMap<>();
474
475
476
477
478
479
480 @Parameter(property = "basedir")
481 private File workingDirectory;
482
483
484
485
486
487
488
489
490
491 @Parameter(property = "childDelegation", defaultValue = "false")
492 private boolean childDelegation;
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507 @Parameter(property = "groups")
508 private String groups;
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523 @Parameter(property = "excludedGroups")
524 private String excludedGroups;
525
526
527
528
529
530
531 @Parameter(property = "junitArtifactName", defaultValue = "junit:junit")
532 private String junitArtifactName;
533
534
535
536
537
538
539 @Parameter(property = "testNGArtifactName", defaultValue = "org.testng:testng")
540 private String testNGArtifactName;
541
542
543
544
545
546
547
548 @Parameter(property = "threadCount")
549 private int threadCount;
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566 @Parameter(property = "forkCount", defaultValue = "1")
567 String forkCount;
568
569
570
571
572
573
574
575 @Parameter(property = "reuseForks", defaultValue = "true")
576 private boolean reuseForks;
577
578
579
580
581
582
583
584 @Parameter(property = "perCoreThreadCount", defaultValue = "true")
585 private boolean perCoreThreadCount;
586
587
588
589
590
591
592
593
594 @Parameter(property = "useUnlimitedThreads", defaultValue = "false")
595 private boolean useUnlimitedThreads;
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620 @Parameter(property = "parallel")
621 private String parallel;
622
623
624
625
626
627
628
629
630
631 @Parameter(property = "parallelOptimized", defaultValue = "true")
632 private boolean parallelOptimized;
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650 @Parameter(property = "threadCountSuites", defaultValue = "0")
651 private int threadCountSuites;
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673 @Parameter(property = "threadCountClasses", defaultValue = "0")
674 private int threadCountClasses;
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695 @Parameter(property = "threadCountMethods", defaultValue = "0")
696 private int threadCountMethods;
697
698
699
700
701
702
703 @Parameter(property = "trimStackTrace", defaultValue = "false")
704 private boolean trimStackTrace;
705
706
707
708
709
710
711
712 @Deprecated
713 @Parameter(property = "disableXmlReport", defaultValue = "false")
714 private boolean disableXmlReport;
715
716
717
718
719
720
721
722 @Parameter(property = "enableAssertions", defaultValue = "true")
723 private boolean enableAssertions;
724
725
726
727
728
729
730
731
732 @Parameter(property = "enableOutErrElements", defaultValue = "true")
733 private boolean enableOutErrElements;
734
735
736
737
738
739
740 @Parameter(property = "enablePropertiesElement", defaultValue = "true")
741 private boolean enablePropertiesElement;
742
743
744
745
746 @Parameter(defaultValue = "${session}", required = true, readonly = true)
747 private MavenSession session;
748
749 @Component
750 private Logger logger;
751
752
753
754
755
756
757 @Parameter(property = "objectFactory")
758 private String objectFactory;
759
760
761
762
763 @Parameter(defaultValue = "${session.parallel}", readonly = true)
764 private Boolean parallelMavenExecution;
765
766
767
768
769
770 @Parameter(defaultValue = "${project.build.directory}", readonly = true, required = true)
771 private File projectBuildDirectory;
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801 @Parameter(property = "dependenciesToScan")
802 private String[] dependenciesToScan;
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837 @Parameter
838 private Map<String, String> jdkToolchain;
839
840
841
842
843 @Component
844 private ToolchainManager toolchainManager;
845
846 @Component
847 private LocationManager locationManager;
848
849 @Component
850 private ProviderDetector providerDetector;
851
852 private Toolchain toolchain;
853
854 private int effectiveForkCount = -1;
855
856 protected abstract String getPluginName();
857
858 protected abstract int getRerunFailingTestsCount();
859
860 @Override
861 public abstract List<String> getIncludes();
862
863 public abstract File getIncludesFile();
864
865 @Override
866 public abstract void setIncludes(List<String> includes);
867
868 public abstract File getExcludesFile();
869
870
871
872
873
874
875
876 protected abstract List<File> suiteXmlFiles();
877
878
879
880
881 protected abstract boolean hasSuiteXmlFiles();
882
883 protected abstract String[] getExcludedEnvironmentVariables();
884
885 public abstract File[] getSuiteXmlFiles();
886
887 public abstract void setSuiteXmlFiles(File[] suiteXmlFiles);
888
889 public abstract String getRunOrder();
890
891 public abstract void setRunOrder(String runOrder);
892
893 public abstract Long getRunOrderRandomSeed();
894
895 public abstract void setRunOrderRandomSeed(Long runOrderRandomSeed);
896
897 protected abstract void handleSummary(RunResult summary, Exception firstForkException)
898 throws MojoExecutionException, MojoFailureException;
899
900 protected abstract boolean isSkipExecution();
901
902 protected abstract String[] getDefaultIncludes();
903
904 protected abstract String getReportSchemaLocation();
905
906 protected abstract boolean useModulePath();
907
908 protected abstract void setUseModulePath(boolean useModulePath);
909
910 protected abstract String getEnableProcessChecker();
911
912 protected abstract ForkNodeFactory getForkNode();
913
914
915
916
917
918
919 protected Artifact getMojoArtifact() {
920 return getPluginDescriptor().getPluginArtifact();
921 }
922
923 private String getDefaultExcludes() {
924 return "**/*$*";
925 }
926
927 @Component(role = SurefireDependencyResolver.class)
928 private SurefireDependencyResolver surefireDependencyResolver;
929
930 private TestListResolver specificTests;
931
932 private TestListResolver includedExcludedTests;
933
934 private List<CommandLineOption> cli;
935
936 private volatile PluginConsoleLogger consoleLogger;
937
938 @Override
939 public void execute() throws MojoExecutionException, MojoFailureException {
940 if (isSkipExecution()) {
941 getConsoleLogger().info("Tests are skipped.");
942 return;
943 }
944
945 cli = commandLineOptions();
946
947 setupStuff();
948 Platform platform = PLATFORM.withJdkExecAttributesForTests(getEffectiveJvm());
949 Thread shutdownThread = new Thread(platform::setShutdownState);
950 addShutDownHook(shutdownThread);
951 try {
952 if (verifyParameters() && !hasExecutedBefore()) {
953 DefaultScanResult scan = scanForTestClasses();
954 if (!hasSuiteXmlFiles() && scan.isEmpty()) {
955 switch (getEffectiveFailIfNoTests()) {
956 case COULD_NOT_RUN_DEFAULT_TESTS:
957 throw new MojoFailureException(
958 "No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)");
959 case COULD_NOT_RUN_SPECIFIED_TESTS:
960 throw new MojoFailureException("No tests matching pattern \""
961 + getSpecificTests().toString()
962 + "\" were executed! (Set "
963 + "-D" + getPluginName()
964 + ".failIfNoSpecifiedTests=false to ignore this error.)");
965 default:
966 handleSummary(noTestsRun(), null);
967 return;
968 }
969 }
970 logReportsDirectory();
971 executeAfterPreconditionsChecked(scan, platform);
972 }
973 } finally {
974 platform.clearShutdownState();
975 removeShutdownHook(shutdownThread);
976 }
977 }
978
979 void setLogger(Logger logger) {
980 this.logger = logger;
981 }
982
983 void setSurefireDependencyResolver(SurefireDependencyResolver surefireDependencyResolver) {
984 this.surefireDependencyResolver = surefireDependencyResolver;
985 }
986
987 @Nonnull
988 protected final PluginConsoleLogger getConsoleLogger() {
989 if (consoleLogger == null) {
990 synchronized (this) {
991 if (consoleLogger == null) {
992 consoleLogger = new PluginConsoleLogger(logger);
993 }
994 }
995 }
996 return consoleLogger;
997 }
998
999 private Toolchain getToolchain() throws MojoFailureException {
1000 Toolchain tc = null;
1001
1002 if (getJdkToolchain() != null) {
1003 List<Toolchain> tcs = getToolchainManager().getToolchains(getSession(), "jdk", getJdkToolchain());
1004 if (tcs.isEmpty()) {
1005 throw new MojoFailureException(
1006 "Requested toolchain specification did not match any configured toolchain: "
1007 + getJdkToolchain());
1008 }
1009 tc = tcs.get(0);
1010 }
1011
1012 if (tc == null) {
1013 tc = getToolchainManager().getToolchainFromBuildContext("jdk", getSession());
1014 }
1015
1016 return tc;
1017 }
1018
1019 private void setupStuff() throws MojoFailureException {
1020
1021 if (getBooterArtifact() == null) {
1022 throw new RuntimeException("Unable to locate surefire-booter in the list of plugin artifacts");
1023 }
1024
1025 if (getToolchainManager() != null) {
1026 toolchain = getToolchain();
1027 }
1028 }
1029
1030 @Nonnull
1031 private DefaultScanResult scanForTestClasses() throws MojoFailureException {
1032 DefaultScanResult scan = scanDirectories();
1033 DefaultScanResult scanDeps = scanDependencies();
1034 return scan.append(scanDeps);
1035 }
1036
1037 private DefaultScanResult scanDirectories() throws MojoFailureException {
1038 DirectoryScanner scanner = new DirectoryScanner(getTestClassesDirectory(), getIncludedAndExcludedTests());
1039 return scanner.scan();
1040 }
1041
1042 List<Artifact> getProjectTestArtifacts() {
1043 return project.getTestArtifacts();
1044 }
1045
1046 DefaultScanResult scanDependencies() throws MojoFailureException {
1047 if (getDependenciesToScan() == null) {
1048 return null;
1049 } else {
1050 try {
1051 DefaultScanResult result = null;
1052
1053 List<Artifact> dependenciesToScan = filter(getProjectTestArtifacts(), asList(getDependenciesToScan()));
1054
1055 for (Artifact artifact : dependenciesToScan) {
1056 String type = artifact.getType();
1057 File out = artifact.getFile();
1058 if (out == null
1059 || !out.exists()
1060 || !("jar".equals(type)
1061 || out.isDirectory()
1062 || out.getName().endsWith(".jar"))) {
1063 continue;
1064 }
1065
1066 if (out.isFile()) {
1067 DependencyScanner scanner =
1068 new DependencyScanner(singletonList(out), getIncludedAndExcludedTests());
1069 result = result == null ? scanner.scan() : result.append(scanner.scan());
1070 } else if (out.isDirectory()) {
1071 DirectoryScanner scanner = new DirectoryScanner(out, getIncludedAndExcludedTests());
1072 result = result == null ? scanner.scan() : result.append(scanner.scan());
1073 }
1074 }
1075
1076 return result;
1077 } catch (Exception e) {
1078 throw new MojoFailureException(e.getLocalizedMessage(), e);
1079 }
1080 }
1081 }
1082
1083 boolean verifyParameters() throws MojoFailureException, MojoExecutionException {
1084 setProperties(new SurefireProperties(getProperties()));
1085
1086 String jvmToUse = getJvm();
1087 if (toolchain != null) {
1088 getConsoleLogger().info("Toolchain in maven-" + getPluginName() + "-plugin: " + toolchain);
1089 if (jvmToUse != null) {
1090 getConsoleLogger().warning("Toolchains are ignored, 'jvm' parameter is set to " + jvmToUse);
1091 }
1092 }
1093
1094 if (!getTestClassesDirectory().exists()
1095 && (getDependenciesToScan() == null || getDependenciesToScan().length == 0)) {
1096 if (getFailIfNoTests()) {
1097 throw new MojoFailureException("No tests to run!");
1098 }
1099 getConsoleLogger().info("No tests to run.");
1100 } else {
1101 ensureEnableProcessChecker();
1102 ensureWorkingDirectoryExists();
1103 ensureParallelRunningCompatibility();
1104 warnIfUselessUseSystemClassLoaderParameter();
1105 warnIfDefunctGroupsCombinations();
1106 warnIfRerunClashes();
1107 warnIfWrongShutdownValue();
1108 warnIfNotApplicableSkipAfterFailureCount();
1109 warnIfIllegalTempDir();
1110 warnIfForkCountIsZero();
1111 warnIfIllegalFailOnFlakeCount();
1112 printDefaultSeedIfNecessary();
1113 }
1114 return true;
1115 }
1116
1117 private void warnIfForkCountIsZero() {
1118 if ("0".equals(getForkCount())) {
1119 getConsoleLogger()
1120 .warning("The parameter forkCount should likely not be 0. Forking a JVM for tests "
1121 + "improves test accuracy. Ensure to have a <forkCount> >= 1.");
1122 }
1123 }
1124
1125 private void executeAfterPreconditionsChecked(@Nonnull DefaultScanResult scanResult, @Nonnull Platform platform)
1126 throws MojoExecutionException, MojoFailureException {
1127 TestClassPath testClasspath = generateTestClasspath();
1128 List<ProviderInfo> providers = createProviders(testClasspath);
1129 ResolvePathResultWrapper wrapper =
1130 findModuleDescriptor(platform.getJdkExecAttributesForTests().getJdkHome());
1131
1132 RunResult current = noTestsRun();
1133
1134 Exception firstForkException = null;
1135 for (ProviderInfo provider : providers) {
1136 try {
1137 current = current.aggregate(executeProvider(provider, scanResult, testClasspath, platform, wrapper));
1138 } catch (SurefireBooterForkException | SurefireExecutionException | TestSetFailedException e) {
1139 if (firstForkException == null) {
1140 firstForkException = e;
1141 }
1142 }
1143 }
1144
1145 if (firstForkException != null) {
1146 current = failure(current, firstForkException);
1147 }
1148
1149 handleSummary(current, firstForkException);
1150 }
1151
1152 protected List<ProviderInfo> createProviders(TestClassPath testClasspath) throws MojoExecutionException {
1153 Artifact junitDepArtifact = getJunitDepArtifact();
1154 return providerDetector.resolve(
1155 new DynamicProviderInfo(null),
1156 new JUnitPlatformProviderInfo(getJUnitPlatformRunnerArtifact(), getJUnit5Artifact(), testClasspath),
1157 new TestNgProviderInfo(getTestNgArtifact()),
1158 new JUnitCoreProviderInfo(getJunitArtifact(), junitDepArtifact),
1159 new JUnit4ProviderInfo(getJunitArtifact(), junitDepArtifact),
1160 new JUnit3ProviderInfo());
1161 }
1162
1163 SurefireProperties setupProperties() {
1164 SurefireProperties sysPropsFromFile = null;
1165 try {
1166 sysPropsFromFile = SurefireProperties.loadProperties(getSystemPropertiesFile());
1167 } catch (IOException e) {
1168 String msg = "The file '" + getSystemPropertiesFile().getAbsolutePath() + "' can't be read.";
1169 if (getConsoleLogger().isDebugEnabled()) {
1170 getConsoleLogger().debug(msg, e);
1171 } else {
1172 getConsoleLogger().warning(msg);
1173 }
1174 }
1175
1176 SurefireProperties result = calculateEffectiveProperties(
1177 getSystemProperties(),
1178 getSystemPropertyVariables(),
1179 promoteUserPropertiesToSystemProperties ? getUserProperties() : new Properties(),
1180 sysPropsFromFile);
1181
1182 result.setProperty("basedir", getBasedir().getAbsolutePath());
1183 result.setProperty("localRepository", getLocalRepositoryPath());
1184 if (isForking()) {
1185 for (Object o : result.propertiesThatCannotBeSetASystemProperties()) {
1186 if (getArgLine() == null || !getArgLine().contains("-D" + o + "=")) {
1187 getConsoleLogger()
1188 .warning(o + " cannot be set as system property, use <argLine>-D" + o
1189 + "=...</argLine> instead");
1190 }
1191 }
1192 for (Object systemPropertyMatchingArgLine : systemPropertiesMatchingArgLine(result)) {
1193 getConsoleLogger()
1194 .warning("The system property "
1195 + systemPropertyMatchingArgLine
1196 + " is configured twice! "
1197 + "The property appears in <argLine/> and any of <systemPropertyVariables/>, "
1198 + "<systemProperties/> or user property.");
1199 }
1200 } else {
1201 result.setProperty("user.dir", getWorkingDirectory().getAbsolutePath());
1202 }
1203
1204 if (getConsoleLogger().isDebugEnabled()) {
1205 showToLog(result, getConsoleLogger());
1206 }
1207
1208 return result;
1209 }
1210
1211 private SurefireProperties calculateEffectiveProperties(
1212 Properties systemProperties,
1213 Map<String, String> systemPropertyVariables,
1214 Properties userProperties,
1215 SurefireProperties sysPropsFromFile) {
1216 SurefireProperties result = new SurefireProperties();
1217 result.copyPropertiesFrom(systemProperties);
1218
1219 Collection<String> overwrittenProperties = result.copyPropertiesFrom(sysPropsFromFile);
1220 if (!overwrittenProperties.isEmpty() && getConsoleLogger().isDebugEnabled()) {
1221 getConsoleLogger().debug(getOverwrittenPropertiesLogMessage(overwrittenProperties, "systemPropertiesFile"));
1222 }
1223 overwrittenProperties = result.copyPropertiesFrom(systemPropertyVariables);
1224 if (!overwrittenProperties.isEmpty() && getConsoleLogger().isDebugEnabled()) {
1225 getConsoleLogger()
1226 .debug(getOverwrittenPropertiesLogMessage(overwrittenProperties, "systemPropertyVariables"));
1227 }
1228
1229
1230
1231
1232 if (!userProperties.isEmpty()) {
1233 overwrittenProperties = result.copyPropertiesFrom(userProperties);
1234 if (!overwrittenProperties.isEmpty()) {
1235 getConsoleLogger()
1236 .warning(getOverwrittenPropertiesLogMessage(
1237 overwrittenProperties, "user properties from Maven session"));
1238 }
1239 }
1240 return result;
1241 }
1242
1243 private Set<Object> systemPropertiesMatchingArgLine(SurefireProperties result) {
1244 Set<Object> intersection = new HashSet<>();
1245 if (isNotBlank(getArgLine())) {
1246 for (Object systemProperty : result.getStringKeySet()) {
1247 if (getArgLine().contains("-D" + systemProperty + "=")) {
1248 intersection.add(systemProperty);
1249 }
1250 }
1251
1252 Set<Object> ignored = result.propertiesThatCannotBeSetASystemProperties();
1253 intersection.removeAll(ignored);
1254 }
1255 return intersection;
1256 }
1257
1258 private String getOverwrittenPropertiesLogMessage(
1259 Collection<String> overwrittenProperties, String overwrittenBySource) {
1260 if (overwrittenProperties.isEmpty()) {
1261 throw new IllegalArgumentException("overwrittenProperties must not be empty");
1262 }
1263
1264 ChoiceFormat propertyChoice = new ChoiceFormat("1#property|1>properties");
1265 StringBuilder message = new StringBuilder("System ");
1266 message.append(propertyChoice.format(overwrittenProperties.size())).append(" ");
1267 message.append(overwrittenProperties.stream().collect(Collectors.joining("], [", "[", "]")));
1268 message.append(" overwritten by ").append(overwrittenBySource);
1269 return message.toString();
1270 }
1271
1272 private void showToLog(SurefireProperties props, ConsoleLogger log) {
1273 for (Object key : props.getStringKeySet()) {
1274 String value = props.getProperty((String) key);
1275 log.debug("Setting system property [" + key + "]=[" + value + "]");
1276 }
1277 }
1278
1279 @Nonnull
1280 private RunResult executeProvider(
1281 @Nonnull ProviderInfo provider,
1282 @Nonnull DefaultScanResult scanResult,
1283 @Nonnull TestClassPath testClasspathWrapper,
1284 @Nonnull Platform platform,
1285 @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult)
1286 throws MojoExecutionException, MojoFailureException, SurefireExecutionException,
1287 SurefireBooterForkException, TestSetFailedException {
1288 getConsoleLogger().debug("Using the provider " + provider.getProviderName());
1289 SurefireProperties effectiveProperties = setupProperties();
1290 ClassLoaderConfiguration classLoaderConfiguration = getClassLoaderConfiguration();
1291 provider.addProviderProperties();
1292 RunOrderParameters runOrderParameters =
1293 new RunOrderParameters(getRunOrder(), getStatisticsFile(getConfigChecksum()), getRunOrderRandomSeed());
1294
1295 if (isNotForking()) {
1296 Properties originalSystemProperties =
1297 (Properties) System.getProperties().clone();
1298 try {
1299 createCopyAndReplaceForkNumPlaceholder(effectiveProperties, 1).copyToSystemProperties();
1300 getConsoleLogger().debug("Using in-process starter");
1301 InPluginVMSurefireStarter surefireStarter = createInprocessStarter(
1302 provider,
1303 classLoaderConfiguration,
1304 runOrderParameters,
1305 scanResult,
1306 platform,
1307 testClasspathWrapper);
1308 return surefireStarter.runSuitesInProcess(scanResult);
1309 } finally {
1310 System.setProperties(originalSystemProperties);
1311 }
1312 } else {
1313 ForkConfiguration forkConfiguration = createForkConfiguration(platform, resolvedJavaModularityResult);
1314 if (getConsoleLogger().isDebugEnabled()) {
1315 getConsoleLogger()
1316 .debug("Using fork starter with configuration implementation "
1317 + forkConfiguration.getClass().getName());
1318 showMap(getEnvironmentVariables(), "environment variable");
1319 showArray(getExcludedEnvironmentVariables(), "excluded environment variable");
1320 }
1321
1322 Properties originalSystemProperties =
1323 (Properties) System.getProperties().clone();
1324 ForkStarter forkStarter = null;
1325 try {
1326 forkStarter = createForkStarter(
1327 provider,
1328 forkConfiguration,
1329 classLoaderConfiguration,
1330 runOrderParameters,
1331 getConsoleLogger(),
1332 scanResult,
1333 testClasspathWrapper,
1334 platform,
1335 resolvedJavaModularityResult);
1336
1337 return forkStarter.run(effectiveProperties, scanResult);
1338 } catch (SurefireBooterForkException e) {
1339 forkStarter.killOrphanForks();
1340 throw e;
1341 } finally {
1342 System.setProperties(originalSystemProperties);
1343 cleanupForkConfiguration(forkConfiguration);
1344 }
1345 }
1346 }
1347
1348 public static SurefireProperties createCopyAndReplaceForkNumPlaceholder(
1349 SurefireProperties effectiveSystemProperties, int threadNumber) {
1350 SurefireProperties filteredProperties = new SurefireProperties((KeyValueSource) effectiveSystemProperties);
1351 for (Entry<Object, Object> entry : effectiveSystemProperties.entrySet()) {
1352 if (entry.getValue() instanceof String) {
1353 String value = (String) entry.getValue();
1354 filteredProperties.put(entry.getKey(), replaceThreadNumberPlaceholders(value, threadNumber));
1355 }
1356 }
1357 return filteredProperties;
1358 }
1359
1360 protected void cleanupForkConfiguration(ForkConfiguration forkConfiguration) {
1361 if (!getConsoleLogger().isDebugEnabled() && forkConfiguration != null) {
1362 File tempDirectory = forkConfiguration.getTempDirectory();
1363 try {
1364 FileUtils.deleteDirectory(tempDirectory);
1365 } catch (IOException e) {
1366 getConsoleLogger()
1367 .warning("Could not delete temp directory " + tempDirectory + " because " + e.getMessage());
1368 }
1369 }
1370 }
1371
1372 protected void logReportsDirectory() {
1373 logDebugOrCliShowErrors(capitalizeFirstLetter(getPluginName()) + " report directory: " + getReportsDirectory());
1374 }
1375
1376 private boolean existsModuleDescriptor(ResolvePathResultWrapper resolvedJavaModularityResult) {
1377 return resolvedJavaModularityResult.getResolvePathResult() != null;
1378 }
1379
1380 private ResolvePathResultWrapper findModuleDescriptor(File jdkHome) {
1381 ResolvePathResultWrapper test = findModuleDescriptor(jdkHome, getTestClassesDirectory(), false);
1382 return test.getResolvePathResult() == null ? findModuleDescriptor(jdkHome, getMainBuildPath(), true) : test;
1383 }
1384
1385 private ResolvePathResultWrapper findModuleDescriptor(File jdkHome, File buildPath, boolean isMainDescriptor) {
1386 boolean isJpmsModule =
1387 buildPath.isDirectory() ? new File(buildPath, "module-info.class").exists() : isModule(buildPath);
1388
1389 if (!isJpmsModule) {
1390 return new ResolvePathResultWrapper(null, isMainDescriptor);
1391 }
1392
1393 try {
1394 ResolvePathRequest<?> request = ResolvePathRequest.ofFile(buildPath).setJdkHome(jdkHome);
1395 ResolvePathResult result = getLocationManager().resolvePath(request);
1396 boolean isEmpty = result.getModuleNameSource() == null;
1397 return new ResolvePathResultWrapper(isEmpty ? null : result, isMainDescriptor);
1398 } catch (Exception e) {
1399 return new ResolvePathResultWrapper(null, isMainDescriptor);
1400 }
1401 }
1402
1403 private static boolean isModule(File jar) {
1404 try (ZipFile zip = new ZipFile(jar)) {
1405 return zip.getEntry("module-info.class") != null;
1406 } catch (IOException e) {
1407 return false;
1408 }
1409 }
1410
1411 private boolean canExecuteProviderWithModularPath(
1412 @Nonnull Platform platform, @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult) {
1413 return useModulePath()
1414 && platform.getJdkExecAttributesForTests().isJava9AtLeast()
1415 && existsModuleDescriptor(resolvedJavaModularityResult);
1416 }
1417
1418
1419
1420
1421
1422 private void convertTestNGParameters() throws MojoExecutionException {
1423 if (this.getParallel() != null) {
1424 getProperties().setProperty(ProviderParameterNames.PARALLEL_PROP, this.getParallel());
1425 }
1426 convertGroupParameters();
1427
1428 if (this.getThreadCount() > 0) {
1429 getProperties()
1430 .setProperty(ProviderParameterNames.THREADCOUNT_PROP, Integer.toString(this.getThreadCount()));
1431 }
1432 if (this.getObjectFactory() != null) {
1433 getProperties().setProperty("objectfactory", this.getObjectFactory());
1434 }
1435 if (this.getTestClassesDirectory() != null) {
1436 getProperties()
1437 .setProperty(
1438 "testng.test.classpath", getTestClassesDirectory().getAbsolutePath());
1439 }
1440
1441 Artifact testNgArtifact = getTestNgArtifact();
1442 if (testNgArtifact != null) {
1443 DefaultArtifactVersion defaultArtifactVersion = new DefaultArtifactVersion(testNgArtifact.getVersion());
1444 getProperties()
1445 .setProperty(
1446 "testng.configurator", getConfiguratorName(defaultArtifactVersion, getConsoleLogger()));
1447 }
1448 }
1449
1450 private static String getConfiguratorName(ArtifactVersion version, PluginConsoleLogger log)
1451 throws MojoExecutionException {
1452 try {
1453 VersionRange range = VersionRange.createFromVersionSpec("[4.7,5.2)");
1454 if (range.containsVersion(version)) {
1455 return "org.apache.maven.surefire.testng.conf.TestNG4751Configurator";
1456 }
1457 range = VersionRange.createFromVersionSpec("[5.2,5.3)");
1458 if (range.containsVersion(version)) {
1459 return "org.apache.maven.surefire.testng.conf.TestNG52Configurator";
1460 }
1461 range = VersionRange.createFromVersionSpec("[5.3,5.10)");
1462 if (range.containsVersion(version)) {
1463 return "org.apache.maven.surefire.testng.conf.TestNGMapConfigurator";
1464 }
1465 range = VersionRange.createFromVersionSpec("[5.10,5.13)");
1466 if (range.containsVersion(version)) {
1467 return "org.apache.maven.surefire.testng.conf.TestNG510Configurator";
1468 }
1469 range = VersionRange.createFromVersionSpec("[5.13,5.14.1)");
1470 if (range.containsVersion(version)) {
1471 return "org.apache.maven.surefire.testng.conf.TestNG513Configurator";
1472 }
1473 range = VersionRange.createFromVersionSpec("[5.14.1,5.14.3)");
1474 if (range.containsVersion(version)) {
1475 log.warning("The 'reporter' or 'listener' may not work properly in TestNG 5.14.1 and 5.14.2.");
1476 return "org.apache.maven.surefire.testng.conf.TestNG5141Configurator";
1477 }
1478 range = VersionRange.createFromVersionSpec("[5.14.3,6.0)");
1479 if (range.containsVersion(version)) {
1480 if (version.equals(new DefaultArtifactVersion("[5.14.3,5.14.5]"))) {
1481 throw new MojoExecutionException("TestNG 5.14.3-5.14.5 is not supported. "
1482 + "System dependency org.testng:guice missed path.");
1483 }
1484 return "org.apache.maven.surefire.testng.conf.TestNG5143Configurator";
1485 }
1486 range = VersionRange.createFromVersionSpec("[6.0,7.4.0)");
1487 if (range.containsVersion(version)) {
1488 return "org.apache.maven.surefire.testng.conf.TestNG60Configurator";
1489 }
1490 range = VersionRange.createFromVersionSpec("[7.4.0,)");
1491 if (range.containsVersion(version)) {
1492 return "org.apache.maven.surefire.testng.conf.TestNG740Configurator";
1493 }
1494
1495 throw new MojoExecutionException("Unknown TestNG version " + version);
1496 } catch (InvalidVersionSpecificationException invsex) {
1497 throw new MojoExecutionException("Bug in plugin. Please report it with the attached stacktrace", invsex);
1498 }
1499 }
1500
1501 private void convertGroupParameters() {
1502 if (this.getExcludedGroups() != null) {
1503 getProperties().setProperty(ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP, this.getExcludedGroups());
1504 }
1505 if (this.getGroups() != null) {
1506 getProperties().setProperty(ProviderParameterNames.TESTNG_GROUPS_PROP, this.getGroups());
1507 }
1508 }
1509
1510 private void convertJunitEngineParameters() {
1511 if (getIncludeJUnit5Engines() != null && getIncludeJUnit5Engines().length != 0) {
1512 getProperties().setProperty(INCLUDE_JUNIT5_ENGINES_PROP, join(getIncludeJUnit5Engines()));
1513 }
1514
1515 if (getExcludeJUnit5Engines() != null && getExcludeJUnit5Engines().length != 0) {
1516 getProperties().setProperty(EXCLUDE_JUNIT5_ENGINES_PROP, join(getExcludeJUnit5Engines()));
1517 }
1518 }
1519
1520 private static String join(String[] array) {
1521 StringBuilder stringBuilder = new StringBuilder();
1522 for (int i = 0, length = array.length; i < length; i++) {
1523 stringBuilder.append(array[i]);
1524 if (i < length - 1) {
1525 stringBuilder.append(',');
1526 }
1527 }
1528 return stringBuilder.toString();
1529 }
1530
1531 protected boolean isAnyConcurrencySelected() {
1532 return getParallel() != null && !getParallel().trim().isEmpty();
1533 }
1534
1535 protected boolean isAnyGroupsSelected() {
1536 return this.getGroups() != null || this.getExcludedGroups() != null;
1537 }
1538
1539
1540
1541
1542
1543 private void convertJunitCoreParameters() throws MojoExecutionException {
1544 checkThreadCountEntity(getThreadCountSuites(), "suites");
1545 checkThreadCountEntity(getThreadCountClasses(), "classes");
1546 checkThreadCountEntity(getThreadCountMethods(), "methods");
1547
1548 String usedParallel = (getParallel() != null) ? getParallel() : "none";
1549
1550 if (!"none".equals(usedParallel)) {
1551 checkNonForkedThreads(parallel);
1552 }
1553
1554 getProperties().setProperty(ProviderParameterNames.PARALLEL_PROP, usedParallel);
1555 if (this.getThreadCount() > 0) {
1556 getProperties().setProperty(ProviderParameterNames.THREADCOUNT_PROP, Integer.toString(getThreadCount()));
1557 }
1558 getProperties().setProperty("perCoreThreadCount", Boolean.toString(getPerCoreThreadCount()));
1559 getProperties().setProperty("useUnlimitedThreads", Boolean.toString(getUseUnlimitedThreads()));
1560 getProperties()
1561 .setProperty(ProviderParameterNames.THREADCOUNTSUITES_PROP, Integer.toString(getThreadCountSuites()));
1562 getProperties()
1563 .setProperty(ProviderParameterNames.THREADCOUNTCLASSES_PROP, Integer.toString(getThreadCountClasses()));
1564 getProperties()
1565 .setProperty(ProviderParameterNames.THREADCOUNTMETHODS_PROP, Integer.toString(getThreadCountMethods()));
1566 getProperties()
1567 .setProperty(
1568 ProviderParameterNames.PARALLEL_TIMEOUT_PROP,
1569 Double.toString(getParallelTestsTimeoutInSeconds()));
1570 getProperties()
1571 .setProperty(
1572 ProviderParameterNames.PARALLEL_TIMEOUTFORCED_PROP,
1573 Double.toString(getParallelTestsTimeoutForcedInSeconds()));
1574 getProperties()
1575 .setProperty(ProviderParameterNames.PARALLEL_OPTIMIZE_PROP, Boolean.toString(isParallelOptimized()));
1576 getProperties()
1577 .setProperty(
1578 ProviderParameterNames.ENABLE_OUT_ERR_ELEMENTS_PROP,
1579 Boolean.toString(isEnableOutErrElements()));
1580 getProperties()
1581 .setProperty(
1582 ProviderParameterNames.ENABLE_PROPERTIES_ELEMENT_PROP,
1583 Boolean.toString(isEnablePropertiesElement()));
1584
1585 String message = "parallel='" + usedParallel + '\''
1586 + ", perCoreThreadCount=" + getPerCoreThreadCount()
1587 + ", threadCount=" + getThreadCount()
1588 + ", useUnlimitedThreads=" + getUseUnlimitedThreads()
1589 + ", threadCountSuites=" + getThreadCountSuites()
1590 + ", threadCountClasses=" + getThreadCountClasses()
1591 + ", threadCountMethods=" + getThreadCountMethods()
1592 + ", parallelOptimized=" + isParallelOptimized()
1593 + ", enableOutErrElements=" + isEnableOutErrElements()
1594 + ", enablePropertiesElement=" + isEnablePropertiesElement();
1595
1596 logDebugOrCliShowErrors(message);
1597 }
1598
1599 private void checkNonForkedThreads(String parallel) throws MojoExecutionException {
1600 if ("suites".equals(parallel)) {
1601 if (!(getUseUnlimitedThreads() || getThreadCount() > 0 ^ getThreadCountSuites() > 0)) {
1602 throw new MojoExecutionException(
1603 "Use threadCount or threadCountSuites > 0 or useUnlimitedThreads=true for parallel='suites'");
1604 }
1605 setThreadCountClasses(0);
1606 setThreadCountMethods(0);
1607 } else if ("classes".equals(parallel)) {
1608 if (!(getUseUnlimitedThreads() || getThreadCount() > 0 ^ getThreadCountClasses() > 0)) {
1609 throw new MojoExecutionException(
1610 "Use threadCount or threadCountClasses > 0 or useUnlimitedThreads=true for parallel='classes'");
1611 }
1612 setThreadCountSuites(0);
1613 setThreadCountMethods(0);
1614 } else if ("methods".equals(parallel)) {
1615 if (!(getUseUnlimitedThreads() || getThreadCount() > 0 ^ getThreadCountMethods() > 0)) {
1616 throw new MojoExecutionException(
1617 "Use threadCount or threadCountMethods > 0 or useUnlimitedThreads=true for parallel='methods'");
1618 }
1619 setThreadCountSuites(0);
1620 setThreadCountClasses(0);
1621 } else if ("suitesAndClasses".equals(parallel)) {
1622 if (!(getUseUnlimitedThreads()
1623 || onlyThreadCount()
1624 || getThreadCountSuites() > 0
1625 && getThreadCountClasses() > 0
1626 && getThreadCount() == 0
1627 && getThreadCountMethods() == 0
1628 || getThreadCount() > 0
1629 && getThreadCountSuites() > 0
1630 && getThreadCountClasses() > 0
1631 && getThreadCountMethods() == 0
1632 || getThreadCount() > 0
1633 && getThreadCountSuites() > 0
1634 && getThreadCount() > getThreadCountSuites()
1635 && getThreadCountClasses() == 0
1636 && getThreadCountMethods() == 0)) {
1637 throw new MojoExecutionException("Use useUnlimitedThreads=true, "
1638 + "or only threadCount > 0, "
1639 + "or (threadCountSuites > 0 and threadCountClasses > 0), "
1640 + "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0) "
1641 + "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) "
1642 + "for parallel='suitesAndClasses' or 'both'");
1643 }
1644 setThreadCountMethods(0);
1645 } else if ("suitesAndMethods".equals(parallel)) {
1646 if (!(getUseUnlimitedThreads()
1647 || onlyThreadCount()
1648 || getThreadCountSuites() > 0
1649 && getThreadCountMethods() > 0
1650 && getThreadCount() == 0
1651 && getThreadCountClasses() == 0
1652 || getThreadCount() > 0
1653 && getThreadCountSuites() > 0
1654 && getThreadCountMethods() > 0
1655 && getThreadCountClasses() == 0
1656 || getThreadCount() > 0
1657 && getThreadCountSuites() > 0
1658 && getThreadCount() > getThreadCountSuites()
1659 && getThreadCountClasses() == 0
1660 && getThreadCountMethods() == 0)) {
1661 throw new MojoExecutionException("Use useUnlimitedThreads=true, "
1662 + "or only threadCount > 0, "
1663 + "or (threadCountSuites > 0 and threadCountMethods > 0), "
1664 + "or (threadCount > 0 and threadCountSuites > 0 and threadCountMethods > 0), "
1665 + "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) "
1666 + "for parallel='suitesAndMethods'");
1667 }
1668 setThreadCountClasses(0);
1669 } else if ("both".equals(parallel) || "classesAndMethods".equals(parallel)) {
1670 if (!(getUseUnlimitedThreads()
1671 || onlyThreadCount()
1672 || getThreadCountClasses() > 0
1673 && getThreadCountMethods() > 0
1674 && getThreadCount() == 0
1675 && getThreadCountSuites() == 0
1676 || getThreadCount() > 0
1677 && getThreadCountClasses() > 0
1678 && getThreadCountMethods() > 0
1679 && getThreadCountSuites() == 0
1680 || getThreadCount() > 0
1681 && getThreadCountClasses() > 0
1682 && getThreadCount() > getThreadCountClasses()
1683 && getThreadCountSuites() == 0
1684 && getThreadCountMethods() == 0)) {
1685 throw new MojoExecutionException("Use useUnlimitedThreads=true, "
1686 + "or only threadCount > 0, "
1687 + "or (threadCountClasses > 0 and threadCountMethods > 0), "
1688 + "or (threadCount > 0 and threadCountClasses > 0 and threadCountMethods > 0), "
1689 + "or (threadCount > 0 and threadCountClasses > 0 and threadCount > threadCountClasses) "
1690 + "for parallel='both' or parallel='classesAndMethods'");
1691 }
1692 setThreadCountSuites(0);
1693 } else if ("all".equals(parallel)) {
1694 if (!(getUseUnlimitedThreads()
1695 || onlyThreadCount()
1696 || getThreadCountSuites() > 0 && getThreadCountClasses() > 0 && getThreadCountMethods() > 0
1697 || getThreadCount() > 0
1698 && getThreadCountSuites() > 0
1699 && getThreadCountClasses() > 0
1700 && getThreadCountMethods() == 0
1701 && getThreadCount() > (getThreadCountSuites() + getThreadCountClasses()))) {
1702 throw new MojoExecutionException("Use useUnlimitedThreads=true, "
1703 + "or only threadCount > 0, "
1704 + "or (threadCountSuites > 0 and threadCountClasses > 0 and threadCountMethods > 0), "
1705 + "or every thread-count is specified, "
1706 + "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0 "
1707 + "and threadCount > threadCountSuites + threadCountClasses) "
1708 + "for parallel='all'");
1709 }
1710 } else {
1711 throw new MojoExecutionException("Illegal parallel='" + parallel + "'");
1712 }
1713 }
1714
1715 private boolean onlyThreadCount() {
1716 return getThreadCount() > 0
1717 && getThreadCountSuites() == 0
1718 && getThreadCountClasses() == 0
1719 && getThreadCountMethods() == 0;
1720 }
1721
1722 private static void checkThreadCountEntity(int count, String entity) throws MojoExecutionException {
1723 if (count < 0) {
1724 throw new MojoExecutionException("parallel maven execution does not allow negative thread-count" + entity);
1725 }
1726 }
1727
1728 private boolean isJunit47Compatible(Artifact artifact) {
1729 return isWithinVersionSpec(artifact, "[4.7,)");
1730 }
1731
1732 private boolean isAnyJunit4(Artifact artifact) {
1733 return isWithinVersionSpec(artifact, "[4.0,)");
1734 }
1735
1736 protected boolean isForking() {
1737 return 0 < getEffectiveForkCount();
1738 }
1739
1740 private List<RunOrder> getRunOrders() {
1741 String runOrderString = getRunOrder();
1742 RunOrder[] runOrder = runOrderString == null ? RunOrder.DEFAULT : RunOrder.valueOfMulti(runOrderString);
1743 return asList(runOrder);
1744 }
1745
1746 private boolean requiresRunHistory() {
1747 final List<RunOrder> runOrders = getRunOrders();
1748 return runOrders.contains(RunOrder.BALANCED) || runOrders.contains(RunOrder.FAILEDFIRST);
1749 }
1750
1751 private PluginFailureReason getEffectiveFailIfNoTests() {
1752 if (isSpecificTestSpecified()) {
1753 return getFailIfNoSpecifiedTests() ? COULD_NOT_RUN_SPECIFIED_TESTS : NONE;
1754 } else {
1755 return getFailIfNoTests() ? COULD_NOT_RUN_DEFAULT_TESTS : NONE;
1756 }
1757 }
1758
1759 private ProviderConfiguration createProviderConfiguration(RunOrderParameters runOrderParameters)
1760 throws MojoExecutionException, MojoFailureException {
1761 final ReporterConfiguration reporterConfiguration =
1762 new ReporterConfiguration(getReportsDirectory(), isTrimStackTrace());
1763
1764 final Artifact testNgArtifact = getTestNgArtifact();
1765 final boolean isTestNg = testNgArtifact != null;
1766 final TestArtifactInfo testNg =
1767 isTestNg ? new TestArtifactInfo(testNgArtifact.getVersion(), testNgArtifact.getClassifier()) : null;
1768 final TestRequest testSuiteDefinition = new TestRequest(
1769 suiteXmlFiles(), getTestSourceDirectory(), getSpecificTests(), getRerunFailingTestsCount());
1770
1771 final boolean actualFailIfNoTests;
1772 DirectoryScannerParameters directoryScannerParameters = null;
1773 if (hasSuiteXmlFiles() && !isSpecificTestSpecified()) {
1774 actualFailIfNoTests = getFailIfNoTests();
1775 if (!isTestNg) {
1776 throw new MojoExecutionException("suiteXmlFiles is configured, but there is no TestNG dependency");
1777 }
1778 } else {
1779
1780
1781
1782
1783 List<String> actualIncludes = getIncludeList();
1784 List<String> actualExcludes = getExcludeList();
1785
1786 List<String> specificTests = Collections.emptyList();
1787
1788 directoryScannerParameters = new DirectoryScannerParameters(
1789 getTestClassesDirectory(), actualIncludes, actualExcludes, specificTests, getRunOrder());
1790 }
1791
1792 Map<String, String> providerProperties = toStringProperties(getProperties());
1793
1794 return new ProviderConfiguration(
1795 directoryScannerParameters,
1796 runOrderParameters,
1797 reporterConfiguration,
1798 testNg,
1799 testSuiteDefinition,
1800 providerProperties,
1801 null,
1802 false,
1803 cli,
1804 getSkipAfterFailureCount(),
1805 Shutdown.parameterOf(getShutdown()),
1806 getForkedProcessExitTimeoutInSeconds());
1807 }
1808
1809 private static Map<String, String> toStringProperties(Properties properties) {
1810 Map<String, String> h = new ConcurrentHashMap<>(properties.size());
1811 for (Enumeration<?> e = properties.keys(); e.hasMoreElements(); ) {
1812 Object k = e.nextElement();
1813 Object v = properties.get(k);
1814 if (k.getClass() == String.class && v.getClass() == String.class) {
1815 h.put((String) k, (String) v);
1816 }
1817 }
1818 return h;
1819 }
1820
1821 private File getStatisticsFile(String configurationHash) {
1822 return new File(getBasedir(), ".surefire-" + configurationHash);
1823 }
1824
1825 private StartupConfiguration createStartupConfiguration(
1826 @Nonnull ProviderInfo provider,
1827 boolean isForking,
1828 @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
1829 @Nonnull DefaultScanResult scanResult,
1830 @Nonnull TestClassPath testClasspathWrapper,
1831 @Nonnull Platform platform,
1832 @Nonnull ResolvePathResultWrapper resolvedJavaModularity)
1833 throws MojoExecutionException {
1834 try {
1835 if (isForking && canExecuteProviderWithModularPath(platform, resolvedJavaModularity)) {
1836 File jdkHome = platform.getJdkExecAttributesForTests().getJdkHome();
1837 return newStartupConfigWithModularPath(
1838 classLoaderConfiguration,
1839 provider,
1840 resolvedJavaModularity,
1841 scanResult,
1842 jdkHome.getAbsolutePath(),
1843 testClasspathWrapper);
1844 } else {
1845 return newStartupConfigWithClasspath(classLoaderConfiguration, provider, testClasspathWrapper);
1846 }
1847 } catch (IOException e) {
1848 throw new MojoExecutionException(e.getMessage(), e);
1849 }
1850 }
1851
1852 private StartupConfiguration newStartupConfigWithClasspath(
1853 @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
1854 @Nonnull ProviderInfo providerInfo,
1855 @Nonnull TestClassPath testClasspathWrapper)
1856 throws MojoExecutionException {
1857 Classpath testClasspath = testClasspathWrapper.toClasspath();
1858 Set<Artifact> providerArtifacts = providerInfo.getProviderClasspath();
1859 String providerName = providerInfo.getProviderName();
1860 Classpath providerClasspath = classpathCache.getCachedClassPath(providerName);
1861 if (providerClasspath == null) {
1862 providerClasspath = classpathCache.setCachedClasspath(providerName, providerArtifacts);
1863 }
1864
1865 getConsoleLogger().debug(testClasspath.getLogMessage("test classpath:"));
1866 getConsoleLogger().debug(providerClasspath.getLogMessage("provider classpath:"));
1867 getConsoleLogger().debug(testClasspath.getCompactLogMessage("test(compact) classpath:"));
1868 getConsoleLogger().debug(providerClasspath.getCompactLogMessage("provider(compact) classpath:"));
1869
1870 Artifact[] additionalInProcArtifacts = {
1871 getCommonArtifact(),
1872 getBooterArtifact(),
1873 getExtensionsArtifact(),
1874 getApiArtifact(),
1875 getSpiArtifact(),
1876 getLoggerApiArtifact(),
1877 getSurefireSharedUtilsArtifact()
1878 };
1879 Set<Artifact> inProcArtifacts = retainInProcArtifactsUnique(providerArtifacts, additionalInProcArtifacts);
1880 Classpath inProcClasspath = createInProcClasspath(providerClasspath, inProcArtifacts);
1881 getConsoleLogger().debug(inProcClasspath.getLogMessage("in-process classpath:"));
1882 getConsoleLogger().debug(inProcClasspath.getCompactLogMessage("in-process(compact) classpath:"));
1883
1884 ClasspathConfiguration classpathConfiguration = new ClasspathConfiguration(
1885 testClasspath, providerClasspath, inProcClasspath, effectiveIsEnableAssertions(), isChildDelegation());
1886 ProviderRequirements forkRequirements = new ProviderRequirements(false, false, false);
1887 return new StartupConfiguration(
1888 providerName,
1889 classpathConfiguration,
1890 classLoaderConfiguration,
1891 ProcessCheckerType.toEnum(getEnableProcessChecker()),
1892 providerInfo.getJpmsArguments(forkRequirements));
1893 }
1894
1895 private static Set<Artifact> retainInProcArtifactsUnique(
1896 Set<Artifact> providerArtifacts, Artifact... inPluginArtifacts) {
1897 Set<Artifact> result = new LinkedHashSet<>();
1898 for (Artifact inPluginArtifact : inPluginArtifacts) {
1899 boolean contains = false;
1900 for (Artifact providerArtifact : providerArtifacts) {
1901 if (hasGroupArtifactId(
1902 providerArtifact.getGroupId(), providerArtifact.getArtifactId(), inPluginArtifact)) {
1903 contains = true;
1904 break;
1905 }
1906 }
1907 if (!contains) {
1908 result.add(inPluginArtifact);
1909 }
1910 }
1911 return result;
1912 }
1913
1914 private static boolean hasGroupArtifactId(String groupId, String artifactId, Artifact artifact) {
1915 return groupId.equals(artifact.getGroupId()) && artifactId.equals(artifact.getArtifactId());
1916 }
1917
1918 private static Classpath createInProcClasspath(Classpath providerClasspath, Set<Artifact> newArtifacts) {
1919 Classpath inprocClasspath = providerClasspath.clone();
1920 for (Artifact newArtifact : newArtifacts) {
1921 inprocClasspath =
1922 inprocClasspath.addClassPathElementUrl(newArtifact.getFile().getAbsolutePath());
1923 }
1924 return inprocClasspath;
1925 }
1926
1927
1928
1929
1930
1931 private LocationManager getLocationManager() {
1932 return locationManager;
1933 }
1934
1935 private StartupConfiguration newStartupConfigWithModularPath(
1936 @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
1937 @Nonnull ProviderInfo providerInfo,
1938 @Nonnull ResolvePathResultWrapper moduleDescriptor,
1939 @Nonnull DefaultScanResult scanResult,
1940 @Nonnull String javaHome,
1941 @Nonnull TestClassPath testClasspathWrapper)
1942 throws MojoExecutionException, IOException {
1943 boolean isMainDescriptor = moduleDescriptor.isMainModuleDescriptor();
1944 JavaModuleDescriptor javaModuleDescriptor =
1945 moduleDescriptor.getResolvePathResult().getModuleDescriptor();
1946 SortedSet<String> packages = new TreeSet<>();
1947
1948 Classpath testClasspath = testClasspathWrapper.toClasspath();
1949 Set<Artifact> providerArtifacts = providerInfo.getProviderClasspath();
1950 String providerName = providerInfo.getProviderName();
1951 Classpath providerClasspath = classpathCache.getCachedClassPath(providerName);
1952 if (providerClasspath == null) {
1953 providerClasspath = classpathCache.setCachedClasspath(providerName, providerArtifacts);
1954 }
1955
1956 final ProviderRequirements providerRequirements;
1957 final Classpath testModulepath;
1958 if (isMainDescriptor) {
1959 providerRequirements = new ProviderRequirements(true, true, false);
1960 ResolvePathsRequest<String> req = ResolvePathsRequest.ofStrings(testClasspath.getClassPath())
1961 .setIncludeAllProviders(true)
1962 .setJdkHome(javaHome)
1963 .setIncludeStatic(true)
1964 .setModuleDescriptor(javaModuleDescriptor);
1965
1966 ResolvePathsResult<String> result = getLocationManager().resolvePaths(req);
1967 for (Entry<String, Exception> entry : result.getPathExceptions().entrySet()) {
1968
1969 getConsoleLogger().warning("Exception for '" + entry.getKey() + "'.", entry.getValue());
1970 }
1971
1972 testClasspath = new Classpath(result.getClasspathElements());
1973 testModulepath = new Classpath(result.getModulepathElements().keySet());
1974
1975 for (String className : scanResult.getClasses()) {
1976 packages.add(substringBeforeLast(className, "."));
1977 }
1978 } else {
1979 providerRequirements = new ProviderRequirements(true, false, true);
1980 testModulepath = testClasspath;
1981 testClasspath = emptyClasspath();
1982 }
1983
1984 getConsoleLogger().debug("main module descriptor name: " + javaModuleDescriptor.name());
1985
1986 ModularClasspath modularClasspath = new ModularClasspath(
1987 javaModuleDescriptor.name(),
1988 testModulepath.getClassPath(),
1989 packages,
1990 isMainDescriptor ? getTestClassesDirectory() : null,
1991 isMainDescriptor);
1992
1993 Artifact[] additionalInProcArtifacts = {
1994 getCommonArtifact(),
1995 getBooterArtifact(),
1996 getExtensionsArtifact(),
1997 getApiArtifact(),
1998 getSpiArtifact(),
1999 getLoggerApiArtifact(),
2000 getSurefireSharedUtilsArtifact()
2001 };
2002 Set<Artifact> inProcArtifacts = retainInProcArtifactsUnique(providerArtifacts, additionalInProcArtifacts);
2003 Classpath inProcClasspath = createInProcClasspath(providerClasspath, inProcArtifacts);
2004
2005 ModularClasspathConfiguration classpathConfiguration = new ModularClasspathConfiguration(
2006 modularClasspath,
2007 testClasspath,
2008 providerClasspath,
2009 inProcClasspath,
2010 effectiveIsEnableAssertions(),
2011 isChildDelegation());
2012
2013 getConsoleLogger().debug(testClasspath.getLogMessage("test classpath:"));
2014 getConsoleLogger().debug(testModulepath.getLogMessage("test modulepath:"));
2015 getConsoleLogger().debug(providerClasspath.getLogMessage("provider classpath:"));
2016 getConsoleLogger().debug(testClasspath.getCompactLogMessage("test(compact) classpath:"));
2017 getConsoleLogger().debug(testModulepath.getCompactLogMessage("test(compact) modulepath:"));
2018 getConsoleLogger().debug(providerClasspath.getCompactLogMessage("provider(compact) classpath:"));
2019 getConsoleLogger().debug(inProcClasspath.getLogMessage("in-process classpath:"));
2020 getConsoleLogger().debug(inProcClasspath.getCompactLogMessage("in-process(compact) classpath:"));
2021
2022 ProcessCheckerType processCheckerType = ProcessCheckerType.toEnum(getEnableProcessChecker());
2023 List<String[]> jpmsArgs = providerInfo.getJpmsArguments(providerRequirements);
2024 return new StartupConfiguration(
2025 providerName, classpathConfiguration, classLoaderConfiguration, processCheckerType, jpmsArgs);
2026 }
2027
2028 private Artifact getCommonArtifact() {
2029 return getPluginArtifactMap().get("org.apache.maven.surefire:maven-surefire-common");
2030 }
2031
2032 private Artifact getExtensionsArtifact() {
2033 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-extensions-api");
2034 }
2035
2036 private Artifact getSpiArtifact() {
2037 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-extensions-spi");
2038 }
2039
2040 private Artifact getApiArtifact() {
2041 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-api");
2042 }
2043
2044 private Artifact getSurefireSharedUtilsArtifact() {
2045 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-shared-utils");
2046 }
2047
2048 private Artifact getLoggerApiArtifact() {
2049 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-logger-api");
2050 }
2051
2052 private Artifact getBooterArtifact() {
2053 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-booter");
2054 }
2055
2056 private Artifact getShadefireArtifact() {
2057 return getPluginArtifactMap().get("org.apache.maven.surefire:surefire-shadefire");
2058 }
2059
2060 private StartupReportConfiguration getStartupReportConfiguration(String configChecksum, boolean isForking) {
2061 SurefireStatelessReporter xmlReporter = statelessTestsetReporter == null
2062 ? new SurefireStatelessReporter( isDisableXmlReport(), "3.0.2")
2063 : statelessTestsetReporter;
2064
2065 xmlReporter.setDisable(isDisableXmlReport());
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 final 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 @Override
3063 public boolean isApplicable() {
3064 return junitPlatformRunnerArtifact == null && junitPlatformArtifact != null;
3065 }
3066
3067 @Override
3068 public void addProviderProperties() {
3069 convertGroupParameters();
3070 convertJunitEngineParameters();
3071 }
3072
3073 @Nonnull
3074 @Override
3075 public List<String[]> getJpmsArguments(@Nonnull ProviderRequirements forkRequirements) {
3076 boolean hasTestDescriptor = forkRequirements.isModularPath() && forkRequirements.hasTestModuleDescriptor();
3077 return hasTestDescriptor ? getJpmsArgs() : Collections.<String[]>emptyList();
3078 }
3079
3080 @Override
3081 @Nonnull
3082 public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
3083 String surefireVersion = getBooterArtifact().getBaseVersion();
3084 Map<String, Artifact> providerArtifacts = surefireDependencyResolver.getProviderClasspathAsMap(
3085 session.getRepositorySession(),
3086 project.getRemotePluginRepositories(),
3087 "surefire-junit-platform",
3088 surefireVersion);
3089 Map<String, Artifact> testDeps = testClasspath.getTestDependencies();
3090
3091 Plugin plugin = getPluginDescriptor().getPlugin();
3092 Map<String, Artifact> pluginDeps = surefireDependencyResolver.resolvePluginDependencies(
3093 session.getRepositorySession(),
3094 project.getRemotePluginRepositories(),
3095 plugin,
3096 getPluginArtifactMap());
3097
3098 if (hasDependencyPlatformEngine(pluginDeps)) {
3099 providerArtifacts.putAll(pluginDeps);
3100 } else {
3101 String engineVersion = null;
3102 if (hasDependencyJupiterAPI(testDeps)
3103 && !testDeps.containsKey("org.junit.jupiter:junit-jupiter-engine")) {
3104 String engineGroupId = "org.junit.jupiter";
3105 String engineArtifactId = "junit-jupiter-engine";
3106 String engineCoordinates = engineGroupId + ":" + engineArtifactId;
3107 String api = "org.junit.jupiter:junit-jupiter-api";
3108 engineVersion = testDeps.get(api).getBaseVersion();
3109 getConsoleLogger()
3110 .debug("Test dependencies contain " + api + ". Resolving " + engineCoordinates + ":"
3111 + engineVersion);
3112 addEngineByApi(engineGroupId, engineArtifactId, engineVersion, providerArtifacts);
3113 }
3114
3115 if ((testDeps.containsKey("junit:junit") || testDeps.containsKey("junit:junit-dep"))
3116 && !testDeps.containsKey("org.junit.vintage:junit-vintage-engine")) {
3117 String engineGroupId = "org.junit.vintage";
3118 String engineArtifactId = "junit-vintage-engine";
3119 String engineCoordinates = engineGroupId + ":" + engineArtifactId;
3120
3121 if (engineVersion != null) {
3122 getConsoleLogger()
3123 .debug("Test dependencies contain JUnit4. Resolving " + engineCoordinates + ":"
3124 + engineVersion);
3125 addEngineByApi(engineGroupId, engineArtifactId, engineVersion, providerArtifacts);
3126 }
3127 }
3128 }
3129
3130 narrowDependencies(providerArtifacts, testDeps);
3131 alignProviderVersions(providerArtifacts);
3132
3133 return new LinkedHashSet<>(providerArtifacts.values());
3134 }
3135
3136 private List<String[]> getJpmsArgs() {
3137 List<String[]> args = new ArrayList<>();
3138
3139 args.add(new String[] {
3140 "--add-opens", "org.junit.platform.commons/org.junit.platform.commons.util=ALL-UNNAMED"
3141 });
3142
3143 args.add(new String[] {
3144 "--add-opens", "org.junit.platform.commons/org.junit.platform.commons.logging=ALL-UNNAMED"
3145 });
3146
3147 return args;
3148 }
3149
3150 private void addEngineByApi(
3151 String engineGroupId,
3152 String engineArtifactId,
3153 String engineVersion,
3154 Map<String, Artifact> providerArtifacts)
3155 throws MojoExecutionException {
3156 for (Artifact dep : resolve(engineGroupId, engineArtifactId, engineVersion, null, "jar")) {
3157 String key = dep.getGroupId() + ":" + dep.getArtifactId();
3158 providerArtifacts.put(key, dep);
3159 }
3160 }
3161
3162 private void narrowDependencies(
3163 Map<String, Artifact> providerArtifacts, Map<String, Artifact> testDependencies) {
3164 providerArtifacts.keySet().removeAll(testDependencies.keySet());
3165 }
3166
3167 private void alignProviderVersions(Map<String, Artifact> providerArtifacts) throws MojoExecutionException {
3168 String version = junitPlatformArtifact.getBaseVersion();
3169 for (Artifact launcherArtifact : resolve(PROVIDER_DEP_GID, PROVIDER_DEP_AID, version, null, "jar")) {
3170 String key = launcherArtifact.getGroupId() + ":" + launcherArtifact.getArtifactId();
3171 if (providerArtifacts.containsKey(key)) {
3172 providerArtifacts.put(key, launcherArtifact);
3173 }
3174 }
3175 }
3176
3177 private Set<Artifact> resolve(String g, String a, String v, String c, String t) throws MojoExecutionException {
3178 ArtifactHandler handler = junitPlatformArtifact.getArtifactHandler();
3179 Artifact artifact = new DefaultArtifact(g, a, v, null, t, c, handler);
3180 getConsoleLogger().debug("Resolving artifact " + g + ":" + a + ":" + v);
3181 Set<Artifact> r = surefireDependencyResolver.resolveArtifacts(
3182 session.getRepositorySession(), project.getRemoteProjectRepositories(), artifact);
3183 getConsoleLogger().debug("Resolved artifact " + g + ":" + a + ":" + v + " to " + r);
3184 return r;
3185 }
3186
3187 private boolean hasDependencyJupiterAPI(Map<String, Artifact> dependencies) {
3188 return dependencies.containsKey("org.junit.jupiter:junit-jupiter-api");
3189 }
3190
3191 private boolean hasDependencyPlatformEngine(Map<String, Artifact> dependencies) {
3192 for (Entry<String, Artifact> dependency : dependencies.entrySet()) {
3193 if (dependency.getKey().equals("org.junit.platform:junit-platform-engine")) {
3194 return true;
3195 }
3196 }
3197
3198 return false;
3199 }
3200 }
3201
3202 final class JUnitCoreProviderInfo implements ProviderInfo {
3203 private final Artifact junitArtifact;
3204
3205 private final Artifact junitDepArtifact;
3206
3207 JUnitCoreProviderInfo(Artifact junitArtifact, Artifact junitDepArtifact) {
3208 this.junitArtifact = junitArtifact;
3209 this.junitDepArtifact = junitDepArtifact;
3210 }
3211
3212 @Override
3213 @Nonnull
3214 public String getProviderName() {
3215 return "org.apache.maven.surefire.junitcore.JUnitCoreProvider";
3216 }
3217
3218 private boolean is47CompatibleJunitDep() {
3219 return isJunit47Compatible(junitDepArtifact);
3220 }
3221
3222 @Override
3223 public boolean isApplicable() {
3224 final boolean isJunitArtifact47 = isAnyJunit4(junitArtifact) && isJunit47Compatible(junitArtifact);
3225 final boolean isAny47ProvidersForces = isAnyConcurrencySelected() || isAnyGroupsSelected();
3226 return isAny47ProvidersForces && (isJunitArtifact47 || is47CompatibleJunitDep());
3227 }
3228
3229 @Override
3230 public void addProviderProperties() throws MojoExecutionException {
3231 convertJunitCoreParameters();
3232 convertGroupParameters();
3233 convertJunitEngineParameters();
3234 }
3235
3236 @Nonnull
3237 @Override
3238 public List<String[]> getJpmsArguments(@Nonnull ProviderRequirements forkRequirements) {
3239 return emptyList();
3240 }
3241
3242 @Override
3243 @Nonnull
3244 public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
3245 String version = getBooterArtifact().getBaseVersion();
3246 return surefireDependencyResolver.getProviderClasspath(
3247 session.getRepositorySession(), project.getRemotePluginRepositories(), "surefire-junit47", version);
3248 }
3249 }
3250
3251
3252
3253
3254 final class DynamicProviderInfo implements ConfigurableProviderInfo {
3255 final String providerName;
3256
3257 DynamicProviderInfo(String providerName) {
3258 this.providerName = providerName;
3259 }
3260
3261 @Override
3262 public ProviderInfo instantiate(String providerName) {
3263 return new DynamicProviderInfo(providerName);
3264 }
3265
3266 @Override
3267 @Nonnull
3268 public String getProviderName() {
3269 return providerName;
3270 }
3271
3272 @Override
3273 public boolean isApplicable() {
3274 return true;
3275 }
3276
3277 @Override
3278 public void addProviderProperties() throws MojoExecutionException {
3279
3280 convertJunitCoreParameters();
3281 convertTestNGParameters();
3282 }
3283
3284 @Nonnull
3285 @Override
3286 public List<String[]> getJpmsArguments(@Nonnull ProviderRequirements forkRequirements) {
3287 return emptyList();
3288 }
3289
3290 @Override
3291 @Nonnull
3292 public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
3293 Plugin plugin = getPluginDescriptor().getPlugin();
3294 Map<String, Artifact> providerArtifacts = surefireDependencyResolver.resolvePluginDependencies(
3295 session.getRepositorySession(),
3296 project.getRemotePluginRepositories(),
3297 plugin,
3298 getPluginArtifactMap());
3299 return new LinkedHashSet<>(providerArtifacts.values());
3300 }
3301 }
3302
3303 File createSurefireBootDirectoryInBuild() {
3304 File tmp = new File(getProjectBuildDirectory(), getTempDir());
3305
3306 tmp.mkdirs();
3307 return tmp;
3308 }
3309
3310 File createSurefireBootDirectoryInTemp() {
3311 try {
3312 return Files.createTempDirectory(getTempDir()).toFile();
3313 } catch (IOException e) {
3314 return createSurefireBootDirectoryInBuild();
3315 }
3316 }
3317
3318 @Override
3319 public String getLocalRepositoryPath() {
3320 return Optional.ofNullable(
3321 session.getRepositorySession().getLocalRepository().getBasedir())
3322 .map(File::getAbsolutePath)
3323 .orElse(".");
3324 }
3325
3326 public Properties getSystemProperties() {
3327 return systemProperties;
3328 }
3329
3330 @SuppressWarnings("UnusedDeclaration")
3331 public void setSystemProperties(Properties systemProperties) {
3332 this.systemProperties = systemProperties;
3333 }
3334
3335 public Map<String, String> getSystemPropertyVariables() {
3336 return systemPropertyVariables;
3337 }
3338
3339 @SuppressWarnings("UnusedDeclaration")
3340 public void setSystemPropertyVariables(Map<String, String> systemPropertyVariables) {
3341 this.systemPropertyVariables = systemPropertyVariables;
3342 }
3343
3344
3345
3346
3347
3348
3349 public abstract File getSystemPropertiesFile();
3350
3351 @SuppressWarnings("UnusedDeclaration")
3352 public abstract void setSystemPropertiesFile(File systemPropertiesFile);
3353
3354 private Properties getProperties() {
3355 return properties;
3356 }
3357
3358 public void setProperties(Properties properties) {
3359 this.properties = properties;
3360 }
3361
3362 public Map<String, Artifact> getPluginArtifactMap() {
3363 return pluginArtifactMap;
3364 }
3365
3366 @SuppressWarnings("UnusedDeclaration")
3367 public void setPluginArtifactMap(Map<String, Artifact> pluginArtifactMap) {
3368 this.pluginArtifactMap = pluginArtifactMap;
3369 }
3370
3371 public Map<String, Artifact> getProjectArtifactMap() {
3372 return projectArtifactMap;
3373 }
3374
3375 @SuppressWarnings("UnusedDeclaration")
3376 public void setProjectArtifactMap(Map<String, Artifact> projectArtifactMap) {
3377 this.projectArtifactMap = projectArtifactMap;
3378 }
3379
3380 public String getReportNameSuffix() {
3381 return reportNameSuffix;
3382 }
3383
3384 @SuppressWarnings("UnusedDeclaration")
3385 public void setReportNameSuffix(String reportNameSuffix) {
3386 this.reportNameSuffix = reportNameSuffix;
3387 }
3388
3389 public boolean isRedirectTestOutputToFile() {
3390 return redirectTestOutputToFile;
3391 }
3392
3393 @SuppressWarnings("UnusedDeclaration")
3394 public void setRedirectTestOutputToFile(boolean redirectTestOutputToFile) {
3395 this.redirectTestOutputToFile = redirectTestOutputToFile;
3396 }
3397
3398 public boolean getFailIfNoTests() {
3399 return failIfNoTests;
3400 }
3401
3402 public void setFailIfNoTests(boolean failIfNoTests) {
3403 this.failIfNoTests = failIfNoTests;
3404 }
3405
3406 public String getJvm() {
3407 return jvm;
3408 }
3409
3410 public String getArgLine() {
3411 return argLine;
3412 }
3413
3414 @SuppressWarnings("UnusedDeclaration")
3415 public void setArgLine(String argLine) {
3416 this.argLine = argLine;
3417 }
3418
3419 public Map<String, String> getEnvironmentVariables() {
3420 return environmentVariables;
3421 }
3422
3423 @SuppressWarnings("UnusedDeclaration")
3424 public void setEnvironmentVariables(Map<String, String> environmentVariables) {
3425 this.environmentVariables = environmentVariables;
3426 }
3427
3428 public File getWorkingDirectory() {
3429 return workingDirectory;
3430 }
3431
3432 @SuppressWarnings("UnusedDeclaration")
3433 public void setWorkingDirectory(File workingDirectory) {
3434 this.workingDirectory = workingDirectory;
3435 }
3436
3437 public boolean isChildDelegation() {
3438 return childDelegation;
3439 }
3440
3441 @SuppressWarnings("UnusedDeclaration")
3442 public void setChildDelegation(boolean childDelegation) {
3443 this.childDelegation = childDelegation;
3444 }
3445
3446 public String getGroups() {
3447 return groups;
3448 }
3449
3450 @SuppressWarnings("UnusedDeclaration")
3451 public void setGroups(String groups) {
3452 this.groups = groups;
3453 }
3454
3455 public String getExcludedGroups() {
3456 return excludedGroups;
3457 }
3458
3459 @SuppressWarnings("UnusedDeclaration")
3460 public void setExcludedGroups(String excludedGroups) {
3461 this.excludedGroups = excludedGroups;
3462 }
3463
3464 public String getJunitArtifactName() {
3465 return junitArtifactName;
3466 }
3467
3468 @SuppressWarnings("UnusedDeclaration")
3469 public void setJunitArtifactName(String junitArtifactName) {
3470 this.junitArtifactName = junitArtifactName;
3471 }
3472
3473 public String getTestNGArtifactName() {
3474 return testNGArtifactName;
3475 }
3476
3477 @SuppressWarnings("UnusedDeclaration")
3478 public void setTestNGArtifactName(String testNGArtifactName) {
3479 this.testNGArtifactName = testNGArtifactName;
3480 }
3481
3482 public int getThreadCount() {
3483 return threadCount;
3484 }
3485
3486 @SuppressWarnings("UnusedDeclaration")
3487 public void setThreadCount(int threadCount) {
3488 this.threadCount = threadCount;
3489 }
3490
3491 public boolean getPerCoreThreadCount() {
3492 return perCoreThreadCount;
3493 }
3494
3495 @SuppressWarnings("UnusedDeclaration")
3496 public void setPerCoreThreadCount(boolean perCoreThreadCount) {
3497 this.perCoreThreadCount = perCoreThreadCount;
3498 }
3499
3500 public boolean getUseUnlimitedThreads() {
3501 return useUnlimitedThreads;
3502 }
3503
3504 @SuppressWarnings("UnusedDeclaration")
3505 public void setUseUnlimitedThreads(boolean useUnlimitedThreads) {
3506 this.useUnlimitedThreads = useUnlimitedThreads;
3507 }
3508
3509 public String getParallel() {
3510 return parallel;
3511 }
3512
3513 @SuppressWarnings("UnusedDeclaration")
3514 public void setParallel(String parallel) {
3515 this.parallel = parallel;
3516 }
3517
3518 public boolean isParallelOptimized() {
3519 return parallelOptimized;
3520 }
3521
3522 @SuppressWarnings("UnusedDeclaration")
3523 public void setParallelOptimized(boolean parallelOptimized) {
3524 this.parallelOptimized = parallelOptimized;
3525 }
3526
3527 public int getThreadCountSuites() {
3528 return threadCountSuites;
3529 }
3530
3531 public void setThreadCountSuites(int threadCountSuites) {
3532 this.threadCountSuites = threadCountSuites;
3533 }
3534
3535 public int getThreadCountClasses() {
3536 return threadCountClasses;
3537 }
3538
3539 public void setThreadCountClasses(int threadCountClasses) {
3540 this.threadCountClasses = threadCountClasses;
3541 }
3542
3543 public int getThreadCountMethods() {
3544 return threadCountMethods;
3545 }
3546
3547 public void setThreadCountMethods(int threadCountMethods) {
3548 this.threadCountMethods = threadCountMethods;
3549 }
3550
3551 public boolean isTrimStackTrace() {
3552 return trimStackTrace;
3553 }
3554
3555 @SuppressWarnings("UnusedDeclaration")
3556 public void setTrimStackTrace(boolean trimStackTrace) {
3557 this.trimStackTrace = trimStackTrace;
3558 }
3559
3560 public boolean isDisableXmlReport() {
3561 return disableXmlReport;
3562 }
3563
3564 @SuppressWarnings("UnusedDeclaration")
3565 public void setDisableXmlReport(boolean disableXmlReport) {
3566 this.disableXmlReport = disableXmlReport;
3567 }
3568
3569 public boolean isEnableAssertions() {
3570 return enableAssertions;
3571 }
3572
3573 public boolean effectiveIsEnableAssertions() {
3574 if (getArgLine() != null) {
3575 List<String> args = asList(getArgLine().split(" "));
3576 if (args.contains("-da") || args.contains("-disableassertions")) {
3577 return false;
3578 }
3579 }
3580 return isEnableAssertions();
3581 }
3582
3583 @SuppressWarnings("UnusedDeclaration")
3584 public void setEnableAssertions(boolean enableAssertions) {
3585 this.enableAssertions = enableAssertions;
3586 }
3587
3588 public boolean isEnableOutErrElements() {
3589 return enableOutErrElements;
3590 }
3591
3592 @SuppressWarnings("UnusedDeclaration")
3593 public void setEnableOutErrElements(boolean enableOutErrElements) {
3594 this.enableOutErrElements = enableOutErrElements;
3595 }
3596
3597 public boolean isEnablePropertiesElement() {
3598 return enablePropertiesElement;
3599 }
3600
3601 @SuppressWarnings("UnusedDeclaration")
3602 public void setEnablePropertiesElement(boolean enablePropertiesElement) {
3603 this.enablePropertiesElement = enablePropertiesElement;
3604 }
3605
3606 public MavenSession getSession() {
3607 return session;
3608 }
3609
3610 @SuppressWarnings("UnusedDeclaration")
3611 public void setSession(MavenSession session) {
3612 this.session = session;
3613 }
3614
3615 public String getObjectFactory() {
3616 return objectFactory;
3617 }
3618
3619 @SuppressWarnings("UnusedDeclaration")
3620 public void setObjectFactory(String objectFactory) {
3621 this.objectFactory = objectFactory;
3622 }
3623
3624 public ToolchainManager getToolchainManager() {
3625 return toolchainManager;
3626 }
3627
3628 @SuppressWarnings("UnusedDeclaration")
3629 public void setToolchainManager(ToolchainManager toolchainManager) {
3630 this.toolchainManager = toolchainManager;
3631 }
3632
3633 public boolean isMavenParallel() {
3634 return parallelMavenExecution != null && parallelMavenExecution;
3635 }
3636
3637 public String[] getDependenciesToScan() {
3638 return dependenciesToScan;
3639 }
3640
3641 public void setDependenciesToScan(String[] dependenciesToScan) {
3642 this.dependenciesToScan = dependenciesToScan;
3643 }
3644
3645 @SuppressWarnings("UnusedDeclaration")
3646 void setPluginDescriptor(PluginDescriptor pluginDescriptor) {
3647 this.pluginDescriptor = pluginDescriptor;
3648 }
3649
3650 public PluginDescriptor getPluginDescriptor() {
3651 return pluginDescriptor;
3652 }
3653
3654 public MavenProject getProject() {
3655 return project;
3656 }
3657
3658 @SuppressWarnings("UnusedDeclaration")
3659 public void setProject(MavenProject project) {
3660 this.project = project;
3661 }
3662
3663 @Override
3664 public File getTestSourceDirectory() {
3665 return testSourceDirectory;
3666 }
3667
3668 @Override
3669 public void setTestSourceDirectory(File testSourceDirectory) {
3670 this.testSourceDirectory = testSourceDirectory;
3671 }
3672
3673 public String getForkCount() {
3674 return forkCount;
3675 }
3676
3677 public boolean isReuseForks() {
3678 return reuseForks;
3679 }
3680
3681 public String[] getAdditionalClasspathElements() {
3682 return additionalClasspathElements;
3683 }
3684
3685 public void setAdditionalClasspathElements(String[] additionalClasspathElements) {
3686 this.additionalClasspathElements = additionalClasspathElements;
3687 }
3688
3689 public String[] getClasspathDependencyExcludes() {
3690 return classpathDependencyExcludes;
3691 }
3692
3693 public void setClasspathDependencyExcludes(String[] classpathDependencyExcludes) {
3694 this.classpathDependencyExcludes = classpathDependencyExcludes;
3695 }
3696
3697 public String getClasspathDependencyScopeExclude() {
3698 return classpathDependencyScopeExclude;
3699 }
3700
3701 public void setClasspathDependencyScopeExclude(String classpathDependencyScopeExclude) {
3702 this.classpathDependencyScopeExclude = classpathDependencyScopeExclude;
3703 }
3704
3705 public File getProjectBuildDirectory() {
3706 return projectBuildDirectory;
3707 }
3708
3709 public void setProjectBuildDirectory(File projectBuildDirectory) {
3710 this.projectBuildDirectory = projectBuildDirectory;
3711 }
3712
3713 protected void logDebugOrCliShowErrors(String s) {
3714 SurefireHelper.logDebugOrCliShowErrors(s, getConsoleLogger(), cli);
3715 }
3716
3717 public Map<String, String> getJdkToolchain() {
3718 return jdkToolchain;
3719 }
3720
3721 public void setJdkToolchain(Map<String, String> jdkToolchain) {
3722 this.jdkToolchain = jdkToolchain;
3723 }
3724
3725 public String getTempDir() {
3726 return tempDir;
3727 }
3728
3729 public void setTempDir(String tempDir) {
3730 this.tempDir = tempDir;
3731 }
3732
3733 private static final class ClasspathCache {
3734 private final Map<String, Classpath> classpaths = new HashMap<>(4);
3735
3736 private Classpath getCachedClassPath(@Nonnull String artifactId) {
3737 return classpaths.get(artifactId);
3738 }
3739
3740 private void setCachedClasspath(@Nonnull String key, @Nonnull Classpath classpath) {
3741 classpaths.put(key, classpath);
3742 }
3743
3744 private Classpath setCachedClasspath(@Nonnull String key, @Nonnull Set<Artifact> artifacts) {
3745 Collection<String> files = new ArrayList<>();
3746 for (Artifact artifact : artifacts) {
3747 files.add(artifact.getFile().getAbsolutePath());
3748 }
3749 Classpath classpath = new Classpath(files);
3750 setCachedClasspath(key, classpath);
3751 return classpath;
3752 }
3753 }
3754
3755
3756
3757
3758 enum PluginFailureReason {
3759 NONE,
3760 COULD_NOT_RUN_SPECIFIED_TESTS,
3761 COULD_NOT_RUN_DEFAULT_TESTS,
3762 }
3763 }