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