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