Browse Source

Give better information in case of timeout for JUnit test,as requested in Bug 39946.

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@420194 13f79535-47bb-0310-9956-ffa450edef68
master
Jacobus Martinus Kruithof 19 years ago
parent
commit
44ecc125fa
4 changed files with 111 additions and 31 deletions
  1. +23
    -12
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
  2. +2
    -1
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
  3. +10
    -4
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
  4. +76
    -14
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java

+ 23
- 12
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java View File

@@ -17,9 +17,11 @@


package org.apache.tools.ant.taskdefs.optional.junit; package org.apache.tools.ant.taskdefs.optional.junit;


import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@@ -35,6 +37,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Vector; import java.util.Vector;

import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
@@ -42,6 +45,7 @@ import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Execute; import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.taskdefs.ExecuteWatchdog; import org.apache.tools.ant.taskdefs.ExecuteWatchdog;
import org.apache.tools.ant.taskdefs.LogOutputStream; import org.apache.tools.ant.taskdefs.LogOutputStream;
import org.apache.tools.ant.taskdefs.PumpStreamHandler;
import org.apache.tools.ant.types.Assertions; import org.apache.tools.ant.types.Assertions;
import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.CommandlineJava; import org.apache.tools.ant.types.CommandlineJava;
@@ -52,7 +56,6 @@ import org.apache.tools.ant.types.Permissions;
import org.apache.tools.ant.types.PropertySet; import org.apache.tools.ant.types.PropertySet;
import org.apache.tools.ant.util.FileUtils; import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.LoaderUtils; import org.apache.tools.ant.util.LoaderUtils;
import org.apache.tools.ant.taskdefs.PumpStreamHandler;


/** /**
* Runs JUnit tests. * Runs JUnit tests.
@@ -938,7 +941,7 @@ public class JUnitTask extends Task {
} }


File vmWatcher = createTempPropertiesFile("junitvmwatcher"); File vmWatcher = createTempPropertiesFile("junitvmwatcher");
formatterArg.append("nocrashfile=");
formatterArg.append("crashfile=");
formatterArg.append(vmWatcher); formatterArg.append(vmWatcher);
cmd.createArgument().setValue(formatterArg.toString()); cmd.createArgument().setValue(formatterArg.toString());


@@ -988,12 +991,20 @@ public class JUnitTask extends Task {
} catch (IOException e) { } catch (IOException e) {
throw new BuildException("Process fork failed.", e, getLocation()); throw new BuildException("Process fork failed.", e, getLocation());
} finally { } finally {
String vmCrashString = "unknown";
try {
BufferedReader br = new BufferedReader(new FileReader(vmWatcher));
vmCrashString = br.readLine();
} catch (Exception e) {
e.printStackTrace();
// ignored.
}
if (watchdog != null && watchdog.killedProcess()) { if (watchdog != null && watchdog.killedProcess()) {
result.timedOut = true; result.timedOut = true;
logTimeout(feArray, test);
} else if (vmWatcher.length() == 0) {
logTimeout(feArray, test, vmCrashString);
} else if (!"terminated successfully".equals(vmCrashString)) {
result.crashed = true; result.crashed = true;
logVmCrash(feArray, test);
logVmCrash(feArray, test, vmCrashString);
} }
vmWatcher.delete(); vmWatcher.delete();


@@ -1335,8 +1346,8 @@ public class JUnitTask extends Task {
* @since Ant 1.5.2 * @since Ant 1.5.2
*/ */


private void logTimeout(FormatterElement[] feArray, JUnitTest test) {
logVmExit(feArray, test, "Timeout occurred. Please note the time in the report does not reflect the time until the timeout.");
private void logTimeout(FormatterElement[] feArray, JUnitTest test, String testCase) {
logVmExit(feArray, test, "Timeout occurred. Please note the time in the report does not reflect the time until the timeout.", testCase);
} }


/** /**
@@ -1346,8 +1357,8 @@ public class JUnitTask extends Task {
* *
* @since Ant 1.7 * @since Ant 1.7
*/ */
private void logVmCrash(FormatterElement[] feArray, JUnitTest test) {
logVmExit(feArray, test, "Forked Java VM exited abnormally. Please note the time in the report does not reflect the time until the VM exit.");
private void logVmCrash(FormatterElement[] feArray, JUnitTest test, String testCase) {
logVmExit(feArray, test, "Forked Java VM exited abnormally. Please note the time in the report does not reflect the time until the VM exit.", testCase);
} }


/** /**
@@ -1357,7 +1368,7 @@ public class JUnitTask extends Task {
* @since Ant 1.7 * @since Ant 1.7
*/ */
private void logVmExit(FormatterElement[] feArray, JUnitTest test, private void logVmExit(FormatterElement[] feArray, JUnitTest test,
String message) {
String message, String testCase) {
try { try {
log("Using System properties " + System.getProperties(), log("Using System properties " + System.getProperties(),
Project.MSG_VERBOSE); Project.MSG_VERBOSE);
@@ -1380,7 +1391,7 @@ public class JUnitTask extends Task {
if (outFile != null && formatter != null) { if (outFile != null && formatter != null) {
try { try {
OutputStream out = new FileOutputStream(outFile); OutputStream out = new FileOutputStream(outFile);
delegate.addVmExit(test, formatter, out, message);
delegate.addVmExit(test, formatter, out, message, testCase);
} catch (IOException e) { } catch (IOException e) {
// ignore // ignore
} }
@@ -1390,7 +1401,7 @@ public class JUnitTask extends Task {
JUnitTaskMirror.SummaryJUnitResultFormatterMirror f = JUnitTaskMirror.SummaryJUnitResultFormatterMirror f =
delegate.newSummaryJUnitResultFormatter(); delegate.newSummaryJUnitResultFormatter();
f.setWithOutAndErr("withoutanderr".equalsIgnoreCase(summaryValue)); f.setWithOutAndErr("withoutanderr".equalsIgnoreCase(summaryValue));
delegate.addVmExit(test, f, getDefaultOutput(), message);
delegate.addVmExit(test, f, getDefaultOutput(), message, testCase);
} }
} finally { } finally {
if (classLoader != null) { if (classLoader != null) {


+ 2
- 1
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java View File

@@ -41,7 +41,8 @@ import org.apache.tools.ant.types.Permissions;
public interface JUnitTaskMirror { public interface JUnitTaskMirror {
void addVmExit(JUnitTest test, JUnitResultFormatterMirror formatter, void addVmExit(JUnitTest test, JUnitResultFormatterMirror formatter,
OutputStream out, String message);
OutputStream out, String message, String testCase);
JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest test, boolean haltOnError, JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest test, boolean haltOnError,
boolean filterTrace, boolean haltOnFailure, boolean showOutput, boolean filterTrace, boolean haltOnFailure, boolean showOutput,


+ 10
- 4
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java View File

@@ -39,14 +39,14 @@ public final class JUnitTaskMirrorImpl implements JUnitTaskMirror {
} }


public void addVmExit(JUnitTest test, JUnitTaskMirror.JUnitResultFormatterMirror aFormatter, public void addVmExit(JUnitTest test, JUnitTaskMirror.JUnitResultFormatterMirror aFormatter,
OutputStream out, final String message) {
OutputStream out, String message, String testCase) {
JUnitResultFormatter formatter = (JUnitResultFormatter) aFormatter; JUnitResultFormatter formatter = (JUnitResultFormatter) aFormatter;
formatter.setOutput(out); formatter.setOutput(out);
formatter.startTestSuite(test); formatter.startTestSuite(test);
//the trick to integrating test output to the formatter, is to //the trick to integrating test output to the formatter, is to
//create a special test class that asserts an error //create a special test class that asserts an error
//and tell the formatter that it raised. //and tell the formatter that it raised.
TestCase t = new VmExitErrorTest(message, test);
TestCase t = new VmExitErrorTest(message, test, testCase);
formatter.startTest(t); formatter.startTest(t);
formatter.addError(t, new AssertionFailedError(message)); formatter.addError(t, new AssertionFailedError(message));
formatter.endTestSuite(test); formatter.endTestSuite(test);
@@ -67,10 +67,12 @@ public final class JUnitTaskMirrorImpl implements JUnitTaskMirror {


private String message; private String message;
private JUnitTest test; private JUnitTest test;
private String testCase;


VmExitErrorTest(String aMessage, JUnitTest anOriginalTest) {
VmExitErrorTest(String aMessage, JUnitTest anOriginalTest, String aTestCase) {
message = aMessage; message = aMessage;
test = anOriginalTest; test = anOriginalTest;
testCase = aTestCase;
} }


public int countTestCases() { public int countTestCases() {
@@ -81,12 +83,16 @@ public final class JUnitTaskMirrorImpl implements JUnitTaskMirror {
throw new AssertionFailedError(message); throw new AssertionFailedError(message);
} }


public String getName() {
return testCase;
}

String getClassName() { String getClassName() {
return test.getName(); return test.getName();
} }


public String toString() { public String toString() {
return test.getName();
return test.getName()+":"+testCase;
} }
} }
} }

+ 76
- 14
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java View File

@@ -22,7 +22,9 @@ 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.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringReader; import java.io.StringReader;
@@ -151,6 +153,12 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
/** Turned on if we are using JUnit 4 for this test suite. see #38811 */ /** Turned on if we are using JUnit 4 for this test suite. see #38811 */
private boolean junit4; private boolean junit4;


/**
* The file used to indicate that the build crashed.
* File will be empty in case the build did not crash.
*/
private static String crashFile = null;
/** /**
* Constructor for fork=true or when the user hasn't specified a * Constructor for fork=true or when the user hasn't specified a
* classpath. * classpath.
@@ -574,7 +582,7 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
Properties props = new Properties(); Properties props = new Properties();
boolean showOut = false; boolean showOut = false;
boolean logTestListenerEvents = false; boolean logTestListenerEvents = 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");
@@ -593,8 +601,9 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
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("crashfile=")) {
crashFile = args[i].substring(12);
registerTestCase("BeforeFirstTest");
} else if (args[i].startsWith("formatter=")) { } else if (args[i].startsWith("formatter=")) {
try { try {
createAndStoreFormatter(args[i].substring(10)); createAndStoreFormatter(args[i].substring(10));
@@ -644,7 +653,7 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
if (errorOccurred || failureOccurred) { if (errorOccurred || failureOccurred) {
if ((errorOccurred && haltError) if ((errorOccurred && haltError)
|| (failureOccurred && haltFail)) { || (failureOccurred && haltFail)) {
registerNonCrash(noCrashFile);
registerNonCrash();
System.exit(code); System.exit(code);
} else { } else {
if (code > returnCode) { if (code > returnCode) {
@@ -664,7 +673,7 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
logTestListenerEvents, props); logTestListenerEvents, props);
} }


registerNonCrash(noCrashFile);
registerNonCrash();
System.exit(returnCode); System.exit(returnCode);
} }


@@ -672,6 +681,37 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR


private static void transferFormatters(JUnitTestRunner runner, private static void transferFormatters(JUnitTestRunner runner,
JUnitTest test) { JUnitTest test) {
runner.addFormatter(new JUnitResultFormatter() {

public void startTestSuite(JUnitTest suite) throws BuildException {
}

public void endTestSuite(JUnitTest suite) throws BuildException {
}

public void setOutput(OutputStream out) {
}

public void setSystemOutput(String out) {
}

public void setSystemError(String err) {
}

public void addError(Test arg0, Throwable arg1) {
}

public void addFailure(Test arg0, AssertionFailedError arg1) {
}

public void endTest(Test arg0) {
}

public void startTest(Test arg0) {
System.out.println(this.getClass().getName() + ":" + arg0);
registerTestCase(JUnitVersionHelper.getTestCaseName(arg0));
}
});
for (int i = 0; i < fromCmdLine.size(); i++) { for (int i = 0; i < fromCmdLine.size(); i++) {
FormatterElement fe = (FormatterElement) fromCmdLine.elementAt(i); FormatterElement fe = (FormatterElement) fromCmdLine.elementAt(i);
if (multipleTests && fe.getUseFile()) { if (multipleTests && fe.getUseFile()) {
@@ -775,23 +815,45 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
/** /**
* @since Ant 1.7 * @since Ant 1.7
*/ */
private static void registerNonCrash(String noCrashFile)
throws IOException {
if (noCrashFile != null) {
FileOutputStream out = null;
private static void registerNonCrash()
throws IOException {
if (crashFile != null) {
FileWriter out = null;
try { try {
out = new FileOutputStream(noCrashFile);
out.write(0);
out = new FileWriter(crashFile);
out.write("terminated successfully\n");
out.flush(); out.flush();
} finally { } finally {
out.close();
if (out != null) {
out.close();
}
}
}
}

private static void registerTestCase(String testCase) {
if (crashFile != null) {
try {
FileWriter out = null;
try {
out = new FileWriter(crashFile);
out.write(testCase + "\n");
out.flush();
} finally {
if (out != null) {
out.close();
}
}
} catch (IOException e) {
// ignored.
} }
} }
} }


/** /**
* Modifies a TestListener when running JUnit 4:
* treats AssertionFailedError as a failure not an error.
* Modifies a TestListener when running JUnit 4: treats AssertionFailedError
* as a failure not an error.
*
* @since Ant 1.7 * @since Ant 1.7
*/ */
private TestListener wrapListener(final TestListener testListener) { private TestListener wrapListener(final TestListener testListener) {


Loading…
Cancel
Save