+
+
.
+ */
+
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import junit.framework.TestListener;
+
+/**
+ * This Interface describes classes that format the results of a JUnit
+ * testrun.
+ *
+ * @author Stefan Bodewig
+ */
+public interface JUnitResultFormatter extends TestListener {
+ /**
+ * The whole testsuite started.
+ */
+ public void startTestSuite(JUnitTest suite);
+
+ /**
+ * The whole testsuite ended.
+ */
+ public void endTestSuite(JUnitTest suite);
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
new file mode 100644
index 000000000..0605d9742
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
@@ -0,0 +1,292 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Path;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.*;
+import org.apache.tools.ant.types.Commandline;
+import org.apache.tools.ant.types.CommandlineJava;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * Ant task to run JUnit tests.
+ *
+ * JUnit is a framework to create unit test. It has been initially
+ * created by Erich Gamma and Kent Beck. JUnit can be found at http://www.xprogramming.com/software.htm.
+ *
+ *
This ant task runs a single TestCase. By default it spans a new
+ * Java VM to prevent interferences between different testcases,
+ * unless fork
has been disabled.
+ *
+ * @author Thomas Haas
+ */
+public class JUnitTask extends Task {
+
+ // private final static int HALT_NOT = 1;
+ // private final static int HALT_IMMEDIATELY = 2;
+ // private final static int HALT_AT_END = 3;
+
+ private CommandlineJava commandline = new CommandlineJava();
+ private Vector tests = new Vector();
+
+ private JUnitTest defaults = new JUnitTest();
+ private boolean defaultOutfile = true;
+ private Integer timeout = null;
+
+ // private int haltOnError = HALT_AT_END;
+ // private int haltOnFailure = HALT_AT_END;
+
+ /**
+ * Set the path to junit classes.
+ * @param junit path to junit classes.
+ */
+ public void setJunit(String junit) {
+ commandline.createClasspath().createPathElement().setLocation(junit);
+ }
+
+ public void setDefaulthaltonerror(boolean value) {
+ defaults.setHaltonerror(value);
+ }
+
+ public void setDefaulthaltonfailure(boolean value) {
+ defaults.setHaltonfailure(value);
+ }
+
+ public void setDefaultprintsummary(boolean value) {
+ defaults.setPrintsummary(value);
+ }
+
+ public void setDefaultprintxml(boolean value) {
+ defaults.setPrintxml(value);
+ }
+
+ public void setDefaultOutFile(boolean value) {
+ defaultOutfile = value;
+ }
+
+ public void setTimeout(Integer value) {
+ timeout = value;
+ }
+
+ public void setFork(boolean value) {
+ defaults.setFork(value);
+ }
+
+ public void setJvm(String value) {
+ defaults.setName(value);
+ commandline.setVm(value);
+ }
+
+ public void setJvmargs(String value) {
+ commandline.createVmArgument().setLine(value);
+ }
+
+
+ /**
+ * Set the classpath to be used by the testcase.
+ * @param classpath the classpath used to run the testcase.
+ */
+ /*public void setClasspath(String classpath) {
+ this.classpath = classpath;
+ }*/
+
+
+ public Path createClasspath() {
+ return commandline.createClasspath();
+ }
+
+ public JUnitTest createTest() {
+ final JUnitTest result;
+ result = new JUnitTest(
+ defaults.getFork(),
+ defaults.getHaltonerror(),
+ defaults.getHaltonfailure(),
+ defaults.getPrintsummary(),
+ defaults.getPrintxml(),
+ null, null);
+
+ tests.addElement(result);
+ return result;
+ }
+
+
+ /**
+ * Creates a new JUnitRunner and enables fork of a new Java VM.
+ */
+ public JUnitTask() throws Exception {
+ commandline.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
+ }
+
+ /**
+ * Runs the testcase.
+ */
+ public void execute() throws BuildException {
+ boolean errorOccurred = false;
+ boolean failureOccurred = false;
+
+ final String oldclasspath = System.getProperty("java.class.path");
+
+ commandline.createClasspath().createPathElement().setPath(oldclasspath);
+ /*
+ * This doesn't work on JDK 1.1, should use a Classloader of our own
+ * anyway --SB
+ *
+ * System.setProperty("java.class.path", commandline.createClasspath().toString());
+ */
+
+ Enumeration list = tests.elements();
+ while (list.hasMoreElements()) {
+ final JUnitTest test = (JUnitTest)list.nextElement();
+
+ final String filename = "TEST-" + test.getName() + ".xml";
+// removed --SB
+// if (new File(filename).exists()) {
+// project.log("Skipping " + test.getName());
+// continue;
+// }
+ project.log("Running " + test.getName());
+
+ if (defaultOutfile && (test.getOutfile() == null ||
+ test.getOutfile().length() == 0)) {
+
+// removed --SB
+// test.setOutfile("RUNNING-" + filename);
+ test.setOutfile(filename);
+ }
+
+ int exitValue = 2;
+
+ if (test.getFork()) {
+ try {
+ // Create a watchdog based on the timeout attribute
+ final Execute execute = new Execute(new PumpStreamHandler(), createWatchdog());
+ final Commandline cmdl = new Commandline();
+ cmdl.addLine(commandline.getCommandline());
+ cmdl.addLine(test.getCommandline());
+ execute.setCommandline(cmdl.getCommandline());
+ log("Execute JUnit: " + cmdl, Project.MSG_VERBOSE);
+ exitValue = execute.execute();
+ }
+ catch (IOException e) {
+ throw new BuildException("Process fork failed.", e,
+ location);
+ }
+ } else {
+ final Object[] arg = { test };
+ final Class[] argType = { arg[0].getClass() };
+ try {
+ final Class target = Class.forName("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
+ final Method main = target.getMethod("runTest", argType);
+ project.log("Load JUnit: " + test, Project.MSG_VERBOSE);
+ exitValue = ((Integer)main.invoke(null, arg)).intValue();
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ String msg = "Running test failed: " + t.getMessage();
+ throw new BuildException(msg, t, location);
+ } catch (Exception e) {
+ String msg = "Running test failed: " + e.getMessage();
+ throw new BuildException(msg, e, location);
+ }
+ }
+
+ boolean errorOccurredHere = exitValue == 2;
+ boolean failureOccurredHere = exitValue == 1;
+// removed --SB
+// if (exitValue != 0) {
+// rename("RUNNING-" + filename, "ERROR-" + filename);
+// } else {
+// rename("RUNNING-" + filename, filename);
+// }
+ // later distinguish HALT_AT_END case
+ if (errorOccurredHere && test.getHaltonerror()
+ || failureOccurredHere && test.getHaltonfailure()) {
+ throw new BuildException("JUNIT FAILED", location);
+ } else if (errorOccurredHere || failureOccurredHere) {
+ log("JUNIT FAILED", Project.MSG_ERR);
+ }
+
+ // Update overall test status
+ errorOccurred = errorOccurred || errorOccurredHere ;
+ failureOccurred = failureOccurred || failureOccurredHere ;
+ }
+
+ // later add HALT_AT_END option
+ // Then test errorOccurred and failureOccurred here.
+ }
+
+ protected ExecuteWatchdog createWatchdog() throws BuildException {
+ if (timeout == null) return null;
+ return new ExecuteWatchdog(timeout.intValue());
+ }
+
+ private void rename(String source, String destination) throws BuildException {
+ final File src = new File(source);
+ final File dest = new File(destination);
+
+ if (dest.exists()) dest.delete();
+ src.renameTo(dest);
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
new file mode 100644
index 000000000..6ed484af4
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
@@ -0,0 +1,202 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.Commandline;
+
+/**
+ *
+ * @author Thomas Haas
+ */
+public class JUnitTest {
+ private boolean systemExit = false;
+ private boolean haltOnError = false;
+ private boolean haltOnFail = false;
+ private boolean printSummary = true;
+ private boolean printXml = true;
+ private String name = null;
+ private String outfile = null;
+ private boolean fork = false;
+
+ private long runs, failures, errors;
+ private long runTime;
+
+ public JUnitTest() {
+ }
+
+ public JUnitTest(boolean fork, boolean haltOnError, boolean haltOnFail,
+ boolean printSummary, boolean printXml, String name,
+ String outfile) {
+ this.fork = fork;
+ this.haltOnError = haltOnError;
+ this.haltOnFail = haltOnFail;
+ this.printSummary = printSummary;
+ this.printXml = printXml;
+ this.name = name;
+ this.outfile = outfile;
+ }
+
+ public void setFork(boolean value) {
+ fork = value;
+ }
+
+ public boolean getFork() {
+ return fork;
+ }
+
+ public void setHaltonerror(boolean value) {
+ haltOnError = value;
+ }
+
+ public void setHaltonfailure(boolean value) {
+ haltOnFail = value;
+ }
+
+ public void setPrintsummary(boolean value) {
+ printSummary = value;
+ }
+
+ public void setPrintxml(boolean value) {
+ printXml = value;
+ }
+
+ public void setName(String value) {
+ name = value;
+ }
+
+ public void setOutfile(String value) {
+ outfile = value;
+ }
+
+
+ public boolean getHaltonerror() {
+ return haltOnError;
+ }
+
+ public boolean getHaltonfailure() {
+ return haltOnFail;
+ }
+
+ public boolean getPrintsummary() {
+ return printSummary;
+ }
+
+ public boolean getPrintxml() {
+ return printXml;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getOutfile() {
+ return outfile;
+ }
+
+ public void setCommandline(String [] args) {
+ for (int i=0; i 0) {
+ result.setExecutable(name);
+ }
+ result.createArgument().setValue("exit=" + systemExit);
+ result.createArgument().setValue("haltOnError=" + haltOnError);
+ result.createArgument().setValue("haltOnFailure=" + haltOnFail);
+ result.createArgument().setValue("printSummary=" + printSummary);
+ result.createArgument().setValue("printXML=" + printXml);
+ if (outfile != null && outfile.length() > 0) {
+ result.createArgument().setValue("outfile=" + outfile);
+ }
+ return result.getCommandline();
+ }
+
+ public void setCounts(long runs, long failures, long errors) {
+ this.runs = runs;
+ this.failures = failures;
+ this.errors = errors;
+ }
+
+ public void setRunTime(long runTime) {
+ this.runTime = runTime;
+ }
+
+ public long runCount() {return runs;}
+ public long failureCount() {return failures;}
+ public long errorCount() {return errors;}
+ public long getRunTime() {return runTime;}
+
+
+ public String toString() {
+ return Commandline.toString(getCommandline());
+ }
+
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
new file mode 100644
index 000000000..a868a0c46
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
@@ -0,0 +1,325 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import org.apache.tools.ant.Project;
+
+import junit.framework.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.Vector;
+
+/**
+ * Simple Testrunner for JUnit that runs all tests of a testsuite.
+ *
+ * This TestRunner expects a name of a TestCase class as its
+ * argument. If this class provides a static suite() method it will be
+ * called and the resulting Test will be run.
+ *
+ *
Otherwise all public methods starting with "test" and taking no
+ * argument will be run.
+ *
+ *
Summary output is generated at the end.
+ *
+ * @author Stefan Bodewig
+ */
+
+public class JUnitTestRunner implements TestListener {
+
+ /**
+ * Holds the registered formatters.
+ */
+ private Vector formatters = new Vector();
+
+ /**
+ * Collects TestResults.
+ */
+ private TestResult res;
+
+ /**
+ * Flag for endTest.
+ */
+ private boolean failed = true;
+
+ /**
+ * The test I'm going to run.
+ */
+ private JUnitTest junitTest;
+
+ /**
+ * The corresponding testsuite.
+ */
+ private Test suite = null;
+
+ /**
+ * Returncode
+ */
+ private int retCode = 0;
+
+ public JUnitTestRunner(JUnitTest test) {
+ junitTest = test;
+ try {
+ if (junitTest.getPrintxml()) {
+ if (test.getOutfile() != null
+ && test.getOutfile().length() > 0) {
+
+ addFormatter(new XMLJUnitResultFormatter(
+ new PrintWriter(
+ new FileWriter(test.getOutfile(), false)
+ )
+ )
+ );
+ } else {
+ addFormatter(new XMLJUnitResultFormatter(
+ new PrintWriter(
+ new OutputStreamWriter(System.out), true)
+ )
+ );
+ }
+ }
+
+ if (junitTest.getPrintsummary()) {
+ addFormatter(new SummaryJUnitResultFormatter());
+ }
+
+ Class testClass = Class.forName(junitTest.getName());
+
+ try {
+ Method suiteMethod= testClass.getMethod("suite", new Class[0]);
+ suite = (Test)suiteMethod.invoke(null, new Class[0]);
+ } catch(NoSuchMethodException e) {
+ } catch(InvocationTargetException e) {
+ } catch(IllegalAccessException e) {
+ }
+
+ if (suite == null) {
+ // try to extract a test suite automatically
+ // this will generate warnings if the class is no suitable Test
+ suite= new TestSuite(testClass);
+ }
+
+ res = new TestResult();
+ res.addListener(this);
+ for (int i=0; i < formatters.size(); i++) {
+ res.addListener((TestListener)formatters.elementAt(i));
+ }
+
+ } catch(Exception e) {
+ retCode = 2;
+
+ fireStartTestSuite();
+ for (int i=0; i < formatters.size(); i++) {
+ ((TestListener)formatters.elementAt(i)).addError(null, e);
+ }
+ junitTest.setCounts(1, 0, 1);
+ junitTest.setRunTime(0);
+ fireEndTestSuite();
+ }
+ }
+
+ public void run() {
+ long start = System.currentTimeMillis();
+
+ if (retCode != 0) { // had an exception in the constructor
+ return;
+ }
+
+ fireStartTestSuite();
+ suite.run(res);
+ junitTest.setRunTime(System.currentTimeMillis()-start);
+ junitTest.setCounts(res.runCount(), res.failureCount(),
+ res.errorCount());
+ fireEndTestSuite();
+
+ if (res.errorCount() != 0) {
+ retCode = 2;
+ } else if (res.failureCount() != 0) {
+ retCode = 1;
+ }
+ }
+
+ /**
+ * Returns what System.exit() would return in the standalone version.
+ *
+ * @return 2 if errors occurred, 1 if tests failed else 0.
+ */
+ public int getRetCode() {
+ return retCode;
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
A new Test is started.
+ */
+ public void startTest(Test t) {
+ failed = false;
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
A Test is finished.
+ */
+ public void endTest(Test test) {
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
A Test failed.
+ */
+ public void addFailure(Test test, Throwable t) {
+ failed = true;
+
+ if (junitTest.getHaltonfailure()) {
+ res.stop();
+ }
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
An error occured while running the test.
+ */
+ public void addError(Test test, Throwable t) {
+ failed = true;
+
+ if (junitTest.getHaltonerror()) {
+ res.stop();
+ }
+ }
+
+ private void fireStartTestSuite() {
+ for (int i=0; i
+ * key | description | default value |
+ *
+ * exit | exit with System.exit after testcase is
+ * complete? | true |
+ *
+ * haltOnError | halt test on
+ * errors? | false |
+ *
+ * haltOnFailure | halt test on
+ * failures? | false |
+ *
+ * printSummary | print summary to System.out? |
+ * true |
+ *
+ * printXML | generate XML report? |
+ * false |
+ *
+ * outfile | where to print the XML report - a
+ * filename | System.out |
+ *
+ *
+ */
+ public static void main(String[] args) throws IOException {
+ boolean exitAtEnd = true;
+ boolean haltError = false;
+ boolean haltFail = false;
+ boolean printSummary = true;
+ boolean printXml = false;
+ PrintWriter out = null;
+
+ if (args.length == 0) {
+ System.err.println("required argument TestClassName missing");
+ if (exitAtEnd) {
+ System.exit(2);
+ }
+ } else {
+
+ JUnitTest test = new JUnitTest();
+ test.setName(args[0]);
+ args[0] = null;
+ test.setCommandline(args);
+ JUnitTestRunner runner = new JUnitTestRunner(test);
+ runner.run();
+
+ if (exitAtEnd) {
+ System.exit(runner.getRetCode());
+ }
+ }
+ }
+
+
+ public static int runTest(JUnitTest test) {
+ final JUnitTestRunner runner = new JUnitTestRunner(test);
+ runner.run();
+ return runner.getRetCode();
+ }
+
+} // JUnitTestRunner
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
new file mode 100644
index 000000000..4580b4db0
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
@@ -0,0 +1,128 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import java.text.NumberFormat;
+import junit.framework.Test;
+
+/**
+ * Prints short summary output of the test to System.out
+ *
+ * @author Stefan Bodewig
+ */
+
+public class SummaryJUnitResultFormatter implements JUnitResultFormatter {
+
+ /**
+ * Formatter for timings.
+ */
+ private NumberFormat nf = NumberFormat.getInstance();
+
+ public SummaryJUnitResultFormatter() {
+ }
+
+ /**
+ * The whole testsuite started.
+ */
+ public void startTestSuite(JUnitTest suite) {
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ * A new Test is started.
+ */
+ public void startTest(Test t) {
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
A Test is finished.
+ */
+ public void endTest(Test test) {
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
A Test failed.
+ */
+ public void addFailure(Test test, Throwable t) {
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
An error occured while running the test.
+ */
+ public void addError(Test test, Throwable t) {
+ }
+
+ /**
+ * The whole testsuite ended.
+ */
+ public void endTestSuite(JUnitTest suite) {
+ System.out.print("Tests run: ");
+ System.out.print(suite.runCount());
+ System.out.print(", Failures: ");
+ System.out.print(suite.failureCount());
+ System.out.print(", Errors: ");
+ System.out.print(suite.errorCount());
+ System.out.print(", Time ellapsed: ");
+ System.out.print(nf.format(suite.getRunTime()/1000.0));
+ System.out.println(" sec");
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java
new file mode 100644
index 000000000..8d2f0ce62
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java
@@ -0,0 +1,235 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.CharacterIterator;
+import java.text.NumberFormat;
+import java.text.StringCharacterIterator;
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+/**
+ * Prints XML output of the test to a specified Writer.
+ *
+ * @author Stefan Bodewig
+ */
+
+public class XMLJUnitResultFormatter implements JUnitResultFormatter {
+
+ /**
+ * OutputStream for XML output.
+ */
+ private PrintWriter out;
+ /**
+ * Collects output during the test run.
+ */
+ private StringBuffer results = new StringBuffer();
+ /**
+ * platform independent line separator.
+ */
+ private static String newLine = System.getProperty("line.separator");
+ /**
+ * Formatter for timings.
+ */
+ private NumberFormat nf = NumberFormat.getInstance();
+ /**
+ * Timing helper.
+ */
+ private long lastTestStart = 0;
+
+ public XMLJUnitResultFormatter(PrintWriter out) {
+ this.out = out;
+ }
+
+ /**
+ * The whole testsuite ended.
+ */
+ public void endTestSuite(JUnitTest suite) {
+ out.println("");
+ out.print("");
+ out.print(results.toString());
+ out.println("");
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * The whole testsuite started.
+ */
+ public void startTestSuite(JUnitTest suite) {
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
A new Test is started.
+ */
+ public void startTest(Test t) {
+ lastTestStart = System.currentTimeMillis();
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
A Test is finished.
+ */
+ public void endTest(Test test) {
+ formatTestCaseOpenTag(test);
+ results.append(" ");
+ results.append(newLine);
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
A Test failed.
+ */
+ public void addFailure(Test test, Throwable t) {
+ formatError("failure", test, t);
+ }
+
+ /**
+ * Interface TestListener.
+ *
+ *
An error occured while running the test.
+ */
+ public void addError(Test test, Throwable t) {
+ formatError("error", test, t);
+ }
+
+ /**
+ * Translates <, & and > to corresponding entities.
+ */
+ private String xmlEscape(String orig) {
+ if (orig == null) return "";
+ StringBuffer temp = new StringBuffer();
+ StringCharacterIterator sci = new StringCharacterIterator(orig);
+ for (char c = sci.first(); c != CharacterIterator.DONE;
+ c = sci.next()) {
+
+ switch (c) {
+ case '<':
+ temp.append("<");
+ break;
+ case '>':
+ temp.append(">");
+ break;
+ case '&':
+ temp.append("&");
+ break;
+ default:
+ temp.append(c);
+ break;
+ }
+ }
+ return temp.toString();
+ }
+
+ private void formatTestCaseOpenTag(Test test) {
+ results.append(" ");
+ results.append(newLine);
+ }
+
+ private void formatError(String type, Test test, Throwable t) {
+ formatTestCaseOpenTag(test);
+ results.append(" <");
+ results.append(type);
+ results.append(" message=\"");
+ results.append(xmlEscape(t.getMessage()));
+ results.append("\" type=\"");
+ results.append(t.getClass().getName());
+ results.append("\">");
+ results.append(newLine);
+
+ results.append("");
+ results.append(newLine);
+
+ results.append(" ");
+ results.append(type);
+ results.append(">");
+ results.append(newLine);
+
+ results.append(" ");
+ results.append(newLine);
+ }
+
+
+} // XMLJUnitResultFormatter