diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java index eaaee4dc8..c9f097398 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java @@ -60,12 +60,13 @@ import java.util.Vector; /** * Baseclass for BatchTest and JUnitTest. * - * @author Stefan Bodewig + * @author Stefan Bodewig * @author Stephane Bailliez */ public abstract class BaseTest { protected boolean haltOnError = false; protected boolean haltOnFail = false; + protected boolean filtertrace = true; protected boolean fork = false; protected String ifProperty = null; protected String unlessProperty = null; @@ -76,6 +77,14 @@ public abstract class BaseTest { protected String failureProperty; protected String errorProperty; + public void setFiltertrace(boolean value) { + filtertrace = value; + } + + public boolean getFiltertrace() { + return filtertrace; + } + public void setFork(boolean value) { fork = value; } @@ -116,12 +125,12 @@ public abstract class BaseTest { * Sets the destination directory. */ public void setTodir(File destDir) { - this.destDir = destDir; + this.destDir = destDir; } /** * @return the destination directory as an absolute path if it exists - * otherwise return null + * otherwise return null */ public String getTodir(){ if (destDir != null){ @@ -133,15 +142,15 @@ public abstract class BaseTest { public java.lang.String getFailureProperty() { return failureProperty; } - + public void setFailureProperty(String failureProperty) { this.failureProperty = failureProperty; } - + public java.lang.String getErrorProperty() { return errorProperty; } - + public void setErrorProperty(String errorProperty) { this.errorProperty = errorProperty; } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java index 9b000869f..292b7c177 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java @@ -199,6 +199,7 @@ public final class BatchTest extends BaseTest { test.setName(classname); test.setHaltonerror(this.haltOnError); test.setHaltonfailure(this.haltOnFail); + test.setFiltertrace(this.filtertrace); test.setFork(this.fork); test.setIf(this.ifProperty); test.setUnless(this.unlessProperty); diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java index cb8ccf503..5277ca98b 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java @@ -155,7 +155,23 @@ public class JUnitTask extends Task { private Integer timeout = null; private boolean summary = false; private String summaryValue = ""; + private boolean filtertrace = true; private JUnitTestRunner runner = null; + + /** + * Tells this task whether to smartly filter the stack frames of JUnit testcase + * errors and failures before reporting them. This property is applied on all + * BatchTest (batchtest) and JUnitTest (test) however it can possibly be + * overridden by their own properties. + * @param value false if it should not filter, otherwise true + */ + public void setFiltertrace(boolean value) { + Enumeration enum = allTests(); + while (enum.hasMoreElements()) { + BaseTest test = (BaseTest) enum.nextElement(); + test.setFiltertrace(value); + } + } /** * Tells this task to halt when there is an error in a test. @@ -361,7 +377,7 @@ public class JUnitTask extends Task { /** * Adds the jars or directories containing Ant, this task and * JUnit to the classpath - this should make the forked JVM work - * without having to specify the directly. + * without having to specify them directly. */ public void init() { addClasspathEntry("/junit/framework/TestCase.class"); @@ -447,6 +463,7 @@ public class JUnitTask extends Task { cmd.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner"); cmd.createArgument().setValue(test.getName()); + cmd.createArgument().setValue("filtertrace=" + test.getFiltertrace()); cmd.createArgument().setValue("haltOnError=" + test.getHaltonerror()); cmd.createArgument().setValue("haltOnFailure=" + test.getHaltonfailure()); if (summary) { @@ -555,8 +572,7 @@ public class JUnitTask extends Task { // will cause trouble in JDK 1.1 if omitted cl.addSystemPackageRoot("org.apache.tools.ant"); } - runner = new JUnitTestRunner(test, test.getHaltonerror(), test.getHaltonfailure(), cl); - + runner = new JUnitTestRunner(test, test.getHaltonerror(), test.getFiltertrace(), test.getHaltonfailure(), cl); if (summary) { log("Running " + test.getName(), Project.MSG_INFO); diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java index 91183bcb4..f1ce16957 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java @@ -100,10 +100,11 @@ public class JUnitTest extends BaseTest { this.name = name; } - public JUnitTest(String name, boolean haltOnError, boolean haltOnFailure) { + public JUnitTest(String name, boolean haltOnError, boolean haltOnFailure, boolean filtertrace) { this.name = name; this.haltOnError = haltOnError; - this.haltOnFail = haltOnFail; + this.haltOnFail = haltOnFailure; + this.filtertrace = filtertrace; } /** diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java index 340958859..b323abcbb 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java @@ -64,7 +64,11 @@ import junit.framework.Test; import junit.framework.TestSuite; import junit.framework.AssertionFailedError; import java.lang.reflect.Method; +import java.io.BufferedReader; import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.FileInputStream; @@ -121,6 +125,24 @@ public class JUnitTestRunner implements TestListener { */ private TestResult res; + /** + * Do we filter junit.*.* stack frames out of failure and error exceptions. + */ + private static boolean filtertrace = true; + + private final static String[] DEFAULT_TRACE_FILTERS = new String[] { + "junit.framework.TestCase", + "junit.framework.TestResult", + "junit.framework.TestSuite", + "junit.framework.Assert.", // don't filter AssertionFailure + "junit.swingui.TestRunner", + "junit.awtui.TestRunner", + "junit.textui.TestRunner", + "java.lang.reflect.Method.invoke(", + "org.apache.tools.ant." + }; + + /** * Do we stop on errors. */ @@ -161,16 +183,18 @@ public class JUnitTestRunner implements TestListener { * Constructor for fork=true or when the user hasn't specified a * classpath. */ - public JUnitTestRunner(JUnitTest test, boolean haltOnError, + public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, boolean haltOnFailure) { - this(test, haltOnError, haltOnFailure, null); + this(test, haltOnError, filtertrace, haltOnFailure, null); } /** * Constructor to use when the user has specified a classpath. */ - public JUnitTestRunner(JUnitTest test, boolean haltOnError, + public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, boolean haltOnFailure, ClassLoader loader) { + //JUnitTestRunner.filtertrace = filtertrace; + this.filtertrace = filtertrace; this.junitTest = test; this.haltOnError = haltOnError; this.haltOnFailure = haltOnFailure; @@ -378,6 +402,7 @@ public class JUnitTestRunner implements TestListener { boolean exitAtEnd = true; boolean haltError = false; boolean haltFail = false; + boolean stackfilter = true; Properties props = new Properties(); if (args.length == 0) { @@ -390,6 +415,8 @@ public class JUnitTestRunner implements TestListener { haltError = Project.toBoolean(args[i].substring(12)); } else if (args[i].startsWith("haltOnFailure=")) { haltFail = Project.toBoolean(args[i].substring(14)); + } else if (args[i].startsWith("filtertrace=")) { + stackfilter = Project.toBoolean(args[i].substring(12)); } else if (args[i].startsWith("formatter=")) { try { createAndStoreFormatter(args[i].substring(10)); @@ -405,7 +432,7 @@ public class JUnitTestRunner implements TestListener { } JUnitTest t = new JUnitTest(args[0]); - + // Add/overlay system properties on the properties from the Ant project Hashtable p = System.getProperties(); for (Enumeration enum = p.keys(); enum.hasMoreElements(); ) { @@ -414,7 +441,7 @@ public class JUnitTestRunner implements TestListener { } t.setProperties(props); - JUnitTestRunner runner = new JUnitTestRunner(t, haltError, haltFail); + JUnitTestRunner runner = new JUnitTestRunner(t, haltError, stackfilter, haltFail); transferFormatters(runner); runner.run(); System.exit(runner.getRetCode()); @@ -443,5 +470,53 @@ public class JUnitTestRunner implements TestListener { } fromCmdLine.addElement(fe.createFormatter()); } + + /** + * Returns a filtered stack trace. + * This is ripped out of junit.runner.BaseTestRunner. + * Scott M. Stirling. + */ + public static String getFilteredTrace(Throwable t) { + StringWriter stringWriter = new StringWriter(); + PrintWriter writer = new PrintWriter(stringWriter); + t.printStackTrace(writer); + StringBuffer buffer = stringWriter.getBuffer(); + String trace = buffer.toString(); + return JUnitTestRunner.filterStack(trace); + } + /** + * Filters stack frames from internal JUnit and Ant classes + */ + public static String filterStack(String stack) { + if (!filtertrace) { + return stack; + } + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + StringReader sr = new StringReader(stack); + BufferedReader br = new BufferedReader(sr); + + String line; + try { + while ((line = br.readLine()) != null) { + if (!filterLine(line)) { + pw.println(line); + } + } + } catch (Exception IOException) { + return stack; // return the stack unfiltered + } + return sw.toString(); + } + + private static boolean filterLine(String line) { + for (int i = 0; i < DEFAULT_TRACE_FILTERS.length; i++) { + if (line.indexOf(DEFAULT_TRACE_FILTERS[i]) > 0) { + return true; + } + } + return false; + } + } // JUnitTestRunner diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java index a2da3117f..5fc75696f 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java @@ -248,7 +248,8 @@ public class PlainJUnitResultFormatter implements JUnitResultFormatter { wri.println(type); wri.println(t.getMessage()); - t.printStackTrace(wri); + String strace = JUnitTestRunner.getFilteredTrace(t); + wri.print(strace); wri.println(""); } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java index d2b2c34e5..a50b368c1 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java @@ -261,9 +261,8 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstan } nested.setAttribute(ATTR_TYPE, t.getClass().getName()); - StringWriter swr = new StringWriter(); - t.printStackTrace(new PrintWriter(swr, true)); - Text trace = doc.createTextNode(swr.toString()); + String strace = JUnitTestRunner.getFilteredTrace(t); + Text trace = doc.createTextNode(strace); nested.appendChild(trace); }