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