package org.testng; | |
import java.io.BufferedWriter; | |
import java.io.File; | |
import java.io.FileWriter; | |
import java.io.IOException; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.text.CharacterIterator; | |
import java.text.StringCharacterIterator; | |
import java.util.ArrayList; | |
import java.util.Enumeration; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Properties; | |
import java.util.StringTokenizer; | |
import org.apache.tools.ant.BuildException; | |
import org.apache.tools.ant.DirectoryScanner; | |
import org.apache.tools.ant.Project; | |
import org.apache.tools.ant.Target; | |
import org.apache.tools.ant.Task; | |
import org.apache.tools.ant.taskdefs.Execute; | |
import org.apache.tools.ant.taskdefs.ExecuteWatchdog; | |
import org.apache.tools.ant.taskdefs.LogStreamHandler; | |
import org.apache.tools.ant.types.Commandline; | |
import org.apache.tools.ant.types.CommandlineJava; | |
import org.apache.tools.ant.types.Environment; | |
import org.apache.tools.ant.types.FileSet; | |
import org.apache.tools.ant.types.Path; | |
import org.apache.tools.ant.types.Reference; | |
import org.apache.tools.ant.types.selectors.FilenameSelector; | |
import org.testng.internal.AnnotationTypeEnum; | |
import org.testng.internal.version.VersionInfo; | |
/** | |
* TestNG settings: | |
* <ul> | |
* <li>classfileset (inner)</li> | |
* <li>classfilesetref (attribute)</li> | |
* <li>xmlfileset (inner)</li> | |
* <li>xmlfilesetref (attribute)</li> | |
* <li>enableAssert (attribute)</li> | |
* <li>excludedGroups (attribute)</li> | |
* <li>groups (attribute)</li> | |
* <li>junit (attribute)</li> | |
* <li>listener (attribute)</li> | |
* <li>outputdir (attribute)</li> | |
* <li>parallel (attribute)</li> | |
* <li>reporter (attribute)</li> | |
* <li>sourcedir (attribute)</li> | |
* <li>sourcedirref (attribute)</li> | |
* <li>suitename (attribute)</li> | |
* <li>suiterunnerclass (attribute)</li> | |
* <li>target (attribute)</li> | |
* <li>testjar (attribute)</li> | |
* <li>testname (attribute)</li> | |
* <li>threadcount (attribute)</li> | |
* <li>verbose (attribute)</li> | |
* | |
* </ul> | |
* | |
* Ant settings: | |
* <ul> | |
* <li>classpath (inner)</li> | |
* <li>classpathref (attribute)</li> | |
* <li>jvm (attribute)</li> | |
* <li>workingDir (attribute)</li> | |
* <li>env (inner)</li> | |
* <li>sysproperty (inner)</li> | |
* <li>jvmarg (inner)</li> | |
* <li>timeout (attribute)</li> | |
* <li>haltonfailure (attribute)</li> | |
* <li>onHaltTarget (attribute)</li> | |
* <li>failureProperty (attribute)</li> | |
* <li>haltonFSP (attribute)</li> | |
* <li>FSPproperty (attribute)</li> | |
* <li>haltonskipped (attribute)</li> | |
* <li>skippedProperty (attribute)</li> | |
* </ul> | |
* | |
* Debug information: | |
* <ul> | |
* <li>dumpCommand (boolean)</li> | |
* <li>dumpEnv (boolean)</li> | |
* <li>dumpSys (boolean)</li> | |
* </ul> | |
* | |
* @author <a href="mailto:the_mindstorm@evolva.ro">Alexandru Popescu</a> | |
* @author Cedric Beust | |
*/ | |
public class TestNGAntTask extends Task { | |
protected CommandlineJava m_javaCommand; | |
protected List<FileSet> m_xmlFilesets= new ArrayList<FileSet>(); | |
protected List<FileSet> m_classFilesets= new ArrayList<FileSet>(); | |
protected Path m_sourceDirPath; | |
protected File m_outputDir; | |
protected File m_testjar; | |
protected File m_workingDir; | |
private Integer m_timeout; | |
protected Boolean m_isJUnit; | |
private List<String> m_listeners= new ArrayList<String>(); | |
private String m_objectFactory; | |
protected Environment m_environment= new Environment(); | |
/** The suite runner name (defaults to TestNG.class.getName(). */ | |
protected String m_mainClass= TestNG.class.getName(); | |
/** The default annotations (should be renamed to m_defaultAnnotations) */ | |
protected String m_target; | |
/** True if the temporary file created by the Ant Task for command line parameters | |
* to TestNG should be preserved after execution. */ | |
protected boolean m_dump; | |
private boolean m_dumpEnv; | |
private boolean m_dumpSys; | |
protected boolean m_assertEnabled= true; | |
protected boolean m_haltOnFailure; | |
protected String m_onHaltTarget; | |
protected String m_failurePropertyName; | |
protected boolean m_haltOnSkipped; | |
protected String m_skippedPropertyName; | |
protected boolean m_haltOnFSP; | |
protected String m_fspPropertyName; | |
protected String m_includedGroups; | |
protected String m_excludedGroups; | |
protected String m_parallelMode; | |
protected String m_threadCount; | |
public String m_useDefaultListeners; | |
private String m_suiteName="Ant suite"; | |
private String m_testName="Ant test"; | |
private Boolean m_skipFailedInvocationCounts; | |
/** | |
* The list of report listeners added via <reporter> sub-element of the Ant task | |
*/ | |
private List<ReporterConfig> reporterConfigs = new ArrayList<ReporterConfig>(); | |
public void setParallel(String parallel) { | |
m_parallelMode= parallel; | |
} | |
public void setThreadCount(String threadCount) { | |
m_threadCount= threadCount; | |
} | |
public void setUseDefaultListeners(String f) { | |
m_useDefaultListeners= f; | |
} | |
// Ant task settings | |
public void setHaltonfailure(boolean value) { | |
m_haltOnFailure= value; | |
} | |
public void setOnHaltTarget(String targetName) { | |
m_onHaltTarget= targetName; | |
} | |
public void setFailureProperty(String propertyName) { | |
m_failurePropertyName= propertyName; | |
} | |
public void setHaltonskipped(boolean value) { | |
m_haltOnSkipped= value; | |
} | |
public void setSkippedProperty(String propertyName) { | |
m_skippedPropertyName= propertyName; | |
} | |
public void setHaltonFSP(boolean value) { | |
m_haltOnFSP= value; | |
} | |
public void setFSPProperty(String propertyName) { | |
m_fspPropertyName= propertyName; | |
} | |
/** | |
* Sets the flag to log the command line. When verbose is set to true | |
* the command line parameters are stored in a temporary file stored | |
* in the user's default temporary file directory. The file created is | |
* prefixed with "testng". | |
*/ | |
public void setDumpCommand(boolean verbose) { | |
m_dump= verbose; | |
} | |
/** | |
* Sets the flag to write on <code>System.out</code> the Ant | |
* Environment properties. | |
* | |
* @param verbose <tt>true</tt> for printing | |
*/ | |
public void setDumpEnv(boolean verbose) { | |
m_dumpEnv= verbose; | |
} | |
/** | |
* Sets te flag to write on <code>System.out</code> the system properties. | |
* @param verbose <tt>true</tt> for dumping the info | |
*/ | |
public void setDumpSys(boolean verbose) { | |
m_dumpSys= verbose; | |
} | |
public void setEnableAssert(boolean flag) { | |
m_assertEnabled= flag; | |
} | |
/** | |
* The directory to invoke the VM in. | |
* @param workingDir the directory to invoke the JVM from. | |
*/ | |
public void setWorkingDir(File workingDir) { | |
m_workingDir= workingDir; | |
} | |
/** | |
* Sets a particular JVM to be used. Default is 'java' and is solved | |
* by <code>Runtime.exec()</code>. | |
* | |
* @param jvm the new jvm | |
*/ | |
public void setJvm(String jvm) { | |
getJavaCommand().setVm(jvm); | |
} | |
/** | |
* Set the timeout value (in milliseconds). | |
* | |
* <p>If the tests are running for more than this value, the tests | |
* will be canceled. | |
* | |
* </p> | |
* @param value the maximum time (in milliseconds) allowed before declaring the test as 'timed-out' | |
*/ | |
public void setTimeout(Integer value) { | |
m_timeout= value; | |
} | |
public Commandline.Argument createJvmarg() { | |
return getJavaCommand().createVmArgument(); | |
} | |
public void addSysproperty(Environment.Variable sysp) { | |
getJavaCommand().addSysproperty(sysp); | |
} | |
/** | |
* Adds an environment variable; used when forking. | |
*/ | |
public void addEnv(Environment.Variable var) { | |
m_environment.addVariable(var); | |
} | |
/** | |
* Adds path to classpath used for tests. | |
* | |
* @return reference to the classpath in the embedded java command line | |
*/ | |
public Path createClasspath() { | |
return getJavaCommand().createClasspath(getProject()).createPath(); | |
} | |
/** | |
* Adds a path to the bootclasspath. | |
* @return reference to the bootclasspath in the embedded java command line | |
*/ | |
public Path createBootclasspath() { | |
return getJavaCommand().createBootclasspath(getProject()).createPath(); | |
} | |
/** | |
* Set the classpath to be used when running the Java class | |
* | |
* @param s an Ant Path object containing the classpath. | |
*/ | |
public void setClasspath(Path s) { | |
createClasspath().append(s); | |
} | |
/** | |
* Classpath to use, by reference. | |
* | |
* @param r a reference to an existing classpath | |
*/ | |
public void setClasspathRef(Reference r) { | |
createClasspath().setRefid(r); | |
} | |
public void addXmlfileset(FileSet fs) { | |
m_xmlFilesets.add(fs); | |
} | |
public void setXmlfilesetRef(Reference ref) { | |
m_xmlFilesets.add(createFileSet(ref)); | |
} | |
public void addClassfileset(FileSet fs) { | |
m_classFilesets.add(appendClassSelector(fs)); | |
} | |
public void setClassfilesetRef(Reference ref) { | |
m_classFilesets.add(appendClassSelector(createFileSet(ref))); | |
} | |
/** | |
* Sets the Path like for source directories. | |
* @param srcDir path for source directories | |
*/ | |
public void setSourcedir(Path srcDir) { | |
if(m_sourceDirPath == null) { | |
m_sourceDirPath= srcDir; | |
} | |
else { | |
m_sourceDirPath.append(srcDir); | |
} | |
} | |
/** | |
* Creates a nested src Path like. | |
* | |
* @return a new Path | |
*/ | |
public Path createSourceDir() { | |
if(m_sourceDirPath == null) { | |
m_sourceDirPath= new Path(getProject()); | |
} | |
return m_sourceDirPath.createPath(); | |
} | |
/** | |
* Sets a reference to a Path-like structure for source directories. | |
* | |
* @param r reference to a Path representing the source directories | |
*/ | |
public void setSourceDirRef(Reference r) { | |
createSourceDir().setRefid(r); | |
} | |
/** | |
* Sets the suite runner class to invoke | |
* @param s the name of the suite runner class | |
*/ | |
public void setSuiteRunnerClass(String s) { | |
m_mainClass= s; | |
} | |
/** | |
* Sets the suite name | |
* @param s the name of the suite | |
*/ | |
public void setSuiteName(String s) { | |
m_suiteName= s; | |
} | |
/** | |
* Sets the test name | |
* @param s the name of the test | |
*/ | |
public void setTestName(String s) { | |
m_testName= s; | |
} | |
// TestNG settings | |
public void setJUnit(boolean value) { | |
m_isJUnit= Boolean.valueOf(value); | |
} | |
/** | |
* Sets the default annotation type for suites that have not explicitly set the | |
* annotation property. The target is used only in JDK5+. | |
* @param defaultAnnotations the default annotation type. This is one of the two constants | |
* (TestNG.JAVADOC_ANNOTATION_TYPE or TestNG.JDK_ANNOTATION_TYPE). | |
* | |
* @since 5.2 | |
*/ | |
public void setAnnotations(String defaultAnnotations) { | |
m_target = defaultAnnotations; | |
} | |
/** | |
* @param target | |
* @deprecated use setAnnotations | |
*/ | |
@Deprecated | |
public void setTarget(String target) { | |
m_target= target; | |
log("The usage of " + TestNGCommandLineArgs.TARGET_COMMAND_OPT + " option is deprecated. Please use " | |
+ TestNGCommandLineArgs.ANNOTATIONS_COMMAND_OPT + " instead", Project.MSG_WARN); | |
} | |
/** | |
* Sets the test output directory | |
* @param dir the name of directory | |
*/ | |
public void setOutputDir(File dir) { | |
m_outputDir= dir; | |
} | |
/** | |
* Sets the test jar | |
* @param s the name of test jar | |
*/ | |
public void setTestJar(File s) { | |
m_testjar= s; | |
} | |
public void setGroups(String groups) { | |
m_includedGroups= groups; | |
} | |
public void setExcludedGroups(String groups) { | |
m_excludedGroups= groups; | |
} | |
private Integer m_verbose= null; | |
public void setVerbose(Integer verbose) { | |
m_verbose= verbose; | |
} | |
public void setReporter(String listener) { | |
m_listeners.add(listener); | |
} | |
public void setObjectFactory(String className) { | |
m_objectFactory = className; | |
} | |
/** | |
* @deprecated Use "listeners" | |
*/ | |
public void setListener(String listener) { | |
m_listeners.add(listener); | |
} | |
public void setListeners(String listeners) { | |
StringTokenizer st= new StringTokenizer(listeners, " ,"); | |
while(st.hasMoreTokens()) { | |
m_listeners.add(st.nextToken()); | |
} | |
} | |
/** | |
* Launches TestNG in a new JVM. | |
* | |
* {@inheritDoc} | |
*/ | |
@Override | |
public void execute() throws BuildException { | |
validateOptions(); | |
CommandlineJava cmd= getJavaCommand(); | |
cmd.setClassname(m_mainClass); | |
List<String> argv= new ArrayList<String>(); | |
if (null != m_isJUnit) { | |
if(m_isJUnit.booleanValue()) { | |
argv.add(TestNGCommandLineArgs.JUNIT_DEF_OPT); | |
} | |
} | |
if (null != m_skipFailedInvocationCounts) { | |
if(m_skipFailedInvocationCounts.booleanValue()) { | |
argv.add(TestNGCommandLineArgs.SKIP_FAILED_INVOCATION_COUNT_OPT); | |
} | |
} | |
if(null != m_verbose) { | |
argv.add(TestNGCommandLineArgs.LOG); | |
argv.add(m_verbose.toString()); | |
} | |
if(m_assertEnabled) { | |
cmd.createVmArgument().setValue("-ea"); | |
} | |
if(m_useDefaultListeners != null) { | |
String useDefaultListeners = "false"; | |
if ("yes".equalsIgnoreCase(m_useDefaultListeners) | |
|| "true".equalsIgnoreCase(m_useDefaultListeners)) | |
{ | |
useDefaultListeners = "true"; | |
} | |
argv.add(TestNGCommandLineArgs.USE_DEFAULT_LISTENERS); | |
argv.add(useDefaultListeners); | |
} | |
if((null != m_outputDir)) { | |
if(!m_outputDir.exists()) { | |
m_outputDir.mkdirs(); | |
} | |
if(m_outputDir.isDirectory()) { | |
argv.add(TestNGCommandLineArgs.OUTDIR_COMMAND_OPT); | |
argv.add(m_outputDir.getAbsolutePath()); | |
} | |
else { | |
throw new BuildException("Output directory is not a directory: " + m_outputDir); | |
} | |
} | |
if(null != m_target) { | |
argv.add(TestNGCommandLineArgs.ANNOTATIONS_COMMAND_OPT); | |
argv.add(m_target); | |
} | |
if((null != m_testjar) && m_testjar.isFile()) { | |
argv.add(TestNGCommandLineArgs.TESTJAR_COMMAND_OPT); | |
argv.add(m_testjar.getAbsolutePath()); | |
} | |
if(null != m_sourceDirPath) { | |
String srcPath= createPathString(m_sourceDirPath, ";"); | |
argv.add(TestNGCommandLineArgs.SRC_COMMAND_OPT); | |
argv.add(srcPath); | |
} | |
if((null != m_includedGroups) && !"".equals(m_includedGroups)) { | |
argv.add(TestNGCommandLineArgs.GROUPS_COMMAND_OPT); | |
argv.add(m_includedGroups); | |
} | |
if((null != m_excludedGroups) && !"".equals(m_excludedGroups)) { | |
argv.add(TestNGCommandLineArgs.EXCLUDED_GROUPS_COMMAND_OPT); | |
argv.add(m_excludedGroups); | |
} | |
if(m_classFilesets.size() > 0) { | |
argv.add(TestNGCommandLineArgs.TESTCLASS_COMMAND_OPT); | |
for(String file : fileset(m_classFilesets)) { | |
argv.add(file); | |
} | |
} | |
if(m_listeners != null && m_listeners.size() > 0) { | |
argv.add(TestNGCommandLineArgs.LISTENER_COMMAND_OPT); | |
StringBuffer listeners= new StringBuffer(); | |
for(int i= 0; i < m_listeners.size(); i++) { | |
listeners.append(m_listeners.get(i)); | |
if(i < m_listeners.size() - 1) listeners.append(';'); | |
} | |
argv.add(listeners.toString()); | |
} | |
if(m_objectFactory != null) { | |
argv.add(TestNGCommandLineArgs.OBJECT_FACTORY_COMMAND_OPT); | |
argv.add(m_objectFactory); | |
} | |
if(m_parallelMode != null) { | |
argv.add(TestNGCommandLineArgs.PARALLEL_MODE); | |
argv.add(m_parallelMode); | |
} | |
if(m_threadCount != null) { | |
argv.add(TestNGCommandLineArgs.THREAD_COUNT); | |
argv.add(m_threadCount); | |
} | |
if(!"".equals(m_suiteName)) { | |
argv.add(TestNGCommandLineArgs.SUITE_NAME_OPT); | |
argv.add(m_suiteName); | |
} | |
if(!"".equals(m_testName)) { | |
argv.add(TestNGCommandLineArgs.TEST_NAME_OPT); | |
argv.add(m_testName); | |
} | |
if (!reporterConfigs.isEmpty()) { | |
for (ReporterConfig reporterConfig : reporterConfigs) { | |
argv.add(TestNGCommandLineArgs.REPORTER); | |
argv.add(reporterConfig.serialize()); | |
} | |
} | |
if(m_xmlFilesets.size() > 0) { | |
for(String file : fileset(m_xmlFilesets)) { | |
argv.add(file); | |
} | |
} | |
String fileName= ""; | |
FileWriter fw= null; | |
BufferedWriter bw= null; | |
try { | |
File f= File.createTempFile("testng", ""); | |
fileName= f.getAbsolutePath(); | |
// If the user asked to see the command, preserve the file | |
if(!m_dump) { | |
f.deleteOnExit(); | |
} | |
fw= new FileWriter(f); | |
bw= new BufferedWriter(fw); | |
for(String arg : argv) { | |
bw.write(arg); | |
bw.newLine(); | |
} | |
bw.flush(); | |
} | |
catch(IOException e) { | |
e.printStackTrace(); | |
} | |
finally { | |
try { | |
if(bw != null) { | |
bw.close(); | |
} | |
if(fw != null) { | |
fw.close(); | |
} | |
} | |
catch(IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
printDebugInfo(fileName); | |
createClasspath().setLocation(findJar()); | |
cmd.createArgument().setValue("@" + fileName); | |
ExecuteWatchdog watchdog= createWatchdog(); | |
boolean wasKilled= false; | |
int exitValue= executeAsForked(cmd, watchdog); | |
if(null != watchdog) { | |
wasKilled= watchdog.killedProcess(); | |
} | |
actOnResult(exitValue, wasKilled); | |
} | |
private void printDebugInfo(String fileName) { | |
if(m_dumpSys) { | |
System.out.println("* SYSTEM PROPERTIES *"); | |
Properties props= System.getProperties(); | |
Enumeration en= props.propertyNames(); | |
while(en.hasMoreElements()) { | |
String key= (String) en.nextElement(); | |
System.out.println(key + ": " + props.getProperty(key)); | |
} | |
System.out.println(""); | |
} | |
if(m_dumpEnv) { | |
String[] vars= m_environment.getVariables(); | |
if(null != vars && vars.length > 0) { | |
System.out.println("* ENVIRONMENT *"); | |
for(String v: vars) { | |
System.out.println(v); | |
} | |
System.out.println(""); | |
} | |
} | |
if(m_dump) { | |
dumpCommand(fileName); | |
} | |
} | |
private void ppp(String string) { | |
System.out.println("[TestNGAntTask] " + string); | |
} | |
protected void actOnResult(int exitValue, boolean wasKilled) { | |
if(exitValue == -1) { | |
executeHaltTarget(exitValue); | |
throw new BuildException("an error occured when running TestNG tests"); | |
} | |
if((exitValue & TestNG.HAS_NO_TEST) == TestNG.HAS_NO_TEST) { | |
if(m_haltOnFailure) { | |
executeHaltTarget(exitValue); | |
throw new BuildException("No tests were run"); | |
} | |
else { | |
if(null != m_failurePropertyName) { | |
getProject().setNewProperty(m_failurePropertyName, "true"); | |
} | |
log("TestNG haven't found any tests to be run", Project.MSG_DEBUG); | |
} | |
} | |
boolean failed= ((exitValue & TestNG.HAS_FAILURE) == TestNG.HAS_FAILURE) || wasKilled; | |
if(failed) { | |
final String msg= wasKilled ? "The tests timed out and were killed." : "The tests failed."; | |
if(m_haltOnFailure) { | |
executeHaltTarget(exitValue); | |
throw new BuildException(msg); | |
} | |
else { | |
if(null != m_failurePropertyName) { | |
getProject().setNewProperty(m_failurePropertyName, "true"); | |
} | |
log(msg, Project.MSG_DEBUG); | |
} | |
} | |
if((exitValue & TestNG.HAS_SKIPPED) == TestNG.HAS_SKIPPED) { | |
if(m_haltOnSkipped) { | |
executeHaltTarget(exitValue); | |
throw new BuildException("There are TestNG SKIPPED tests"); | |
} | |
else { | |
if(null != m_skippedPropertyName) { | |
getProject().setNewProperty(m_skippedPropertyName, "true"); | |
} | |
log("There are TestNG SKIPPED tests", Project.MSG_DEBUG); | |
} | |
} | |
if((exitValue & TestNG.HAS_FSP) == TestNG.HAS_FSP) { | |
if(m_haltOnFSP) { | |
executeHaltTarget(exitValue); | |
throw new BuildException("There are TestNG FAILED WITHIN SUCCESS PERCENTAGE tests"); | |
} | |
else { | |
if(null != m_fspPropertyName) { | |
getProject().setNewProperty(m_fspPropertyName, "true"); | |
} | |
log("There are TestNG FAILED WITHIN SUCCESS PERCENTAGE tests", Project.MSG_DEBUG); | |
} | |
} | |
} | |
/** Executes the target, if any, that user designates executing before failing the test */ | |
private void executeHaltTarget(int exitValue) { | |
if(m_onHaltTarget != null) { | |
if(m_outputDir != null) { | |
getProject().setProperty("testng.outputdir", m_outputDir.getAbsolutePath()); | |
} | |
getProject().setProperty("testng.returncode", String.valueOf(exitValue)); | |
Target t= (Target) getProject().getTargets().get(m_onHaltTarget); | |
if(t != null) { | |
t.execute(); | |
} | |
} | |
} | |
/** | |
* Executes the command line as a new process. | |
* | |
* @param cmd the command to execute | |
* @param watchdog | |
* @return the exit status of the subprocess or INVALID. | |
*/ | |
protected int executeAsForked(CommandlineJava cmd, ExecuteWatchdog watchdog) { | |
Execute execute= new Execute(new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN), | |
watchdog); | |
execute.setCommandline(cmd.getCommandline()); | |
execute.setAntRun(getProject()); | |
if(m_workingDir != null) { | |
if(m_workingDir.exists() && m_workingDir.isDirectory()) { | |
execute.setWorkingDirectory(m_workingDir); | |
} | |
else { | |
log("Ignoring invalid working directory : " + m_workingDir, Project.MSG_WARN); | |
} | |
} | |
String[] environment= m_environment.getVariables(); | |
if(null != environment) { | |
for(String envEntry : environment) { | |
log("Setting environment variable: " + envEntry, Project.MSG_VERBOSE); | |
} | |
} | |
execute.setEnvironment(environment); | |
log(cmd.describeCommand(), Project.MSG_VERBOSE); | |
int retVal; | |
try { | |
retVal= execute.execute(); | |
} | |
catch(IOException e) { | |
throw new BuildException("Process fork failed.", e, getLocation()); | |
} | |
return retVal; | |
} | |
/** | |
* Creates or returns the already created <CODE>CommandlineJava</CODE>. | |
*/ | |
protected CommandlineJava getJavaCommand() { | |
if(null == m_javaCommand) { | |
m_javaCommand= new CommandlineJava(); | |
} | |
return m_javaCommand; | |
} | |
/** | |
* @return <tt>null</tt> if there is no timeout value, otherwise the | |
* watchdog instance. | |
* | |
* @throws BuildException under unspecified circumstances | |
* @since Ant 1.2 | |
*/ | |
protected ExecuteWatchdog createWatchdog() /*throws BuildException*/ { | |
if(m_timeout == null) { | |
return null; | |
} | |
return new ExecuteWatchdog(m_timeout.longValue()); | |
} | |
protected void validateOptions() throws BuildException { | |
if((m_xmlFilesets.size() == 0) | |
&& (m_classFilesets.size() == 0) | |
&& ((null == m_testjar) || !m_testjar.isFile())) { | |
throw new BuildException("No suite or classes or jar is specified."); | |
} | |
if((null != m_includedGroups) && (m_classFilesets.size() == 0)) { | |
throw new BuildException("No classfileset specified while using groups"); | |
} | |
if (m_target != null) { | |
try { | |
m_target = AnnotationTypeEnum.valueOf(m_target).getName(); | |
} | |
catch (RuntimeException pEx) { | |
throw new BuildException("Illegal default annotations: " + m_target, pEx); | |
} | |
} | |
if (VersionInfo.IS_JDK14) { | |
if (null == m_sourceDirPath) { | |
throw new BuildException("No sourceDir is specified."); | |
} | |
} | |
if(m_onHaltTarget != null) { | |
if(!getProject().getTargets().containsKey(m_onHaltTarget)) { | |
throw new BuildException("Target " + m_onHaltTarget + " not found in this project"); | |
} | |
} | |
} | |
private FileSet createFileSet(Reference ref) { | |
FileSet fs= new FileSet(); | |
fs.setRefid(ref); | |
fs.setProject(getProject()); | |
return fs; | |
} | |
private FileSet appendClassSelector(FileSet fs) { | |
FilenameSelector selector= new FilenameSelector(); | |
selector.setName("**/*.class"); | |
selector.setProject(getProject()); | |
fs.appendSelector(selector); | |
return fs; | |
} | |
private File findJar() { | |
Class thisClass= getClass(); | |
String resource= thisClass.getName().replace('.', '/') + ".class"; | |
URL url= thisClass.getClassLoader().getResource(resource); | |
if(null != url) { | |
String u= url.toString(); | |
if(u.startsWith("jar:file:")) { | |
int pling= u.indexOf("!"); | |
String jarName= u.substring(4, pling); | |
return new File(fromURI(jarName)); | |
} | |
else if(u.startsWith("file:")) { | |
int tail= u.indexOf(resource); | |
String dirName= u.substring(0, tail); | |
return new File(fromURI(dirName)); | |
} | |
} | |
return null; | |
} | |
private String fromURI(String uri) { | |
URL url= null; | |
try { | |
url= new URL(uri); | |
} | |
catch(MalformedURLException murle) { | |
} | |
if((null == url) || !("file".equals(url.getProtocol()))) { | |
throw new IllegalArgumentException("Can only handle valid file: URIs"); | |
} | |
StringBuffer buf= new StringBuffer(url.getHost()); | |
if(buf.length() > 0) { | |
buf.insert(0, File.separatorChar).insert(0, File.separatorChar); | |
} | |
String file= url.getFile(); | |
int queryPos= file.indexOf('?'); | |
buf.append((queryPos < 0) ? file : file.substring(0, queryPos)); | |
uri= buf.toString().replace('/', File.separatorChar); | |
if((File.pathSeparatorChar == ';') && uri.startsWith("\\") && (uri.length() > 2) | |
&& Character.isLetter(uri.charAt(1)) && (uri.lastIndexOf(':') > -1)) { | |
uri= uri.substring(1); | |
} | |
StringBuffer sb= new StringBuffer(); | |
CharacterIterator iter= new StringCharacterIterator(uri); | |
for(char c= iter.first(); c != CharacterIterator.DONE; c= iter.next()) { | |
if(c == '%') { | |
char c1= iter.next(); | |
if(c1 != CharacterIterator.DONE) { | |
int i1= Character.digit(c1, 16); | |
char c2= iter.next(); | |
if(c2 != CharacterIterator.DONE) { | |
int i2= Character.digit(c2, 16); | |
sb.append((char) ((i1 << 4) + i2)); | |
} | |
} | |
} | |
else { | |
sb.append(c); | |
} | |
} | |
return sb.toString(); | |
} | |
/** | |
* Returns the list of files corresponding to the filesets | |
* | |
* @param filesets | |
* @return the list of files corresponding to the filesets | |
* @throws BuildException | |
*/ | |
private List<String> fileset(List<FileSet> filesets) throws BuildException { | |
List<String> files= new ArrayList<String>(); | |
for(Iterator<FileSet> iterator= filesets.iterator(); iterator.hasNext();) { | |
FileSet fileset= iterator.next(); | |
DirectoryScanner ds= fileset.getDirectoryScanner(getProject()); | |
for(String file : ds.getIncludedFiles()) { | |
files.add(ds.getBasedir() + File.separator + file); | |
} | |
} | |
return files; | |
} | |
/** | |
* Adds double quotes to the command line argument if it contains spaces. | |
* @param pCommandLineArg the command line argument | |
* @return pCommandLineArg in double quotes if it contains space. | |
* | |
*/ | |
private static String doubleQuote(String pCommandLineArg) { | |
if(pCommandLineArg.indexOf(" ") != -1 && !(pCommandLineArg.startsWith("\"") && pCommandLineArg.endsWith("\""))) { | |
return "\"" + pCommandLineArg + '\"'; | |
} | |
return pCommandLineArg; | |
} | |
/** | |
* Creates a string representation of the path. | |
*/ | |
private String createPathString(Path path, String sep) { | |
if(path == null) { | |
return null; | |
} | |
final StringBuffer buf= new StringBuffer(); | |
for(int i= 0; i < path.list().length; i++) { | |
File file= getProject().resolveFile(path.list()[i]); | |
if(!file.exists()) { | |
log("Classpath entry not found: " + file, Project.MSG_WARN); | |
} | |
buf.append(file.getAbsolutePath()).append(sep); | |
} | |
if(path.list().length > 0) { // cut the last ; | |
buf.deleteCharAt(buf.length() - 1); | |
} | |
return buf.toString(); | |
} | |
private void dumpCommand(String fileName) { | |
ppp("TESTNG PASSED @" + fileName + " WHICH CONTAINS:"); | |
List<String> lines= TestNGCommandLineArgs.readFile(fileName); | |
for(String line : lines) { | |
ppp(line); | |
} | |
} | |
public void addConfiguredReporter(ReporterConfig reporterConfig) { | |
reporterConfigs.add(reporterConfig); | |
} | |
public void setSkipFailedInvocationCounts(boolean skip) { | |
m_skipFailedInvocationCounts = Boolean.valueOf(skip); | |
} | |
} |