Merge "Allow legacy subprocess reporter to use TF/CTS 9+ methods if possible"
diff --git a/invocation_interfaces/com/android/tradefed/result/ITestInvocationListener.java b/invocation_interfaces/com/android/tradefed/result/ITestInvocationListener.java
index e6f5357..ed8e1b7 100644
--- a/invocation_interfaces/com/android/tradefed/result/ITestInvocationListener.java
+++ b/invocation_interfaces/com/android/tradefed/result/ITestInvocationListener.java
@@ -73,6 +73,23 @@
default public void invocationFailed(Throwable cause) { }
/**
+ * Reports an incomplete invocation due to some error condition.
+ *
+ * <p>Will be automatically called by the TradeFederation framework.
+ *
+ * @param failure the {@link FailureDescription} describing the cause of the failure
+ */
+ public default void invocationFailed(FailureDescription failure) {
+ if (failure.getCause() != null) {
+ invocationFailed(failure.getCause());
+ } else {
+ invocationFailed(
+ new RuntimeException(
+ String.format("ConvertedFailure: %s", failure.getErrorMessage())));
+ }
+ }
+
+ /**
* Allows the InvocationListener to return a summary.
*
* @return A {@link TestSummary} summarizing the run, or null
diff --git a/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java b/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java
index 4cea7b1..1f5be9d 100644
--- a/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java
+++ b/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java
@@ -204,6 +204,11 @@
}
@Override
+ public final void invocationFailed(FailureDescription failure) {
+ mForwarder.invocationFailed(failure);
+ }
+
+ @Override
public final void invocationEnded(long elapsedTime) {
mForwarder.invocationEnded(elapsedTime);
}
diff --git a/src/com/android/tradefed/postprocessor/BasePostProcessor.java b/src/com/android/tradefed/postprocessor/BasePostProcessor.java
index afa7b8a..7b2c464 100644
--- a/src/com/android/tradefed/postprocessor/BasePostProcessor.java
+++ b/src/com/android/tradefed/postprocessor/BasePostProcessor.java
@@ -107,6 +107,11 @@
}
@Override
+ public final void invocationFailed(FailureDescription failure) {
+ mForwarder.invocationFailed(failure);
+ }
+
+ @Override
public final void invocationEnded(long elapsedTime) {
mForwarder.invocationEnded(elapsedTime);
}
diff --git a/src/com/android/tradefed/result/ResultForwarder.java b/src/com/android/tradefed/result/ResultForwarder.java
index 750b125..ba38e54 100644
--- a/src/com/android/tradefed/result/ResultForwarder.java
+++ b/src/com/android/tradefed/result/ResultForwarder.java
@@ -118,6 +118,21 @@
}
}
+ /** {@inheritDoc} */
+ @Override
+ public void invocationFailed(FailureDescription failure) {
+ for (ITestInvocationListener listener : mListeners) {
+ try {
+ listener.invocationFailed(failure);
+ } catch (RuntimeException e) {
+ CLog.e(
+ "Exception while invoking %s#invocationFailed",
+ listener.getClass().getName());
+ CLog.e(e);
+ }
+ }
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/com/android/tradefed/retry/ResultAggregator.java b/src/com/android/tradefed/retry/ResultAggregator.java
index 306604c..42af517 100644
--- a/src/com/android/tradefed/retry/ResultAggregator.java
+++ b/src/com/android/tradefed/retry/ResultAggregator.java
@@ -119,6 +119,13 @@
/** {@inheritDoc} */
@Override
+ public void invocationFailed(FailureDescription failure) {
+ super.invocationFailed(failure);
+ mAllForwarder.invocationFailed(failure);
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void invocationEnded(long elapsedTime) {
if (!mPureRunResultForAgg.isEmpty()) {
for (String name : mPureRunResultForAgg.keySet()) {
diff --git a/test_result_interfaces/com/android/tradefed/result/FailureDescription.java b/test_result_interfaces/com/android/tradefed/result/FailureDescription.java
index 23d4994..1acb558 100644
--- a/test_result_interfaces/com/android/tradefed/result/FailureDescription.java
+++ b/test_result_interfaces/com/android/tradefed/result/FailureDescription.java
@@ -33,6 +33,8 @@
private @Nullable ActionInProgress mActionInProgress = null;
// Optional: A free-formed text that help debugging the failure
private @Nullable String mDebugHelpMessage = null;
+ // Optional: The exception that triggered the failure
+ private @Nullable Throwable mCause = null;
FailureDescription() {}
@@ -75,6 +77,17 @@
return mDebugHelpMessage;
}
+ /** Sets the exception that caused the failure if any. */
+ public FailureDescription setCause(Throwable cause) {
+ mCause = cause;
+ return this;
+ }
+
+ /** Returns the exception that caused the failure. Can be null. */
+ public @Nullable Throwable getCause() {
+ return mCause;
+ }
+
/** Sets the error message. */
public void setErrorMessage(String errorMessage) {
mErrorMessage = errorMessage;
diff --git a/tests/src/com/android/tradefed/device/metric/BaseDeviceMetricCollectorTest.java b/tests/src/com/android/tradefed/device/metric/BaseDeviceMetricCollectorTest.java
index ea2a0dc..fa4144a 100644
--- a/tests/src/com/android/tradefed/device/metric/BaseDeviceMetricCollectorTest.java
+++ b/tests/src/com/android/tradefed/device/metric/BaseDeviceMetricCollectorTest.java
@@ -112,7 +112,7 @@
Mockito.verify(mMockListener, times(1)).testRunStopped(0L);
Mockito.verify(mMockListener, times(1)).testRunEnded(0L, new HashMap<String, Metric>());
Mockito.verify(mMockListener, times(1)).testModuleEnded();
- Mockito.verify(mMockListener, times(1)).invocationFailed(Mockito.any());
+ Mockito.verify(mMockListener, times(1)).invocationFailed(Mockito.<Throwable>any());
Mockito.verify(mMockListener, times(1)).invocationEnded(0L);
Assert.assertSame(mMockListener, mBase.getInvocationListener());
@@ -198,7 +198,7 @@
Mockito.verify(mMockListener, times(1)).testRunFailed("test run failed");
Mockito.verify(mMockListener, times(1)).testRunStopped(0L);
Mockito.verify(mMockListener, times(1)).testRunEnded(0L, new HashMap<String, Metric>());
- Mockito.verify(mMockListener, times(1)).invocationFailed(Mockito.any());
+ Mockito.verify(mMockListener, times(1)).invocationFailed(Mockito.<Throwable>any());
Mockito.verify(mMockListener, times(1)).invocationEnded(0L);
Assert.assertSame(mMockListener, mBase.getInvocationListener());
diff --git a/tests/src/com/android/tradefed/invoker/TestInvocationMultiTest.java b/tests/src/com/android/tradefed/invoker/TestInvocationMultiTest.java
index 98ed019..9257c88 100644
--- a/tests/src/com/android/tradefed/invoker/TestInvocationMultiTest.java
+++ b/tests/src/com/android/tradefed/invoker/TestInvocationMultiTest.java
@@ -193,7 +193,7 @@
mMockTestListener.invocationStarted(mContext);
EasyMock.expect(mMockTestListener.getSummary()).andReturn(null);
mMockLogSaver.invocationStarted(mContext);
- mMockTestListener.invocationFailed(EasyMock.anyObject());
+ mMockTestListener.invocationFailed(EasyMock.<Throwable>anyObject());
mMockTestListener.testLog(EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject());
EasyMock.expect(
mMockLogSaver.saveLogData(
@@ -359,7 +359,7 @@
mMockTestListener.invocationStarted(mContext);
EasyMock.expect(mMockTestListener.getSummary()).andReturn(null);
mMockLogSaver.invocationStarted(mContext);
- mMockTestListener.invocationFailed(EasyMock.anyObject());
+ mMockTestListener.invocationFailed(EasyMock.<Throwable>anyObject());
mMockTestListener.testLog(EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject());
EasyMock.expect(
mMockLogSaver.saveLogData(
@@ -446,7 +446,7 @@
mMockTestListener.invocationStarted(mContext);
EasyMock.expect(mMockTestListener.getSummary()).andReturn(null);
mMockLogSaver.invocationStarted(mContext);
- mMockTestListener.invocationFailed(EasyMock.anyObject());
+ mMockTestListener.invocationFailed(EasyMock.<Throwable>anyObject());
mMockTestListener.testLog(EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject());
EasyMock.expect(
mMockLogSaver.saveLogData(
diff --git a/tests/src/com/android/tradefed/invoker/TestInvocationTest.java b/tests/src/com/android/tradefed/invoker/TestInvocationTest.java
index 48a2590..8f4044c 100644
--- a/tests/src/com/android/tradefed/invoker/TestInvocationTest.java
+++ b/tests/src/com/android/tradefed/invoker/TestInvocationTest.java
@@ -1073,8 +1073,8 @@
// invocationFailed
if (!status.equals(InvocationStatus.SUCCESS)) {
if (stubFailures) {
- mMockTestListener.invocationFailed(EasyMock.anyObject());
- mMockSummaryListener.invocationFailed(EasyMock.anyObject());
+ mMockTestListener.invocationFailed(EasyMock.<Throwable>anyObject());
+ mMockSummaryListener.invocationFailed(EasyMock.<Throwable>anyObject());
} else {
mMockTestListener.invocationFailed(EasyMock.eq(throwable));
mMockSummaryListener.invocationFailed(EasyMock.eq(throwable));