Author: jglick Date: Mon Feb 27 14:24:26 2006 New Revision: 381467 URL: http://svn.apache.org/viewcvs?rev=381467&view=rev Log: #38799: <junit> task should work so long as junit.jar present in <classpath> even if not among Ant libs.
Added: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java (with props) ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java (with props) Modified: ant/core/trunk/WHATSNEW ant/core/trunk/docs/manual/OptionalTasks/junit.html ant/core/trunk/docs/manual/install.html ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java ant/core/trunk/xdocs/faq.xml Modified: ant/core/trunk/WHATSNEW URL: http://svn.apache.org/viewcvs/ant/core/trunk/WHATSNEW?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/WHATSNEW (original) +++ ant/core/trunk/WHATSNEW Mon Feb 27 14:24:26 2006 @@ -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: @@ -76,6 +76,8 @@ Fixed bugs: ----------- + +* <junit> can now work with junit.jar in its <classpath>. Bugzilla Report 38799. * Some potential NullPointerExceptions, Bugzilla Reports 37765 and 38056 Modified: ant/core/trunk/docs/manual/OptionalTasks/junit.html URL: http://svn.apache.org/viewcvs/ant/core/trunk/docs/manual/OptionalTasks/junit.html?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/docs/manual/OptionalTasks/junit.html (original) +++ ant/core/trunk/docs/manual/OptionalTasks/junit.html Mon Feb 27 14:24:26 2006 @@ -19,12 +19,12 @@ </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 @@ 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 @@ 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 @@ <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> Modified: ant/core/trunk/docs/manual/install.html URL: http://svn.apache.org/viewcvs/ant/core/trunk/docs/manual/install.html?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/docs/manual/install.html (original) +++ ant/core/trunk/docs/manual/install.html Mon Feb 27 14:24:26 2006 @@ -456,7 +456,7 @@ </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 @@ <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> Modified: ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/AntClassLoader.java Mon Feb 27 14:24:26 2006 @@ -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. @@ -1488,6 +1488,10 @@ String packageName = (String) e.nextElement(); addSystemPackageRoot(packageName); } + } + + public String toString() { + return "AntClassLoader[" + getClasspath() + "]"; } } Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java Mon Feb 27 14:24:26 2006 @@ -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 @@ /** * @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 @@ 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 @@ 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 { Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java Mon Feb 27 14:24:26 2006 @@ -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 @@ * testrun. * */ -public interface JUnitResultFormatter extends TestListener { +public interface JUnitResultFormatter extends TestListener, JUnitTaskMirror.JUnitResultFormatterMirror { /** * The whole testsuite started. */ Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java Mon Feb 27 14:24:26 2006 @@ -24,6 +24,7 @@ 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.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 @@ 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 @@ 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 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 @@ * @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 @@ } } finally { deleteClassLoader(); + if (mirrorLoader instanceof SplitLoader) { + ((SplitLoader) mirrorLoader).cleanup(); + } + delegate = null; } } @@ -1061,18 +1147,22 @@ 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 @@ 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 @@ * 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 @@ 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 @@ 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 @@ } } 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 @@ * 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 @@ // 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 @@ } protected class TestResultHolder { - public int exitCode = JUnitTestRunner.ERRORS; + public int exitCode = JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS; public boolean timedOut = false; public boolean crashed = false; } Added: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java?rev=381467&view=auto ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java (added) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java Mon Feb 27 14:24:26 2006 @@ -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 [EMAIL PROTECTED] 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. [EMAIL PROTECTED] 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); + + } + +} Propchange: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java ------------------------------------------------------------------------------ svn:eol-style = native Added: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java?rev=381467&view=auto ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java (added) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java Mon Feb 27 14:24:26 2006 @@ -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(); + } + +} Propchange: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java Mon Feb 27 14:24:26 2006 @@ -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 @@ * @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 @@ 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 @@ * * @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 @@ formatters.addElement(f); } + public void addFormatter(JUnitTaskMirror.JUnitResultFormatterMirror f) { + formatters.addElement((JUnitResultFormatter) f); + } + /** * Entry point for standalone (forked) mode. * @@ -645,7 +625,7 @@ test.getOutfile() + fe.getExtension()); fe.setOutfile(destFile); } - runner.addFormatter(fe.createFormatter()); + runner.addFormatter((JUnitResultFormatter) fe.createFormatter()); } } Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java Mon Feb 27 14:24:26 2006 @@ -29,7 +29,7 @@ * */ -public class SummaryJUnitResultFormatter implements JUnitResultFormatter { +public class SummaryJUnitResultFormatter implements JUnitResultFormatter, JUnitTaskMirror.SummaryJUnitResultFormatterMirror { /** * Formatter for timings. Modified: ant/core/trunk/xdocs/faq.xml URL: http://svn.apache.org/viewcvs/ant/core/trunk/xdocs/faq.xml?rev=381467&r1=381466&r2=381467&view=diff ============================================================================== --- ant/core/trunk/xdocs/faq.xml (original) +++ ant/core/trunk/xdocs/faq.xml Mon Feb 27 14:24:26 2006 @@ -1386,6 +1386,10 @@ <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 @@ </faq> </faqsection> -</document> \ No newline at end of file +</document> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]