• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.testng;
2 
3 
4 import java.io.BufferedReader;
5 import java.io.BufferedWriter;
6 import java.io.File;
7 import java.io.FileReader;
8 import java.io.FileWriter;
9 import java.io.IOException;
10 import java.net.MalformedURLException;
11 import java.net.URL;
12 import java.text.CharacterIterator;
13 import java.text.StringCharacterIterator;
14 import java.util.Enumeration;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Properties;
18 import java.util.StringTokenizer;
19 
20 import org.apache.tools.ant.BuildException;
21 import org.apache.tools.ant.DirectoryScanner;
22 import org.apache.tools.ant.Project;
23 import org.apache.tools.ant.Target;
24 import org.apache.tools.ant.Task;
25 import org.apache.tools.ant.taskdefs.Execute;
26 import org.apache.tools.ant.taskdefs.ExecuteWatchdog;
27 import org.apache.tools.ant.taskdefs.LogOutputStream;
28 import org.apache.tools.ant.taskdefs.PumpStreamHandler;
29 import org.apache.tools.ant.types.Commandline;
30 import org.apache.tools.ant.types.CommandlineJava;
31 import org.apache.tools.ant.types.Environment;
32 import org.apache.tools.ant.types.FileSet;
33 import org.apache.tools.ant.types.Path;
34 import org.apache.tools.ant.types.PropertySet;
35 import org.apache.tools.ant.types.Reference;
36 import org.apache.tools.ant.types.ResourceCollection;
37 import org.apache.tools.ant.types.resources.FileResource;
38 import org.apache.tools.ant.types.selectors.FilenameSelector;
39 import org.testng.collections.Lists;
40 import org.testng.internal.Utils;
41 import org.testng.reporters.VerboseReporter;
42 
43 import static java.lang.Boolean.TRUE;
44 import static org.testng.internal.Utils.isStringNotBlank;
45 
46 /**
47  * TestNG settings:
48  * <ul>
49  * <li>classfileset (inner)</li>
50  * <li>classfilesetref (attribute)</li>
51  * <li>xmlfileset (inner)</li>
52  * <li>xmlfilesetref (attribute)</li>
53  * <li>enableAssert (attribute)</li>
54  * <li>excludedGroups (attribute)</li>
55  * <li>groups (attribute)</li>
56  * <li>junit (attribute)</li>
57  * <li>listener (attribute)</li>
58  * <li>outputdir (attribute)</li>
59  * <li>parallel (attribute)</li>
60  * <li>reporter (attribute)</li>
61  * <li>sourcedir (attribute)</li>
62  * <li>sourcedirref (attribute)</li>
63  * <li>suitename (attribute)</li>
64  * <li>suiterunnerclass (attribute)</li>
65  * <li>target (attribute)</li>
66  * <li>testjar (attribute)</li>
67  * <li>testname (attribute)</li>
68  * <li>threadcount (attribute)</li>
69  * <li>dataproviderthreadcount (attribute)</li>
70  * <li>verbose (attribute)</li>
71  * <li>testrunfactory (attribute)</li>
72  * <li>configFailurepolicy (attribute)</li>
73  * <li>randomizeSuites (attribute)</li>
74  * <li>methodselectors (attribute)</li>
75  * </ul>
76  *
77  * Ant settings:
78  * <ul>
79  * <li>classpath (inner)</li>
80  * <li>classpathref (attribute)</li>
81  * <li>jvm (attribute)</li>
82  * <li>workingDir (attribute)</li>
83  * <li>env (inner)</li>
84  * <li>sysproperty (inner)</li>
85  * <li>propertyset (inner)</li>
86  * <li>jvmarg (inner)</li>
87  * <li>timeout (attribute)</li>
88  * <li>haltonfailure (attribute)</li>
89  * <li>onHaltTarget (attribute)</li>
90  * <li>failureProperty (attribute)</li>
91  * <li>haltonFSP (attribute)</li>
92  * <li>FSPproperty (attribute)</li>
93  * <li>haltonskipped (attribute)</li>
94  * <li>skippedProperty (attribute)</li>
95  * <li>testRunnerFactory (attribute)</li>
96  * </ul>
97  *
98  * Debug information:
99  * <ul>
100  * <li>dumpCommand (boolean)</li>
101  * <li>dumpEnv (boolean)</li>
102  * <li>dumpSys (boolean)</li>
103  * </ul>
104  *
105  * @author <a href="mailto:the_mindstorm@evolva.ro">Alexandru Popescu</a>
106  * @author Cedric Beust
107  * @author Lukas Jungmann
108  */
109 public class TestNGAntTask extends Task {
110 
111   protected CommandlineJava m_javaCommand;
112 
113   protected List<ResourceCollection> m_xmlFilesets= Lists.newArrayList();
114   protected List<ResourceCollection> m_classFilesets= Lists.newArrayList();
115   protected File m_outputDir;
116   protected File m_testjar;
117   protected File m_workingDir;
118   private Integer m_timeout;
119   private List<String> m_listeners= Lists.newArrayList();
120   private List<String> m_methodselectors= Lists.newArrayList();
121   private String m_objectFactory;
122   protected String m_testRunnerFactory;
123   private boolean m_delegateCommandSystemProperties = false;
124 
125   protected Environment m_environment= new Environment();
126 
127   /** The suite runner name (defaults to TestNG.class.getName(). */
128   protected String m_mainClass = TestNG.class.getName();
129 
130   /** True if the temporary file created by the Ant Task for command line parameters
131    * to TestNG should be preserved after execution. */
132   protected boolean m_dump;
133   private boolean m_dumpEnv;
134   private boolean m_dumpSys;
135 
136   protected boolean m_assertEnabled= true;
137   protected boolean m_haltOnFailure;
138   protected String m_onHaltTarget;
139   protected String m_failurePropertyName;
140   protected boolean m_haltOnSkipped;
141   protected String m_skippedPropertyName;
142   protected boolean m_haltOnFSP;
143   protected String m_fspPropertyName;
144   protected String m_includedGroups;
145   protected String m_excludedGroups;
146   protected String m_parallelMode;
147   protected String m_threadCount;
148   protected String m_dataproviderthreadCount;
149   protected String m_configFailurePolicy;
150   protected Boolean m_randomizeSuites;
151   public String m_useDefaultListeners;
152   private String m_suiteName="Ant suite";
153   private String m_testName="Ant test";
154   private Boolean m_skipFailedInvocationCounts;
155   private String m_methods;
156   private Mode mode = Mode.testng;
157 
158   public enum Mode {
159       //lower-case to better look in build scripts
160       testng, junit, mixed;
161   }
162 
163   /**
164    * The list of report listeners added via &lt;reporter&gt; sub-element of the Ant task
165    */
166   private List<ReporterConfig> reporterConfigs = Lists.newArrayList();
167 
168   private String m_testNames = "";
169 
setParallel(String parallel)170   public void setParallel(String parallel) {
171     m_parallelMode= parallel;
172   }
173 
setThreadCount(String threadCount)174   public void setThreadCount(String threadCount) {
175     m_threadCount= threadCount;
176   }
177 
setDataProviderThreadCount(String dataproviderthreadCount)178   public void setDataProviderThreadCount(String dataproviderthreadCount) {
179     m_dataproviderthreadCount = dataproviderthreadCount;
180   }
181 
setUseDefaultListeners(String f)182   public void setUseDefaultListeners(String f) {
183     m_useDefaultListeners= f;
184   }
185 
186   // Ant task settings
setHaltonfailure(boolean value)187   public void setHaltonfailure(boolean value) {
188     m_haltOnFailure= value;
189   }
190 
setOnHaltTarget(String targetName)191   public void setOnHaltTarget(String targetName) {
192     m_onHaltTarget= targetName;
193   }
194 
setFailureProperty(String propertyName)195   public void setFailureProperty(String propertyName) {
196     m_failurePropertyName= propertyName;
197   }
198 
setHaltonskipped(boolean value)199   public void setHaltonskipped(boolean value) {
200     m_haltOnSkipped= value;
201   }
202 
setSkippedProperty(String propertyName)203   public void setSkippedProperty(String propertyName) {
204     m_skippedPropertyName= propertyName;
205   }
206 
setHaltonFSP(boolean value)207   public void setHaltonFSP(boolean value) {
208     m_haltOnFSP= value;
209   }
210 
setFSPProperty(String propertyName)211   public void setFSPProperty(String propertyName) {
212     m_fspPropertyName= propertyName;
213   }
214 
setDelegateCommandSystemProperties(boolean value)215   public void setDelegateCommandSystemProperties(boolean value){
216     m_delegateCommandSystemProperties = value;
217   }
218 
219   /**
220    * Sets the flag to log the command line. When verbose is set to true
221    * the command line parameters are stored in a temporary file stored
222    * in the user's default temporary file directory. The file created is
223    * prefixed with "testng".
224    */
setDumpCommand(boolean verbose)225   public void setDumpCommand(boolean verbose) {
226     m_dump = verbose;
227   }
228 
229   /**
230    * Sets the flag to write on <code>System.out</code> the Ant
231    * Environment properties.
232    *
233    * @param verbose <tt>true</tt> for printing
234    */
setDumpEnv(boolean verbose)235   public void setDumpEnv(boolean verbose) {
236     m_dumpEnv= verbose;
237   }
238 
239   /**
240    * Sets te flag to write on <code>System.out</code> the system properties.
241    * @param verbose <tt>true</tt> for dumping the info
242    */
setDumpSys(boolean verbose)243   public void setDumpSys(boolean verbose) {
244     m_dumpSys= verbose;
245   }
246 
setEnableAssert(boolean flag)247   public void setEnableAssert(boolean flag) {
248     m_assertEnabled= flag;
249   }
250 
251   /**
252    * The directory to invoke the VM in.
253    * @param workingDir the directory to invoke the JVM from.
254    */
setWorkingDir(File workingDir)255   public void setWorkingDir(File workingDir) {
256     m_workingDir= workingDir;
257   }
258 
259   /**
260    * Sets a particular JVM to be used. Default is 'java' and is solved
261    * by <code>Runtime.exec()</code>.
262    *
263    * @param jvm the new jvm
264    */
setJvm(String jvm)265   public void setJvm(String jvm) {
266     getJavaCommand().setVm(jvm);
267   }
268 
269   /**
270    * Set the timeout value (in milliseconds).
271    *
272    * <p>If the tests are running for more than this value, the tests
273    * will be canceled.
274    *
275    * </p>
276    * @param value the maximum time (in milliseconds) allowed before declaring the test as 'timed-out'
277    */
setTimeout(Integer value)278   public void setTimeout(Integer value) {
279     m_timeout= value;
280   }
281 
createJvmarg()282   public Commandline.Argument createJvmarg() {
283     return getJavaCommand().createVmArgument();
284   }
285 
addSysproperty(Environment.Variable sysp)286   public void addSysproperty(Environment.Variable sysp) {
287     getJavaCommand().addSysproperty(sysp);
288   }
289 
290   /**
291    * Adds an environment variable; used when forking.
292    */
addEnv(Environment.Variable var)293   public void addEnv(Environment.Variable var) {
294     m_environment.addVariable(var);
295   }
296 
297   /**
298    * Adds path to classpath used for tests.
299    *
300    * @return reference to the classpath in the embedded java command line
301    */
createClasspath()302   public Path createClasspath() {
303     return getJavaCommand().createClasspath(getProject()).createPath();
304   }
305 
306   /**
307    * Adds a path to the bootclasspath.
308    * @return reference to the bootclasspath in the embedded java command line
309    */
createBootclasspath()310   public Path createBootclasspath() {
311     return getJavaCommand().createBootclasspath(getProject()).createPath();
312   }
313 
314   /**
315    * Set the classpath to be used when running the Java class
316    *
317    * @param s an Ant Path object containing the classpath.
318    */
setClasspath(Path s)319   public void setClasspath(Path s) {
320     createClasspath().append(s);
321   }
322 
323   /**
324    * Classpath to use, by reference.
325    *
326    * @param r a reference to an existing classpath
327    */
setClasspathRef(Reference r)328   public void setClasspathRef(Reference r) {
329     createClasspath().setRefid(r);
330   }
331 
addXmlfileset(FileSet fs)332   public void addXmlfileset(FileSet fs) {
333     m_xmlFilesets.add(fs);
334   }
335 
setXmlfilesetRef(Reference ref)336   public void setXmlfilesetRef(Reference ref) {
337     m_xmlFilesets.add(createResourceCollection(ref));
338   }
339 
addClassfileset(FileSet fs)340   public void addClassfileset(FileSet fs) {
341     m_classFilesets.add(appendClassSelector(fs));
342   }
343 
setClassfilesetRef(Reference ref)344   public void setClassfilesetRef(Reference ref) {
345     m_classFilesets.add(createResourceCollection(ref));
346   }
347 
setTestNames(String testNames)348   public void setTestNames(String testNames) {
349     m_testNames = testNames;
350   }
351 
352   /**
353    * Sets the suite runner class to invoke
354    * @param s the name of the suite runner class
355    */
setSuiteRunnerClass(String s)356   public void setSuiteRunnerClass(String s) {
357     m_mainClass= s;
358   }
359 
360   /**
361    * Sets the suite name
362    * @param s the name of the suite
363    */
setSuiteName(String s)364   public void setSuiteName(String s) {
365     m_suiteName= s;
366   }
367 
368   /**
369    * Sets the test name
370    * @param s the name of the test
371    */
setTestName(String s)372   public void setTestName(String s) {
373     m_testName= s;
374   }
375 
376   // TestNG settings
setJUnit(boolean value)377   public void setJUnit(boolean value) {
378     mode = value ? Mode.junit : Mode.testng;
379   }
380 
381   // TestNG settings
setMode(Mode mode)382   public void setMode(Mode mode) {
383     this.mode = mode;
384   }
385 
386   /**
387    * Sets the test output directory
388    * @param dir the name of directory
389    */
setOutputDir(File dir)390   public void setOutputDir(File dir) {
391     m_outputDir= dir;
392   }
393 
394   /**
395    * Sets the test jar
396    * @param s the name of test jar
397    */
setTestJar(File s)398   public void setTestJar(File s) {
399     m_testjar= s;
400   }
401 
setGroups(String groups)402   public void setGroups(String groups) {
403     m_includedGroups= groups;
404   }
405 
setExcludedGroups(String groups)406   public void setExcludedGroups(String groups) {
407     m_excludedGroups= groups;
408   }
409 
410   private Integer m_verbose= null;
411 
412   private Integer m_suiteThreadPoolSize;
413 
414   private String m_xmlPathInJar;
415 
setVerbose(Integer verbose)416   public void setVerbose(Integer verbose) {
417     m_verbose= verbose;
418   }
419 
setReporter(String listener)420   public void setReporter(String listener) {
421     m_listeners.add(listener);
422   }
423 
setObjectFactory(String className)424   public void setObjectFactory(String className) {
425     m_objectFactory = className;
426   }
427 
setTestRunnerFactory(String testRunnerFactory)428   public void setTestRunnerFactory(String testRunnerFactory) {
429     m_testRunnerFactory = testRunnerFactory;
430   }
431 
setSuiteThreadPoolSize(Integer n)432   public void setSuiteThreadPoolSize(Integer n) {
433     m_suiteThreadPoolSize = n;
434   }
435 
436   /**
437    * @deprecated Use "listeners"
438    */
439   @Deprecated
setListener(String listener)440   public void setListener(String listener) {
441     m_listeners.add(listener);
442   }
443 
setListeners(String listeners)444   public void setListeners(String listeners) {
445     StringTokenizer st= new StringTokenizer(listeners, " ,");
446     while(st.hasMoreTokens()) {
447       m_listeners.add(st.nextToken());
448     }
449   }
450 
setMethodSelectors(String methodSelectors)451   public void setMethodSelectors(String methodSelectors) {
452 	StringTokenizer st= new StringTokenizer(methodSelectors, " ,");
453 	while(st.hasMoreTokens()) {
454 	 m_methodselectors.add(st.nextToken());
455 	}
456   }
457 
setConfigFailurePolicy(String failurePolicy)458   public void setConfigFailurePolicy(String failurePolicy) {
459     m_configFailurePolicy = failurePolicy;
460   }
461 
setRandomizeSuites(Boolean randomizeSuites)462   public void setRandomizeSuites(Boolean randomizeSuites) {
463     m_randomizeSuites = randomizeSuites;
464   }
465 
setMethods(String methods)466   public void setMethods(String methods) {
467     m_methods = methods;
468   }
469 
470   /**
471    * Launches TestNG in a new JVM.
472    *
473    * {@inheritDoc}
474    */
475   @Override
execute()476   public void execute() throws BuildException {
477     validateOptions();
478 
479     CommandlineJava cmd = getJavaCommand();
480     cmd.setClassname(m_mainClass);
481     if(m_assertEnabled) {
482       cmd.createVmArgument().setValue("-ea");
483     }
484     if (m_delegateCommandSystemProperties) {
485       delegateCommandSystemProperties();
486     }
487     List<String> argv = createArguments();
488 
489     String fileName= "";
490     FileWriter fw= null;
491     BufferedWriter bw= null;
492     try {
493       File f= File.createTempFile("testng", "");
494       fileName= f.getAbsolutePath();
495 
496       // If the user asked to see the command, preserve the file
497       if(!m_dump) {
498         f.deleteOnExit();
499       }
500       fw= new FileWriter(f);
501       bw= new BufferedWriter(fw);
502       for(String arg : argv) {
503         bw.write(arg);
504         bw.newLine();
505       }
506       bw.flush();
507     }
508     catch(IOException e) {
509       e.printStackTrace();
510     }
511     finally {
512       try {
513         if(bw != null) {
514           bw.close();
515         }
516         if(fw != null) {
517           fw.close();
518         }
519       }
520       catch(IOException e) {
521         e.printStackTrace();
522       }
523     }
524 
525     printDebugInfo(fileName);
526 
527     createClasspath().setLocation(findJar());
528 
529     cmd.createArgument().setValue("@" + fileName);
530 
531     ExecuteWatchdog watchdog= createWatchdog();
532     boolean wasKilled= false;
533     int exitValue= executeAsForked(cmd, watchdog);
534     if(null != watchdog) {
535       wasKilled= watchdog.killedProcess();
536     }
537 
538     actOnResult(exitValue, wasKilled);
539   }
540 
createArguments()541   private List<String> createArguments() {
542 	List<String> argv= Lists.newArrayList();
543     addBooleanIfTrue(argv, CommandLineArgs.JUNIT, mode == Mode.junit);
544     addBooleanIfTrue(argv, CommandLineArgs.MIXED, mode == Mode.mixed);
545     addBooleanIfTrue(argv, CommandLineArgs.SKIP_FAILED_INVOCATION_COUNTS, m_skipFailedInvocationCounts);
546     addIntegerIfNotNull(argv, CommandLineArgs.LOG, m_verbose);
547     addDefaultListeners(argv);
548     addOutputDir(argv);
549     addFileIfFile(argv, CommandLineArgs.TEST_JAR, m_testjar);
550     addStringIfNotBlank(argv, CommandLineArgs.GROUPS, m_includedGroups);
551     addStringIfNotBlank(argv, CommandLineArgs.EXCLUDED_GROUPS, m_excludedGroups);
552     addFilesOfRCollection(argv, CommandLineArgs.TEST_CLASS, m_classFilesets);
553     addListOfStringIfNotEmpty(argv, CommandLineArgs.LISTENER, m_listeners);
554     addListOfStringIfNotEmpty(argv, CommandLineArgs.METHOD_SELECTORS, m_methodselectors);
555     addStringIfNotNull(argv, CommandLineArgs.OBJECT_FACTORY, m_objectFactory);
556     addStringIfNotNull(argv, CommandLineArgs.TEST_RUNNER_FACTORY, m_testRunnerFactory);
557     addStringIfNotNull(argv, CommandLineArgs.PARALLEL, m_parallelMode);
558     addStringIfNotNull(argv, CommandLineArgs.CONFIG_FAILURE_POLICY, m_configFailurePolicy);
559     addBooleanIfTrue(argv, CommandLineArgs.RANDOMIZE_SUITES, m_randomizeSuites);
560     addStringIfNotNull(argv, CommandLineArgs.THREAD_COUNT, m_threadCount);
561     addStringIfNotNull(argv, CommandLineArgs.DATA_PROVIDER_THREAD_COUNT, m_dataproviderthreadCount);
562     addStringIfNotBlank(argv, CommandLineArgs.SUITE_NAME, m_suiteName);
563     addStringIfNotBlank(argv, CommandLineArgs.TEST_NAME, m_testName);
564     addStringIfNotBlank(argv, CommandLineArgs.TEST_NAMES, m_testNames);
565     addStringIfNotBlank(argv, CommandLineArgs.METHODS, m_methods);
566     addReporterConfigs(argv);
567     addIntegerIfNotNull(argv, CommandLineArgs.SUITE_THREAD_POOL_SIZE, m_suiteThreadPoolSize);
568     addStringIfNotNull(argv, CommandLineArgs.XML_PATH_IN_JAR, m_xmlPathInJar);
569     addXmlFiles(argv);
570 	return argv;
571   }
572 
addDefaultListeners(List<String> argv)573   private void addDefaultListeners(List<String> argv) {
574     if (m_useDefaultListeners != null) {
575       String useDefaultListeners = "false";
576       if ("yes".equalsIgnoreCase(m_useDefaultListeners) || "true".equalsIgnoreCase(m_useDefaultListeners)) {
577         useDefaultListeners = "true";
578       }
579       argv.add(CommandLineArgs.USE_DEFAULT_LISTENERS);
580       argv.add(useDefaultListeners);
581     }
582   }
583 
addOutputDir(List<String> argv)584   private void addOutputDir(List<String> argv) {
585     if (null != m_outputDir) {
586       if (!m_outputDir.exists()) {
587         m_outputDir.mkdirs();
588       }
589       if (m_outputDir.isDirectory()) {
590         argv.add(CommandLineArgs.OUTPUT_DIRECTORY);
591         argv.add(m_outputDir.getAbsolutePath());
592       } else {
593         throw new BuildException("Output directory is not a directory: " + m_outputDir);
594       }
595     }
596   }
597 
addReporterConfigs(List<String> argv)598   private void addReporterConfigs(List<String> argv) {
599     for (ReporterConfig reporterConfig : reporterConfigs) {
600       argv.add(CommandLineArgs.REPORTER);
601       argv.add(reporterConfig.serialize());
602     }
603   }
604 
addFilesOfRCollection(List<String> argv, String name, List<ResourceCollection> resources)605   private void addFilesOfRCollection(List<String> argv, String name, List<ResourceCollection> resources) {
606 	addArgumentsIfNotEmpty(argv, name, getFiles(resources), ",");
607   }
608 
addListOfStringIfNotEmpty(List<String> argv, String name, List<String> arguments)609   private void addListOfStringIfNotEmpty(List<String> argv, String name, List<String> arguments) {
610 	addArgumentsIfNotEmpty(argv, name, arguments, ";");
611   }
612 
addArgumentsIfNotEmpty(List<String> argv, String name, List<String> arguments, String separator)613   private void addArgumentsIfNotEmpty(List<String> argv, String name, List<String> arguments, String separator) {
614 	if (arguments != null && !arguments.isEmpty()) {
615       argv.add(name);
616       String value= Utils.join(arguments, separator);
617 	    argv.add(value);
618   	}
619   }
620 
addFileIfFile(List<String> argv, String name, File file)621   private void addFileIfFile(List<String> argv, String name, File file) {
622     if ((null != file) && file.isFile()) {
623       argv.add(name);
624       argv.add(file.getAbsolutePath());
625     }
626   }
627 
addBooleanIfTrue(List<String> argv, String name, Boolean value)628   private void addBooleanIfTrue(List<String> argv, String name, Boolean value) {
629     if (TRUE.equals(value)) {
630       argv.add(name);
631     }
632   }
633 
addIntegerIfNotNull(List<String> argv, String name, Integer value)634   private void addIntegerIfNotNull(List<String> argv, String name, Integer value) {
635     if (value != null) {
636       argv.add(name);
637       argv.add(value.toString());
638     }
639   }
640 
addStringIfNotNull(List<String> argv, String name, String value)641   private void addStringIfNotNull(List<String> argv, String name, String value) {
642     if (value != null) {
643       argv.add(name);
644       argv.add(value);
645     }
646   }
647 
addStringIfNotBlank(List<String> argv, String name, String value)648   private void addStringIfNotBlank(List<String> argv, String name, String value) {
649     if (isStringNotBlank(value)) {
650       argv.add(name);
651       argv.add(value);
652     }
653   }
654 
addXmlFiles(List<String> argv)655   private void addXmlFiles(List<String> argv) {
656     for (String file : getSuiteFileNames()) {
657       argv.add(file);
658     }
659   }
660 
661   /**
662    * @return the list of the XML file names. This method can be overridden by subclasses.
663    */
getSuiteFileNames()664   protected List<String> getSuiteFileNames() {
665     List<String> result = Lists.newArrayList();
666 
667     for(String file : getFiles(m_xmlFilesets)) {
668       result.add(file);
669     }
670 
671     return result;
672   }
673 
delegateCommandSystemProperties()674   private void delegateCommandSystemProperties() {
675     // Iterate over command-line args and pass them through as sysproperty
676     // exclude any built-in properties that start with "ant."
677     for (Object propKey : getProject().getUserProperties().keySet()) {
678       String propName = (String) propKey;
679       String propVal = getProject().getUserProperty(propName);
680       if (propName.startsWith("ant.")) {
681         log("Excluding ant property: " + propName + ": " + propVal, Project.MSG_DEBUG);
682       }	else {
683         log("Including user property: " + propName + ": " + propVal, Project.MSG_DEBUG);
684         Environment.Variable var = new Environment.Variable();
685         var.setKey(propName);
686         var.setValue(propVal);
687         addSysproperty(var);
688       }
689     }
690   }
691 
printDebugInfo(String fileName)692   private void printDebugInfo(String fileName) {
693     if(m_dumpSys) {
694       System.out.println("* SYSTEM PROPERTIES *");
695       Properties props= System.getProperties();
696       Enumeration en= props.propertyNames();
697       while(en.hasMoreElements()) {
698         String key= (String) en.nextElement();
699         System.out.println(key + ": " + props.getProperty(key));
700       }
701       System.out.println("");
702     }
703     if(m_dumpEnv) {
704       String[] vars= m_environment.getVariables();
705       if(null != vars && vars.length > 0) {
706         System.out.println("* ENVIRONMENT *");
707         for(String v: vars) {
708           System.out.println(v);
709         }
710         System.out.println("");
711       }
712     }
713     if(m_dump) {
714       dumpCommand(fileName);
715     }
716   }
717 
ppp(String string)718   private void ppp(String string) {
719     System.out.println("[TestNGAntTask] " + string);
720   }
721 
actOnResult(int exitValue, boolean wasKilled)722   protected void actOnResult(int exitValue, boolean wasKilled) {
723     if(exitValue == -1) {
724       executeHaltTarget(exitValue);
725       throw new BuildException("an error occured when running TestNG tests");
726     }
727 
728     if((exitValue & TestNG.HAS_NO_TEST) == TestNG.HAS_NO_TEST) {
729       if(m_haltOnFailure) {
730         executeHaltTarget(exitValue);
731         throw new BuildException("No tests were run");
732       }
733       else {
734         if(null != m_failurePropertyName) {
735           getProject().setNewProperty(m_failurePropertyName, "true");
736         }
737 
738         log("TestNG haven't found any tests to be run", Project.MSG_DEBUG);
739       }
740     }
741 
742     boolean failed= ((exitValue & TestNG.HAS_FAILURE) == TestNG.HAS_FAILURE) || wasKilled;
743     if(failed) {
744       final String msg= wasKilled ? "The tests timed out and were killed." : "The tests failed.";
745       if(m_haltOnFailure) {
746         executeHaltTarget(exitValue);
747         throw new BuildException(msg);
748       }
749       else {
750         if(null != m_failurePropertyName) {
751           getProject().setNewProperty(m_failurePropertyName, "true");
752         }
753 
754         log(msg, Project.MSG_INFO);
755       }
756     }
757 
758     if((exitValue & TestNG.HAS_SKIPPED) == TestNG.HAS_SKIPPED) {
759       if(m_haltOnSkipped) {
760         executeHaltTarget(exitValue);
761         throw new BuildException("There are TestNG SKIPPED tests");
762       }
763       else {
764         if(null != m_skippedPropertyName) {
765           getProject().setNewProperty(m_skippedPropertyName, "true");
766         }
767 
768         log("There are TestNG SKIPPED tests", Project.MSG_DEBUG);
769       }
770     }
771 
772     if((exitValue & TestNG.HAS_FSP) == TestNG.HAS_FSP) {
773       if(m_haltOnFSP) {
774         executeHaltTarget(exitValue);
775         throw new BuildException("There are TestNG FAILED WITHIN SUCCESS PERCENTAGE tests");
776       }
777       else {
778         if(null != m_fspPropertyName) {
779           getProject().setNewProperty(m_fspPropertyName, "true");
780         }
781 
782         log("There are TestNG FAILED WITHIN SUCCESS PERCENTAGE tests", Project.MSG_DEBUG);
783       }
784     }
785   }
786 
787   /** Executes the target, if any, that user designates executing before failing the test */
executeHaltTarget(int exitValue)788   private void executeHaltTarget(int exitValue) {
789     if(m_onHaltTarget != null) {
790       if(m_outputDir != null) {
791         getProject().setProperty("testng.outputdir", m_outputDir.getAbsolutePath());
792       }
793       getProject().setProperty("testng.returncode", String.valueOf(exitValue));
794       Target t= (Target) getProject().getTargets().get(m_onHaltTarget);
795       if(t != null) {
796         t.execute();
797       }
798     }
799   }
800 
801   /**
802    * Executes the command line as a new process.
803    *
804    * @param cmd the command to execute
805    * @param watchdog
806    * @return the exit status of the subprocess or INVALID.
807    */
executeAsForked(CommandlineJava cmd, ExecuteWatchdog watchdog)808   protected int executeAsForked(CommandlineJava cmd, ExecuteWatchdog watchdog) {
809     Execute execute= new Execute(new TestNGLogSH(this, Project.MSG_INFO, Project.MSG_WARN, (m_verbose == null || m_verbose < 5)),
810                                  watchdog);
811     execute.setCommandline(cmd.getCommandline());
812     execute.setAntRun(getProject());
813     if(m_workingDir != null) {
814       if(m_workingDir.exists() && m_workingDir.isDirectory()) {
815         execute.setWorkingDirectory(m_workingDir);
816       }
817       else {
818         log("Ignoring invalid working directory : " + m_workingDir, Project.MSG_WARN);
819       }
820     }
821 
822     String[] environment= m_environment.getVariables();
823     if(null != environment) {
824       for(String envEntry : environment) {
825         log("Setting environment variable: " + envEntry, Project.MSG_VERBOSE);
826       }
827     }
828 
829     execute.setEnvironment(environment);
830 
831     log(cmd.describeCommand(), Project.MSG_VERBOSE);
832     int retVal;
833     try {
834       retVal= execute.execute();
835     }
836     catch(IOException e) {
837       throw new BuildException("Process fork failed.", e, getLocation());
838     }
839 
840     return retVal;
841   }
842 
843   /**
844    * Creates or returns the already created <CODE>CommandlineJava</CODE>.
845    */
getJavaCommand()846   protected CommandlineJava getJavaCommand() {
847     if(null == m_javaCommand) {
848       m_javaCommand = new CommandlineJava();
849     }
850 
851     return m_javaCommand;
852   }
853 
854   /**
855    * @return <tt>null</tt> if there is no timeout value, otherwise the
856    * watchdog instance.
857    *
858    * @throws BuildException under unspecified circumstances
859    * @since Ant 1.2
860    */
createWatchdog()861   protected ExecuteWatchdog createWatchdog() /*throws BuildException*/ {
862     if(m_timeout == null) {
863       return null;
864     }
865 
866     return new ExecuteWatchdog(m_timeout.longValue());
867   }
868 
validateOptions()869   protected void validateOptions() throws BuildException {
870     int suiteCount = getSuiteFileNames().size();
871     if (suiteCount == 0
872       && m_classFilesets.size() == 0
873       && Utils.isStringEmpty(m_methods)
874       && ((null == m_testjar) || !m_testjar.isFile())) {
875       throw new BuildException("No suites, classes, methods or jar file was specified.");
876     }
877 
878     if((null != m_includedGroups) && (m_classFilesets.size() == 0 && suiteCount == 0)) {
879       throw new BuildException("No class filesets or xml file sets specified while using groups");
880     }
881 
882     if(m_onHaltTarget != null) {
883       if(!getProject().getTargets().containsKey(m_onHaltTarget)) {
884         throw new BuildException("Target " + m_onHaltTarget + " not found in this project");
885       }
886     }
887 
888   }
889 
createResourceCollection(Reference ref)890   private ResourceCollection createResourceCollection(Reference ref) {
891     Object o = ref.getReferencedObject();
892     if (!(o instanceof ResourceCollection)) {
893         throw new BuildException("Only File based ResourceCollections are supported.");
894     }
895     ResourceCollection rc = (ResourceCollection) o;
896     if (!rc.isFilesystemOnly()) {
897         throw new BuildException("Only ResourceCollections from local file system are supported.");
898     }
899     return rc;
900   }
901 
appendClassSelector(FileSet fs)902   private FileSet appendClassSelector(FileSet fs) {
903     FilenameSelector selector= new FilenameSelector();
904     selector.setName("**/*.class");
905     selector.setProject(getProject());
906     fs.appendSelector(selector);
907 
908     return fs;
909   }
910 
findJar()911   private File findJar() {
912     Class thisClass= getClass();
913     String resource= thisClass.getName().replace('.', '/') + ".class";
914     URL url= thisClass.getClassLoader().getResource(resource);
915 
916     if(null != url) {
917       String u= url.toString();
918       if(u.startsWith("jar:file:")) {
919         int pling= u.indexOf("!");
920         String jarName= u.substring(4, pling);
921 
922         return new File(fromURI(jarName));
923       }
924       else if(u.startsWith("file:")) {
925         int tail= u.indexOf(resource);
926         String dirName= u.substring(0, tail);
927 
928         return new File(fromURI(dirName));
929       }
930     }
931 
932     return null;
933   }
934 
fromURI(String uri)935   private String fromURI(String uri) {
936     URL url= null;
937     try {
938       url= new URL(uri);
939     }
940     catch(MalformedURLException murle) {
941     }
942     if((null == url) || !("file".equals(url.getProtocol()))) {
943       throw new IllegalArgumentException("Can only handle valid file: URIs");
944     }
945 
946     StringBuffer buf= new StringBuffer(url.getHost());
947     if(buf.length() > 0) {
948       buf.insert(0, File.separatorChar).insert(0, File.separatorChar);
949     }
950 
951     String file= url.getFile();
952     int queryPos= file.indexOf('?');
953     buf.append((queryPos < 0) ? file : file.substring(0, queryPos));
954 
955     uri= buf.toString().replace('/', File.separatorChar);
956 
957     if((File.pathSeparatorChar == ';') && uri.startsWith("\\") && (uri.length() > 2)
958       && Character.isLetter(uri.charAt(1)) && (uri.lastIndexOf(':') > -1)) {
959       uri= uri.substring(1);
960     }
961 
962     StringBuffer sb= new StringBuffer();
963     CharacterIterator iter= new StringCharacterIterator(uri);
964     for(char c= iter.first(); c != CharacterIterator.DONE; c= iter.next()) {
965       if(c == '%') {
966         char c1= iter.next();
967         if(c1 != CharacterIterator.DONE) {
968           int i1= Character.digit(c1, 16);
969           char c2= iter.next();
970           if(c2 != CharacterIterator.DONE) {
971             int i2= Character.digit(c2, 16);
972             sb.append((char) ((i1 << 4) + i2));
973           }
974         }
975       }
976       else {
977         sb.append(c);
978       }
979     }
980 
981     return sb.toString();
982   }
983 
984   /**
985    * Returns the list of files corresponding to the resource collection
986    *
987    * @param resources
988    * @return the list of files corresponding to the resource collection
989    * @throws BuildException
990    */
getFiles(List<ResourceCollection> resources)991   private List<String> getFiles(List<ResourceCollection> resources) throws BuildException {
992     List<String> files= Lists.newArrayList();
993     for (ResourceCollection rc : resources) {
994         for (Iterator i = rc.iterator(); i.hasNext();) {
995           Object o = i.next();
996           if (o instanceof FileResource) {
997             FileResource fr = ((FileResource) o);
998             if (fr.isDirectory()) {
999               throw new BuildException("Directory based FileResources are not supported.");
1000             }
1001             if (!fr.isExists()) {
1002               log("'" + fr.toLongString() + "' does not exist", Project.MSG_VERBOSE);
1003             }
1004             files.add(fr.getFile().getAbsolutePath());
1005           } else {
1006               log("Unsupported Resource type: " + o.toString(), Project.MSG_VERBOSE);
1007           }
1008         }
1009     }
1010     return files;
1011   }
1012 
1013   /**
1014    * Returns the list of files corresponding to the fileset
1015    *
1016    * @param filesets
1017    * @return the list of files corresponding to the fileset
1018    * @throws BuildException
1019    */
fileset(FileSet fileset)1020   private List<String> fileset(FileSet fileset) throws BuildException {
1021     List<String> files= Lists.newArrayList();
1022 
1023       DirectoryScanner ds= fileset.getDirectoryScanner(getProject());
1024 
1025       for(String file : ds.getIncludedFiles()) {
1026         files.add(ds.getBasedir() + File.separator + file);
1027       }
1028 
1029     return files;
1030   }
1031 
1032   /**
1033    * Adds double quotes to the command line argument if it contains spaces.
1034    * @param pCommandLineArg the command line argument
1035    * @return pCommandLineArg in double quotes if it contains space.
1036    *
1037    */
doubleQuote(String pCommandLineArg)1038   private static String doubleQuote(String pCommandLineArg) {
1039     if(pCommandLineArg.indexOf(" ") != -1 && !(pCommandLineArg.startsWith("\"") && pCommandLineArg.endsWith("\""))) {
1040       return "\"" + pCommandLineArg + '\"';
1041     }
1042 
1043     return pCommandLineArg;
1044   }
1045 
1046   /**
1047    * Creates a string representation of the path.
1048    */
createPathString(Path path, String sep)1049   private String createPathString(Path path, String sep) {
1050     if(path == null) {
1051       return null;
1052     }
1053 
1054     final StringBuffer buf= new StringBuffer();
1055 
1056     for(int i= 0; i < path.list().length; i++) {
1057       File file= getProject().resolveFile(path.list()[i]);
1058 
1059       if(!file.exists()) {
1060         log("Classpath entry not found: " + file, Project.MSG_WARN);
1061       }
1062 
1063       buf.append(file.getAbsolutePath()).append(sep);
1064     }
1065 
1066     if(path.list().length > 0) { // cut the last ;
1067       buf.deleteCharAt(buf.length() - 1);
1068     }
1069 
1070     return buf.toString();
1071   }
1072 
dumpCommand(String fileName)1073   private void dumpCommand(String fileName) {
1074     ppp("TESTNG PASSED @" + fileName + " WHICH CONTAINS:");
1075     readAndPrintFile(fileName);
1076   }
1077 
readAndPrintFile(String fileName)1078   private void readAndPrintFile(String fileName) {
1079     File file = new File(fileName);
1080     BufferedReader br = null;
1081     try {
1082       br = new BufferedReader(new FileReader(file));
1083       String line = br.readLine();
1084       while (line != null) {
1085         System.out.println("  " + line);
1086         line = br.readLine();
1087       }
1088     }
1089     catch(IOException ex) {
1090       ex.printStackTrace();
1091     } finally {
1092       if (br != null) {
1093         try {
1094           br.close();
1095         } catch (IOException e) {
1096           e.printStackTrace();
1097         }
1098       }
1099     }
1100   }
1101 
addConfiguredReporter(ReporterConfig reporterConfig)1102   public void addConfiguredReporter(ReporterConfig reporterConfig) {
1103     reporterConfigs.add(reporterConfig);
1104   }
1105 
setSkipFailedInvocationCounts(boolean skip)1106   public void setSkipFailedInvocationCounts(boolean skip) {
1107     m_skipFailedInvocationCounts = skip;
1108   }
1109 
setXmlPathInJar(String path)1110   public void setXmlPathInJar(String path) {
1111     m_xmlPathInJar = path;
1112   }
1113   /**
1114    * Add the referenced property set as system properties for the TestNG JVM.
1115    *
1116    * @param sysPropertySet A PropertySet of system properties.
1117    */
addConfiguredPropertySet(PropertySet sysPropertySet)1118   public void addConfiguredPropertySet(PropertySet sysPropertySet) {
1119     Properties properties = sysPropertySet.getProperties();
1120     log(properties.keySet().size() + " properties found in nested propertyset", Project.MSG_VERBOSE);
1121     for (Object propKeyObj : properties.keySet()) {
1122       String propKey = (String) propKeyObj;
1123       Environment.Variable sysProp = new Environment.Variable();
1124       sysProp.setKey(propKey);
1125       if (properties.get(propKey) instanceof String) {
1126         String propVal = (String) properties.get(propKey);
1127         sysProp.setValue(propVal);
1128         getJavaCommand().addSysproperty(sysProp);
1129         log("Added system property " + propKey + " with value " + propVal, Project.MSG_VERBOSE);
1130       } else {
1131         log("Ignoring non-String property " + propKey, Project.MSG_WARN);
1132       }
1133     }
1134   }
1135 
1136     @Override
handleOutput(String output)1137     protected void handleOutput(String output) {
1138         if (output.startsWith(VerboseReporter.LISTENER_PREFIX)) {
1139             //send everything from VerboseReporter to verbose level unless log level is > 4
1140             log(output, m_verbose < 5 ? Project.MSG_VERBOSE : Project.MSG_INFO);
1141         } else {
1142             super.handleOutput(output);
1143         }
1144     }
1145 
1146     private static class TestNGLogOS extends LogOutputStream {
1147 
1148         private Task task;
1149         private boolean verbose;
1150 
TestNGLogOS(Task task, int level, boolean verbose)1151         public TestNGLogOS(Task task, int level, boolean verbose) {
1152             super(task, level);
1153             this.task = task;
1154             this.verbose = verbose;
1155         }
1156 
1157         @Override
processLine(String line, int level)1158         protected void processLine(String line, int level) {
1159             if (line.startsWith(VerboseReporter.LISTENER_PREFIX)) {
1160                 task.log(line, verbose ? Project.MSG_VERBOSE : Project.MSG_INFO);
1161             } else {
1162                 super.processLine(line, level);
1163             }
1164         }
1165     }
1166 
1167     protected static class TestNGLogSH extends PumpStreamHandler {
1168 
TestNGLogSH(Task task, int outlevel, int errlevel, boolean verbose)1169         public TestNGLogSH(Task task, int outlevel, int errlevel, boolean verbose) {
1170             super(new TestNGLogOS(task, outlevel, verbose),
1171                     new LogOutputStream(task, errlevel));
1172         }
1173     }
1174 }
1175