From c58f8e6e7a80372127af34f7ef9c9bd94d9c221b Mon Sep 17 00:00:00 2001 From: Stephane Bailliez Date: Sun, 9 Dec 2001 13:38:18 +0000 Subject: [PATCH] Patch from Scott Stirling that allows stack trace filtering for formatters. It will filter out those unneeded frame from Ant and JUnit so the stack will be much more readable. nb: Looks like the JUnit task need serious refactoring since we have been adding feature incrementally. It starts to be a real mess, I can barely read my own code :-( git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270099 13f79535-47bb-0310-9956-ffa450edef68 --- .../ant/taskdefs/optional/junit/BaseTest.java | 21 +++-- .../taskdefs/optional/junit/BatchTest.java | 1 + .../taskdefs/optional/junit/JUnitTask.java | 22 ++++- .../taskdefs/optional/junit/JUnitTest.java | 5 +- .../optional/junit/JUnitTestRunner.java | 85 +++++++++++++++++-- .../junit/PlainJUnitResultFormatter.java | 3 +- .../junit/XMLJUnitResultFormatter.java | 5 +- 7 files changed, 122 insertions(+), 20 deletions(-) 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); }