Merge "Complete the proto events if it's missing due to interruption"
diff --git a/invocation_interfaces/com/android/tradefed/result/TestRunResult.java b/invocation_interfaces/com/android/tradefed/result/TestRunResult.java
index 91e934e..234ef2b 100644
--- a/invocation_interfaces/com/android/tradefed/result/TestRunResult.java
+++ b/invocation_interfaces/com/android/tradefed/result/TestRunResult.java
@@ -298,6 +298,10 @@
updateTestResult(test, TestStatus.FAILURE, FailureDescription.create(trace));
}
+ public void testFailed(TestDescription test, FailureDescription failure) {
+ updateTestResult(test, TestStatus.FAILURE, failure);
+ }
+
public void testAssumptionFailure(TestDescription test, String trace) {
updateTestResult(test, TestStatus.ASSUMPTION_FAILURE, FailureDescription.create(trace));
}
diff --git a/src/com/android/tradefed/result/CollectingTestListener.java b/src/com/android/tradefed/result/CollectingTestListener.java
index 7f46ee1..e12902a 100644
--- a/src/com/android/tradefed/result/CollectingTestListener.java
+++ b/src/com/android/tradefed/result/CollectingTestListener.java
@@ -298,6 +298,12 @@
}
@Override
+ public void testFailed(TestDescription test, FailureDescription failure) {
+ setCountDirty();
+ mCurrentTestRunResult.testFailed(test, failure);
+ }
+
+ @Override
public void testAssumptionFailure(TestDescription test, String trace) {
setCountDirty();
mCurrentTestRunResult.testAssumptionFailure(test, trace);
diff --git a/src/com/android/tradefed/result/ConsoleResultReporter.java b/src/com/android/tradefed/result/ConsoleResultReporter.java
index 6cedd57..1955b7d 100644
--- a/src/com/android/tradefed/result/ConsoleResultReporter.java
+++ b/src/com/android/tradefed/result/ConsoleResultReporter.java
@@ -125,28 +125,33 @@
public void invocationEnded(long elapsedTime) {
int[] results = mResultCountListener.getResultCounts();
StringBuilder sb = new StringBuilder();
+ sb.append("========== Result Summary ==========");
sb.append(String.format("\nResults summary for test-tag '%s': ", mTestTag));
sb.append(mResultCountListener.getTotalTests());
sb.append(" Tests [");
sb.append(results[TestStatus.PASSED.ordinal()]);
- sb.append(" Passed ");
+ sb.append(" Passed");
if (results[TestStatus.FAILURE.ordinal()] > 0) {
+ sb.append(" ");
sb.append(results[TestStatus.FAILURE.ordinal()]);
- sb.append(" Failed ");
+ sb.append(" Failed");
}
if (results[TestStatus.IGNORED.ordinal()] > 0) {
+ sb.append(" ");
sb.append(results[TestStatus.IGNORED.ordinal()]);
- sb.append(" Ignored ");
+ sb.append(" Ignored");
}
if (results[TestStatus.ASSUMPTION_FAILURE.ordinal()] > 0) {
+ sb.append(" ");
sb.append(results[TestStatus.ASSUMPTION_FAILURE.ordinal()]);
- sb.append(" Assumption failures ");
+ sb.append(" Assumption failures");
}
if (results[TestStatus.INCOMPLETE.ordinal()] > 0) {
+ sb.append(" ");
sb.append(results[TestStatus.INCOMPLETE.ordinal()]);
sb.append(" Incomplete");
}
- sb.append("\r\n");
+ sb.append("] \r\n");
print(sb.toString());
if (mDisplayFailureSummary) {
for (Entry<TestDescription, TestResult> entry : mFailures.entrySet()) {
diff --git a/test_framework/com/android/tradefed/testtype/InstrumentationFileTest.java b/test_framework/com/android/tradefed/testtype/InstrumentationFileTest.java
index 5fbbd76..7c0d7b6 100644
--- a/test_framework/com/android/tradefed/testtype/InstrumentationFileTest.java
+++ b/test_framework/com/android/tradefed/testtype/InstrumentationFileTest.java
@@ -203,7 +203,7 @@
} finally {
deleteTestFileFromDevice(mFilePathOnDevice);
Collection<TestDescription> completedTests =
- testTracker.getCurrentRunResults().getCompletedTests();
+ InstrumentationTest.excludeNonExecuted(testTracker.getCurrentRunResults());
if (mTests.removeAll(completedTests) && !mTests.isEmpty()) {
// re-run remaining tests from file
writeTestsToFileAndRun(mTests, testInfo, listener);
diff --git a/test_framework/com/android/tradefed/testtype/InstrumentationListener.java b/test_framework/com/android/tradefed/testtype/InstrumentationListener.java
index 2a96294..baafb76 100644
--- a/test_framework/com/android/tradefed/testtype/InstrumentationListener.java
+++ b/test_framework/com/android/tradefed/testtype/InstrumentationListener.java
@@ -45,6 +45,7 @@
private Set<TestDescription> mDuplicateTests = new HashSet<>();
private final Collection<TestDescription> mExpectedTests;
private boolean mDisableDuplicateCheck = false;
+ private boolean mReportUnexecutedTests = false;
private ProcessInfo mSystemServerProcess = null;
/**
@@ -68,6 +69,10 @@
mSystemServerProcess = info;
}
+ public void setReportUnexecutedTests(boolean enable) {
+ mReportUnexecutedTests = enable;
+ }
+
@Override
public void testRunStarted(String runName, int testCount) {
// In case of crash, run will attempt to report with 0
@@ -123,6 +128,18 @@
mDuplicateTests));
error.setFailureStatus(FailureStatus.TEST_FAILURE);
super.testRunFailed(error);
+ } else if (mReportUnexecutedTests && mExpectedTests.size() > mTests.size()) {
+ Set<TestDescription> missingTests = new LinkedHashSet<>(mExpectedTests);
+ missingTests.removeAll(mTests);
+ for (TestDescription miss : missingTests) {
+ super.testStarted(miss);
+ FailureDescription failure =
+ FailureDescription.create(
+ "test did not run due to instrumentation issue.",
+ FailureStatus.NOT_EXECUTED);
+ super.testFailed(miss, failure);
+ super.testEnded(miss, new HashMap<String, Metric>());
+ }
}
super.testRunEnded(elapsedTime, runMetrics);
}
diff --git a/test_framework/com/android/tradefed/testtype/InstrumentationTest.java b/test_framework/com/android/tradefed/testtype/InstrumentationTest.java
index 97ae0dd..108f920 100644
--- a/test_framework/com/android/tradefed/testtype/InstrumentationTest.java
+++ b/test_framework/com/android/tradefed/testtype/InstrumentationTest.java
@@ -45,8 +45,10 @@
import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.TestDescription;
+import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.result.ddmlib.DefaultRemoteAndroidTestRunner;
+import com.android.tradefed.result.proto.TestRecordProto.FailureStatus;
import com.android.tradefed.retry.IRetryDecision;
import com.android.tradefed.retry.RetryStrategy;
import com.android.tradefed.testtype.coverage.CoverageOptions;
@@ -68,6 +70,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -315,6 +318,12 @@
+ "a system_server restart.")
private boolean mEnableSoftRestartCheck = false;
+ @Option(
+ name = "report-unexecuted-tests",
+ description =
+ "Whether or not to enable reporting all unexecuted tests from instrumentation.")
+ private boolean mReportUnexecuted = true;
+
private IAbi mAbi = null;
private Collection<String> mInstallArgs = new ArrayList<>();
@@ -1053,13 +1062,14 @@
instrumentationListener.setOriginalSystemServer(
getDevice().getProcessByName("system_server"));
}
+ instrumentationListener.setReportUnexecutedTests(mReportUnexecuted);
mDevice.runInstrumentationTests(mRunner, instrumentationListener);
TestRunResult testRun = testTracker.getCurrentRunResults();
if (testRun.isRunFailure() || !testRun.getCompletedTests().containsAll(expectedTests)) {
// Don't re-run any completed tests, unless this is a coverage run.
if (mConfiguration != null
&& !mConfiguration.getCoverageOptions().isCoverageEnabled()) {
- expectedTests.removeAll(testTracker.getCurrentRunResults().getCompletedTests());
+ expectedTests.removeAll(excludeNonExecuted(testTracker.getCurrentRunResults()));
IRetryDecision decision = mConfiguration.getRetryDecision();
if (!RetryStrategy.NO_RETRY.equals(decision.getRetryStrategy())
&& decision.getMaxRetryCount() > 1) {
@@ -1073,6 +1083,20 @@
}
}
+ /** Filter out "NOT_EXECUTED" for the purpose of tracking what needs to be rerun. */
+ protected static Set<TestDescription> excludeNonExecuted(TestRunResult results) {
+ Set<TestDescription> completedTest = results.getCompletedTests();
+ for (Entry<TestDescription, TestResult> entry : results.getTestResults().entrySet()) {
+ if (completedTest.contains(entry.getKey()) && entry.getValue().getFailure() != null) {
+ if (FailureStatus.NOT_EXECUTED.equals(
+ entry.getValue().getFailure().getFailureStatus())) {
+ completedTest.remove(entry.getKey());
+ }
+ }
+ }
+ return completedTest;
+ }
+
/**
* Rerun any <var>mRemainingTests</var>
*
diff --git a/tests/src/com/android/tradefed/result/ConsoleResultReporterTest.java b/tests/src/com/android/tradefed/result/ConsoleResultReporterTest.java
index f1290f8..fd0a169 100644
--- a/tests/src/com/android/tradefed/result/ConsoleResultReporterTest.java
+++ b/tests/src/com/android/tradefed/result/ConsoleResultReporterTest.java
@@ -88,7 +88,7 @@
public void testSummary() {
mResultReporter.testResult(mTest, createTestResult(TestStatus.PASSED));
mResultReporter.invocationEnded(0);
- Truth.assertThat(mOutput.toString()).contains("1 Tests [1 Passed ");
+ Truth.assertThat(mOutput.toString()).contains("1 Tests [1 Passed]");
}
@Test
diff --git a/tests/src/com/android/tradefed/testtype/InstrumentationFileTestTest.java b/tests/src/com/android/tradefed/testtype/InstrumentationFileTestTest.java
index 09c5ef4..46e4b7b 100644
--- a/tests/src/com/android/tradefed/testtype/InstrumentationFileTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/InstrumentationFileTestTest.java
@@ -31,6 +31,7 @@
import com.android.tradefed.invoker.InvocationContext;
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
+import com.android.tradefed.result.FailureDescription;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.ITestLifeCycleReceiver;
import com.android.tradefed.result.TestDescription;
@@ -262,6 +263,7 @@
@Test
public void testRun_serialReRunOfTwoFailedToCompleteTests()
throws DeviceNotAvailableException, ConfigurationException {
+ mMockListener = EasyMock.createStrictMock(ITestInvocationListener.class);
final Collection<TestDescription> testsList = new ArrayList<>(1);
final TestDescription test1 = new TestDescription("ClassFoo1", "methodBar1");
final TestDescription test2 = new TestDescription("ClassFoo2", "methodBar2");
@@ -351,6 +353,10 @@
mMockListener.testStarted(EasyMock.eq(test1), EasyMock.anyLong());
mMockListener.testEnded(
EasyMock.eq(test1), EasyMock.anyLong(), EasyMock.eq(new HashMap<String, Metric>()));
+ mMockListener.testStarted(EasyMock.eq(test2), EasyMock.anyLong());
+ mMockListener.testFailed(EasyMock.eq(test2), EasyMock.<FailureDescription>anyObject());
+ mMockListener.testEnded(
+ EasyMock.eq(test2), EasyMock.anyLong(), EasyMock.eq(new HashMap<String, Metric>()));
mMockListener.testRunEnded(EasyMock.anyLong(), EasyMock.eq(new HashMap<String, Metric>()));
// first serial re-run:
mMockListener.testRunStarted(TEST_PACKAGE_VALUE, 0, 1);
diff --git a/tests/src/com/android/tradefed/testtype/InstrumentationTestTest.java b/tests/src/com/android/tradefed/testtype/InstrumentationTestTest.java
index c633824..1c5e61a 100644
--- a/tests/src/com/android/tradefed/testtype/InstrumentationTestTest.java
+++ b/tests/src/com/android/tradefed/testtype/InstrumentationTestTest.java
@@ -465,6 +465,9 @@
inOrder.verify(mMockListener)
.testRunFailed(
FailureDescription.create(RUN_ERROR_MSG, FailureStatus.TEST_FAILURE));
+ inOrder.verify(mMockListener).testStarted(eq(TEST2), anyLong());
+ inOrder.verify(mMockListener).testFailed(eq(TEST2), (FailureDescription) any());
+ inOrder.verify(mMockListener).testEnded(eq(TEST2), anyLong(), eq(EMPTY_STRING_MAP));
inOrder.verify(mMockListener).testRunEnded(1, EMPTY_STRING_MAP);
inOrder.verify(mMockListener).testRunStarted(TEST_PACKAGE_VALUE, 0, 1);