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 | ||||