diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitHelper.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitHelper.java index b9984cc2e..658f1aa5b 100644 --- a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitHelper.java +++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitHelper.java @@ -54,10 +54,15 @@ package org.apache.tools.ant.taskdefs.optional.junit; import java.lang.reflect.Method; +import java.io.File; +import java.net.URL; import junit.framework.Test; import junit.framework.TestSuite; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.Path; + /** * A set of helpers functions to deal with JUnit. * @@ -124,4 +129,51 @@ public final class JUnitHelper { } return null; } + + /** + * Search for the given resource and return the directory or archive + * that contains it. + * + *

Doesn't work for archives in JDK 1.1 as the URL returned by + * getResource doesn't contain the name of the archive.

+ * + * @param resource the resource to look for in the JVM classpath. + * @return the file or directory containing the resource or + * null if it does not know how to handle it. + */ + public static File getResourceEntry(String resource){ + URL url = JUnitHelper.class.getResource(resource); + if (url != null) { + // can't find the resource... + return null; + } + String u = url.toString(); + if (u.startsWith("jar:file:")) { + int pling = u.indexOf("!"); + String jarName = u.substring(9, pling); + return new File((new File(jarName)).getAbsolutePath()); + } else if (u.startsWith("file:")) { + int tail = u.indexOf(resource); + String dirName = u.substring(5, tail); + return new File((new File(dirName)).getAbsolutePath()); + } + // don't know how to handle it... + return null; + } + + /** + * Add the entry corresponding to a specific resource to the + * specified path instance. The entry can either be a directory + * or an archive. + * @param path the path to add the resource entry to. + * @param resource the resource to look for. + * @see #getResourceEntry(String) + */ + public static void addClasspathEntry(Path path, String resource){ + File f = getResourceEntry(resource); + if (f != null) { + path.createPathElement().setLocation(f); + } + } + } diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java index 8166e4ab2..571585684 100644 --- a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java +++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java @@ -53,12 +53,24 @@ */ package org.apache.tools.ant.taskdefs.optional.junit; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Properties; import java.util.Vector; -import org.apache.tools.ant.Task; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.optional.junit.formatter.Formatter; -import org.apache.tools.ant.taskdefs.optional.junit.remote.TestRunner; +import org.apache.tools.ant.taskdefs.Execute; +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.Path; +import org.apache.tools.ant.util.FileUtils; /** * @@ -81,10 +93,70 @@ public class JUnitTask extends Task { /** stop the test run if an error occurs */ private boolean haltOnError = false; + /** the command line to launch the TestRunner */ + private CommandlineJava cmd = new CommandlineJava(); + // task implementation public void execute() throws BuildException { + File tmp = configureTestRunner(); + Execute execute = new Execute(new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN)); + execute.setCommandline(cmd.getCommandline()); + execute.setAntRun(project); + + log("Executing: " + cmd.toString(), Project.MSG_VERBOSE); + int retVal; + try { + retVal = execute.execute(); + } catch (IOException e) { + throw new BuildException("Process fork failed.", e, location); + } finally { + tmp.delete(); + } + + } + /** + * Configure the runner with the appropriate configuration file. + * @return the reference to the temporary configuration file + * to be deleted once the TestRunner has ended. + */ + public File configureTestRunner() { + Properties props = new Properties(); + props.setProperty("debug", "true"); + props.setProperty("host", "127.0.0.1"); + props.setProperty("port", String.valueOf(port)); + StringBuffer classnames = new StringBuffer(); + //@fixme get all test classes to run... + final int testcount = 0; + for (int i = 0; i < testcount; i++) { + classnames.append("").append("\n"); + } + props.setProperty("classnames", classnames.toString()); + + // dump the properties to a temporary file. + FileUtils futils = FileUtils.newFileUtils(); + File f = futils.createTempFile("junit-antrunner", "tmp", new File(".")); + OutputStream os = null; + try { + os = new BufferedOutputStream(new FileOutputStream(f)); + props.store(os, "JUnit Ant Runner configuration file"); + } catch (IOException e) { + throw new BuildException(e); + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + } + } + } + + // configure the runner + cmd.createArgument().setValue("-file"); + cmd.createArgument().setValue(f.getAbsolutePath()); + + return f; } // Ant bean accessors @@ -106,8 +178,67 @@ public class JUnitTask extends Task { } /** add a new formatter element */ - public void addFormatter(FormatterElement fe){ + public void addFormatter(FormatterElement fe) { Formatter f = fe.createFormatter(); this.formatters.addElement(f); } + + /** + * Set the maximum memory to be used by the TestRunner + * @param max the value as defined by -mx or -Xmx + * in the java command line options. + */ + public void setMaxmemory(String max) { + if (Project.getJavaVersion().startsWith("1.1")) { + createJvmarg().setValue("-mx" + max); + } else { + createJvmarg().setValue("-Xmx" + max); + } + } + + /** + * Create a new JVM argument. Ignored if no JVM is forked. + * @return create a new JVM argument so that any argument can be passed to the JVM. + * @see #setFork(boolean) + */ + public Commandline.Argument createJvmarg() { + return cmd.createVmArgument(); + } + + /** + * <classpath> allows classpath to be set for tests. + */ + public Path createClasspath() { + return cmd.createClasspath(project).createPath(); + } + + /** + * Creates a new JUnitRunner and enables fork of a new Java VM. + */ + public JUnitTask() throws Exception { + cmd.setClassname("org.apache.tools.ant.taskdefs.optional.junit.remote.TestRunner"); + } + + /** + * Adds the jars or directories containing Ant, this task and + * JUnit to the classpath - this should make the forked JVM work + * without having to specify them directly. + */ + public void init() { + addClasspathEntry("/junit/framework/TestCase.class"); + addClasspathEntry("/org/apache/tools/ant/Task.class"); + addClasspathEntry("/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.class"); + } + + /** + * Add the directory or archive containing the resource to + * the command line classpath. + * @param the resource to look for. + */ + protected void addClasspathEntry(String resource) { + File f = JUnitHelper.getResourceEntry(resource); + if (f != null) { + createClasspath().setLocation(f); + } + } } diff --git a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote/TestRunner.java b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote/TestRunner.java index 6e33cdb47..c71ed3fde 100644 --- a/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote/TestRunner.java +++ b/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote/TestRunner.java @@ -192,24 +192,24 @@ public class TestRunner implements TestListener { if ("-file".equalsIgnoreCase(args[i])) { // @fixme if you mix file and other options it will be a mess, // not important right now. - FileInputStream fis = new FileInputStream(args[i + 1]); + FileInputStream fis = new FileInputStream(args[++i]); Properties props = new Properties(); props.load(fis); fis.close(); init(props); } if ("-classnames".equalsIgnoreCase(args[i])) { - for (int j = i + 1; j < args.length; j++) { + for (int j = ++i; j < args.length; j++) { if (args[j].startsWith("-")) break; addTestClassName(args[j]); } } if ("-port".equalsIgnoreCase(args[i])) { - setPort(Integer.parseInt(args[i + 1])); + setPort(Integer.parseInt(args[++i])); } if ("-host".equalsIgnoreCase(args[i])) { - setHost(args[i + 1]); + setHost(args[++i]); } if ("-debug".equalsIgnoreCase(args[i])) { setDebug(true);