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