down when the VM runs multiple tests. The old code used a TestFormatter and detected a crash if the expected output had not been written. If multiple tests get run in one VM, the TestRunner ignores the filename that has been passed in - and the task doesn't find any output. Even if it didn't ignore the file name, a single non-crashing test would have made the task think, the VM finished in a healthy way. Make the crash-detection more explcit and let the TestRunner cooperate more than before. This bug has been presented by Gump in cooperation with the Hivemind build. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276942 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1,108 +0,0 @@ | |||||
/* | |||||
* Copyright 2004 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 junit.framework.AssertionFailedError; | |||||
import junit.framework.Test; | |||||
import org.apache.tools.ant.BuildException; | |||||
/** | |||||
* writes a single 0 byte to the given output stream in endTestSuite. | |||||
*/ | |||||
public class ForkedVMWatcher implements JUnitResultFormatter { | |||||
/** | |||||
* OutputStream to write to. | |||||
*/ | |||||
private OutputStream out; | |||||
/** | |||||
* Empty | |||||
*/ | |||||
public ForkedVMWatcher() { | |||||
} | |||||
/** | |||||
* Empty | |||||
*/ | |||||
public void startTestSuite(JUnitTest suite) { | |||||
} | |||||
/** | |||||
* Empty | |||||
*/ | |||||
public void startTest(Test t) { | |||||
} | |||||
/** | |||||
* Empty | |||||
*/ | |||||
public void endTest(Test test) { | |||||
} | |||||
/** | |||||
* Empty | |||||
*/ | |||||
public void addFailure(Test test, Throwable t) { | |||||
} | |||||
/** | |||||
* Interface TestListener for JUnit > 3.4. | |||||
* | |||||
* <p>A Test failed. | |||||
*/ | |||||
public void addFailure(Test test, AssertionFailedError t) { | |||||
addFailure(test, (Throwable) t); | |||||
} | |||||
/** | |||||
* Empty | |||||
*/ | |||||
public void addError(Test test, Throwable t) { | |||||
} | |||||
/** | |||||
* Empty | |||||
*/ | |||||
public void setSystemOutput(String out) { | |||||
} | |||||
/** | |||||
* Empty | |||||
*/ | |||||
public void setSystemError(String err) { | |||||
} | |||||
public void setOutput(OutputStream out) { | |||||
this.out = out; | |||||
} | |||||
/** | |||||
* The whole testsuite ended. | |||||
*/ | |||||
public void endTestSuite(JUnitTest suite) throws BuildException { | |||||
try { | |||||
out.write(0); | |||||
out.flush(); | |||||
} catch (IOException ioex) { | |||||
throw new BuildException("Unable to write output", ioex); | |||||
} finally { | |||||
if (out != System.out && out != System.err) { | |||||
try { | |||||
out.close(); | |||||
} catch (IOException e) { | |||||
// ignore | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -847,9 +847,7 @@ public class JUnitTask extends Task { | |||||
} | } | ||||
File vmWatcher = createTempPropertiesFile("junitvmwatcher"); | File vmWatcher = createTempPropertiesFile("junitvmwatcher"); | ||||
formatterArg.append("formatter="); | |||||
formatterArg.append(ForkedVMWatcher.class.getName()); | |||||
formatterArg.append(","); | |||||
formatterArg.append("nocrashfile="); | |||||
formatterArg.append(vmWatcher); | formatterArg.append(vmWatcher); | ||||
cmd.createArgument().setValue(formatterArg.toString()); | cmd.createArgument().setValue(formatterArg.toString()); | ||||
@@ -21,6 +21,7 @@ import java.io.BufferedReader; | |||||
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.io.File; | import java.io.File; | ||||
import java.io.FileInputStream; | import java.io.FileInputStream; | ||||
import java.io.FileOutputStream; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.PrintStream; | import java.io.PrintStream; | ||||
import java.io.PrintWriter; | import java.io.PrintWriter; | ||||
@@ -475,6 +476,7 @@ public class JUnitTestRunner implements TestListener { | |||||
boolean stackfilter = true; | boolean stackfilter = true; | ||||
Properties props = new Properties(); | Properties props = new Properties(); | ||||
boolean showOut = false; | boolean showOut = false; | ||||
String noCrashFile = null; | |||||
if (args.length == 0) { | if (args.length == 0) { | ||||
System.err.println("required argument TestClassName missing"); | System.err.println("required argument TestClassName missing"); | ||||
@@ -493,6 +495,8 @@ public class JUnitTestRunner implements TestListener { | |||||
haltFail = Project.toBoolean(args[i].substring(14)); | haltFail = Project.toBoolean(args[i].substring(14)); | ||||
} else if (args[i].startsWith("filtertrace=")) { | } else if (args[i].startsWith("filtertrace=")) { | ||||
stackfilter = Project.toBoolean(args[i].substring(12)); | stackfilter = Project.toBoolean(args[i].substring(12)); | ||||
} else if (args[i].startsWith("nocrashfile=")) { | |||||
noCrashFile = args[i].substring(12); | |||||
} else if (args[i].startsWith("formatter=")) { | } else if (args[i].startsWith("formatter=")) { | ||||
try { | try { | ||||
createAndStoreFormatter(args[i].substring(10)); | createAndStoreFormatter(args[i].substring(10)); | ||||
@@ -540,6 +544,7 @@ public class JUnitTestRunner implements TestListener { | |||||
if (errorOccured || failureOccured ) { | if (errorOccured || failureOccured ) { | ||||
if ((errorOccured && haltError) | if ((errorOccured && haltError) | ||||
|| (failureOccured && haltFail)) { | || (failureOccured && haltFail)) { | ||||
registerNonCrash(noCrashFile); | |||||
System.exit(code); | System.exit(code); | ||||
} else { | } else { | ||||
if (code > returnCode) { | if (code > returnCode) { | ||||
@@ -558,6 +563,7 @@ public class JUnitTestRunner implements TestListener { | |||||
stackfilter, haltFail, showOut, props); | stackfilter, haltFail, showOut, props); | ||||
} | } | ||||
registerNonCrash(noCrashFile); | |||||
System.exit(returnCode); | System.exit(returnCode); | ||||
} | } | ||||
@@ -655,4 +661,21 @@ public class JUnitTestRunner implements TestListener { | |||||
runner.run(); | runner.run(); | ||||
return runner.getRetCode(); | return runner.getRetCode(); | ||||
} | } | ||||
/** | |||||
* @since Ant 1.7 | |||||
*/ | |||||
private static void registerNonCrash(String noCrashFile) | |||||
throws IOException { | |||||
if (noCrashFile != null) { | |||||
FileOutputStream out = null; | |||||
try { | |||||
out = new FileOutputStream(noCrashFile); | |||||
out.write(0); | |||||
out.flush(); | |||||
} finally { | |||||
out.close(); | |||||
} | |||||
} | |||||
} | |||||
} // JUnitTestRunner | } // JUnitTestRunner |