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