summaryrefslogtreecommitdiffstats
path: root/vespa-osgi-testrunner
diff options
context:
space:
mode:
authorJon Marius Venstad <venstad@gmail.com>2022-03-02 09:49:09 +0100
committerJon Marius Venstad <venstad@gmail.com>2022-03-02 09:49:09 +0100
commit623915011b25095ecf4b52265b00468070aba712 (patch)
tree462e352a0362458fbe4e0a2f59b507eacfb9b76f /vespa-osgi-testrunner
parent360915382dd6346a209fe693c021746d8f633084 (diff)
Trim stacks below user test code, for JUnit runner-caught exceptions
Diffstat (limited to 'vespa-osgi-testrunner')
-rw-r--r--vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/JunitRunner.java5
-rw-r--r--vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestReport.java25
-rw-r--r--vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/AggregateTestRunnerTest.java24
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<>();