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