View Javadoc

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