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