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