present in <classpath> even if not among Ant libs. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@381467 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -1,4 +1,4 @@ | |||
| Changes from current Ant 1.6.5 version to current RCS version | |||
| Changes from current Ant 1.6.5 version to current SVN version | |||
| ============================================================= | |||
| Changes that could break older environments: | |||
| @@ -77,6 +77,8 @@ Changes that could break older environments: | |||
| Fixed bugs: | |||
| ----------- | |||
| * <junit> can now work with junit.jar in its <classpath>. Bugzilla Report 38799. | |||
| * Some potential NullPointerExceptions, Bugzilla Reports 37765 and 38056 | |||
| * Problem when adding multiple filter files, Bugzilla Report 37341 | |||
| @@ -19,12 +19,12 @@ Library Dependencies</a> for more information. | |||
| </p> | |||
| <p> | |||
| <strong>Note</strong>: | |||
| You must have <code>junit.jar</code> and the class files for the | |||
| <code><junit></code> task in the same classpath. | |||
| You must have <code>junit.jar</code> available. | |||
| You can do one of: | |||
| </p> | |||
| <ol> | |||
| <li> | |||
| Put both <code>junit.jar</code> and the optional tasks jar file in | |||
| Put both <code>junit.jar</code> and <code>ant-junit.jar</code> in | |||
| <code>ANT_HOME/lib</code>. | |||
| </li> | |||
| <li> | |||
| @@ -32,15 +32,23 @@ Do not put either in <code>ANT_HOME/lib</code>, and instead | |||
| include their locations in your <code>CLASSPATH</code> environment variable. | |||
| </li> | |||
| <li> | |||
| Do neither of the above, and instead, specify their locations using | |||
| a <code><classpath></code> element in the build file. | |||
| Add both JARs to your classpath using <code>-lib</code>. | |||
| </li> | |||
| <li> | |||
| Specify the locations of both JARs using | |||
| a <code><classpath></code> element in a <code><taskdef></code> in the build file. | |||
| </li> | |||
| <li> | |||
| Leave <code>ant-junit.jar</code> in its default location in <code>ANT_HOME/lib</code> | |||
| but include <code>junit.jar</code> in the <code><classpath></code> passed | |||
| to <code><junit></code>. <em>(since Ant 1.7)</em> | |||
| </li> | |||
| </ol> | |||
| <p> | |||
| See <a href="../../faq.html#delegating-classloader" target="_top">the | |||
| FAQ</a> for details. | |||
| </ol> | |||
| </p> | |||
| <p>Tests are defined by nested <code>test</code> or | |||
| <code>batchtest</code> tags (see <a href="#nested">nested | |||
| elements</a>).</p> | |||
| @@ -217,6 +225,9 @@ supports a nested <code><classpath></code> | |||
| element that represents a <a href="../using.html#path">PATH like | |||
| structure</a>.</p> | |||
| <p>As of Ant 1.7, this classpath may be used to refer to <code>junit.jar</code> | |||
| as well as your tests and the tested code. | |||
| <h4>jvmarg</h4> | |||
| <p>If <code>fork</code> is enabled, additional parameters may be passed to | |||
| @@ -580,7 +591,7 @@ aborted. Results are collected in files named | |||
| <code>${reports.tests}</code>.</p> | |||
| <hr> | |||
| <p align="center">Copyright © 2000-2005 The Apache Software Foundation. All rights | |||
| <p align="center">Copyright © 2000-2006 The Apache Software Foundation. All rights | |||
| Reserved.</p> | |||
| </body> | |||
| </html> | |||
| @@ -456,7 +456,7 @@ you need jakarta-oro 2.0.1 or later, and <a href="#commons-net">commons-net</a>< | |||
| </tr> | |||
| <tr> | |||
| <td>junit.jar</td> | |||
| <td>junit tasks</td> | |||
| <td><code><junit></code> task. May be in classpath passed to task rather than Ant's classpath.</td> | |||
| <td><a href="http://www.junit.org/" target="_top">http://www.junit.org/</a></td> | |||
| </tr> | |||
| <tr> | |||
| @@ -698,7 +698,7 @@ advised to do it by the user mailing list. | |||
| <hr> | |||
| <p align="center">Copyright © 2000-2005 The Apache Software Foundation. All rights | |||
| <p align="center">Copyright © 2000-2006 The Apache Software Foundation. All rights | |||
| Reserved.</p> | |||
| </body> | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| * Copyright 2000-2005 The Apache Software Foundation | |||
| * Copyright 2000-2006 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| @@ -1490,4 +1490,8 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener { | |||
| } | |||
| } | |||
| public String toString() { | |||
| return "AntClassLoader[" + getClasspath() + "]"; | |||
| } | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| * Copyright 2001-2004 The Apache Software Foundation | |||
| * Copyright 2001-2004,2006 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| @@ -188,14 +188,14 @@ public class FormatterElement { | |||
| /** | |||
| * @since Ant 1.2 | |||
| */ | |||
| JUnitResultFormatter createFormatter() throws BuildException { | |||
| JUnitTaskMirror.JUnitResultFormatterMirror createFormatter() throws BuildException { | |||
| return createFormatter(null); | |||
| } | |||
| /** | |||
| * @since Ant 1.6 | |||
| */ | |||
| JUnitResultFormatter createFormatter(ClassLoader loader) | |||
| JUnitTaskMirror.JUnitResultFormatterMirror createFormatter(ClassLoader loader) | |||
| throws BuildException { | |||
| if (classname == null) { | |||
| @@ -210,7 +210,9 @@ public class FormatterElement { | |||
| f = Class.forName(classname, true, loader); | |||
| } | |||
| } catch (ClassNotFoundException e) { | |||
| throw new BuildException(e); | |||
| throw new BuildException("Using loader " + loader + " on class " + classname + ": " + e, e); | |||
| } catch (NoClassDefFoundError e) { | |||
| throw new BuildException("Using loader " + loader + " on class " + classname + ": " + e, e); | |||
| } | |||
| Object o = null; | |||
| @@ -222,12 +224,11 @@ public class FormatterElement { | |||
| throw new BuildException(e); | |||
| } | |||
| if (!(o instanceof JUnitResultFormatter)) { | |||
| if (!(o instanceof JUnitTaskMirror.JUnitResultFormatterMirror)) { | |||
| throw new BuildException(classname | |||
| + " is not a JUnitResultFormatter"); | |||
| } | |||
| JUnitResultFormatter r = (JUnitResultFormatter) o; | |||
| JUnitTaskMirror.JUnitResultFormatterMirror r = (JUnitTaskMirror.JUnitResultFormatterMirror) o; | |||
| if (useFile && outFile != null) { | |||
| try { | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| * Copyright 2001-2002,2004 The Apache Software Foundation | |||
| * Copyright 2001-2002,2004,2006 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| @@ -26,7 +26,7 @@ import org.apache.tools.ant.BuildException; | |||
| * testrun. | |||
| * | |||
| */ | |||
| public interface JUnitResultFormatter extends TestListener { | |||
| public interface JUnitResultFormatter extends TestListener, JUnitTaskMirror.JUnitResultFormatterMirror { | |||
| /** | |||
| * The whole testsuite started. | |||
| */ | |||
| @@ -24,6 +24,7 @@ import java.io.FileWriter; | |||
| import java.io.IOException; | |||
| import java.io.OutputStream; | |||
| import java.io.PrintWriter; | |||
| import java.lang.reflect.Constructor; | |||
| import java.util.ArrayList; | |||
| import java.util.Collection; | |||
| import java.util.Enumeration; | |||
| @@ -34,9 +35,6 @@ import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.Properties; | |||
| import java.util.Vector; | |||
| import junit.framework.AssertionFailedError; | |||
| import junit.framework.Test; | |||
| import junit.framework.TestResult; | |||
| import org.apache.tools.ant.AntClassLoader; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| @@ -134,7 +132,7 @@ public class JUnitTask extends Task { | |||
| private boolean summary = false; | |||
| private boolean reloading = true; | |||
| private String summaryValue = ""; | |||
| private JUnitTestRunner runner = null; | |||
| private JUnitTaskMirror.JUnitTestRunnerMirror runner = null; | |||
| private boolean newEnvironment = false; | |||
| private Environment env = new Environment(); | |||
| @@ -148,6 +146,9 @@ public class JUnitTask extends Task { | |||
| private Permissions perm = null; | |||
| private ForkMode forkMode = new ForkMode("perTest"); | |||
| private boolean splitJunit = false; | |||
| private JUnitTaskMirror delegate; | |||
| private static final int STRING_BUFFER_SIZE = 128; | |||
| /** | |||
| * @since Ant 1.7 | |||
| @@ -632,12 +633,81 @@ public class JUnitTask extends Task { | |||
| */ | |||
| public void init() { | |||
| antRuntimeClasses = new Path(getProject()); | |||
| addClasspathEntry("/junit/framework/TestCase.class"); | |||
| splitJunit = !addClasspathEntry("/junit/framework/TestCase.class"); | |||
| addClasspathEntry("/org/apache/tools/ant/launch/AntMain.class"); | |||
| addClasspathEntry("/org/apache/tools/ant/Task.class"); | |||
| addClasspathEntry("/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.class"); | |||
| } | |||
| private static JUnitTaskMirror createMirror(JUnitTask task, ClassLoader loader) { | |||
| try { | |||
| loader.loadClass("junit.framework.Test"); // sanity check | |||
| } catch (ClassNotFoundException e) { | |||
| throw new BuildException( | |||
| "The <classpath> for <junit> must include junit.jar if not in Ant's own classpath", | |||
| e, task.getLocation()); | |||
| } | |||
| try { | |||
| Class c = loader.loadClass(JUnitTaskMirror.class.getName() + "Impl"); | |||
| if (c.getClassLoader() != loader) { | |||
| throw new BuildException("Overdelegating loader", task.getLocation()); | |||
| } | |||
| Constructor cons = c.getConstructor(new Class[] {JUnitTask.class}); | |||
| return (JUnitTaskMirror) cons.newInstance(new Object[] {task}); | |||
| } catch (Exception e) { | |||
| throw new BuildException(e, task.getLocation()); | |||
| } | |||
| } | |||
| private final class SplitLoader extends AntClassLoader { | |||
| public SplitLoader(ClassLoader parent, Path path) { | |||
| super(parent, getProject(), path, true); | |||
| } | |||
| // forceLoadClass is not convenient here since it would not | |||
| // properly deal with inner classes of these classes. | |||
| protected synchronized Class loadClass(String classname, boolean resolve) | |||
| throws ClassNotFoundException { | |||
| Class theClass = findLoadedClass(classname); | |||
| if (theClass != null) { | |||
| return theClass; | |||
| } | |||
| if (isSplit(classname)) { | |||
| theClass = findClass(classname); | |||
| if (resolve) { | |||
| resolveClass(theClass); | |||
| } | |||
| return theClass; | |||
| } else { | |||
| return super.loadClass(classname, resolve); | |||
| } | |||
| } | |||
| private final String[] SPLIT_CLASSES = { | |||
| "BriefJUnitResultFormatter", | |||
| "JUnitResultFormatter", | |||
| "JUnitTaskMirrorImpl", | |||
| "JUnitTestRunner", | |||
| "JUnitVersionHelper", | |||
| "OutErrSummaryJUnitResultFormatter", | |||
| "PlainJUnitResultFormatter", | |||
| "SummaryJUnitResultFormatter", | |||
| "XMLJUnitResultFormatter", | |||
| }; | |||
| private boolean isSplit(String classname) { | |||
| String simplename = classname.substring(classname.lastIndexOf('.') + 1); | |||
| for (int i = 0; i < SPLIT_CLASSES.length; i++) { | |||
| if (simplename.equals(SPLIT_CLASSES[i]) || simplename.startsWith(SPLIT_CLASSES[i] + '$')) { | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| /** | |||
| * Runs the testcase. | |||
| * | |||
| @@ -645,6 +715,18 @@ public class JUnitTask extends Task { | |||
| * @since Ant 1.2 | |||
| */ | |||
| public void execute() throws BuildException { | |||
| ClassLoader myLoader = JUnitTask.class.getClassLoader(); | |||
| ClassLoader mirrorLoader; | |||
| if (splitJunit) { | |||
| Path path = new Path(getProject()); | |||
| path.add(antRuntimeClasses); | |||
| path.add(getCommandline().getClasspath()); | |||
| mirrorLoader = new SplitLoader(myLoader, path); | |||
| } else { | |||
| mirrorLoader = myLoader; | |||
| } | |||
| delegate = createMirror(this, mirrorLoader); | |||
| List testLists = new ArrayList(); | |||
| boolean forkPerTest = forkMode.getValue().equals(ForkMode.PER_TEST); | |||
| @@ -672,6 +754,10 @@ public class JUnitTask extends Task { | |||
| } | |||
| } finally { | |||
| deleteClassLoader(); | |||
| if (mirrorLoader instanceof SplitLoader) { | |||
| ((SplitLoader) mirrorLoader).cleanup(); | |||
| } | |||
| delegate = null; | |||
| } | |||
| } | |||
| @@ -1061,18 +1147,22 @@ public class JUnitTask extends Task { | |||
| try { | |||
| log("Using System properties " + System.getProperties(), | |||
| Project.MSG_VERBOSE); | |||
| createClassLoader(); | |||
| if (splitJunit) { | |||
| classLoader = (AntClassLoader) delegate.getClass().getClassLoader(); | |||
| } else { | |||
| createClassLoader(); | |||
| } | |||
| if (classLoader != null) { | |||
| classLoader.setThreadContextLoader(); | |||
| } | |||
| runner = new JUnitTestRunner(test, test.getHaltonerror(), | |||
| runner = delegate.newJUnitTestRunner(test, test.getHaltonerror(), | |||
| test.getFiltertrace(), | |||
| test.getHaltonfailure(), false, | |||
| true, classLoader); | |||
| if (summary) { | |||
| SummaryJUnitResultFormatter f = | |||
| new SummaryJUnitResultFormatter(); | |||
| JUnitTaskMirror.SummaryJUnitResultFormatterMirror f = | |||
| delegate.newSummaryJUnitResultFormatter(); | |||
| f.setWithOutAndErr("withoutanderr" | |||
| .equalsIgnoreCase(summaryValue)); | |||
| f.setOutput(getDefaultOutput()); | |||
| @@ -1186,7 +1276,7 @@ public class JUnitTask extends Task { | |||
| if (fe.getUseFile()) { | |||
| String base = test.getOutfile(); | |||
| if (base == null) { | |||
| base = JUnitTestRunner.IGNORED_FILE_NAME; | |||
| base = JUnitTaskMirror.JUnitTestRunnerMirror.IGNORED_FILE_NAME; | |||
| } | |||
| String filename = base + fe.getExtension(); | |||
| File destFile = new File(test.getTodir(), filename); | |||
| @@ -1204,9 +1294,10 @@ public class JUnitTask extends Task { | |||
| * getResource doesn't contain the name of the archive.</p> | |||
| * | |||
| * @param resource resource that one wants to lookup | |||
| * @return true if something was in fact added | |||
| * @since Ant 1.4 | |||
| */ | |||
| protected void addClasspathEntry(String resource) { | |||
| protected boolean addClasspathEntry(String resource) { | |||
| /* | |||
| * pre Ant 1.6 this method used to call getClass().getResource | |||
| * while Ant 1.6 will call ClassLoader.getResource(). | |||
| @@ -1228,8 +1319,10 @@ public class JUnitTask extends Task { | |||
| if (f != null) { | |||
| log("Found " + f.getAbsolutePath(), Project.MSG_DEBUG); | |||
| antRuntimeClasses.createPath().setLocation(f); | |||
| return true; | |||
| } else { | |||
| log("Couldn\'t find " + resource, Project.MSG_DEBUG); | |||
| return false; | |||
| } | |||
| } | |||
| @@ -1269,7 +1362,7 @@ public class JUnitTask extends Task { | |||
| for (int i = 0; i < feArray.length; i++) { | |||
| FormatterElement fe = feArray[i]; | |||
| File outFile = getOutput(fe, test); | |||
| JUnitResultFormatter formatter = fe.createFormatter(classLoader); | |||
| JUnitTaskMirror.JUnitResultFormatterMirror formatter = fe.createFormatter(classLoader); | |||
| if (outFile != null && formatter != null) { | |||
| try { | |||
| OutputStream out = new FileOutputStream(outFile); | |||
| @@ -1280,7 +1373,7 @@ public class JUnitTask extends Task { | |||
| } | |||
| } | |||
| if (summary) { | |||
| SummaryJUnitResultFormatter f = new SummaryJUnitResultFormatter(); | |||
| JUnitTaskMirror.SummaryJUnitResultFormatterMirror f = delegate.newSummaryJUnitResultFormatter(); | |||
| f.setWithOutAndErr("withoutanderr".equalsIgnoreCase(summaryValue)); | |||
| addVmExit(test, f, getDefaultOutput(), message); | |||
| } | |||
| @@ -1291,23 +1384,9 @@ public class JUnitTask extends Task { | |||
| * Only used from the logVmExit method. | |||
| * @since Ant 1.7 | |||
| */ | |||
| private void addVmExit(JUnitTest test, JUnitResultFormatter formatter, | |||
| private void addVmExit(JUnitTest test, JUnitTaskMirror.JUnitResultFormatterMirror formatter, | |||
| OutputStream out, final String message) { | |||
| formatter.setOutput(out); | |||
| formatter.startTestSuite(test); | |||
| //the trick to integrating test output to the formatter, is to | |||
| //create a special test class that asserts an error | |||
| //and tell the formatter that it raised. | |||
| Test t = new Test() { | |||
| public int countTestCases() { return 1; } | |||
| public void run(TestResult r) { | |||
| throw new AssertionFailedError(message); | |||
| } | |||
| }; | |||
| formatter.startTest(t); | |||
| formatter.addError(t, new AssertionFailedError(message)); | |||
| formatter.endTestSuite(test); | |||
| delegate.addVmExit(test, formatter, out, message); | |||
| } | |||
| /** | |||
| @@ -1535,9 +1614,9 @@ public class JUnitTask extends Task { | |||
| // everything otherwise just log a statement | |||
| boolean fatal = result.timedOut || result.crashed; | |||
| boolean errorOccurredHere = | |||
| result.exitCode == JUnitTestRunner.ERRORS || fatal; | |||
| result.exitCode == JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS || fatal; | |||
| boolean failureOccurredHere = | |||
| result.exitCode != JUnitTestRunner.SUCCESS || fatal; | |||
| result.exitCode != JUnitTaskMirror.JUnitTestRunnerMirror.SUCCESS || fatal; | |||
| if (errorOccurredHere || failureOccurredHere) { | |||
| if ((errorOccurredHere && test.getHaltonerror()) | |||
| || (failureOccurredHere && test.getHaltonfailure())) { | |||
| @@ -1559,7 +1638,7 @@ public class JUnitTask extends Task { | |||
| } | |||
| protected class TestResultHolder { | |||
| public int exitCode = JUnitTestRunner.ERRORS; | |||
| public int exitCode = JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS; | |||
| public boolean timedOut = false; | |||
| public boolean crashed = false; | |||
| } | |||
| @@ -0,0 +1,110 @@ | |||
| /* | |||
| * Copyright 2006 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junit; | |||
| import java.io.IOException; | |||
| import java.io.OutputStream; | |||
| import org.apache.tools.ant.AntClassLoader; | |||
| import org.apache.tools.ant.types.Permissions; | |||
| /** | |||
| * Handles the portions of {@link JUnitTask} which need to directly access | |||
| * actual JUnit classes, so that junit.jar need not be on Ant's startup classpath. | |||
| * Neither JUnitTask.java nor JUnitTaskMirror.java nor their transitive static | |||
| * deps may import any junit.** classes! | |||
| * Specifically, need to not refer to | |||
| * - JUnitResultFormatter or its subclasses | |||
| * - JUnitVersionHelper | |||
| * - JUnitTestRunner | |||
| * Cf. {@link JUnitTask.SplitLoader#isSplit} | |||
| * Public only to permit access from classes in this package; do not use directly. | |||
| * | |||
| * @author refactoring tricks by Jesse Glick, real code by others | |||
| * @since 1.7 | |||
| * @see "bug #38799" | |||
| */ | |||
| public interface JUnitTaskMirror { | |||
| void addVmExit(JUnitTest test, JUnitResultFormatterMirror formatter, | |||
| OutputStream out, final String message); | |||
| JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest test, boolean haltOnError, | |||
| boolean filterTrace, boolean haltOnFailure, boolean showOutput, | |||
| boolean logTestListenerEvents, AntClassLoader classLoader); | |||
| SummaryJUnitResultFormatterMirror newSummaryJUnitResultFormatter(); | |||
| public interface JUnitResultFormatterMirror { | |||
| void setOutput(OutputStream outputStream); | |||
| } | |||
| public interface SummaryJUnitResultFormatterMirror extends JUnitResultFormatterMirror { | |||
| void setWithOutAndErr(boolean value); | |||
| } | |||
| public interface JUnitTestRunnerMirror { | |||
| /** | |||
| * Used in formatter arguments as a placeholder for the basename | |||
| * of the output file (which gets replaced by a test specific | |||
| * output file name later). | |||
| * | |||
| * @since Ant 1.6.3 | |||
| */ | |||
| String IGNORED_FILE_NAME = "IGNORETHIS"; | |||
| /** | |||
| * No problems with this test. | |||
| */ | |||
| int SUCCESS = 0; | |||
| /** | |||
| * Some tests failed. | |||
| */ | |||
| int FAILURES = 1; | |||
| /** | |||
| * An error occurred. | |||
| */ | |||
| int ERRORS = 2; | |||
| void setPermissions(Permissions perm); | |||
| void run(); | |||
| void addFormatter(JUnitResultFormatterMirror formatter); | |||
| int getRetCode(); | |||
| void handleErrorFlush(String output); | |||
| void handleErrorOutput(String output); | |||
| void handleOutput(String output); | |||
| int handleInput(byte[] buffer, int offset, int length) throws IOException; | |||
| void handleFlush(String output); | |||
| } | |||
| } | |||
| @@ -0,0 +1,72 @@ | |||
| /* | |||
| * Copyright 2006 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junit; | |||
| import java.io.OutputStream; | |||
| import junit.framework.AssertionFailedError; | |||
| import junit.framework.Test; | |||
| import junit.framework.TestResult; | |||
| import org.apache.tools.ant.AntClassLoader; | |||
| /** | |||
| * Implementation of the part of the junit task which can directly refer to junit.* classes. | |||
| * Public only to permit use of reflection; do not use directly. | |||
| * @see JUnitTaskMirror | |||
| * @see "bug #38799" | |||
| * @since 1.7 | |||
| */ | |||
| public final class JUnitTaskMirrorImpl implements JUnitTaskMirror { | |||
| private final JUnitTask task; | |||
| public JUnitTaskMirrorImpl(JUnitTask task) { | |||
| this.task = task; | |||
| } | |||
| public void addVmExit(JUnitTest test, JUnitResultFormatterMirror _formatter, | |||
| OutputStream out, final String message) { | |||
| JUnitResultFormatter formatter = (JUnitResultFormatter) _formatter; | |||
| formatter.setOutput(out); | |||
| formatter.startTestSuite(test); | |||
| //the trick to integrating test output to the formatter, is to | |||
| //create a special test class that asserts an error | |||
| //and tell the formatter that it raised. | |||
| Test t = new Test() { | |||
| public int countTestCases() { return 1; } | |||
| public void run(TestResult r) { | |||
| throw new AssertionFailedError(message); | |||
| } | |||
| }; | |||
| formatter.startTest(t); | |||
| formatter.addError(t, new AssertionFailedError(message)); | |||
| formatter.endTestSuite(test); | |||
| } | |||
| public JUnitTaskMirror.JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest test, | |||
| boolean haltOnError, boolean filterTrace, boolean haltOnFailure, | |||
| boolean showOutput, boolean logTestListenerEvents, AntClassLoader classLoader) { | |||
| return new JUnitTestRunner(test, haltOnError, filterTrace, haltOnFailure, | |||
| showOutput, logTestListenerEvents, classLoader); | |||
| } | |||
| public JUnitTaskMirror.SummaryJUnitResultFormatterMirror newSummaryJUnitResultFormatter() { | |||
| return new SummaryJUnitResultFormatter(); | |||
| } | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| * Copyright 2000-2005 The Apache Software Foundation | |||
| * Copyright 2000-2006 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| @@ -62,31 +62,7 @@ import org.apache.tools.ant.util.TeeOutputStream; | |||
| * @since Ant 1.2 | |||
| */ | |||
| public class JUnitTestRunner implements TestListener { | |||
| /** | |||
| * No problems with this test. | |||
| */ | |||
| public static final int SUCCESS = 0; | |||
| /** | |||
| * Some tests failed. | |||
| */ | |||
| public static final int FAILURES = 1; | |||
| /** | |||
| * An error occurred. | |||
| */ | |||
| public static final int ERRORS = 2; | |||
| /** | |||
| * Used in formatter arguments as a placeholder for the basename | |||
| * of the output file (which gets replaced by a test specific | |||
| * output file name later). | |||
| * | |||
| * @since Ant 1.6.3 | |||
| */ | |||
| public static final String IGNORED_FILE_NAME = "IGNORETHIS"; | |||
| public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestRunnerMirror { | |||
| /** | |||
| * Holds the registered formatters. | |||
| @@ -441,7 +417,7 @@ public class JUnitTestRunner implements TestListener { | |||
| perm = permissions; | |||
| } | |||
| protected void handleOutput(String output) { | |||
| public void handleOutput(String output) { | |||
| if (!logTestListenerEvents && output.startsWith(JUnitTask.TESTLISTENER_PREFIX)) | |||
| ; // ignore | |||
| else if (systemOut != null) { | |||
| @@ -454,24 +430,24 @@ public class JUnitTestRunner implements TestListener { | |||
| * | |||
| * @since Ant 1.6 | |||
| */ | |||
| protected int handleInput(byte[] buffer, int offset, int length) | |||
| public int handleInput(byte[] buffer, int offset, int length) | |||
| throws IOException { | |||
| return -1; | |||
| } | |||
| protected void handleErrorOutput(String output) { | |||
| public void handleErrorOutput(String output) { | |||
| if (systemError != null) { | |||
| systemError.print(output); | |||
| } | |||
| } | |||
| protected void handleFlush(String output) { | |||
| public void handleFlush(String output) { | |||
| if (systemOut != null) { | |||
| systemOut.print(output); | |||
| } | |||
| } | |||
| protected void handleErrorFlush(String output) { | |||
| public void handleErrorFlush(String output) { | |||
| if (systemError != null) { | |||
| systemError.print(output); | |||
| } | |||
| @@ -505,6 +481,10 @@ public class JUnitTestRunner implements TestListener { | |||
| formatters.addElement(f); | |||
| } | |||
| public void addFormatter(JUnitTaskMirror.JUnitResultFormatterMirror f) { | |||
| formatters.addElement((JUnitResultFormatter) f); | |||
| } | |||
| /** | |||
| * Entry point for standalone (forked) mode. | |||
| * | |||
| @@ -645,7 +625,7 @@ public class JUnitTestRunner implements TestListener { | |||
| test.getOutfile() + fe.getExtension()); | |||
| fe.setOutfile(destFile); | |||
| } | |||
| runner.addFormatter(fe.createFormatter()); | |||
| runner.addFormatter((JUnitResultFormatter) fe.createFormatter()); | |||
| } | |||
| } | |||
| @@ -29,7 +29,7 @@ import org.apache.tools.ant.BuildException; | |||
| * | |||
| */ | |||
| public class SummaryJUnitResultFormatter implements JUnitResultFormatter { | |||
| public class SummaryJUnitResultFormatter implements JUnitResultFormatter, JUnitTaskMirror.SummaryJUnitResultFormatterMirror { | |||
| /** | |||
| * Formatter for timings. | |||
| @@ -1386,6 +1386,10 @@ mv /tmp/foo $ANT_HOME/bin/antRun | |||
| <code>org.apache.tools.ant.taskdefs.XSLTLiaison</code> | |||
| class.</p> | |||
| <p><em>As of Ant 1.7</em> <code><junit></code> no longer | |||
| requires you to have <code>junit.jar</code> in Ant's startup | |||
| classpath even if <code>ant-junit.jar</code> is present there.</p> | |||
| <p>Ant's class loader implementation uses Java's | |||
| delegation model, see <a | |||
| href="http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html">http://java.sun.com/products/jdk/1.2/docs/api/java/lang/ClassLoader.html</a> | |||
| @@ -1776,4 +1780,4 @@ mv /tmp/foo $ANT_HOME/bin/antRun | |||
| </faq> | |||
| </faqsection> | |||
| </document> | |||
| </document> | |||