Continue updating internal structures to FailureDescription
Also start forwarding testAssumption with
FailureDescription.
Test: unit tests
Bug: 147887662
Change-Id: I0f049aff2e3bac6738eaefa7d33cb3f56987b9f3
diff --git a/invocation_interfaces/com/android/tradefed/result/TestResult.java b/invocation_interfaces/com/android/tradefed/result/TestResult.java
index 078dab2..94298be 100644
--- a/invocation_interfaces/com/android/tradefed/result/TestResult.java
+++ b/invocation_interfaces/com/android/tradefed/result/TestResult.java
@@ -33,7 +33,7 @@
public static final String IS_FLAKY = "is_flaky";
private TestStatus mStatus;
- private String mStackTrace;
+ private FailureDescription mFailureDescription;
private Map<String, String> mMetrics;
private HashMap<String, Metric> mProtoMetrics;
private Map<String, LogFile> mLoggedFiles;
@@ -59,7 +59,18 @@
* #getStatus()} is {@link TestStatus#PASSED}.
*/
public String getStackTrace() {
- return mStackTrace;
+ if (mFailureDescription == null) {
+ return null;
+ }
+ return mFailureDescription.toString();
+ }
+
+ /**
+ * Get the associated {@link FailureDescription}. Should be <code>null</code> if {@link
+ * #getStatus()} is {@link TestStatus#PASSED}.
+ */
+ public FailureDescription getFailure() {
+ return mFailureDescription;
}
/** Get the associated test metrics. */
@@ -123,8 +134,13 @@
}
/** Set the stack trace. */
- public void setStackTrace(String trace) {
- mStackTrace = trace;
+ public void setStackTrace(String stackTrace) {
+ mFailureDescription = FailureDescription.create(stackTrace);
+ }
+
+ /** Set the stack trace. */
+ public void setFailure(FailureDescription failureDescription) {
+ mFailureDescription = failureDescription;
}
/** Sets the end time */
@@ -134,7 +150,7 @@
@Override
public int hashCode() {
- return Arrays.hashCode(new Object[] {mMetrics, mStackTrace, mStatus});
+ return Arrays.hashCode(new Object[] {mMetrics, mFailureDescription, mStatus});
}
@Override
@@ -150,7 +166,7 @@
}
TestResult other = (TestResult) obj;
return equal(mMetrics, other.mMetrics)
- && equal(mStackTrace, other.mStackTrace)
+ && equal(mFailureDescription.toString(), other.mFailureDescription.toString())
&& equal(mStatus, other.mStatus);
}
@@ -186,7 +202,7 @@
long earliestStartTime = Long.MAX_VALUE;
long latestEndTime = Long.MIN_VALUE;
- List<String> errorMsg = new ArrayList<>();
+ List<FailureDescription> errors = new ArrayList<>();
int pass = 0;
int fail = 0;
int assumption_failure = 0;
@@ -205,18 +221,18 @@
break;
case FAILURE:
fail++;
- if (attempt.getStackTrace() != null) {
- errorMsg.add(attempt.getStackTrace());
+ if (attempt.getFailure() != null) {
+ errors.add(attempt.getFailure());
}
break;
case INCOMPLETE:
incomplete++;
- errorMsg.add("incomplete test case result.");
+ errors.add(FailureDescription.create("incomplete test case result."));
break;
case ASSUMPTION_FAILURE:
assumption_failure++;
- if (attempt.getStackTrace() != null) {
- errorMsg.add(attempt.getStackTrace());
+ if (attempt.getFailure() != null) {
+ errors.add(attempt.getFailure());
}
break;
case IGNORED:
@@ -263,10 +279,12 @@
}
break;
}
- if (errorMsg.isEmpty()) {
- mergedResult.mStackTrace = null;
+ if (errors.isEmpty()) {
+ mergedResult.mFailureDescription = null;
+ } else if (errors.size() == 1) {
+ mergedResult.mFailureDescription = errors.get(0);
} else {
- mergedResult.mStackTrace = String.join("\n\n", errorMsg);
+ mergedResult.mFailureDescription = new MultiFailureDescription(errors);
}
mergedResult.setStartTime(earliestStartTime);
mergedResult.setEndTime(latestEndTime);
diff --git a/invocation_interfaces/com/android/tradefed/result/TestRunResult.java b/invocation_interfaces/com/android/tradefed/result/TestRunResult.java
index dcc10cb..0d9af0e 100644
--- a/invocation_interfaces/com/android/tradefed/result/TestRunResult.java
+++ b/invocation_interfaces/com/android/tradefed/result/TestRunResult.java
@@ -277,23 +277,26 @@
mTestResults.put(test, testResult);
}
- private void updateTestResult(TestDescription test, TestStatus status, String trace) {
+ private void updateTestResult(
+ TestDescription test, TestStatus status, FailureDescription failure) {
TestResult r = mTestResults.get(test);
if (r == null) {
CLog.d("received test event without test start for %s", test);
r = new TestResult();
}
r.setStatus(status);
- r.setStackTrace(trace);
+ if (failure != null) {
+ r.setFailure(failure);
+ }
addTestResult(test, r);
}
public void testFailed(TestDescription test, String trace) {
- updateTestResult(test, TestStatus.FAILURE, trace);
+ updateTestResult(test, TestStatus.FAILURE, FailureDescription.create(trace));
}
public void testAssumptionFailure(TestDescription test, String trace) {
- updateTestResult(test, TestStatus.ASSUMPTION_FAILURE, trace);
+ updateTestResult(test, TestStatus.ASSUMPTION_FAILURE, FailureDescription.create(trace));
}
public void testIgnored(TestDescription test) {
diff --git a/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java b/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java
index 05c68c7..4cea7b1 100644
--- a/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java
+++ b/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java
@@ -358,6 +358,19 @@
}
@Override
+ public final void testAssumptionFailure(TestDescription test, FailureDescription failure) {
+ if (!mSkipTestCase) {
+ try {
+ onTestAssumptionFailure(mTestData, test);
+ } catch (Throwable t) {
+ // Prevent exception from messing up the status reporting.
+ CLog.e(t);
+ }
+ }
+ mForwarder.testAssumptionFailure(test, failure);
+ }
+
+ @Override
public final void testIgnored(TestDescription test) {
mForwarder.testIgnored(test);
}
diff --git a/src/com/android/tradefed/postprocessor/BasePostProcessor.java b/src/com/android/tradefed/postprocessor/BasePostProcessor.java
index 727cafc..afa7b8a 100644
--- a/src/com/android/tradefed/postprocessor/BasePostProcessor.java
+++ b/src/com/android/tradefed/postprocessor/BasePostProcessor.java
@@ -272,6 +272,11 @@
}
@Override
+ public final void testAssumptionFailure(TestDescription test, FailureDescription failure) {
+ mForwarder.testAssumptionFailure(test, failure);
+ }
+
+ @Override
public final void testIgnored(TestDescription test) {
mForwarder.testIgnored(test);
}
diff --git a/test_result_interfaces/com/android/tradefed/result/ITestLifeCycleReceiver.java b/test_result_interfaces/com/android/tradefed/result/ITestLifeCycleReceiver.java
index 99f563f..74203cf 100644
--- a/test_result_interfaces/com/android/tradefed/result/ITestLifeCycleReceiver.java
+++ b/test_result_interfaces/com/android/tradefed/result/ITestLifeCycleReceiver.java
@@ -174,6 +174,16 @@
public default void testAssumptionFailure(TestDescription test, String trace) {}
/**
+ * Called when an atomic test flags that it assumes a condition that is false
+ *
+ * @param test identifies the test
+ * @param failure {@link FailureDescription} describing the failure and its context.
+ */
+ public default void testAssumptionFailure(TestDescription test, FailureDescription failure) {
+ testAssumptionFailure(test, failure.toString());
+ }
+
+ /**
* Called when a test will not be run, generally because a test method is annotated with
* org.junit.Ignore.
*
diff --git a/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java b/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java
index e6d11f6..00795f4 100644
--- a/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java
+++ b/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java
@@ -34,12 +34,17 @@
public MultiFailureDescription(List<FailureDescription> failures) {
super();
- mFailures.addAll(failures);
+ for (FailureDescription failure : failures) {
+ if (failure instanceof MultiFailureDescription) {
+ mFailures.addAll(((MultiFailureDescription) failure).getFailures());
+ } else {
+ mFailures.add(failure);
+ }
+ }
}
public MultiFailureDescription(FailureDescription... failures) {
- super();
- mFailures.addAll(Arrays.asList(failures));
+ this(Arrays.asList(failures));
}
/**
diff --git a/tests/src/com/android/tradefed/result/TestResultTest.java b/tests/src/com/android/tradefed/result/TestResultTest.java
index 92b46ef..23a5317 100644
--- a/tests/src/com/android/tradefed/result/TestResultTest.java
+++ b/tests/src/com/android/tradefed/result/TestResultTest.java
@@ -69,7 +69,7 @@
assertEquals(TestStatus.FAILURE, finalRes.getStatus());
assertEquals(2, finalRes.getStartTime());
assertEquals(7, finalRes.getEndTime());
- assertEquals("failed\n\nfailed", finalRes.getStackTrace());
+ assertEquals("There were 2 failures:\n failed\n failed", finalRes.getStackTrace());
}
@Test
diff --git a/tests/src/com/android/tradefed/result/TestRunResultTest.java b/tests/src/com/android/tradefed/result/TestRunResultTest.java
index 76de395..2f14eb0 100644
--- a/tests/src/com/android/tradefed/result/TestRunResultTest.java
+++ b/tests/src/com/android/tradefed/result/TestRunResultTest.java
@@ -291,8 +291,10 @@
assertEquals(TestStatus.FAILURE, test3Result.getStatus());
assertEquals(null, test1Result.getStackTrace());
- assertEquals("flaky 1\n\nflaky 2", test2Result.getStackTrace());
- assertEquals("bad_code1\n\nbad_code2\n\nbad_code3", test3Result.getStackTrace());
+ assertEquals("There were 2 failures:\n flaky 1\n flaky 2", test2Result.getStackTrace());
+ assertEquals(
+ "There were 3 failures:\n bad_code1\n bad_code2\n bad_code3",
+ test3Result.getStackTrace());
}
/** Ensure that the merging logic among multiple testRunResults for the same test is correct. */
@@ -342,7 +344,9 @@
TestResult testResult = testRunResult.get(testcase);
assertEquals(TestStatus.PASSED, testResult.getStatus());
- assertEquals("Second run failed.\n\nFourth run failed.", testResult.getStackTrace());
+ assertEquals(
+ "There were 2 failures:\n Second run failed.\n Fourth run failed.",
+ testResult.getStackTrace());
}
/** Ensure that merge will raise exceptions if merge TestRunResult for different test. */
@@ -602,6 +606,8 @@
TestResult testResult = testRunResult.get(testcase);
assertEquals(TestStatus.PASSED, testResult.getStatus());
- assertEquals("Second run failed.\n\nthird run failed.", testResult.getStackTrace());
+ assertEquals(
+ "There were 2 failures:\n Second run failed.\n third run failed.",
+ testResult.getStackTrace());
}
}
diff --git a/tests/src/com/android/tradefed/testtype/HostTestTest.java b/tests/src/com/android/tradefed/testtype/HostTestTest.java
index c119c26..5ac0f23 100644
--- a/tests/src/com/android/tradefed/testtype/HostTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/HostTestTest.java
@@ -1282,7 +1282,7 @@
new TestDescription(JUnit4TestClassAssume.class.getName(), "testPass5");
mListener.testRunStarted((String) EasyMock.anyObject(), EasyMock.eq(1));
mListener.testStarted(EasyMock.eq(test1));
- mListener.testAssumptionFailure(EasyMock.eq(test1), EasyMock.anyObject());
+ mListener.testAssumptionFailure(EasyMock.eq(test1), (String) EasyMock.anyObject());
mListener.testEnded(EasyMock.eq(test1), (HashMap<String, Metric>) EasyMock.anyObject());
mListener.testRunEnded(EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
EasyMock.replay(mListener);