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