git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278072 13f79535-47bb-0310-9956-ffa450edef68master
@@ -34,6 +34,9 @@ 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; | |||
@@ -41,7 +44,6 @@ import org.apache.tools.ant.Task; | |||
import org.apache.tools.ant.taskdefs.Execute; | |||
import org.apache.tools.ant.taskdefs.ExecuteWatchdog; | |||
import org.apache.tools.ant.taskdefs.LogOutputStream; | |||
import org.apache.tools.ant.taskdefs.LogStreamHandler; | |||
import org.apache.tools.ant.types.Assertions; | |||
import org.apache.tools.ant.types.Commandline; | |||
import org.apache.tools.ant.types.CommandlineJava; | |||
@@ -52,9 +54,7 @@ import org.apache.tools.ant.types.Permissions; | |||
import org.apache.tools.ant.types.PropertySet; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.LoaderUtils; | |||
import junit.framework.AssertionFailedError; | |||
import junit.framework.Test; | |||
import junit.framework.TestResult; | |||
import org.apache.tools.ant.taskdefs.PumpStreamHandler; | |||
/** | |||
* Runs JUnit tests. | |||
@@ -149,6 +149,11 @@ public class JUnitTask extends Task { | |||
private ForkMode forkMode = new ForkMode("perTest"); | |||
private static final int STRING_BUFFER_SIZE = 128; | |||
/** | |||
* @since Ant 1.7 | |||
*/ | |||
public static final String TESTLISTENER_PREFIX = | |||
"junit.framework.TestListener: "; | |||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
@@ -829,6 +834,7 @@ public class JUnitTask extends Task { | |||
cmd.createArgument().setValue("showoutput=" | |||
+ String.valueOf(showOutput)); | |||
cmd.createArgument().setValue("logtestlistenerevents=true"); // #31885 | |||
StringBuffer formatterArg = new StringBuffer(STRING_BUFFER_SIZE); | |||
final FormatterElement[] feArray = mergeFormatters(test); | |||
@@ -871,9 +877,9 @@ public class JUnitTask extends Task { | |||
+ "file.", e, getLocation()); | |||
} | |||
Execute execute = new Execute(new LogStreamHandler(this, | |||
Project.MSG_INFO, | |||
Project.MSG_WARN), | |||
Execute execute = new Execute(new JUnitLogStreamHandler(this, | |||
Project.MSG_INFO, | |||
Project.MSG_WARN), | |||
watchdog); | |||
execute.setCommandline(cmd.getCommandline()); | |||
execute.setAntRun(getProject()); | |||
@@ -941,7 +947,9 @@ public class JUnitTask extends Task { | |||
* @since Ant 1.5 | |||
*/ | |||
protected void handleOutput(String output) { | |||
if (runner != null) { | |||
if (output.startsWith(TESTLISTENER_PREFIX)) | |||
log(output, Project.MSG_VERBOSE); | |||
else if (runner != null) { | |||
runner.handleOutput(output); | |||
if (showOutput) { | |||
super.handleOutput(output); | |||
@@ -1063,7 +1071,8 @@ public class JUnitTask extends Task { | |||
} | |||
runner = new JUnitTestRunner(test, test.getHaltonerror(), | |||
test.getFiltertrace(), | |||
test.getHaltonfailure(), classLoader); | |||
test.getHaltonfailure(), false, | |||
true, classLoader); | |||
if (summary) { | |||
log("Running " + test.getName(), Project.MSG_INFO); | |||
@@ -1549,4 +1558,33 @@ public class JUnitTask extends Task { | |||
public boolean timedOut = false; | |||
public boolean crashed = false; | |||
} | |||
/** | |||
* @since Ant 1.7 | |||
*/ | |||
protected static class JUnitLogOutputStream extends LogOutputStream { | |||
private Task task; // local copy since LogOutputStream.task is private | |||
public JUnitLogOutputStream(Task task, int level) { | |||
super(task, level); | |||
this.task = task; | |||
} | |||
protected void processLine(String line, int level) { | |||
if (line.startsWith(TESTLISTENER_PREFIX)) | |||
task.log(line, Project.MSG_VERBOSE); | |||
else | |||
super.processLine(line, level); | |||
} | |||
} | |||
/** | |||
* @since Ant 1.7 | |||
*/ | |||
protected static class JUnitLogStreamHandler extends PumpStreamHandler { | |||
public JUnitLogStreamHandler(Task task, int outlevel, int errlevel) { | |||
super(new JUnitLogOutputStream(task, outlevel), | |||
new LogOutputStream(task, errlevel)); | |||
} | |||
} | |||
} |
@@ -161,6 +161,9 @@ public class JUnitTestRunner implements TestListener { | |||
/** ClassLoader passed in in non-forked mode. */ | |||
private ClassLoader loader; | |||
/** Do we print TestListener events? */ | |||
private boolean logTestListenerEvents = false; | |||
/** | |||
* Constructor for fork=true or when the user hasn't specified a | |||
@@ -178,7 +181,19 @@ public class JUnitTestRunner implements TestListener { | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, | |||
boolean filtertrace, boolean haltOnFailure, | |||
boolean showOutput) { | |||
this(test, haltOnError, filtertrace, haltOnFailure, showOutput, null); | |||
this(test, haltOnError, filtertrace, haltOnFailure, showOutput, false); | |||
} | |||
/** | |||
* Constructor for fork=true or when the user hasn't specified a | |||
* classpath. | |||
* @since Ant 1.7 | |||
*/ | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, | |||
boolean filtertrace, boolean haltOnFailure, | |||
boolean showOutput, boolean logTestListenerEvents) { | |||
this(test, haltOnError, filtertrace, haltOnFailure, showOutput, | |||
logTestListenerEvents, null); | |||
} | |||
/** | |||
@@ -196,14 +211,29 @@ public class JUnitTestRunner implements TestListener { | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, | |||
boolean filtertrace, boolean haltOnFailure, | |||
boolean showOutput, ClassLoader loader) { | |||
this(test, haltOnError, filtertrace, haltOnFailure, showOutput, | |||
false, loader); | |||
} | |||
/** | |||
* Constructor to use when the user has specified a classpath. | |||
* @since Ant 1.7 | |||
*/ | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, | |||
boolean filtertrace, boolean haltOnFailure, | |||
boolean showOutput, boolean logTestListenerEvents, | |||
ClassLoader loader) { | |||
JUnitTestRunner.filtertrace = filtertrace; | |||
this.junitTest = test; | |||
this.haltOnError = haltOnError; | |||
this.haltOnFailure = haltOnFailure; | |||
this.showOutput = showOutput; | |||
this.logTestListenerEvents = logTestListenerEvents; | |||
this.loader = loader; | |||
} | |||
private PrintStream savedOut = null; | |||
public void run() { | |||
res = new TestResult(); | |||
res.addListener(this); | |||
@@ -217,7 +247,6 @@ public class JUnitTestRunner implements TestListener { | |||
ByteArrayOutputStream outStrm = new ByteArrayOutputStream(); | |||
systemOut = new PrintStream(outStrm); | |||
PrintStream savedOut = null; | |||
PrintStream savedErr = null; | |||
if (forked) { | |||
@@ -295,6 +324,7 @@ public class JUnitTestRunner implements TestListener { | |||
junitTest.setRunTime(0); | |||
} else { | |||
try { | |||
logTestListenerEvent("tests to run: " + suite.countTestCases()); | |||
suite.run(res); | |||
} finally { | |||
junitTest.setCounts(res.runCount(), res.failureCount(), | |||
@@ -344,6 +374,8 @@ public class JUnitTestRunner implements TestListener { | |||
* <p>A new Test is started. | |||
*/ | |||
public void startTest(Test t) { | |||
String testName = JUnitVersionHelper.getTestCaseName(t); | |||
logTestListenerEvent("startTest(" + testName + ")"); | |||
} | |||
/** | |||
@@ -352,6 +384,17 @@ public class JUnitTestRunner implements TestListener { | |||
* <p>A Test is finished. | |||
*/ | |||
public void endTest(Test test) { | |||
String testName = JUnitVersionHelper.getTestCaseName(test); | |||
logTestListenerEvent("endTest(" + testName + ")"); | |||
} | |||
private void logTestListenerEvent(String msg) { | |||
PrintStream out = forked ? savedOut : System.out; | |||
if (logTestListenerEvents) { | |||
out.flush(); | |||
out.println(JUnitTask.TESTLISTENER_PREFIX + msg); | |||
out.flush(); | |||
} | |||
} | |||
/** | |||
@@ -360,6 +403,8 @@ public class JUnitTestRunner implements TestListener { | |||
* <p>A Test failed. | |||
*/ | |||
public void addFailure(Test test, Throwable t) { | |||
String testName = JUnitVersionHelper.getTestCaseName(test); | |||
logTestListenerEvent("addFailure(" + testName + ", " + t.getMessage() + ")"); | |||
if (haltOnFailure) { | |||
res.stop(); | |||
} | |||
@@ -380,6 +425,8 @@ public class JUnitTestRunner implements TestListener { | |||
* <p>An error occurred while running the test. | |||
*/ | |||
public void addError(Test test, Throwable t) { | |||
String testName = JUnitVersionHelper.getTestCaseName(test); | |||
logTestListenerEvent("addError(" + testName + ", " + t.getMessage() + ")"); | |||
if (haltOnError) { | |||
res.stop(); | |||
} | |||
@@ -395,7 +442,9 @@ public class JUnitTestRunner implements TestListener { | |||
} | |||
protected void handleOutput(String output) { | |||
if (systemOut != null) { | |||
if (!logTestListenerEvents && output.startsWith(JUnitTask.TESTLISTENER_PREFIX)) | |||
; // ignore | |||
else if (systemOut != null) { | |||
systemOut.print(output); | |||
} | |||
} | |||
@@ -478,6 +527,9 @@ public class JUnitTestRunner implements TestListener { | |||
* <tr><td>showoutput</td><td>send output to System.err/.out as | |||
* well as to the formatters?</td><td>false</td></tr> | |||
* | |||
* <tr><td>logtestlistenerevents</td><td>log TestListener events to | |||
* System.out.</td><td>false</td></tr> | |||
* | |||
* </table> | |||
*/ | |||
public static void main(String[] args) throws IOException { | |||
@@ -486,6 +538,7 @@ public class JUnitTestRunner implements TestListener { | |||
boolean stackfilter = true; | |||
Properties props = new Properties(); | |||
boolean showOut = false; | |||
boolean logTestListenerEvents = false; | |||
String noCrashFile = null; | |||
if (args.length == 0) { | |||
@@ -521,6 +574,8 @@ public class JUnitTestRunner implements TestListener { | |||
in.close(); | |||
} else if (args[i].startsWith("showoutput=")) { | |||
showOut = Project.toBoolean(args[i].substring(11)); | |||
} else if (args[i].startsWith("logtestlistenerevents=")) { | |||
logTestListenerEvents = Project.toBoolean(args[i].substring(22)); | |||
} | |||
} | |||
@@ -548,7 +603,7 @@ public class JUnitTestRunner implements TestListener { | |||
t.setTodir(new File(st.nextToken())); | |||
t.setOutfile(st.nextToken()); | |||
code = launch(t, haltError, stackfilter, haltFail, | |||
showOut, props); | |||
showOut, logTestListenerEvents, props); | |||
errorOccured = (code == ERRORS); | |||
failureOccured = (code != SUCCESS); | |||
if (errorOccured || failureOccured) { | |||
@@ -570,7 +625,8 @@ public class JUnitTestRunner implements TestListener { | |||
} | |||
} else { | |||
returnCode = launch(new JUnitTest(args[0]), haltError, | |||
stackfilter, haltFail, showOut, props); | |||
stackfilter, haltFail, showOut, | |||
logTestListenerEvents, props); | |||
} | |||
registerNonCrash(noCrashFile); | |||
@@ -668,10 +724,12 @@ public class JUnitTestRunner implements TestListener { | |||
*/ | |||
private static int launch(JUnitTest t, boolean haltError, | |||
boolean stackfilter, boolean haltFail, | |||
boolean showOut, Properties props) { | |||
boolean showOut, boolean logTestListenerEvents, | |||
Properties props) { | |||
t.setProperties(props); | |||
JUnitTestRunner runner = | |||
new JUnitTestRunner(t, haltError, stackfilter, haltFail, showOut); | |||
new JUnitTestRunner(t, haltError, stackfilter, haltFail, showOut, | |||
logTestListenerEvents); | |||
runner.forked = true; | |||
transferFormatters(runner, t); | |||
@@ -0,0 +1,79 @@ | |||
/* | |||
* Copyright 2005 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 org.apache.tools.ant.BuildFileTest; | |||
public class JUnitTestListenerTest extends BuildFileTest { | |||
// The captureToSummary test writes to stdout and stderr, good for | |||
// verifying that the TestListener support doesn't break anything. | |||
private static final String PASS_TEST_TARGET = "captureToSummary"; | |||
// testNoCrash is the test invoked by the captureToSummary's junit task | |||
private static final String PASS_TEST = "testNoCrash"; | |||
public JUnitTestListenerTest(String name) { | |||
super(name); | |||
} | |||
public void setUp() { | |||
configureProject("src/etc/testcases/taskdefs/optional/junit.xml"); | |||
} | |||
public void testFullLogOutput() { | |||
executeTarget(PASS_TEST_TARGET); | |||
assertTrue("expecting full log to have BuildListener events", | |||
hasBuildListenerEvents(getFullLog())); | |||
} | |||
public void testNoLogOutput() { | |||
executeTarget(PASS_TEST_TARGET); | |||
assertFalse("expecting log to not have BuildListener events", | |||
hasBuildListenerEvents(getLog())); | |||
} | |||
public void testTestCountFired() { | |||
executeTarget(PASS_TEST_TARGET); | |||
assertTrue("expecting test count message", | |||
hasEventMessage(JUnitTask.TESTLISTENER_PREFIX + | |||
"tests to run: ")); | |||
} | |||
public void testStartTestFired() { | |||
executeTarget(PASS_TEST_TARGET); | |||
assertTrue("expecting test started message", | |||
hasEventMessage(JUnitTask.TESTLISTENER_PREFIX + | |||
"startTest(" + PASS_TEST + ")")); | |||
} | |||
public void testEndTestFired() { | |||
executeTarget(PASS_TEST_TARGET); | |||
assertTrue("expecting test ended message", | |||
hasEventMessage(JUnitTask.TESTLISTENER_PREFIX + | |||
"endTest(" + PASS_TEST + ")")); | |||
} | |||
private boolean hasBuildListenerEvents(String log) { | |||
return log.indexOf(JUnitTask.TESTLISTENER_PREFIX) >= 0; | |||
} | |||
private boolean hasEventMessage(String eventPrefix) { | |||
return getFullLog().indexOf(eventPrefix) >= 0; | |||
} | |||
} |