Merge "Create a Feature Flag to allow enabling early device release"
diff --git a/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java b/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java
index 1929e6f..aedd63f 100644
--- a/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java
+++ b/src/com/android/tradefed/device/metric/BaseDeviceMetricCollector.java
@@ -24,6 +24,7 @@
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.log.LogUtil.CLog;
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.InputStreamSource;
import com.android.tradefed.result.LogDataType;
@@ -253,6 +254,11 @@
}
@Override
+ public final void testRunFailed(FailureDescription failure) {
+ mForwarder.testRunFailed(failure);
+ }
+
+ @Override
public final void testRunStopped(long elapsedTime) {
mForwarder.testRunStopped(elapsedTime);
}
@@ -305,6 +311,20 @@
}
@Override
+ public final void testFailed(TestDescription test, FailureDescription failure) {
+ mSkipTestCase = shouldSkip(test);
+ if (!mSkipTestCase) {
+ try {
+ onTestFail(mTestData, test);
+ } catch (Throwable t) {
+ // Prevent exception from messing up the status reporting.
+ CLog.e(t);
+ }
+ }
+ mForwarder.testFailed(test, failure);
+ }
+
+ @Override
public final void testEnded(TestDescription test, HashMap<String, Metric> testMetrics) {
testEnded(test, System.currentTimeMillis(), testMetrics);
}
diff --git a/src/com/android/tradefed/invoker/ShardListener.java b/src/com/android/tradefed/invoker/ShardListener.java
index 7cfc0d1..6292a62 100644
--- a/src/com/android/tradefed/invoker/ShardListener.java
+++ b/src/com/android/tradefed/invoker/ShardListener.java
@@ -20,6 +20,7 @@
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.FailureDescription;
import com.android.tradefed.result.ILogSaverListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.InputStreamSource;
@@ -152,6 +153,17 @@
/** {@inheritDoc} */
@Override
+ public void testRunFailed(FailureDescription failure) {
+ super.testRunFailed(failure);
+ CLog.logAndDisplay(
+ LogLevel.ERROR,
+ "FAILED: %s failed with message: %s",
+ getCurrentRunResults().getName(),
+ failure.toString());
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics) {
super.testRunEnded(elapsedTime, runMetrics);
CLog.logAndDisplay(
diff --git a/src/com/android/tradefed/postprocessor/BasePostProcessor.java b/src/com/android/tradefed/postprocessor/BasePostProcessor.java
index 983d435..727cafc 100644
--- a/src/com/android/tradefed/postprocessor/BasePostProcessor.java
+++ b/src/com/android/tradefed/postprocessor/BasePostProcessor.java
@@ -20,6 +20,7 @@
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.metrics.proto.MetricMeasurement.DataType;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
+import com.android.tradefed.result.FailureDescription;
import com.android.tradefed.result.ILogSaver;
import com.android.tradefed.result.ILogSaverListener;
import com.android.tradefed.result.ITestInvocationListener;
@@ -142,6 +143,11 @@
}
@Override
+ public final void testRunFailed(FailureDescription failure) {
+ mForwarder.testRunFailed(failure);
+ }
+
+ @Override
public final void testRunStopped(long elapsedTime) {
mForwarder.testRunStopped(elapsedTime);
}
@@ -200,6 +206,11 @@
}
@Override
+ public final void testFailed(TestDescription test, FailureDescription failure) {
+ mForwarder.testFailed(test, failure);
+ }
+
+ @Override
public final void testEnded(TestDescription test, Map<String, String> testMetrics) {
testEnded(test, System.currentTimeMillis(), testMetrics);
}
diff --git a/src/com/android/tradefed/result/proto/ProtoResultReporter.java b/src/com/android/tradefed/result/proto/ProtoResultReporter.java
index 7459b34..c66527d 100644
--- a/src/com/android/tradefed/result/proto/ProtoResultReporter.java
+++ b/src/com/android/tradefed/result/proto/ProtoResultReporter.java
@@ -20,6 +20,7 @@
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
+import com.android.tradefed.result.FailureDescription;
import com.android.tradefed.result.ILogSaverListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.LogFile;
@@ -293,6 +294,26 @@
}
@Override
+ public final void testRunFailed(FailureDescription failure) {
+ TestRecord.Builder current = mLatestChild.peek();
+ DebugInfo.Builder debugBuilder = DebugInfo.newBuilder();
+ debugBuilder.setErrorMessage(failure.toString());
+ if (failure.getFailureStatus() != null) {
+ debugBuilder.setFailureStatus(failure.getFailureStatus());
+ }
+ if (TestStatus.UNKNOWN.equals(current.getStatus())) {
+ current.setDebugInfo(debugBuilder.build());
+ } else {
+ // We are in a test case and we need the run parent.
+ TestRecord.Builder test = mLatestChild.pop();
+ TestRecord.Builder run = mLatestChild.peek();
+ run.setDebugInfo(debugBuilder.build());
+ // Re-add the test
+ mLatestChild.add(test);
+ }
+ }
+
+ @Override
public final void testRunEnded(long elapsedTimeMillis, HashMap<String, Metric> runMetrics) {
TestRecord.Builder runBuilder = mLatestChild.pop();
long startTime = timeStampToMillis(runBuilder.getStartTime());
@@ -373,6 +394,21 @@
}
@Override
+ public final void testFailed(TestDescription test, FailureDescription failure) {
+ TestRecord.Builder testBuilder = mLatestChild.peek();
+
+ testBuilder.setStatus(TestStatus.FAIL);
+ DebugInfo.Builder debugBuilder = DebugInfo.newBuilder();
+ // FIXME: extract the error message from the trace
+ debugBuilder.setErrorMessage(failure.toString());
+ debugBuilder.setTrace(failure.toString());
+ if (failure.getFailureStatus() != null) {
+ debugBuilder.setFailureStatus(failure.getFailureStatus());
+ }
+ testBuilder.setDebugInfo(debugBuilder.build());
+ }
+
+ @Override
public final void testIgnored(TestDescription test) {
TestRecord.Builder testBuilder = mLatestChild.peek();
testBuilder.setStatus(TestStatus.IGNORED);
diff --git a/src/com/android/tradefed/result/suite/FormattedGeneratorReporter.java b/src/com/android/tradefed/result/suite/FormattedGeneratorReporter.java
index bedd4a4..dbd521f 100644
--- a/src/com/android/tradefed/result/suite/FormattedGeneratorReporter.java
+++ b/src/com/android/tradefed/result/suite/FormattedGeneratorReporter.java
@@ -15,13 +15,28 @@
*/
package com.android.tradefed.result.suite;
+import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.config.IConfigurationReceiver;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.suite.retry.ResultsPlayer;
/** Reporter that allows to generate reports in a particular format. TODO: fix logged file */
-public abstract class FormattedGeneratorReporter extends SuiteResultReporter {
+public abstract class FormattedGeneratorReporter extends SuiteResultReporter
+ implements IConfigurationReceiver {
private Throwable mTestHarnessError = null;
+ private IConfiguration mConfiguration;
+
+ @Override
+ public final void setConfiguration(IConfiguration configuration) {
+ mConfiguration = configuration;
+ }
+
+ public final IConfiguration getConfiguration() {
+ return mConfiguration;
+ }
/** {@inheritDoc} */
@Override
@@ -31,11 +46,19 @@
// If invocation failed due to a test harness error and did not see any tests
if (mTestHarnessError != null) {
- CLog.e(
- "Invocation failed and we couldn't ensure results are consistent, skip "
- + "generating the formatted report due to:");
- CLog.e(mTestHarnessError);
- return;
+ Boolean replaySuccess = null;
+ for (IRemoteTest test : mConfiguration.getTests()) {
+ if (test instanceof ResultsPlayer) {
+ replaySuccess = ((ResultsPlayer) test).completed();
+ }
+ }
+ if (replaySuccess != null && !replaySuccess) {
+ CLog.e(
+ "Invocation failed and previous session results couldn't be copied, skip "
+ + "generating the formatted report due to:");
+ CLog.e(mTestHarnessError);
+ return;
+ }
}
SuiteResultHolder holder = generateResultHolder();
diff --git a/src/com/android/tradefed/sandbox/SandboxInvocationRunner.java b/src/com/android/tradefed/sandbox/SandboxInvocationRunner.java
index ab0033f..5628636 100644
--- a/src/com/android/tradefed/sandbox/SandboxInvocationRunner.java
+++ b/src/com/android/tradefed/sandbox/SandboxInvocationRunner.java
@@ -57,6 +57,9 @@
try {
CommandResult result = sandbox.run(config, listener);
if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
+ CLog.e(
+ "Sandbox finished with status: %s and exit code: %s",
+ result.getStatus(), result.getExitCode());
handleStderrException(result.getStderr());
}
} finally {
diff --git a/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java b/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java
index c1a10d7..7da2c6c 100644
--- a/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java
+++ b/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java
@@ -15,6 +15,7 @@
*/
package com.android.tradefed.testtype.suite.retry;
+import com.android.annotations.VisibleForTesting;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.IConfigurationReceiver;
@@ -50,12 +51,18 @@
private Map<TestRunResult, ReplayModuleHolder> mModuleResult;
private IConfiguration mConfiguration;
+ private boolean mCompleted;
/** Ctor. */
public ResultsPlayer() {
mModuleResult = new LinkedHashMap<>();
}
+ @VisibleForTesting
+ public ResultsPlayer(boolean completed) {
+ mCompleted = completed;
+ }
+
@Override
public void run(TestInformation testInfo, ITestInvocationListener listener)
throws DeviceNotAvailableException {
@@ -115,6 +122,7 @@
"Done replaying results in %s",
TimeUtil.formatElapsedTime(System.currentTimeMillis() - startReplay));
mModuleResult.clear();
+ mCompleted = true;
}
/**
@@ -146,6 +154,11 @@
mConfiguration = configuration;
}
+ /** Returns whether or not the ResultsReplayer is done replaying the results. */
+ public boolean completed() {
+ return mCompleted;
+ }
+
private void forwardTestResults(
TestRunResult module,
Collection<Entry<TestDescription, TestResult>> testSet,
diff --git a/src/com/android/tradefed/util/sl4a/Sl4aClient.java b/src/com/android/tradefed/util/sl4a/Sl4aClient.java
index b066c91..b2610a2 100644
--- a/src/com/android/tradefed/util/sl4a/Sl4aClient.java
+++ b/src/com/android/tradefed/util/sl4a/Sl4aClient.java
@@ -240,14 +240,14 @@
* @throws IOException
*/
private synchronized Object sendThroughSocket(String message) throws IOException {
- CLog.d("preparing sending: '%s' to device %s", message, mDevice.getSerialNumber());
+ CLog.v("preparing sending: '%s' to device %s", message, mDevice.getSerialNumber());
PrintWriter out = new PrintWriter(mSocket.getOutputStream(), false);
out.print(message);
out.print('\n');
out.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
String response = in.readLine();
- CLog.d("response: '%s' from device %s", response, mDevice.getSerialNumber());
+ CLog.v("response: '%s' from device %s", response, mDevice.getSerialNumber());
try {
JSONObject resp = new JSONObject(response);
if (!resp.isNull("error")) {
diff --git a/test_framework/com/android/tradefed/device/metric/HostStatsdMetricCollector.java b/test_framework/com/android/tradefed/device/metric/HostStatsdMetricCollector.java
index 4f2e029..d86de45 100644
--- a/test_framework/com/android/tradefed/device/metric/HostStatsdMetricCollector.java
+++ b/test_framework/com/android/tradefed/device/metric/HostStatsdMetricCollector.java
@@ -43,48 +43,48 @@
@Option(name = "binary-stats-config", description = "Path to the binary Statsd config file")
private File mBinaryConfig;
+ @Option(name = "per-run", description = "Collect Metrics at per-test level or per-run level")
+ private boolean mPerRun = true;
+
/** Map from device serial number to config ID on that device */
private Map<String, Long> mDeviceConfigIds = new HashMap<>();
+ /**
+ * Counting the test in the same run. It is used to distinguish the statsd result file from
+ * multiple tests
+ */
+ private int mTestCount = 1;
+
@Override
public void onTestRunStart(DeviceMetricData runData) {
- mDeviceConfigIds.clear();
- for (ITestDevice device : getDevices()) {
- String serialNumber = device.getSerialNumber();
- try {
- long configId = pushBinaryStatsConfig(device, mBinaryConfig);
- CLog.d(
- "Pushed binary stats config to device %s with config id: %d",
- serialNumber, configId);
- mDeviceConfigIds.put(serialNumber, configId);
- } catch (IOException | DeviceNotAvailableException e) {
- CLog.e("Failed to push stats config to device %s, error: %s", serialNumber, e);
- }
+ if (mPerRun) {
+ mDeviceConfigIds.clear();
+ startCollection();
+ }
+ }
+
+ @Override
+ public void onTestStart(DeviceMetricData testData) {
+ if (!mPerRun) {
+ mDeviceConfigIds.clear();
+ startCollection();
+ }
+ }
+
+ @Override
+ public void onTestEnd(
+ DeviceMetricData testData, final Map<String, Metric> currentTestCaseMetrics) {
+ if (!mPerRun) {
+ stopCollection(testData);
+ mTestCount++;
}
}
@Override
public void onTestRunEnd(
DeviceMetricData runData, final Map<String, Metric> currentRunMetrics) {
- for (ITestDevice device : getDevices()) {
- String serialNumber = device.getSerialNumber();
- if (mDeviceConfigIds.containsKey(serialNumber)) {
- long configId = mDeviceConfigIds.get(serialNumber);
- try {
- InputStreamSource dataStream = getReportByteStream(device, configId);
- CLog.d(
- "Retrieved stats report from device %s for config %d",
- serialNumber, configId);
- processStatsReport(device, dataStream, runData);
- testLog(
- String.format("device_%s_stats_report", serialNumber),
- LogDataType.PB,
- dataStream);
- removeConfig(device, configId);
- } catch (DeviceNotAvailableException e) {
- CLog.e("Device %s not available: %s", serialNumber, e);
- }
- }
+ if (mPerRun) {
+ stopCollection(runData);
}
}
@@ -114,5 +114,47 @@
* @param runData The destination where the processed metrics will be stored
*/
protected void processStatsReport(
- ITestDevice device, InputStreamSource dataStream, DeviceMetricData runData) {}
+ ITestDevice device, InputStreamSource dataStream, DeviceMetricData runData) {
+ // Empty method by default
+ }
+
+ private void startCollection() {
+ for (ITestDevice device : getDevices()) {
+ String serialNumber = device.getSerialNumber();
+ try {
+ long configId = pushBinaryStatsConfig(device, mBinaryConfig);
+ CLog.d(
+ "Pushed binary stats config to device %s with config id: %d",
+ serialNumber, configId);
+ mDeviceConfigIds.put(serialNumber, configId);
+ } catch (IOException | DeviceNotAvailableException e) {
+ CLog.e("Failed to push stats config to device %s, error: %s", serialNumber, e);
+ }
+ }
+ }
+
+ private void stopCollection(DeviceMetricData metricData) {
+ for (ITestDevice device : getDevices()) {
+ String serialNumber = device.getSerialNumber();
+ if (mDeviceConfigIds.containsKey(serialNumber)) {
+ long configId = mDeviceConfigIds.get(serialNumber);
+ try (InputStreamSource dataStream = getReportByteStream(device, configId)) {
+ CLog.d(
+ "Retrieved stats report from device %s for config %d",
+ serialNumber, configId);
+ removeConfig(device, configId);
+ String reportName =
+ mPerRun
+ ? String.format("device_%s_stats_report", serialNumber)
+ : String.format(
+ "device_%s_stats_report_test_%d",
+ serialNumber, mTestCount);
+ testLog(reportName, LogDataType.PB, dataStream);
+ processStatsReport(device, dataStream, metricData);
+ } catch (DeviceNotAvailableException e) {
+ CLog.e("Device %s not available: %s", serialNumber, e);
+ }
+ }
+ }
+ }
}
diff --git a/test_framework/com/android/tradefed/targetprep/InstallApexModuleTargetPreparer.java b/test_framework/com/android/tradefed/targetprep/InstallApexModuleTargetPreparer.java
index 2239bf8..18d142b 100644
--- a/test_framework/com/android/tradefed/targetprep/InstallApexModuleTargetPreparer.java
+++ b/test_framework/com/android/tradefed/targetprep/InstallApexModuleTargetPreparer.java
@@ -105,6 +105,7 @@
installer(testInfo, testAppFileNames);
if (containsApex(testAppFileNames)
|| containsPersistentApk(testAppFileNames, testInfo)) {
+ RunUtil.getDefault().sleep(mApexStagingWaitTime);
device.reboot();
}
if (mTestApexInfoList.isEmpty()) {
diff --git a/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java b/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java
index 55ad8dc..10ec246 100644
--- a/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java
+++ b/test_result_interfaces/com/android/tradefed/result/MultiFailureDescription.java
@@ -63,14 +63,20 @@
@Override
public @Nullable FailureStatus getFailureStatus() {
- throw new UnsupportedOperationException(
- "Cannot call #getFailureStatus on MultiFailureDescription");
+ if (mFailures.isEmpty()) {
+ return null;
+ }
+ // Default to the first reported failure
+ return mFailures.get(0).getFailureStatus();
}
@Override
public String getErrorMessage() {
- throw new UnsupportedOperationException(
- "Cannot call #getErrorMessage on MultiFailureDescription");
+ if (mFailures.isEmpty()) {
+ return null;
+ }
+ // Default to the first reported failure
+ return mFailures.get(0).getErrorMessage();
}
@Override
diff --git a/tests/src/com/android/tradefed/device/metric/HostStatsdMetricCollectorTest.java b/tests/src/com/android/tradefed/device/metric/HostStatsdMetricCollectorTest.java
index 8056036..8f13ba9 100644
--- a/tests/src/com/android/tradefed/device/metric/HostStatsdMetricCollectorTest.java
+++ b/tests/src/com/android/tradefed/device/metric/HostStatsdMetricCollectorTest.java
@@ -20,6 +20,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
@@ -31,6 +32,7 @@
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.TestDescription;
import org.junit.Before;
import org.junit.Rule;
@@ -43,15 +45,15 @@
import java.io.File;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/** Unit Tests for {@link HostStatsdMetricCollector}. */
@RunWith(JUnit4.class)
public class HostStatsdMetricCollectorTest {
private static final String STATSD_CONFIG = "statsd.config";
- private static final String[] DEVICE_SERIALS = new String[] {"device_1", "device_2"};
private static final long CONFIG_ID = 54321L;
@Mock private IInvocationContext mContext;
@@ -59,34 +61,58 @@
@Spy private HostStatsdMetricCollector mCollector;
@Rule public TemporaryFolder mFolder = new TemporaryFolder();
- @Before
- public void setUp() throws IOException {
- initMocks(this);
- }
+ private TestDescription mTest = new TestDescription("Foo", "Bar");
+ private List<ITestDevice> mDevices =
+ Stream.of("device_1", "device_2").map(this::mockDevice).collect(Collectors.toList());
+ private HashMap<String, Metric> mMetrics = new HashMap<>();
- /** Test that a binary config is pushed and report is dumped from multiple devices. */
- @Test
- public void testMetricCollection_binaryConfig_multiDevice()
- throws IOException, ConfigurationException, DeviceNotAvailableException {
+ @Before
+ public void setUp() throws IOException, ConfigurationException, DeviceNotAvailableException {
+ initMocks(this);
OptionSetter options = new OptionSetter(mCollector);
options.setOptionValue(
"binary-stats-config", mFolder.newFile(STATSD_CONFIG).getAbsolutePath());
- List<ITestDevice> devices = new ArrayList<>();
- for (String serial : DEVICE_SERIALS) {
- devices.add(mockDevice(serial));
- }
- when(mContext.getDevices()).thenReturn(devices);
+ when(mContext.getDevices()).thenReturn(mDevices);
doReturn(CONFIG_ID)
.when(mCollector)
.pushBinaryStatsConfig(any(ITestDevice.class), any(File.class));
+ }
- HashMap<String, Metric> runMetrics = new HashMap<>();
+ /** Test at per-test level that a binary config is pushed and report is dumped */
+ @Test
+ public void testCollect_perTest()
+ throws IOException, DeviceNotAvailableException, ConfigurationException {
+ OptionSetter options = new OptionSetter(mCollector);
+ options.setOptionValue("per-run", "false");
+
mCollector.init(mContext, mListener);
- mCollector.testRunStarted("collect-metrics", 1);
- mCollector.testRunEnded(0L, runMetrics);
+ mCollector.testRunStarted("collect-metrics", 2);
+ mCollector.testStarted(mTest);
+ mCollector.testEnded(mTest, mMetrics);
+ mCollector.testStarted(mTest);
+ mCollector.testEnded(mTest, mMetrics);
+ mCollector.testRunEnded(0L, mMetrics);
- for (ITestDevice device : devices) {
+ for (ITestDevice device : mDevices) {
+ verify(mCollector, times(2)).pushBinaryStatsConfig(eq(device), any(File.class));
+ verify(mCollector, times(2)).getReportByteStream(eq(device), anyLong());
+ verify(mCollector, times(2)).removeConfig(eq(device), anyLong());
+ }
+ }
+
+ /** Test at per-run level that a binary config is pushed and report is dumped at run level. */
+ @Test
+ public void testCollect_perRun() throws IOException, DeviceNotAvailableException {
+ mCollector.init(mContext, mListener);
+ mCollector.testRunStarted("collect-metrics", 2);
+ mCollector.testStarted(mTest);
+ mCollector.testEnded(mTest, mMetrics);
+ mCollector.testStarted(mTest);
+ mCollector.testEnded(mTest, mMetrics);
+ mCollector.testRunEnded(0L, mMetrics);
+
+ for (ITestDevice device : mDevices) {
verify(mCollector).pushBinaryStatsConfig(eq(device), any(File.class));
verify(mCollector).getReportByteStream(eq(device), anyLong());
verify(mCollector).removeConfig(eq(device), anyLong());
diff --git a/tests/src/com/android/tradefed/result/suite/FormattedGeneratorReporterTest.java b/tests/src/com/android/tradefed/result/suite/FormattedGeneratorReporterTest.java
index 1a96516..961bb0f 100644
--- a/tests/src/com/android/tradefed/result/suite/FormattedGeneratorReporterTest.java
+++ b/tests/src/com/android/tradefed/result/suite/FormattedGeneratorReporterTest.java
@@ -18,6 +18,8 @@
import com.android.tradefed.build.BuildInfo;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.command.remote.DeviceDescriptor;
+import com.android.tradefed.config.Configuration;
+import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.invoker.InvocationContext;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
@@ -25,7 +27,9 @@
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.testtype.Abi;
import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.StubTest;
import com.android.tradefed.testtype.suite.ModuleDefinition;
+import com.android.tradefed.testtype.suite.retry.ResultsPlayer;
import org.junit.Assert;
import org.junit.Before;
@@ -44,12 +48,14 @@
private FormattedGeneratorReporter mReporter;
private IInvocationContext mContext;
private IBuildInfo mBuildInfo;
+ private IConfiguration mConfig;
@Before
public void setUp() {
mContext = new InvocationContext();
mBuildInfo = new BuildInfo();
mContext.addDeviceBuildInfo("default", mBuildInfo);
+ mConfig = new Configuration("stub", "stub");
}
/** Test the value in the result holder when no module or tests actually ran. */
@@ -176,6 +182,8 @@
return null;
}
};
+ mConfig.setTest(new ResultsPlayer(false));
+ mReporter.setConfiguration(mConfig);
mReporter.invocationStarted(mContext);
DeviceDescriptor descriptor = null;
mReporter.invocationFailed(new TargetSetupError("Invocation failed.", descriptor));
@@ -198,11 +206,46 @@
return null;
}
};
+ mConfig.setTest(new ResultsPlayer(false));
+ mReporter.setConfiguration(mConfig);
mReporter.invocationStarted(mContext);
mReporter.invocationFailed(new NullPointerException("Invocation failed."));
mReporter.invocationEnded(500L);
}
+ @Test
+ public void testFinalizedResults_notRetry() {
+ mReporter =
+ new FormattedGeneratorReporter() {
+
+ @Override
+ public void finalizeResults(
+ IFormatterGenerator generator, SuiteResultHolder resultHolder) {
+ validateSuiteHolder(
+ resultHolder, 1, 1, 1, 0, 0L, mContext, new HashMap<>());
+ }
+
+ @Override
+ public IFormatterGenerator createFormatter() {
+ return null;
+ }
+
+ @Override
+ protected long getCurrentTime() {
+ return 0L;
+ }
+ };
+ mConfig.setTest(new StubTest());
+ mReporter.setConfiguration(mConfig);
+ mReporter.invocationStarted(mContext);
+ mReporter.testRunStarted("run1", 1);
+ mReporter.testStarted(new TestDescription("class", "method"));
+ mReporter.testEnded(new TestDescription("class", "method"), new HashMap<String, Metric>());
+ mReporter.testRunEnded(450L, new HashMap<String, Metric>());
+ mReporter.invocationFailed(new NullPointerException("Invocation failed."));
+ mReporter.invocationEnded(500L);
+ }
+
/** Validate the information inside the suite holder. */
private void validateSuiteHolder(
SuiteResultHolder holder,