1 package org.apache.maven.plugin.surefire;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.lang.reflect.Method;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Map.Entry;
33 import java.util.Properties;
34 import java.util.Set;
35 import org.apache.maven.artifact.Artifact;
36 import org.apache.maven.artifact.factory.ArtifactFactory;
37 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
38 import org.apache.maven.artifact.repository.ArtifactRepository;
39 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
40 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
41 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
42 import org.apache.maven.artifact.resolver.ArtifactResolver;
43 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
44 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
45 import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
46 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
47 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
48 import org.apache.maven.artifact.versioning.VersionRange;
49 import org.apache.maven.execution.MavenSession;
50 import org.apache.maven.model.Plugin;
51 import org.apache.maven.plugin.AbstractMojo;
52 import org.apache.maven.plugin.MojoExecutionException;
53 import org.apache.maven.plugin.MojoFailureException;
54 import org.apache.maven.plugin.descriptor.PluginDescriptor;
55 import org.apache.maven.plugin.surefire.booterclient.ChecksumCalculator;
56 import org.apache.maven.plugin.surefire.booterclient.ForkConfiguration;
57 import org.apache.maven.plugin.surefire.booterclient.ForkStarter;
58 import org.apache.maven.plugin.surefire.util.DirectoryScanner;
59 import org.apache.maven.plugins.annotations.Component;
60 import org.apache.maven.plugins.annotations.Parameter;
61 import org.apache.maven.project.MavenProject;
62 import org.apache.maven.shared.artifact.filter.PatternIncludesArtifactFilter;
63 import org.apache.maven.shared.utils.StringUtils;
64 import org.apache.maven.shared.utils.io.FileUtils;
65 import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
66 import org.apache.maven.surefire.booter.Classpath;
67 import org.apache.maven.surefire.booter.ClasspathConfiguration;
68 import org.apache.maven.surefire.booter.ProviderConfiguration;
69 import org.apache.maven.surefire.booter.ProviderParameterNames;
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.report.ReporterConfiguration;
74 import org.apache.maven.surefire.suite.RunResult;
75 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
76 import org.apache.maven.surefire.testset.RunOrderParameters;
77 import org.apache.maven.surefire.testset.TestArtifactInfo;
78 import org.apache.maven.surefire.testset.TestRequest;
79 import org.apache.maven.surefire.testset.TestSetFailedException;
80 import org.apache.maven.surefire.util.DefaultScanResult;
81 import org.apache.maven.surefire.util.NestedCheckedException;
82 import org.apache.maven.surefire.util.NestedRuntimeException;
83 import org.apache.maven.surefire.util.RunOrder;
84 import org.apache.maven.toolchain.Toolchain;
85 import org.apache.maven.toolchain.ToolchainManager;
86
87
88
89
90
91
92
93 public abstract class AbstractSurefireMojo
94 extends AbstractMojo
95 implements SurefireExecutionParameters
96 {
97
98
99
100
101
102
103
104
105
106 @Parameter( defaultValue = "${plugin}", readonly = true )
107 protected PluginDescriptor pluginDescriptor;
108
109
110
111
112
113
114
115 @Parameter( property = "skipTests", defaultValue = "false" )
116 protected boolean skipTests;
117
118
119
120
121
122
123
124 @Parameter( property = "maven.test.skip.exec" )
125 protected boolean skipExec;
126
127
128
129
130
131
132 @Parameter( property = "maven.test.skip", defaultValue = "false" )
133 protected boolean skip;
134
135
136
137
138 @Component
139 protected MavenProject project;
140
141
142
143
144
145 @Parameter( defaultValue = "${basedir}" )
146 protected File basedir;
147
148
149
150
151
152 @Parameter( defaultValue = "${project.build.testOutputDirectory}" )
153 protected File testClassesDirectory;
154
155
156
157
158
159 @Parameter( defaultValue = "${project.build.outputDirectory}" )
160 protected File classesDirectory;
161
162
163
164
165
166
167
168 @Parameter
169 protected List<String> classpathDependencyExcludes;
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 @Parameter( defaultValue = "" )
186 protected String classpathDependencyScopeExclude;
187
188
189
190
191
192
193 @Parameter
194 protected List<String> additionalClasspathElements;
195
196
197
198
199
200
201 @Parameter( defaultValue = "${project.build.testSourceDirectory}", required = true )
202 protected File testSourceDirectory;
203
204
205
206
207
208 @Parameter
209 protected File includesFile;
210
211
212
213
214
215
216
217
218
219
220
221
222
223 @Parameter
224 protected List<String> excludes;
225
226
227
228
229
230 @Parameter
231 protected File excludesFile;
232
233
234
235
236
237 @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
238 protected ArtifactRepository localRepository;
239
240
241
242
243
244
245 @Parameter
246 protected Properties systemProperties;
247
248
249
250
251
252
253 @Parameter
254 protected Map<String, String> systemPropertyVariables;
255
256
257
258
259
260
261 @Parameter
262 protected File systemPropertiesFile;
263
264
265
266
267
268
269
270 @Parameter
271 protected Properties properties;
272
273
274
275
276
277 @Parameter( property = "plugin.artifactMap", required = true, readonly = true )
278 protected Map<String, Artifact> pluginArtifactMap;
279
280
281
282
283
284 @Parameter( property = "project.artifactMap", readonly = true, required = true )
285 protected Map<String, Artifact> projectArtifactMap;
286
287
288
289
290
291
292
293 @Parameter( property = "surefire.reportNameSuffix", defaultValue = "" )
294 protected String reportNameSuffix;
295
296
297
298
299
300
301
302 @Parameter( property = "maven.test.redirectTestOutputToFile", defaultValue = "false" )
303 protected boolean redirectTestOutputToFile;
304
305
306
307
308
309
310 @Parameter( property = "failIfNoTests" )
311 protected Boolean failIfNoTests;
312
313
314
315
316
317
318
319
320
321
322 @Parameter( property = "forkMode", defaultValue = "once" )
323 protected String forkMode;
324
325
326
327
328
329
330
331
332 @Parameter( property = "jvm" )
333 protected String jvm;
334
335
336
337
338
339
340 @Parameter( property = "argLine" )
341 protected String argLine;
342
343
344
345
346
347
348 @Parameter
349 protected Map<String, String> environmentVariables = new HashMap<String, String>();
350
351
352
353
354
355
356 @Parameter( property = "basedir" )
357 protected File workingDirectory;
358
359
360
361
362
363
364
365
366
367 @Parameter( property = "childDelegation", defaultValue = "false" )
368 protected boolean childDelegation;
369
370
371
372
373
374
375
376
377 @Parameter( property = "groups" )
378 protected String groups;
379
380
381
382
383
384
385
386
387 @Parameter( property = "excludedGroups" )
388 protected String excludedGroups;
389
390
391
392
393
394
395
396
397
398
399 @Parameter
400 protected File[] suiteXmlFiles;
401
402
403
404
405
406
407 @Parameter( property = "junitArtifactName", defaultValue = "junit:junit" )
408 protected String junitArtifactName;
409
410
411
412
413
414
415 @Parameter( property = "testNGArtifactName", defaultValue = "org.testng:testng" )
416 protected String testNGArtifactName;
417
418
419
420
421
422
423
424 @Parameter( property = "threadCount" )
425 protected int threadCount;
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442 @Parameter( property = "forkCount", defaultValue="1")
443 private String forkCount;
444
445
446
447
448
449
450
451
452 @Parameter( property = "reuseForks", defaultValue = "true" )
453 private boolean reuseForks;
454
455
456
457
458
459
460 @Parameter( property = "perCoreThreadCount", defaultValue = "true" )
461 protected boolean perCoreThreadCount;
462
463
464
465
466
467
468
469
470 @Parameter( property = "useUnlimitedThreads", defaultValue = "false" )
471 protected boolean useUnlimitedThreads;
472
473
474
475
476
477
478
479
480
481
482
483 @Parameter( property = "parallel" )
484 protected String parallel;
485
486
487
488
489
490
491 @Parameter( property = "trimStackTrace", defaultValue = "true" )
492 protected boolean trimStackTrace;
493
494
495
496
497 @Component
498 protected ArtifactResolver artifactResolver;
499
500
501
502
503 @Component
504 protected ArtifactFactory artifactFactory;
505
506
507
508
509
510
511 @Parameter( defaultValue = "${project.pluginArtifactRepositories}" )
512 protected List<ArtifactRepository> remoteRepositories;
513
514
515
516
517 @Component
518 protected ArtifactMetadataSource metadataSource;
519
520
521
522
523
524
525 @Parameter( property = "disableXmlReport", defaultValue = "false" )
526 protected boolean disableXmlReport;
527
528
529
530
531
532
533
534 @Parameter( property = "enableAssertions", defaultValue = "true" )
535 protected boolean enableAssertions;
536
537
538
539
540 @Component
541 protected MavenSession session;
542
543
544
545
546
547
548 @Parameter( property = "objectFactory" )
549 protected String objectFactory;
550
551
552
553
554 @Parameter( defaultValue = "${session.parallel}", readonly = true )
555 protected Boolean parallelMavenExecution;
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577 @Parameter( defaultValue = "filesystem" )
578 protected String runOrder;
579
580
581
582
583 @Component
584 protected ToolchainManager toolchainManager;
585
586 private Artifact surefireBooterArtifact;
587
588 private Toolchain toolchain;
589
590 private int effectiveForkCount = -1;
591
592
593
594
595
596
597 public static final String THREAD_NUMBER_PLACEHOLDER = "${surefire.threadNumber}";
598
599
600
601
602
603 public static final String FORK_NUMBER_PLACEHOLDER = "${surefire.forkNumber}";
604
605 protected abstract String getPluginName();
606
607 private SurefireDependencyResolver dependencyResolver;
608
609 public void execute()
610 throws MojoExecutionException, MojoFailureException
611 {
612
613 setupStuff();
614
615 if ( verifyParameters() && !hasExecutedBefore() )
616 {
617 DefaultScanResult scan = scanDirectories();
618 if ( !isValidSuiteXmlFileConfig() && scan.isEmpty() )
619 {
620 if ( getEffectiveFailIfNoTests() )
621 {
622 throw new MojoFailureException(
623 "No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)" );
624 }
625 handleSummary( RunResult.noTestsRun(), null );
626 return;
627 }
628 logReportsDirectory();
629 executeAfterPreconditionsChecked( scan );
630 }
631 }
632
633 private void setupStuff()
634 {
635 createDependencyResolver();
636 surefireBooterArtifact = getSurefireBooterArtifact();
637 toolchain = getToolchain();
638 }
639
640 private DefaultScanResult scanDirectories()
641 {
642 return new DirectoryScanner( getTestClassesDirectory(), getIncludeList(), getExcludeList(),
643 getSpecificTests() ).scan();
644 }
645
646 boolean verifyParameters()
647 throws MojoFailureException, MojoExecutionException
648 {
649 setProperties( new SurefireProperties( getProperties() ) );
650 if ( isSkipExecution() )
651 {
652 getLog().info( "Tests are skipped." );
653 return false;
654 }
655
656 String jvmToUse = getJvm();
657 if ( toolchain != null )
658 {
659 getLog().info( "Toolchain in " + getPluginName() + "-plugin: " + toolchain );
660 if ( jvmToUse != null )
661 {
662 getLog().warn( "Toolchains are ignored, 'executable' parameter is set to " + jvmToUse );
663 }
664 }
665
666 if ( !getTestClassesDirectory().exists() )
667 {
668 if ( Boolean.TRUE.equals( getFailIfNoTests() ) )
669 {
670 throw new MojoFailureException( "No tests to run!" );
671 }
672 getLog().info( "No tests to run." );
673 }
674 else
675 {
676 convertDeprecatedForkMode();
677 ensureWorkingDirectoryExists();
678 ensureParallelRunningCompatibility();
679 ensureThreadCountWithPerThread();
680 warnIfUselessUseSystemClassLoaderParameter();
681 warnIfDefunctGroupsCombinations();
682 }
683 return true;
684 }
685
686 protected abstract boolean isSkipExecution();
687
688 protected void executeAfterPreconditionsChecked( DefaultScanResult scanResult )
689 throws MojoExecutionException, MojoFailureException
690 {
691
692 List<ProviderInfo> providers = createProviders();
693
694 RunResult current = RunResult.noTestsRun();
695
696 NestedCheckedException firstForkException = null;
697 for ( ProviderInfo provider : providers )
698 {
699 try
700 {
701 current = current.aggregate( executeProvider( provider, scanResult ) );
702 }
703 catch ( SurefireBooterForkException e )
704 {
705 if ( firstForkException == null )
706 {
707 firstForkException = e;
708 }
709 }
710 catch ( SurefireExecutionException e )
711 {
712 if ( firstForkException == null )
713 {
714 firstForkException = e;
715 }
716 }
717 catch ( TestSetFailedException e )
718 {
719 if ( firstForkException == null )
720 {
721 firstForkException = e;
722 }
723 }
724 }
725
726 if ( firstForkException != null )
727 {
728 current = RunResult.failure( current, firstForkException );
729 }
730
731 handleSummary( current, firstForkException );
732 }
733
734
735 private void createDependencyResolver()
736 {
737 dependencyResolver =
738 new SurefireDependencyResolver( getArtifactResolver(), getArtifactFactory(), getLog(), getLocalRepository(),
739 getRemoteRepositories(), getMetadataSource(), getPluginName() );
740 }
741
742 protected List<ProviderInfo> createProviders()
743 throws MojoFailureException, MojoExecutionException
744 {
745 final Artifact junitDepArtifact = getJunitDepArtifact();
746 ProviderList wellKnownProviders =
747 new ProviderList( new DynamicProviderInfo( null ), new TestNgProviderInfo( getTestNgArtifact() ),
748 new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
749 new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ),
750 new JUnit3ProviderInfo() );
751
752 return wellKnownProviders.resolve( getLog() );
753 }
754
755 private SurefireProperties setupProperties()
756 {
757 SurefireProperties result =
758 SurefireProperties.calculateEffectiveProperties( getSystemProperties(), getSystemPropertiesFile(),
759 getSystemPropertyVariables(), getUserProperties(),
760 getLog() );
761
762 result.setProperty( "basedir", getBasedir().getAbsolutePath() );
763 result.setProperty( "user.dir", getWorkingDirectory().getAbsolutePath() );
764 result.setProperty( "localRepository", getLocalRepository().getBasedir() );
765
766 result.verifyLegalSystemProperties( getLog() );
767 if ( getLog().isDebugEnabled() )
768 {
769 result.showToLog( getLog(), "system property" );
770 }
771 return result;
772 }
773
774 private RunResult executeProvider( ProviderInfo provider, DefaultScanResult scanResult )
775 throws MojoExecutionException, MojoFailureException, SurefireExecutionException, SurefireBooterForkException,
776 TestSetFailedException
777 {
778 SurefireProperties effectiveProperties = setupProperties();
779 ClassLoaderConfiguration classLoaderConfiguration = getClassLoaderConfiguration( isForking() );
780
781 RunOrderParameters runOrderParameters =
782 new RunOrderParameters( getRunOrder(), getStatisticsFileName( getConfigChecksum() ) );
783
784 final RunResult result;
785 if ( isNotForking() )
786 {
787 createCopyAndReplaceForkNumPlaceholder( effectiveProperties, 1 ).copyToSystemProperties();
788
789 InPluginVMSurefireStarter surefireStarter =
790 createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters );
791 result = surefireStarter.runSuitesInProcess( scanResult );
792 }
793 else
794 {
795 ForkConfiguration forkConfiguration = getForkConfiguration();
796 if ( getLog().isDebugEnabled() )
797 {
798 showMap( getEnvironmentVariables(), "environment variable" );
799 }
800
801 Properties originalSystemProperties = (Properties) System.getProperties().clone();
802 try
803 {
804 ForkStarter forkStarter =
805 createForkStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters );
806 result = forkStarter.run( effectiveProperties, scanResult );
807 }
808 finally
809 {
810 System.setProperties( originalSystemProperties );
811 cleanupForkConfiguration( forkConfiguration );
812 }
813 }
814 return result;
815 }
816
817
818 public static SurefireProperties createCopyAndReplaceForkNumPlaceholder(
819 SurefireProperties effectiveSystemProperties, int threadNumber )
820 {
821 SurefireProperties filteredProperties = new SurefireProperties( effectiveSystemProperties );
822 String threadNumberString = String.valueOf( threadNumber );
823 for ( Entry<Object, Object> entry : effectiveSystemProperties.entrySet() )
824 {
825 if ( entry.getValue() instanceof String )
826 {
827 String value = (String) entry.getValue();
828 value = value.replace( THREAD_NUMBER_PLACEHOLDER, threadNumberString );
829 value = value.replace( FORK_NUMBER_PLACEHOLDER, threadNumberString );
830
831 filteredProperties.put( entry.getKey(), value );
832 }
833 }
834 return filteredProperties;
835 }
836
837 protected void cleanupForkConfiguration( ForkConfiguration forkConfiguration )
838 {
839 if ( !getLog().isDebugEnabled() && forkConfiguration != null )
840 {
841 File tempDirectory = forkConfiguration.getTempDirectory();
842 try
843 {
844 FileUtils.deleteDirectory( tempDirectory );
845 }
846 catch ( IOException ioe )
847 {
848 getLog().warn( "Could not delete temp direcotry " + tempDirectory + " because " + ioe.getMessage() );
849 }
850 }
851 }
852
853 protected abstract void handleSummary( RunResult summary, NestedCheckedException firstForkException )
854 throws MojoExecutionException, MojoFailureException;
855
856 protected void logReportsDirectory()
857 {
858 getLog().info(
859 StringUtils.capitalizeFirstLetter( getPluginName() ) + " report directory: " + getReportsDirectory() );
860 }
861
862
863 final Toolchain getToolchain()
864 {
865 Toolchain tc = null;
866
867 if ( getToolchainManager() != null )
868 {
869 tc = getToolchainManager().getToolchainFromBuildContext( "jdk", getSession() );
870 }
871
872 return tc;
873 }
874
875
876
877
878
879 private void convertTestNGParameters()
880 {
881 if ( this.getParallel() != null )
882 {
883 getProperties().setProperty( ProviderParameterNames.PARALLEL_PROP, this.getParallel() );
884 }
885 convertGroupParameters();
886
887 if ( this.getThreadCount() > 0 )
888 {
889 getProperties().setProperty( ProviderParameterNames.THREADCOUNT_PROP,
890 Integer.toString( this.getThreadCount() ) );
891 }
892 if ( this.getObjectFactory() != null )
893 {
894 getProperties().setProperty( "objectfactory", this.getObjectFactory() );
895 }
896 if ( this.getTestClassesDirectory() != null )
897 {
898 getProperties().setProperty( "testng.test.classpath", getTestClassesDirectory().getAbsolutePath() );
899 }
900
901
902 }
903
904 private void convertGroupParameters()
905 {
906 if ( this.getExcludedGroups() != null )
907 {
908 getProperties().setProperty( ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP, this.getExcludedGroups() );
909 }
910 if ( this.getGroups() != null )
911 {
912 getProperties().setProperty( ProviderParameterNames.TESTNG_GROUPS_PROP, this.getGroups() );
913 }
914 }
915
916 protected boolean isAnyConcurrencySelected()
917 {
918 return this.getParallel() != null && this.getParallel().trim().length() > 0;
919 }
920
921 protected boolean isAnyGroupsSelected()
922 {
923 return this.getGroups() != null || this.getExcludedGroups() != null;
924 }
925
926
927
928
929
930 private void convertJunitCoreParameters()
931 {
932 if ( this.getParallel() != null )
933 {
934 getProperties().setProperty( ProviderParameterNames.PARALLEL_PROP, this.getParallel() );
935 }
936 if ( this.getThreadCount() > 0 )
937 {
938 getProperties().setProperty( ProviderParameterNames.THREADCOUNT_PROP,
939 Integer.toString( this.getThreadCount() ) );
940 }
941 getProperties().setProperty( "reuseForks", Boolean.toString( reuseForks ) );
942 getProperties().setProperty( "perCoreThreadCount", Boolean.toString( getPerCoreThreadCount() ) );
943 getProperties().setProperty( "useUnlimitedThreads", Boolean.toString( getUseUnlimitedThreads() ) );
944 }
945
946 private boolean isJunit47Compatible( Artifact artifact )
947 {
948 return dependencyResolver.isWithinVersionSpec( artifact, "[4.7,)" );
949 }
950
951 private boolean isAnyJunit4( Artifact artifact )
952 {
953 return dependencyResolver.isWithinVersionSpec( artifact, "[4.0,)" );
954 }
955
956 static boolean isForkModeNever( String forkMode )
957 {
958 return ForkConfiguration.FORK_NEVER.equals( forkMode );
959 }
960
961 boolean isForking()
962 {
963 return 0 < getEffectiveForkCount();
964 }
965
966 String getEffectiveForkMode()
967 {
968 String forkMode1 = getForkMode();
969
970 if ( toolchain != null && isForkModeNever( forkMode1 ) )
971 {
972 return ForkConfiguration.FORK_ONCE;
973 }
974
975 return ForkConfiguration.getEffectiveForkMode( forkMode1 );
976 }
977
978 private List<RunOrder> getRunOrders()
979 {
980 String runOrderString = getRunOrder();
981 RunOrder[] runOrder = runOrderString == null ? RunOrder.DEFAULT : RunOrder.valueOfMulti( runOrderString );
982 return Arrays.asList( runOrder );
983 }
984
985 private boolean requiresRunHistory()
986 {
987 final List<RunOrder> runOrders = getRunOrders();
988 return runOrders.contains( RunOrder.BALANCED ) || runOrders.contains( RunOrder.FAILEDFIRST );
989 }
990
991 private boolean getEffectiveFailIfNoTests()
992 {
993 if ( isSpecificTestSpecified() )
994 {
995 if ( getFailIfNoSpecifiedTests() != null )
996 {
997 return getFailIfNoSpecifiedTests();
998 }
999 else if ( getFailIfNoTests() != null )
1000 {
1001 return getFailIfNoTests();
1002 }
1003 else
1004 {
1005 return true;
1006 }
1007 }
1008 else
1009 {
1010 return getFailIfNoTests() != null && getFailIfNoTests();
1011 }
1012 }
1013
1014 private ProviderConfiguration createProviderConfiguration( RunOrderParameters runOrderParameters )
1015 throws MojoExecutionException, MojoFailureException
1016 {
1017 ReporterConfiguration reporterConfiguration =
1018 new ReporterConfiguration( getReportsDirectory(), isTrimStackTrace() );
1019
1020 Artifact testNgArtifact;
1021 testNgArtifact = getTestNgArtifact();
1022
1023 DirectoryScannerParameters directoryScannerParameters = null;
1024 final boolean isTestNg = testNgArtifact != null;
1025 TestArtifactInfo testNg =
1026 isTestNg ? new TestArtifactInfo( testNgArtifact.getVersion(), testNgArtifact.getClassifier() ) : null;
1027 List<File> testXml = getSuiteXmlFiles() != null ? Arrays.asList( getSuiteXmlFiles() ) : null;
1028 TestRequest testSuiteDefinition =
1029 new TestRequest( testXml, getTestSourceDirectory(), getTest(), getTestMethod() );
1030 final boolean failIfNoTests;
1031
1032 if ( isValidSuiteXmlFileConfig() && getTest() == null )
1033 {
1034 failIfNoTests = getFailIfNoTests() != null && getFailIfNoTests();
1035 if ( !isTestNg )
1036 {
1037 throw new MojoExecutionException( "suiteXmlFiles is configured, but there is no TestNG dependency" );
1038 }
1039 }
1040 else
1041 {
1042 if ( isSpecificTestSpecified() )
1043 {
1044 failIfNoTests = getEffectiveFailIfNoTests();
1045 setFailIfNoTests( failIfNoTests );
1046 }
1047 else
1048 {
1049 failIfNoTests = getFailIfNoTests() != null && getFailIfNoTests();
1050 }
1051
1052 List<String> includes = getIncludeList();
1053 List<String> excludes = getExcludeList();
1054 List<String> specificTests = getSpecificTests();
1055 directoryScannerParameters =
1056 new DirectoryScannerParameters( getTestClassesDirectory(), includes, excludes, specificTests,
1057 failIfNoTests, getRunOrder() );
1058 }
1059
1060 Properties providerProperties = getProperties();
1061
1062 return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, failIfNoTests,
1063 reporterConfiguration, testNg, testSuiteDefinition, providerProperties, null,
1064 false );
1065 }
1066
1067 public String getStatisticsFileName( String configurationHash )
1068 {
1069 return getReportsDirectory().getParentFile().getParentFile() + File.separator + ".surefire-"
1070 + configurationHash;
1071 }
1072
1073
1074 StartupConfiguration createStartupConfiguration( ProviderInfo provider,
1075 ClassLoaderConfiguration classLoaderConfiguration )
1076 throws MojoExecutionException, MojoFailureException
1077 {
1078
1079 try
1080 {
1081 provider.addProviderProperties();
1082
1083 String providerName = provider.getProviderName();
1084 Classpath providerClasspath = ClasspathCache.getCachedClassPath( providerName );
1085 if ( providerClasspath == null )
1086 {
1087 providerClasspath = provider.getProviderClasspath();
1088 ClasspathCache.setCachedClasspath( providerName, providerClasspath );
1089
1090 }
1091 Classpath inprocClassPath = new Classpath( providerClasspath );
1092 Artifact surefireArtifact = getCommonArtifact();
1093 inprocClassPath.addClassPathElementUrl( surefireArtifact.getFile().getAbsolutePath() );
1094
1095 final Classpath testClasspath = generateTestClasspath();
1096
1097 logClasspath( testClasspath, "test classpath" );
1098 logClasspath( providerClasspath, "provider classpath" );
1099 final ClasspathConfiguration classpathConfiguration =
1100 new ClasspathConfiguration( testClasspath, providerClasspath, inprocClassPath,
1101 effectiveIsEnableAssertions(), isChildDelegation() );
1102
1103 return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration,
1104 isForking(), false );
1105 }
1106 catch ( ArtifactResolutionException e )
1107 {
1108 throw new MojoExecutionException( "Unable to generate classpath: " + e, e );
1109 }
1110 catch ( ArtifactNotFoundException e )
1111 {
1112 throw new MojoExecutionException( "Unable to generate classpath: " + e, e );
1113 }
1114 catch ( InvalidVersionSpecificationException e )
1115 {
1116 throw new MojoExecutionException( "Unable to generate classpath: " + e, e );
1117 }
1118
1119 }
1120
1121 private Artifact getCommonArtifact()
1122 {
1123 return getPluginArtifactMap().get( "org.apache.maven.surefire:maven-surefire-common" );
1124 }
1125
1126 private StartupReportConfiguration getStartupReportConfiguration( String configChecksum )
1127 {
1128 return new StartupReportConfiguration( isUseFile(), isPrintSummary(), getReportFormat(),
1129 isRedirectTestOutputToFile(), isDisableXmlReport(),
1130 getReportsDirectory(), isTrimStackTrace(), getReportNameSuffix(),
1131 configChecksum, requiresRunHistory() );
1132 }
1133
1134 void logClasspath( Classpath classpath, String descriptor )
1135 {
1136 getLog().debug( descriptor + " classpath:" );
1137 @SuppressWarnings( "unchecked" ) final List<String> classPath = classpath.getClassPath();
1138 for ( String classpathElement : classPath )
1139 {
1140 if ( classpathElement == null )
1141 {
1142 getLog().warn( "The test classpath contains a null element." );
1143 }
1144 else
1145 {
1146 getLog().debug( " " + classpathElement );
1147 }
1148 }
1149 }
1150
1151
1152 private boolean isSpecificTestSpecified()
1153 {
1154 return getTest() != null;
1155 }
1156
1157 private boolean isValidSuiteXmlFileConfig()
1158 {
1159 return getSuiteXmlFiles() != null && getSuiteXmlFiles().length > 0;
1160 }
1161
1162 private List<String> readListFromFile( final File file )
1163 {
1164 List<String> list;
1165
1166 getLog().debug( "Reading list from: " + file );
1167
1168 if ( !file.exists() )
1169 {
1170 throw new RuntimeException( "Failed to load list from file: " + file );
1171 }
1172
1173 try
1174 {
1175 list = FileUtils.loadFile( file );
1176 }
1177 catch ( IOException e )
1178 {
1179 throw new RuntimeException( "Failed to load list from file: " + file, e );
1180 }
1181
1182 if ( getLog().isDebugEnabled() )
1183 {
1184 getLog().debug( "List contents:" );
1185 for ( String entry : list )
1186 {
1187 getLog().debug( " " + entry );
1188 }
1189 }
1190 return list;
1191 }
1192
1193 private void maybeAppendList( final List<String> base, final List<String> list )
1194 {
1195 if ( list != null )
1196 {
1197 base.addAll( list );
1198 }
1199 }
1200
1201 private List<String> getExcludeList()
1202 {
1203 List<String> excludes = null;
1204 if ( isSpecificTestSpecified() )
1205 {
1206
1207
1208
1209
1210 excludes = new ArrayList<String>();
1211 }
1212 else
1213 {
1214 if ( getExcludesFile() != null )
1215 {
1216 excludes = readListFromFile( getExcludesFile() );
1217 }
1218
1219
1220 if ( excludes == null )
1221 {
1222 excludes = this.getExcludes();
1223 }
1224 else
1225 {
1226 maybeAppendList( excludes, this.getExcludes() );
1227 }
1228
1229
1230
1231 if ( excludes == null || excludes.size() == 0 )
1232 {
1233 excludes = Arrays.asList( new String[]{ "**/*$*" } );
1234 }
1235 }
1236 return filterNulls( excludes );
1237 }
1238
1239 private List<String> getIncludeList()
1240 {
1241 List<String> includes = null;
1242 if ( isSpecificTestSpecified() && !isMultipleExecutionBlocksDetected() )
1243 {
1244 includes = getSpecificTests();
1245 }
1246 else
1247 {
1248 if ( getIncludesFile() != null )
1249 {
1250 includes = readListFromFile( getIncludesFile() );
1251 }
1252
1253
1254 if ( includes == null )
1255 {
1256 includes = this.getIncludes();
1257 }
1258 else
1259 {
1260 maybeAppendList( includes, this.getIncludes() );
1261 }
1262 }
1263
1264
1265
1266 if ( includes == null || includes.size() == 0 )
1267 {
1268 includes = Arrays.asList( getDefaultIncludes() );
1269 }
1270
1271 return filterNulls( includes );
1272 }
1273
1274 private List<String> filterNulls( List<String> toFilter )
1275 {
1276 List<String> result = new ArrayList<String>( toFilter.size() );
1277 for ( String item : toFilter )
1278 {
1279 if ( item != null )
1280 {
1281 result.add( item );
1282 }
1283 }
1284
1285 return result;
1286 }
1287
1288 private boolean isMultipleExecutionBlocksDetected()
1289 {
1290 MavenProject project = getProject();
1291 if ( project != null )
1292 {
1293 String key = getPluginDescriptor().getPluginLookupKey();
1294 Plugin plugin = (Plugin) project.getBuild().getPluginsAsMap().get( key );
1295
1296 if ( plugin != null )
1297 {
1298 @SuppressWarnings( "rawtypes" ) List executions = plugin.getExecutions();
1299 return executions != null && executions.size() > 1;
1300 }
1301 }
1302
1303 return false;
1304 }
1305
1306 private List<String> getSpecificTests()
1307 {
1308 if ( !isSpecificTestSpecified() )
1309 {
1310 return Collections.emptyList();
1311 }
1312
1313 List<String> specificTests = new ArrayList<String>();
1314 String[] testRegexes = StringUtils.split( getTest(), "," );
1315
1316 for ( String testRegexe : testRegexes )
1317 {
1318 String testRegex = testRegexe;
1319 if ( testRegex.endsWith( ".java" ) )
1320 {
1321 testRegex = testRegex.substring( 0, testRegex.length() - 5 );
1322 }
1323
1324 testRegex = testRegex.replace( '.', '/' );
1325 specificTests.add( "**/" + testRegex + ".java" );
1326 }
1327
1328 return specificTests;
1329 }
1330
1331 private Artifact getTestNgArtifact()
1332 throws MojoExecutionException
1333 {
1334 Artifact artifact = getProjectArtifactMap().get( getTestNGArtifactName() );
1335
1336 if ( artifact != null )
1337 {
1338 VersionRange range = createVersionRange();
1339 if ( !range.containsVersion( new DefaultArtifactVersion( artifact.getVersion() ) ) )
1340 {
1341 throw new MojoExecutionException(
1342 "TestNG support requires version 4.7 or above. You have declared version "
1343 + artifact.getVersion() );
1344 }
1345 }
1346 return artifact;
1347
1348 }
1349
1350 private VersionRange createVersionRange()
1351 {
1352 try
1353 {
1354 return VersionRange.createFromVersionSpec( "[4.7,)" );
1355 }
1356 catch ( InvalidVersionSpecificationException e )
1357 {
1358 throw new RuntimeException( e );
1359 }
1360 }
1361
1362 private Artifact getJunitArtifact()
1363 {
1364 return getProjectArtifactMap().get( getJunitArtifactName() );
1365 }
1366
1367 private Artifact getJunitDepArtifact()
1368 {
1369 return getProjectArtifactMap().get( "junit:junit-dep" );
1370 }
1371
1372 protected ForkStarter createForkStarter( ProviderInfo provider, ForkConfiguration forkConfiguration,
1373 ClassLoaderConfiguration classLoaderConfiguration,
1374 RunOrderParameters runOrderParameters )
1375 throws MojoExecutionException, MojoFailureException
1376 {
1377 StartupConfiguration startupConfiguration = createStartupConfiguration( provider, classLoaderConfiguration );
1378 String configChecksum = getConfigChecksum();
1379 StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
1380 ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
1381 return new ForkStarter( providerConfiguration, startupConfiguration, forkConfiguration,
1382 getForkedProcessTimeoutInSeconds(), startupReportConfiguration );
1383 }
1384
1385 protected InPluginVMSurefireStarter createInprocessStarter( ProviderInfo provider,
1386 ClassLoaderConfiguration classLoaderConfiguration,
1387 RunOrderParameters runOrderParameters )
1388 throws MojoExecutionException, MojoFailureException
1389 {
1390 StartupConfiguration startupConfiguration = createStartupConfiguration( provider, classLoaderConfiguration );
1391 String configChecksum = getConfigChecksum();
1392 StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
1393 ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
1394 return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration, startupReportConfiguration );
1395
1396 }
1397
1398 protected ForkConfiguration getForkConfiguration()
1399 {
1400 File tmpDir = getSurefireTempDir();
1401
1402 tmpDir.mkdirs();
1403
1404 Artifact shadeFire = getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-shadefire" );
1405
1406 final Classpath bootClasspathConfiguration =
1407 getArtifactClasspath( shadeFire != null ? shadeFire : surefireBooterArtifact );
1408
1409 return new ForkConfiguration( bootClasspathConfiguration, tmpDir, getEffectiveDebugForkedProcess(),
1410 getEffectiveJvm(),
1411 getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
1412 getArgLine(), getEnvironmentVariables(), getLog().isDebugEnabled(),
1413 getEffectiveForkCount(), reuseForks );
1414 }
1415
1416 private void convertDeprecatedForkMode()
1417 {
1418 String effectiveForkMode = getEffectiveForkMode();
1419
1420 if ( ForkConfiguration.FORK_PERTHREAD.equals( effectiveForkMode ) )
1421 {
1422 forkCount = String.valueOf(threadCount);
1423 }
1424 else if ( ForkConfiguration.FORK_NEVER.equals( effectiveForkMode ) )
1425 {
1426 forkCount = "0";
1427 } else if ( ForkConfiguration.FORK_ALWAYS.equals( effectiveForkMode )) {
1428 forkCount = "1";
1429 reuseForks = false;
1430 }
1431
1432 if ( !ForkConfiguration.FORK_ONCE.equals( getForkMode() ) )
1433 {
1434 getLog().warn( "The parameter forkMode is deprecated since version 2.14. Use forkCount and reuseForks instead." );
1435 }
1436 }
1437
1438 protected int getEffectiveForkCount()
1439 {
1440 if ( effectiveForkCount < 0 )
1441 {
1442 try
1443 {
1444 effectiveForkCount = convertWithCoreCount( forkCount );
1445 }
1446 catch ( NumberFormatException ignored )
1447 {
1448 }
1449
1450 if ( effectiveForkCount < 0 )
1451 {
1452 throw new IllegalArgumentException( "Fork count " + forkCount.trim() + " is not a legal value." );
1453 }
1454 }
1455
1456 return effectiveForkCount;
1457 }
1458
1459 protected int convertWithCoreCount( String count )
1460 {
1461 String trimmed = count.trim();
1462 if ( trimmed.endsWith( "C" ) )
1463 {
1464 double multiplier = Double.parseDouble( trimmed.substring( 0, trimmed.length() - 1 ) );
1465 return (int) ( multiplier * ( (double) Runtime.getRuntime().availableProcessors() ) );
1466 }
1467 else
1468 {
1469 return Integer.parseInt( trimmed );
1470 }
1471 }
1472
1473 private String getEffectiveDebugForkedProcess()
1474 {
1475 String debugForkedProcess = getDebugForkedProcess();
1476 if ( "true".equals( debugForkedProcess ) )
1477 {
1478 return "-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005";
1479 }
1480 return debugForkedProcess;
1481 }
1482
1483 private String getEffectiveJvm()
1484 {
1485 String jvmToUse = getJvm();
1486 if ( toolchain != null && jvmToUse == null )
1487 {
1488 jvmToUse = toolchain.findTool( "java" );
1489 }
1490
1491 if ( StringUtils.isEmpty( jvmToUse ) )
1492 {
1493
1494 jvmToUse = System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java";
1495 getLog().debug( "Using JVM: " + jvmToUse );
1496 }
1497
1498 return jvmToUse;
1499 }
1500
1501
1502 private Artifact getSurefireBooterArtifact()
1503 {
1504 Artifact artifact = getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-booter" );
1505 if ( artifact == null )
1506 {
1507 throw new RuntimeException( "Unable to locate surefire-booter in the list of plugin artifacts" );
1508 }
1509 artifact.isSnapshot();
1510 return artifact;
1511 }
1512
1513
1514
1515
1516
1517
1518
1519 private File getSurefireTempDir()
1520 {
1521 return new File( getReportsDirectory().getParentFile(), "surefire" );
1522 }
1523
1524
1525
1526
1527
1528
1529 private String getConfigChecksum()
1530 {
1531 ChecksumCalculator checksum = new ChecksumCalculator();
1532 checksum.add( getPluginName() );
1533 checksum.add( isSkipTests() );
1534 checksum.add( isSkipExec() );
1535 checksum.add( isSkip() );
1536 checksum.add( getTestClassesDirectory() );
1537 checksum.add( getClassesDirectory() );
1538 checksum.add( getClasspathDependencyExcludes() );
1539 checksum.add( getClasspathDependencyScopeExclude() );
1540 checksum.add( getAdditionalClasspathElements() );
1541 checksum.add( getReportsDirectory() );
1542 checksum.add( getTestSourceDirectory() );
1543 checksum.add( getTest() );
1544 checksum.add( getIncludes() );
1545 checksum.add( getExcludes() );
1546 checksum.add( getLocalRepository() );
1547 checksum.add( getSystemProperties() );
1548 checksum.add( getSystemPropertyVariables() );
1549 checksum.add( getSystemPropertiesFile() );
1550 checksum.add( getProperties() );
1551 checksum.add( isPrintSummary() );
1552 checksum.add( getReportFormat() );
1553 checksum.add( getReportNameSuffix() );
1554 checksum.add( isUseFile() );
1555 checksum.add( isRedirectTestOutputToFile() );
1556 checksum.add( getForkMode() );
1557 checksum.add( getForkCount() );
1558 checksum.add( isReuseForks() );
1559 checksum.add( getJvm() );
1560 checksum.add( getArgLine() );
1561 checksum.add( getDebugForkedProcess() );
1562 checksum.add( getForkedProcessTimeoutInSeconds() );
1563 checksum.add( getEnvironmentVariables() );
1564 checksum.add( getWorkingDirectory() );
1565 checksum.add( isChildDelegation() );
1566 checksum.add( getGroups() );
1567 checksum.add( getExcludedGroups() );
1568 checksum.add( getSuiteXmlFiles() );
1569 checksum.add( getJunitArtifact() );
1570 checksum.add( getTestNGArtifactName() );
1571 checksum.add( getThreadCount() );
1572 checksum.add( getPerCoreThreadCount() );
1573 checksum.add( getUseUnlimitedThreads() );
1574 checksum.add( getParallel() );
1575 checksum.add( isTrimStackTrace() );
1576 checksum.add( getRemoteRepositories() );
1577 checksum.add( isDisableXmlReport() );
1578 checksum.add( isUseSystemClassLoader() );
1579 checksum.add( isUseManifestOnlyJar() );
1580 checksum.add( isEnableAssertions() );
1581 checksum.add( getObjectFactory() );
1582 checksum.add( getFailIfNoTests() );
1583 checksum.add( getRunOrder() );
1584 addPluginSpecificChecksumItems( checksum );
1585 return checksum.getSha1();
1586
1587 }
1588
1589 protected void addPluginSpecificChecksumItems( ChecksumCalculator checksum )
1590 {
1591
1592 }
1593
1594 protected boolean hasExecutedBefore()
1595 {
1596
1597 String configChecksum = getConfigChecksum();
1598 @SuppressWarnings( "unchecked" ) Map<String, String> pluginContext = getPluginContext();
1599 if ( pluginContext.containsKey( configChecksum ) )
1600 {
1601 getLog().info( "Skipping execution of surefire because it has already been run for this configuration" );
1602 return true;
1603 }
1604 pluginContext.put( configChecksum, configChecksum );
1605
1606 return false;
1607 }
1608
1609 protected ClassLoaderConfiguration getClassLoaderConfiguration( boolean isForking )
1610 {
1611 return isForking
1612 ? new ClassLoaderConfiguration( isUseSystemClassLoader(), isUseManifestOnlyJar() )
1613 : new ClassLoaderConfiguration( false, false );
1614 }
1615
1616 protected abstract String[] getDefaultIncludes();
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628 Classpath generateTestClasspath()
1629 throws InvalidVersionSpecificationException, MojoFailureException, ArtifactResolutionException,
1630 ArtifactNotFoundException, MojoExecutionException
1631 {
1632 List<String> classpath = new ArrayList<String>( 2 + getProject().getArtifacts().size() );
1633
1634 classpath.add( getTestClassesDirectory().getAbsolutePath() );
1635
1636 classpath.add( getClassesDirectory().getAbsolutePath() );
1637
1638 @SuppressWarnings( "unchecked" ) Set<Artifact> classpathArtifacts = getProject().getArtifacts();
1639
1640 if ( getClasspathDependencyScopeExclude() != null && !getClasspathDependencyScopeExclude().equals( "" ) )
1641 {
1642 ArtifactFilter dependencyFilter = new ScopeArtifactFilter( getClasspathDependencyScopeExclude() );
1643 classpathArtifacts = this.filterArtifacts( classpathArtifacts, dependencyFilter );
1644 }
1645
1646 if ( getClasspathDependencyExcludes() != null )
1647 {
1648 ArtifactFilter dependencyFilter = new PatternIncludesArtifactFilter( getClasspathDependencyExcludes() );
1649 classpathArtifacts = this.filterArtifacts( classpathArtifacts, dependencyFilter );
1650 }
1651
1652 for ( Artifact artifact : classpathArtifacts )
1653 {
1654 if ( artifact.getArtifactHandler().isAddedToClasspath() )
1655 {
1656 File file = artifact.getFile();
1657 if ( file != null )
1658 {
1659 classpath.add( file.getPath() );
1660 }
1661 }
1662 }
1663
1664
1665 if ( getAdditionalClasspathElements() != null )
1666 {
1667 for ( String classpathElement : getAdditionalClasspathElements() )
1668 {
1669 if ( classpathElement != null )
1670 {
1671 classpath.add( classpathElement );
1672 }
1673 }
1674 }
1675
1676
1677
1678 if ( getTestNgArtifact() != null )
1679 {
1680 addTestNgUtilsArtifacts( classpath );
1681 }
1682
1683 return new Classpath( classpath );
1684 }
1685
1686 void addTestNgUtilsArtifacts( List<String> classpath )
1687 throws ArtifactResolutionException, ArtifactNotFoundException
1688 {
1689 Artifact surefireArtifact = getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-booter" );
1690 String surefireVersion = surefireArtifact.getBaseVersion();
1691
1692 Artifact[] extraTestNgArtifacts =
1693 { getArtifactFactory().createArtifact( "org.apache.maven.surefire", "surefire-testng-utils",
1694 surefireVersion, "runtime", "jar" ),
1695 getArtifactFactory().createArtifact( "org.apache.maven.surefire", "surefire-grouper", surefireVersion,
1696 "runtime", "jar" ) };
1697
1698 for ( Artifact artifact : extraTestNgArtifacts )
1699 {
1700 getArtifactResolver().resolve( artifact, getRemoteRepositories(), getLocalRepository() );
1701
1702 String path = artifact.getFile().getPath();
1703 classpath.add( path );
1704 }
1705 }
1706
1707
1708
1709
1710
1711
1712
1713
1714 private Set<Artifact> filterArtifacts( Set<Artifact> artifacts, ArtifactFilter filter )
1715 {
1716 Set<Artifact> filteredArtifacts = new LinkedHashSet<Artifact>();
1717
1718 for ( Artifact artifact : artifacts )
1719 {
1720 if ( !filter.include( artifact ) )
1721 {
1722 filteredArtifacts.add( artifact );
1723 }
1724 }
1725
1726 return filteredArtifacts;
1727 }
1728
1729 private void showMap( Map<?, ?> map, String setting )
1730 {
1731 for ( Object o : map.keySet() )
1732 {
1733 String key = (String) o;
1734 String value = (String) map.get( key );
1735 getLog().debug( "Setting " + setting + " [" + key + "]=[" + value + "]" );
1736 }
1737 }
1738
1739
1740 private ArtifactResolutionResult resolveArtifact( Artifact filteredArtifact, Artifact providerArtifact )
1741 {
1742 ArtifactFilter filter = null;
1743 if ( filteredArtifact != null )
1744 {
1745 filter = new ExcludesArtifactFilter(
1746 Collections.singletonList( filteredArtifact.getGroupId() + ":" + filteredArtifact.getArtifactId() ) );
1747 }
1748
1749 Artifact originatingArtifact = getArtifactFactory().createBuildArtifact( "dummy", "dummy", "1.0", "jar" );
1750
1751 try
1752 {
1753 return getArtifactResolver().resolveTransitively( Collections.singleton( providerArtifact ),
1754 originatingArtifact, getLocalRepository(),
1755 getRemoteRepositories(), getMetadataSource(), filter );
1756 }
1757 catch ( ArtifactResolutionException e )
1758 {
1759 throw new NestedRuntimeException( e );
1760 }
1761 catch ( ArtifactNotFoundException e )
1762 {
1763 throw new NestedRuntimeException( e );
1764 }
1765 }
1766
1767 private Classpath getArtifactClasspath( Artifact surefireArtifact )
1768 {
1769 Classpath existing = ClasspathCache.getCachedClassPath( surefireArtifact.getArtifactId() );
1770 if ( existing == null )
1771 {
1772 ArtifactResolutionResult result = resolveArtifact( null, surefireArtifact );
1773
1774 List<String> items = new ArrayList<String>();
1775 for ( Object o : result.getArtifacts() )
1776 {
1777 Artifact artifact = (Artifact) o;
1778
1779 getLog().debug(
1780 "Adding to " + getPluginName() + " booter test classpath: " + artifact.getFile().getAbsolutePath() +
1781 " Scope: " + artifact.getScope() );
1782
1783 items.add( artifact.getFile().getAbsolutePath() );
1784 }
1785 existing = new Classpath( items );
1786 ClasspathCache.setCachedClasspath( surefireArtifact.getArtifactId(), existing );
1787 }
1788 return existing;
1789 }
1790
1791 private Properties getUserProperties()
1792 {
1793 Properties props = null;
1794 try
1795 {
1796
1797 Method getUserProperties = getSession().getClass().getMethod( "getUserProperties" );
1798 props = (Properties) getUserProperties.invoke( getSession() );
1799 }
1800 catch ( Exception e )
1801 {
1802 String msg = "Build uses Maven 2.0.x, cannot propagate system properties"
1803 + " from command line to tests (cf. SUREFIRE-121)";
1804 if ( getLog().isDebugEnabled() )
1805 {
1806 getLog().warn( msg, e );
1807 }
1808 else
1809 {
1810 getLog().warn( msg );
1811 }
1812 }
1813 if ( props == null )
1814 {
1815 props = new Properties();
1816 }
1817 return props;
1818 }
1819
1820
1821 void ensureWorkingDirectoryExists()
1822 throws MojoFailureException
1823 {
1824 if ( getWorkingDirectory() == null )
1825 {
1826 throw new MojoFailureException( "workingDirectory cannot be null" );
1827 }
1828
1829 if ( !getWorkingDirectory().exists() )
1830 {
1831 if ( !getWorkingDirectory().mkdirs() )
1832 {
1833 throw new MojoFailureException( "Cannot create workingDirectory " + getWorkingDirectory() );
1834 }
1835 }
1836
1837 if ( !getWorkingDirectory().isDirectory() )
1838 {
1839 throw new MojoFailureException(
1840 "workingDirectory " + getWorkingDirectory() + " exists and is not a directory" );
1841 }
1842 }
1843
1844 void ensureParallelRunningCompatibility()
1845 throws MojoFailureException
1846 {
1847 if ( isMavenParallel() && isNotForking() )
1848 {
1849 throw new MojoFailureException( "parallel maven execution is not compatible with surefire forkCount 0" );
1850 }
1851 }
1852
1853 void ensureThreadCountWithPerThread()
1854 throws MojoFailureException
1855 {
1856 if ( ForkConfiguration.FORK_PERTHREAD.equals( getEffectiveForkMode() ) && getThreadCount() < 1 )
1857 {
1858 throw new MojoFailureException( "Fork mode perthread requires a thread count" );
1859 }
1860 }
1861
1862 void warnIfUselessUseSystemClassLoaderParameter()
1863 {
1864 if ( isUseSystemClassLoader() && isNotForking() )
1865 {
1866 getLog().warn( "useSystemClassloader setting has no effect when not forking" );
1867 }
1868 }
1869
1870 private boolean isNotForking()
1871 {
1872 return !isForking();
1873 }
1874
1875 void warnIfDefunctGroupsCombinations()
1876 throws MojoFailureException, MojoExecutionException
1877 {
1878 if ( isAnyGroupsSelected() )
1879 {
1880 if ( getTestNgArtifact() != null )
1881 {
1882 return;
1883 }
1884 Artifact junitArtifact = getJunitArtifact();
1885 boolean junit47Compatible = isJunit47Compatible( junitArtifact );
1886 if ( junit47Compatible )
1887 {
1888 return;
1889 }
1890 if ( junitArtifact != null && !junit47Compatible )
1891 {
1892 throw new MojoFailureException( "groups/excludedGroups are specified but JUnit version on classpath"
1893 + " is too old to support groups. Check your dependency:tree to see if your project is picking up an old junit version" );
1894 }
1895 throw new MojoFailureException(
1896 "groups/excludedGroups require TestNG or JUnit48+ on project test classpath" );
1897
1898 }
1899 }
1900
1901 class TestNgProviderInfo
1902 implements ProviderInfo
1903 {
1904 private final Artifact testNgArtifact;
1905
1906 TestNgProviderInfo( Artifact testNgArtifact )
1907 {
1908 this.testNgArtifact = testNgArtifact;
1909 }
1910
1911 public String getProviderName()
1912 {
1913 return "org.apache.maven.surefire.testng.TestNGProvider";
1914 }
1915
1916 public boolean isApplicable()
1917 {
1918 return testNgArtifact != null;
1919 }
1920
1921 public void addProviderProperties()
1922 {
1923 convertTestNGParameters();
1924 }
1925
1926 public Classpath getProviderClasspath()
1927 throws ArtifactResolutionException, ArtifactNotFoundException
1928 {
1929 Artifact surefireArtifact = getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-booter" );
1930 return dependencyResolver.getProviderClasspath( "surefire-testng", surefireArtifact.getBaseVersion(),
1931 testNgArtifact );
1932 }
1933 }
1934
1935 class JUnit3ProviderInfo
1936 implements ProviderInfo
1937 {
1938 public String getProviderName()
1939 {
1940 return "org.apache.maven.surefire.junit.JUnit3Provider";
1941 }
1942
1943 public boolean isApplicable()
1944 {
1945 return true;
1946 }
1947
1948 public void addProviderProperties()
1949 {
1950 }
1951
1952 public Classpath getProviderClasspath()
1953 throws ArtifactResolutionException, ArtifactNotFoundException
1954 {
1955
1956
1957 return dependencyResolver.getProviderClasspath( "surefire-junit3", surefireBooterArtifact.getBaseVersion(),
1958 null );
1959
1960 }
1961
1962 }
1963
1964 class JUnit4ProviderInfo
1965 implements ProviderInfo
1966 {
1967 private final Artifact junitArtifact;
1968
1969 private final Artifact junitDepArtifact;
1970
1971 JUnit4ProviderInfo( Artifact junitArtifact, Artifact junitDepArtifact )
1972 {
1973 this.junitArtifact = junitArtifact;
1974 this.junitDepArtifact = junitDepArtifact;
1975 }
1976
1977 public String getProviderName()
1978 {
1979 return "org.apache.maven.surefire.junit4.JUnit4Provider";
1980 }
1981
1982 public boolean isApplicable()
1983 {
1984 return junitDepArtifact != null || isAnyJunit4( junitArtifact );
1985 }
1986
1987 public void addProviderProperties()
1988 {
1989 }
1990
1991 public Classpath getProviderClasspath()
1992 throws ArtifactResolutionException, ArtifactNotFoundException
1993 {
1994 return dependencyResolver.getProviderClasspath( "surefire-junit4", surefireBooterArtifact.getBaseVersion(),
1995 null );
1996
1997 }
1998
1999 }
2000
2001 class JUnitCoreProviderInfo
2002 implements ProviderInfo
2003 {
2004 private final Artifact junitArtifact;
2005
2006 private final Artifact junitDepArtifact;
2007
2008 JUnitCoreProviderInfo( Artifact junitArtifact, Artifact junitDepArtifact )
2009 {
2010 this.junitArtifact = junitArtifact;
2011 this.junitDepArtifact = junitDepArtifact;
2012 }
2013
2014 public String getProviderName()
2015 {
2016 return "org.apache.maven.surefire.junitcore.JUnitCoreProvider";
2017 }
2018
2019 private boolean is47CompatibleJunitDep()
2020 {
2021 return junitDepArtifact != null && isJunit47Compatible( junitDepArtifact );
2022 }
2023
2024 public boolean isApplicable()
2025 {
2026 final boolean isJunitArtifact47 = isAnyJunit4( junitArtifact ) && isJunit47Compatible( junitArtifact );
2027 final boolean isAny47ProvidersForcers = isAnyConcurrencySelected() || isAnyGroupsSelected();
2028 return isAny47ProvidersForcers && ( isJunitArtifact47 || is47CompatibleJunitDep() );
2029 }
2030
2031 public void addProviderProperties()
2032 {
2033 convertJunitCoreParameters();
2034 convertGroupParameters();
2035 }
2036
2037 public Classpath getProviderClasspath()
2038 throws ArtifactResolutionException, ArtifactNotFoundException
2039 {
2040 return dependencyResolver.getProviderClasspath( "surefire-junit47", surefireBooterArtifact.getBaseVersion(),
2041 null );
2042 }
2043
2044 }
2045
2046 public class DynamicProviderInfo
2047 implements ConfigurableProviderInfo
2048 {
2049 final String providerName;
2050
2051 DynamicProviderInfo( String providerName )
2052 {
2053 this.providerName = providerName;
2054 }
2055
2056 public ProviderInfo instantiate( String providerName )
2057 {
2058 return new DynamicProviderInfo( providerName );
2059 }
2060
2061 public String getProviderName()
2062 {
2063 return providerName;
2064 }
2065
2066 public boolean isApplicable()
2067 {
2068 return true;
2069 }
2070
2071 public void addProviderProperties()
2072 {
2073
2074 convertJunitCoreParameters();
2075 convertTestNGParameters();
2076 }
2077
2078
2079 public Classpath getProviderClasspath()
2080 throws ArtifactResolutionException, ArtifactNotFoundException
2081 {
2082 final Map<String, Artifact> pluginArtifactMap = getPluginArtifactMap();
2083 Artifact plugin = pluginArtifactMap.get( "org.apache.maven.plugins:maven-surefire-plugin" );
2084 return dependencyResolver.addProviderToClasspath( pluginArtifactMap, plugin );
2085 }
2086
2087 }
2088
2089
2090 public abstract List<String> getIncludes();
2091
2092 public File getIncludesFile()
2093 {
2094 return includesFile;
2095 }
2096
2097 public abstract void setIncludes( List<String> includes );
2098
2099 public List<String> getExcludes()
2100 {
2101 return excludes;
2102 }
2103
2104 public File getExcludesFile()
2105 {
2106 return excludesFile;
2107 }
2108
2109 public void setExcludes( List<String> excludes )
2110 {
2111 this.excludes = excludes;
2112 }
2113
2114 public ArtifactRepository getLocalRepository()
2115 {
2116 return localRepository;
2117 }
2118
2119 public void setLocalRepository( ArtifactRepository localRepository )
2120 {
2121 this.localRepository = localRepository;
2122 }
2123
2124
2125
2126
2127 public Properties getSystemProperties()
2128 {
2129 return systemProperties;
2130 }
2131
2132 @SuppressWarnings( { "UnusedDeclaration", "deprecation" } )
2133 public void setSystemProperties( Properties systemProperties )
2134 {
2135 this.systemProperties = systemProperties;
2136 }
2137
2138 public Map<String, String> getSystemPropertyVariables()
2139 {
2140 return systemPropertyVariables;
2141 }
2142
2143 @SuppressWarnings( "UnusedDeclaration" )
2144 public void setSystemPropertyVariables( Map<String, String> systemPropertyVariables )
2145 {
2146 this.systemPropertyVariables = systemPropertyVariables;
2147 }
2148
2149 public File getSystemPropertiesFile()
2150 {
2151 return systemPropertiesFile;
2152 }
2153
2154 @SuppressWarnings( "UnusedDeclaration" )
2155 public void setSystemPropertiesFile( File systemPropertiesFile )
2156 {
2157 this.systemPropertiesFile = systemPropertiesFile;
2158 }
2159
2160 public Properties getProperties()
2161 {
2162 return properties;
2163 }
2164
2165 public void setProperties( Properties properties )
2166 {
2167 this.properties = properties;
2168 }
2169
2170 public Map<String, Artifact> getPluginArtifactMap()
2171 {
2172 return pluginArtifactMap;
2173 }
2174
2175 @SuppressWarnings( "UnusedDeclaration" )
2176 public void setPluginArtifactMap( Map<String, Artifact> pluginArtifactMap )
2177 {
2178 this.pluginArtifactMap = pluginArtifactMap;
2179 }
2180
2181 public Map<String, Artifact> getProjectArtifactMap()
2182 {
2183 return projectArtifactMap;
2184 }
2185
2186 @SuppressWarnings( "UnusedDeclaration" )
2187 public void setProjectArtifactMap( Map<String, Artifact> projectArtifactMap )
2188 {
2189 this.projectArtifactMap = projectArtifactMap;
2190 }
2191
2192
2193 public String getReportNameSuffix()
2194 {
2195 return reportNameSuffix;
2196 }
2197
2198 @SuppressWarnings( "UnusedDeclaration" )
2199 public void setReportNameSuffix( String reportNameSuffix )
2200 {
2201 this.reportNameSuffix = reportNameSuffix;
2202 }
2203
2204
2205 public boolean isRedirectTestOutputToFile()
2206 {
2207 return redirectTestOutputToFile;
2208 }
2209
2210 @SuppressWarnings( "UnusedDeclaration" )
2211 public void setRedirectTestOutputToFile( boolean redirectTestOutputToFile )
2212 {
2213 this.redirectTestOutputToFile = redirectTestOutputToFile;
2214 }
2215
2216
2217 public Boolean getFailIfNoTests()
2218 {
2219 return failIfNoTests;
2220 }
2221
2222 public void setFailIfNoTests( Boolean failIfNoTests )
2223 {
2224 this.failIfNoTests = failIfNoTests;
2225 }
2226
2227 public String getForkMode()
2228 {
2229 return forkMode;
2230 }
2231
2232 @SuppressWarnings( "UnusedDeclaration" )
2233 public void setForkMode( String forkMode )
2234 {
2235 this.forkMode = forkMode;
2236 }
2237
2238 public String getJvm()
2239 {
2240 return jvm;
2241 }
2242
2243 public String getArgLine()
2244 {
2245 return argLine;
2246 }
2247
2248 @SuppressWarnings( "UnusedDeclaration" )
2249 public void setArgLine( String argLine )
2250 {
2251 this.argLine = argLine;
2252 }
2253
2254
2255 public Map<String, String> getEnvironmentVariables()
2256 {
2257 return environmentVariables;
2258 }
2259
2260 @SuppressWarnings( "UnusedDeclaration" )
2261 public void setEnvironmentVariables( Map<String, String> environmentVariables )
2262 {
2263 this.environmentVariables = environmentVariables;
2264 }
2265
2266 public File getWorkingDirectory()
2267 {
2268 return workingDirectory;
2269 }
2270
2271 @SuppressWarnings( "UnusedDeclaration" )
2272 public void setWorkingDirectory( File workingDirectory )
2273 {
2274 this.workingDirectory = workingDirectory;
2275 }
2276
2277 public boolean isChildDelegation()
2278 {
2279 return childDelegation;
2280 }
2281
2282 @SuppressWarnings( "UnusedDeclaration" )
2283 public void setChildDelegation( boolean childDelegation )
2284 {
2285 this.childDelegation = childDelegation;
2286 }
2287
2288 public String getGroups()
2289 {
2290 return groups;
2291 }
2292
2293 @SuppressWarnings( "UnusedDeclaration" )
2294 public void setGroups( String groups )
2295 {
2296 this.groups = groups;
2297 }
2298
2299 public String getExcludedGroups()
2300 {
2301 return excludedGroups;
2302 }
2303
2304 @SuppressWarnings( "UnusedDeclaration" )
2305 public void setExcludedGroups( String excludedGroups )
2306 {
2307 this.excludedGroups = excludedGroups;
2308 }
2309
2310 public File[] getSuiteXmlFiles()
2311 {
2312 return suiteXmlFiles;
2313 }
2314
2315 @SuppressWarnings( "UnusedDeclaration" )
2316 public void setSuiteXmlFiles( File[] suiteXmlFiles )
2317 {
2318 this.suiteXmlFiles = suiteXmlFiles;
2319 }
2320
2321 public String getJunitArtifactName()
2322 {
2323 return junitArtifactName;
2324 }
2325
2326 @SuppressWarnings( "UnusedDeclaration" )
2327 public void setJunitArtifactName( String junitArtifactName )
2328 {
2329 this.junitArtifactName = junitArtifactName;
2330 }
2331
2332 public String getTestNGArtifactName()
2333 {
2334 return testNGArtifactName;
2335 }
2336
2337 @SuppressWarnings( "UnusedDeclaration" )
2338 public void setTestNGArtifactName( String testNGArtifactName )
2339 {
2340 this.testNGArtifactName = testNGArtifactName;
2341 }
2342
2343 public int getThreadCount()
2344 {
2345 return threadCount;
2346 }
2347
2348 @SuppressWarnings( "UnusedDeclaration" )
2349 public void setThreadCount( int threadCount )
2350 {
2351 this.threadCount = threadCount;
2352 }
2353
2354 public boolean getPerCoreThreadCount()
2355 {
2356 return perCoreThreadCount;
2357 }
2358
2359 @SuppressWarnings( "UnusedDeclaration" )
2360 public void setPerCoreThreadCount( boolean perCoreThreadCount )
2361 {
2362 this.perCoreThreadCount = perCoreThreadCount;
2363 }
2364
2365 public boolean getUseUnlimitedThreads()
2366 {
2367 return useUnlimitedThreads;
2368 }
2369
2370 @SuppressWarnings( "UnusedDeclaration" )
2371 public void setUseUnlimitedThreads( boolean useUnlimitedThreads )
2372 {
2373 this.useUnlimitedThreads = useUnlimitedThreads;
2374 }
2375
2376 public String getParallel()
2377 {
2378 return parallel;
2379 }
2380
2381 @SuppressWarnings( "UnusedDeclaration" )
2382 public void setParallel( String parallel )
2383 {
2384 this.parallel = parallel;
2385 }
2386
2387 public boolean isTrimStackTrace()
2388 {
2389 return trimStackTrace;
2390 }
2391
2392 @SuppressWarnings( "UnusedDeclaration" )
2393 public void setTrimStackTrace( boolean trimStackTrace )
2394 {
2395 this.trimStackTrace = trimStackTrace;
2396 }
2397
2398 public ArtifactResolver getArtifactResolver()
2399 {
2400 return artifactResolver;
2401 }
2402
2403 @SuppressWarnings( "UnusedDeclaration" )
2404 public void setArtifactResolver( ArtifactResolver artifactResolver )
2405 {
2406 this.artifactResolver = artifactResolver;
2407 }
2408
2409 public ArtifactFactory getArtifactFactory()
2410 {
2411 return artifactFactory;
2412 }
2413
2414 @SuppressWarnings( "UnusedDeclaration" )
2415 public void setArtifactFactory( ArtifactFactory artifactFactory )
2416 {
2417 this.artifactFactory = artifactFactory;
2418 }
2419
2420 public List<ArtifactRepository> getRemoteRepositories()
2421 {
2422 return remoteRepositories;
2423 }
2424
2425 @SuppressWarnings( "UnusedDeclaration" )
2426 public void setRemoteRepositories( List<ArtifactRepository> remoteRepositories )
2427 {
2428 this.remoteRepositories = remoteRepositories;
2429 }
2430
2431 public ArtifactMetadataSource getMetadataSource()
2432 {
2433 return metadataSource;
2434 }
2435
2436 @SuppressWarnings( "UnusedDeclaration" )
2437 public void setMetadataSource( ArtifactMetadataSource metadataSource )
2438 {
2439 this.metadataSource = metadataSource;
2440 }
2441
2442
2443 public boolean isDisableXmlReport()
2444 {
2445 return disableXmlReport;
2446 }
2447
2448 @SuppressWarnings( "UnusedDeclaration" )
2449 public void setDisableXmlReport( boolean disableXmlReport )
2450 {
2451 this.disableXmlReport = disableXmlReport;
2452 }
2453
2454
2455 public boolean isEnableAssertions()
2456 {
2457 return enableAssertions;
2458 }
2459
2460 public boolean effectiveIsEnableAssertions()
2461 {
2462 if ( getArgLine() != null )
2463 {
2464 List<String> args = Arrays.asList( getArgLine().split( " " ) );
2465 if ( args.contains( "-da" ) || args.contains( "-disableassertions" ) )
2466 {
2467 return false;
2468 }
2469 }
2470 return isEnableAssertions();
2471 }
2472
2473 @SuppressWarnings( "UnusedDeclaration" )
2474 public void setEnableAssertions( boolean enableAssertions )
2475 {
2476 this.enableAssertions = enableAssertions;
2477 }
2478
2479 public MavenSession getSession()
2480 {
2481 return session;
2482 }
2483
2484 @SuppressWarnings( "UnusedDeclaration" )
2485 public void setSession( MavenSession session )
2486 {
2487 this.session = session;
2488 }
2489
2490 public String getObjectFactory()
2491 {
2492 return objectFactory;
2493 }
2494
2495 @SuppressWarnings( "UnusedDeclaration" )
2496 public void setObjectFactory( String objectFactory )
2497 {
2498 this.objectFactory = objectFactory;
2499 }
2500
2501 public ToolchainManager getToolchainManager()
2502 {
2503 return toolchainManager;
2504 }
2505
2506 @SuppressWarnings( "UnusedDeclaration" )
2507 public void setToolchainManager( ToolchainManager toolchainManager )
2508 {
2509 this.toolchainManager = toolchainManager;
2510 }
2511
2512 public boolean isMavenParallel()
2513 {
2514 return parallelMavenExecution != null && parallelMavenExecution;
2515 }
2516
2517 public String getRunOrder()
2518 {
2519 return runOrder;
2520 }
2521
2522 @SuppressWarnings( "UnusedDeclaration" )
2523 public void setRunOrder( String runOrder )
2524 {
2525 this.runOrder = runOrder;
2526 }
2527
2528 public PluginDescriptor getPluginDescriptor()
2529 {
2530 return pluginDescriptor;
2531 }
2532
2533 public MavenProject getProject()
2534 {
2535 return project;
2536 }
2537
2538 @SuppressWarnings( "UnusedDeclaration" )
2539 public void setProject( MavenProject project )
2540 {
2541 this.project = project;
2542 }
2543
2544 public File getTestSourceDirectory()
2545 {
2546 return testSourceDirectory;
2547 }
2548
2549 public void setTestSourceDirectory( File testSourceDirectory )
2550 {
2551 this.testSourceDirectory = testSourceDirectory;
2552 }
2553
2554 public String getForkCount()
2555 {
2556 return forkCount;
2557 }
2558
2559 public boolean isReuseForks()
2560 {
2561 return reuseForks;
2562 }
2563 }