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