diff options
author | Jon Marius Venstad <venstad@gmail.com> | 2022-03-02 09:49:09 +0100 |
---|---|---|
committer | Jon Marius Venstad <venstad@gmail.com> | 2022-03-02 09:49:09 +0100 |
commit | 623915011b25095ecf4b52265b00468070aba712 (patch) | |
tree | 462e352a0362458fbe4e0a2f59b507eacfb9b76f /vespa-osgi-testrunner | |
parent | 360915382dd6346a209fe693c021746d8f633084 (diff) |
Trim stacks below user test code, for JUnit runner-caught exceptions
Diffstat (limited to 'vespa-osgi-testrunner')
3 files changed, 52 insertions, 2 deletions
diff --git a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/JunitRunner.java b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/JunitRunner.java index a7c40ddfad2..05c5dd24f1e 100644 --- a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/JunitRunner.java +++ b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/JunitRunner.java @@ -198,7 +198,10 @@ public class JunitRunner extends AbstractComponent implements TestRunner { launcher.execute(discoveryRequest); var report = summaryListener.getSummary(); var failures = report.getFailures().stream() - .map(failure -> new TestReport.Failure(failure.getTestIdentifier().getUniqueId(), failure.getException())) + .map(failure -> { + TestReport.trimStackTraces(failure.getException(), JunitRunner.class.getName()); + return new TestReport.Failure(failure.getTestIdentifier().getUniqueId(), failure.getException()); + }) .collect(Collectors.toList()); long inconclusive = isProductionTest ? failures.stream() .filter(failure -> failure.exception() instanceof InconclusiveTestException) diff --git a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestReport.java b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestReport.java index a9ac950e30a..bcb865c55ff 100644 --- a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestReport.java +++ b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestReport.java @@ -10,6 +10,7 @@ import static com.yahoo.vespa.testrunner.TestRunner.Status.FAILURE; import static com.yahoo.vespa.testrunner.TestRunner.Status.INCONCLUSIVE; import static com.yahoo.vespa.testrunner.TestRunner.Status.NO_TESTS; import static com.yahoo.vespa.testrunner.TestRunner.Status.SUCCESS; +import static java.util.Arrays.copyOf; /** * @author mortent @@ -119,4 +120,28 @@ public class TestReport { } + /** + * Recursively trims stack traces for the given throwable and its causes/suppressed. + * This is based on the assumption that the relevant stack is anything above the first native + * reflection invocation, above any frame in the given root class. + */ + static void trimStackTraces(Throwable thrown, String testFrameworkRootClass) { + if (thrown == null) + return; + + StackTraceElement[] stack = thrown.getStackTrace(); + int i = stack.length; + boolean rootedInTestFramework = false; + while (--i > 0 && ! stack[i].isNativeMethod()) // Native method invokes the first user test frame. + rootedInTestFramework |= testFrameworkRootClass.equals(stack[i].getClassName()); + + if (rootedInTestFramework && i > 0) + thrown.setStackTrace(copyOf(stack, i)); + + for (Throwable suppressed : thrown.getSuppressed()) + trimStackTraces(suppressed, testFrameworkRootClass); + + trimStackTraces(thrown.getCause(), testFrameworkRootClass); + } + } diff --git a/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/AggregateTestRunnerTest.java b/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/AggregateTestRunnerTest.java index f8e13ac5d6a..14e139b3fbf 100644 --- a/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/AggregateTestRunnerTest.java +++ b/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/AggregateTestRunnerTest.java @@ -1,6 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.testrunner; +import com.yahoo.exception.ExceptionUtils; +import com.yahoo.vespa.testrunner.TestReport.Failure; import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -123,7 +125,7 @@ class AggregateTestRunnerTest { // Verify reports are merged. assertNull(runner.getReport()); - TestReport.Failure failure = new TestReport.Failure("test", null); + Failure failure = new Failure("test", null); TestReport report = TestReport.builder() .withLogs(List.of(record1)) .withFailures(List.of(failure)) @@ -156,6 +158,26 @@ class AggregateTestRunnerTest { assertEquals(FAILURE, JunitRunner.createReportWithFailedInitialization(new RuntimeException("hello")).status()); } + @Test + void testStackTrimming() { + try { + try { + throw new RuntimeException("inner"); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + catch (Exception e) { + TestReport.trimStackTraces(e, "org.junit.platform.launcher.core.SessionPerRequestLauncher"); + assertEquals("java.lang.RuntimeException: java.lang.RuntimeException: inner\n" + + "\tat com.yahoo.vespa.testrunner.AggregateTestRunnerTest.testStackTrimming(AggregateTestRunnerTest.java:168)\n" + + "Caused by: java.lang.RuntimeException: inner\n" + + "\tat com.yahoo.vespa.testrunner.AggregateTestRunnerTest.testStackTrimming(AggregateTestRunnerTest.java:165)\n", + ExceptionUtils.getStackTraceAsString(e)); + } + } + static class MockTestRunner implements TestRunner { final List<LogRecord> log = new ArrayList<>(); |