From b6f240bdfc9b54e0d0f609adcd56d83f4f845c93 Mon Sep 17 00:00:00 2001 From: Kevin Cooney Date: Sun, 22 Jan 2017 22:46:21 -0800 Subject: [PATCH] Move trimStackTrace() to Throwables. --- .../java/org/junit/internal/StackTraces.java | 150 ------------------ .../java/org/junit/internal/Throwables.java | 141 ++++++++++++++++ .../junit/runner/notification/Failure.java | 3 +- .../tests/running/methods/TimeoutTest.java | 1 - 4 files changed, 142 insertions(+), 153 deletions(-) delete mode 100644 src/main/java/org/junit/internal/StackTraces.java diff --git a/src/main/java/org/junit/internal/StackTraces.java b/src/main/java/org/junit/internal/StackTraces.java deleted file mode 100644 index b7521c4d9404d..0000000000000 --- a/src/main/java/org/junit/internal/StackTraces.java +++ /dev/null @@ -1,150 +0,0 @@ -package org.junit.internal; - -import java.util.AbstractList; -import java.util.Arrays; -import java.util.List; - -/** - * Utility class for working with stack traces. - */ -public class StackTraces { - - private StackTraces() { - } - - /** - * Trims the stack trace of the given exception. Stack trace elements that are - * below the test method are filtered out. - */ - public static void trimStackTrace(Throwable exception) { - if (exception == null) { - throw new NullPointerException("exception cannot be null"); - } - - Throwable nextException = exception; - do { - exception = nextException; - nextException = null; - List stackTraceElements = Arrays.asList(exception.getStackTrace()); - int originalStackTraceDepth = stackTraceElements.size(); - int linesToInclude = originalStackTraceDepth; - - State state = State.PROCESSING_OTHER_CODE; - for (StackTraceElement stackTraceElement : asReversedList(stackTraceElements)) { - state = state.processStackTraceElement(stackTraceElement); - if (state == State.DONE) { - if (linesToInclude >= originalStackTraceDepth) { - return; - } - StackTraceElement[] newStackTrace = stackTraceElements - .subList(0, linesToInclude) - .toArray(new StackTraceElement[linesToInclude]); - exception.setStackTrace(newStackTrace); - nextException = exception.getCause(); - break; - } - linesToInclude--; - } - } while (nextException != null); - } - - private static List asReversedList(final List list) { - return new AbstractList() { - - @Override - public T get(int index) { - return list.get(list.size() - index - 1); - } - - @Override - public int size() { - return list.size(); - } - }; - } - - private enum State { - PROCESSING_OTHER_CODE { - @Override public State processLine(String methodName) { - if (isTestFrameworkMethod(methodName)) { - return PROCESSING_TEST_FRAMEWORK_CODE; - } - return this; - } - }, - PROCESSING_TEST_FRAMEWORK_CODE { - @Override public State processLine(String methodName) { - if (isReflectionMethod(methodName)) { - return PROCESSING_REFLECTION_CODE; - } else if (isTestFrameworkMethod(methodName)) { - return this; - } - return PROCESSING_OTHER_CODE; - } - }, - PROCESSING_REFLECTION_CODE { - @Override public State processLine(String methodName) { - if (isReflectionMethod(methodName)) { - return this; - } else if (isTestFrameworkMethod(methodName)) { - // This is here to handle TestCase.runBare() calling TestCase.runTest(). - return PROCESSING_TEST_FRAMEWORK_CODE; - } - return DONE; - } - }, - DONE { - @Override public State processLine(String methodName) { - return this; - } - }; - - /** Processes a stack trace element method name, possibly moving to a new state. */ - protected abstract State processLine(String methodName); - - /** Processes a stack trace element, possibly moving to a new state. */ - public final State processStackTraceElement(StackTraceElement element) { - return processLine(element.getClassName() + "." + element.getMethodName() + "()"); - } - } - - private static final String[] TEST_FRAMEWORK_METHOD_NAME_PREFIXES = { - "org.junit.runner.", - "org.junit.runners.", - "org.junit.experimental.runners.", - "org.junit.internal.", - "junit.", - }; - - private static final String[] TEST_FRAMEWORK_TEST_METHOD_NAME_PREFIXES = { - "org.junit.internal.StackTracesTest", - }; - - private static boolean isTestFrameworkMethod(String methodName) { - return isMatchingMethod(methodName, TEST_FRAMEWORK_METHOD_NAME_PREFIXES) && - !isMatchingMethod(methodName, TEST_FRAMEWORK_TEST_METHOD_NAME_PREFIXES); - } - - private static final String[] REFLECTION_METHOD_NAME_PREFIXES = { - "sun.reflect.", - "java.lang.reflect.", - "org.junit.rules.RunRules.(", - "org.junit.rules.RunRules.applyAll(", // calls TestRules - "org.junit.runners.BlockJUnit4ClassRunner.withMethodRules(", // calls MethodRules - "junit.framework.TestCase.runBare(", // runBare() directly calls setUp() and tearDown() - }; - - private static boolean isReflectionMethod(String methodName) { - return isMatchingMethod(methodName, REFLECTION_METHOD_NAME_PREFIXES); - } - - private static boolean isMatchingMethod(String methodName, String[] methodNamePrefixes) { - for (String methodNamePrefix : methodNamePrefixes) { - if (methodName.startsWith(methodNamePrefix)) { - return true; - } - } - - return false; - } -} diff --git a/src/main/java/org/junit/internal/Throwables.java b/src/main/java/org/junit/internal/Throwables.java index 92b8d2f8d467b..2b1ccdc76d0ea 100644 --- a/src/main/java/org/junit/internal/Throwables.java +++ b/src/main/java/org/junit/internal/Throwables.java @@ -2,6 +2,9 @@ import java.io.PrintWriter; import java.io.StringWriter; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.List; /** * Miscellaneous functions dealing with {@code Throwable}. @@ -54,4 +57,142 @@ public static String getStacktrace(Throwable exception) { exception.printStackTrace(writer); return stringWriter.toString(); } + + /** + * Trims the stack trace of the given exception. Stack trace elements that are + * below the test method are filtered out. + * + * @since 4.13 + */ + public static void trimStackTrace(Throwable exception) { + if (exception == null) { + throw new NullPointerException("exception cannot be null"); + } + + Throwable nextException = exception; + do { + exception = nextException; + nextException = null; + List stackTraceElements = Arrays.asList(exception.getStackTrace()); + int originalStackTraceDepth = stackTraceElements.size(); + int linesToInclude = originalStackTraceDepth; + + State state = State.PROCESSING_OTHER_CODE; + for (StackTraceElement stackTraceElement : asReversedList(stackTraceElements)) { + state = state.processStackTraceElement(stackTraceElement); + if (state == State.DONE) { + if (linesToInclude >= originalStackTraceDepth) { + return; + } + StackTraceElement[] newStackTrace = stackTraceElements + .subList(0, linesToInclude) + .toArray(new StackTraceElement[linesToInclude]); + exception.setStackTrace(newStackTrace); + nextException = exception.getCause(); + break; + } + linesToInclude--; + } + } while (nextException != null); + } + + private static List asReversedList(final List list) { + return new AbstractList() { + + @Override + public T get(int index) { + return list.get(list.size() - index - 1); + } + + @Override + public int size() { + return list.size(); + } + }; + } + + private enum State { + PROCESSING_OTHER_CODE { + @Override public State processLine(String methodName) { + if (isTestFrameworkMethod(methodName)) { + return PROCESSING_TEST_FRAMEWORK_CODE; + } + return this; + } + }, + PROCESSING_TEST_FRAMEWORK_CODE { + @Override public State processLine(String methodName) { + if (isReflectionMethod(methodName)) { + return PROCESSING_REFLECTION_CODE; + } else if (isTestFrameworkMethod(methodName)) { + return this; + } + return PROCESSING_OTHER_CODE; + } + }, + PROCESSING_REFLECTION_CODE { + @Override public State processLine(String methodName) { + if (isReflectionMethod(methodName)) { + return this; + } else if (isTestFrameworkMethod(methodName)) { + // This is here to handle TestCase.runBare() calling TestCase.runTest(). + return PROCESSING_TEST_FRAMEWORK_CODE; + } + return DONE; + } + }, + DONE { + @Override public State processLine(String methodName) { + return this; + } + }; + + /** Processes a stack trace element method name, possibly moving to a new state. */ + protected abstract State processLine(String methodName); + + /** Processes a stack trace element, possibly moving to a new state. */ + public final State processStackTraceElement(StackTraceElement element) { + return processLine(element.getClassName() + "." + element.getMethodName() + "()"); + } + } + + private static final String[] TEST_FRAMEWORK_METHOD_NAME_PREFIXES = { + "org.junit.runner.", + "org.junit.runners.", + "org.junit.experimental.runners.", + "org.junit.internal.", + "junit.", + }; + + private static final String[] TEST_FRAMEWORK_TEST_METHOD_NAME_PREFIXES = { + "org.junit.internal.StackTracesTest", + }; + + private static boolean isTestFrameworkMethod(String methodName) { + return isMatchingMethod(methodName, TEST_FRAMEWORK_METHOD_NAME_PREFIXES) && + !isMatchingMethod(methodName, TEST_FRAMEWORK_TEST_METHOD_NAME_PREFIXES); + } + + private static final String[] REFLECTION_METHOD_NAME_PREFIXES = { + "sun.reflect.", + "java.lang.reflect.", + "org.junit.rules.RunRules.(", + "org.junit.rules.RunRules.applyAll(", // calls TestRules + "org.junit.runners.BlockJUnit4ClassRunner.withMethodRules(", // calls MethodRules + "junit.framework.TestCase.runBare(", // runBare() directly calls setUp() and tearDown() + }; + + private static boolean isReflectionMethod(String methodName) { + return isMatchingMethod(methodName, REFLECTION_METHOD_NAME_PREFIXES); + } + + private static boolean isMatchingMethod(String methodName, String[] methodNamePrefixes) { + for (String methodNamePrefix : methodNamePrefixes) { + if (methodName.startsWith(methodNamePrefix)) { + return true; + } + } + + return false; + } } diff --git a/src/main/java/org/junit/runner/notification/Failure.java b/src/main/java/org/junit/runner/notification/Failure.java index 8086b32d7009e..986c042cd8488 100644 --- a/src/main/java/org/junit/runner/notification/Failure.java +++ b/src/main/java/org/junit/runner/notification/Failure.java @@ -2,7 +2,6 @@ import java.io.Serializable; -import org.junit.internal.StackTraces; import org.junit.internal.Throwables; import org.junit.runner.Description; @@ -37,7 +36,7 @@ public Failure(Description description, Throwable thrownException) { this.fThrownException = thrownException; this.fDescription = description; if (!disableStackTraceTrimming && thrownException != null) { - StackTraces.trimStackTrace(thrownException); + Throwables.trimStackTrace(thrownException); } } diff --git a/src/test/java/org/junit/tests/running/methods/TimeoutTest.java b/src/test/java/org/junit/tests/running/methods/TimeoutTest.java index 5bf67d63fd504..8e7bc430b3f1b 100644 --- a/src/test/java/org/junit/tests/running/methods/TimeoutTest.java +++ b/src/test/java/org/junit/tests/running/methods/TimeoutTest.java @@ -17,7 +17,6 @@ import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; -import org.junit.internal.StackTraces; import org.junit.internal.Throwables; import org.junit.rules.TestRule; import org.junit.rules.Timeout;