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