Refactor ResultReporter to facilitate other tests suites extending it and customizing the build info.
Bug: 64458205
Test: Ran existing unit tests and cts invocation and retry session.
cts-tradefed run cts
cts-tradefed run cts -r 0
run_unit_tests.sh
Change-Id: I35fe8d85f09f2e8103c0a5007061a9aaf189b22e
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
index 7b64881..3fedf00 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
@@ -64,6 +64,7 @@
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -83,9 +84,14 @@
private static final String CTS_PREFIX = "cts:";
private static final String BUILD_INFO = CTS_PREFIX + "build_";
- /**
- * List of files and directories that should NOT be copied when retrying CTS.
- */
+ public static final String BUILD_VERSION_RELEASE = "build_version_release";
+ public static final String BUILD_ID = "build_id";
+ public static final String BUILD_PRODUCT = "build_product";
+ public static final String BUILD_DEVICE = "build_device";
+ public static final String BUILD_MANUFACTURER = "build_manufacturer";
+ public static final String BUILD_BRAND = "build_brand";
+ public static final String BUILD_FINGERPRINT = "build_fingerprint";
+
private static final List<String> NOT_RETRY_FILES = Arrays.asList(
ChecksumReporter.NAME,
ChecksumReporter.PREV_NAME,
@@ -129,7 +135,7 @@
private int invocationEndedCount = 0;
private CountDownLatch mFinalized = null;
- private IInvocationResult mResult = new InvocationResult();
+ protected IInvocationResult mResult = new InvocationResult();
private IModuleResult mCurrentModuleResult;
private ICaseResult mCurrentCaseResult;
private ITestResult mCurrentResult;
@@ -158,6 +164,9 @@
private LogFileSaver mTestLogSaver;
+ // Elapsed time from invocation started to ended.
+ private long mElapsedTime;
+
/**
* Default constructor.
*/
@@ -460,27 +469,25 @@
if (++invocationEndedCount < mMasterBuildInfos.size()) {
return;
}
- finalizeResults(elapsedTime);
+ mElapsedTime = elapsedTime;
+ finalizeResults();
mFinalized.countDown();
}
}
- private void finalizeResults(long elapsedTime) {
+ private void finalizeResults() {
// Add all device serials into the result to be serialized
for (String deviceSerial : mMasterDeviceSerials) {
mResult.addDeviceSerial(deviceSerial);
}
+ addDeviceBuildInfoToResult();
+
Set<String> allExpectedModules = new HashSet<>();
- // Add all build info to the result to be serialized
for (IBuildInfo buildInfo : mMasterBuildInfos) {
for (Map.Entry<String, String> entry : buildInfo.getBuildAttributes().entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
- if (key.startsWith(BUILD_INFO)) {
- mResult.addInvocationInfo(key.substring(CTS_PREFIX.length()), value);
- }
-
if (key.equals(CompatibilityBuildHelper.MODULE_IDS) && value.length() > 0) {
Collections.addAll(allExpectedModules, value.split(","));
}
@@ -496,17 +503,13 @@
String moduleProgress = String.format("%d of %d",
mResult.getModuleCompleteCount(), mResult.getModules().size());
- long startTime = mResult.getStartTime();
+
try {
// Zip the full test results directory.
copyDynamicConfigFiles();
copyFormattingFiles(mResultDir, mBuildHelper.getSuiteName());
- File resultFile = ResultHandler.writeResults(mBuildHelper.getSuiteName(),
- mBuildHelper.getSuiteVersion(), mBuildHelper.getSuitePlan(),
- mBuildHelper.getSuiteBuild(), mResult, mResultDir, startTime,
- elapsedTime + startTime, mReferenceUrl, getLogUrl(),
- mBuildHelper.getCommandLineArgs());
+ File resultFile = generateResultXmlFile();
if (mRetrySessionId != null) {
copyRetryFiles(ResultHandler.getResultDirectory(
mBuildHelper.getResultsDir(), mRetrySessionId), mResultDir);
@@ -532,7 +535,7 @@
}
// print the run results last.
info("Invocation finished in %s. PASSED: %d, FAILED: %d, MODULES: %s",
- TimeUtil.formatElapsedTime(elapsedTime),
+ TimeUtil.formatElapsedTime(mElapsedTime),
mResult.countResults(TestStatus.PASS),
mResult.countResults(TestStatus.FAIL),
moduleProgress);
@@ -658,6 +661,82 @@
}
/**
+ * Create results file compatible with CTSv2 (xml) report format.
+ */
+ protected File generateResultXmlFile()
+ throws IOException, XmlPullParserException {
+ return ResultHandler.writeResults(mBuildHelper.getSuiteName(),
+ mBuildHelper.getSuiteVersion(), mBuildHelper.getSuitePlan(),
+ mBuildHelper.getSuiteBuild(), mResult, mResultDir, mResult.getStartTime(),
+ mElapsedTime + mResult.getStartTime(), mReferenceUrl, getLogUrl(),
+ mBuildHelper.getCommandLineArgs());
+ }
+
+ /**
+ * Add build info collected from the device attributes to the results.
+ */
+ protected void addDeviceBuildInfoToResult() {
+ // Add all build info to the result to be serialized
+ Map<String, String> buildProperties = mapBuildInfo();
+ addBuildInfoToResult(buildProperties, mResult);
+ }
+
+ /**
+ * Override specific build properties so the report will be associated with the
+ * build fingerprint being certified.
+ */
+ protected void addDeviceBuildInfoToResult(String buildFingerprintOverride,
+ String manufactureOverride) {
+
+ Map<String, String> buildProperties = mapBuildInfo();
+
+ // Extract and override values from build fingerprint.
+ // Build fingerprint format: brand/product/device:version/build_id/tags
+ String fingerprintPrefix = buildFingerprintOverride.split(":")[0];
+ String fingerprintTail = buildFingerprintOverride.split(":")[1];
+ String buildIdOverride = fingerprintTail.split("/")[1];
+ buildProperties.put(BUILD_ID, buildIdOverride);
+ String brandOverride = fingerprintPrefix.split("/")[0];
+ buildProperties.put(BUILD_BRAND, brandOverride);
+ String deviceOverride = fingerprintPrefix.split("/")[2];
+ buildProperties.put(BUILD_DEVICE, deviceOverride);
+ String productOverride = fingerprintPrefix.split("/")[1];
+ buildProperties.put(BUILD_PRODUCT, productOverride);
+ String versionOverride = fingerprintTail.split("/")[0];
+ buildProperties.put(BUILD_VERSION_RELEASE, versionOverride);
+ buildProperties.put(BUILD_FINGERPRINT, buildFingerprintOverride);
+ buildProperties.put(BUILD_MANUFACTURER, manufactureOverride);
+
+ // Add modified values to results.
+ addBuildInfoToResult(buildProperties, mResult);
+ mResult.setBuildFingerprint(buildFingerprintOverride);
+ }
+ /** Aggregate build info from member device info. */
+ protected Map<String, String> mapBuildInfo() {
+ Map<String, String> buildProperties = new HashMap<>();
+ for (IBuildInfo buildInfo : mMasterBuildInfos) {
+ for (Map.Entry<String, String> entry : buildInfo.getBuildAttributes().entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+ if (key.startsWith(BUILD_INFO)) {
+ buildProperties.put(key.substring(CTS_PREFIX.length()), value);
+ }
+ }
+ }
+ return buildProperties;
+ }
+
+ /**
+ * Add build info to results.
+ * @param buildProperties Build info to add.
+ */
+ protected static void addBuildInfoToResult(Map<String, String> buildProperties,
+ IInvocationResult invocationResult) {
+ buildProperties.entrySet().stream().forEach(entry ->
+ invocationResult.addInvocationInfo(entry.getKey(), entry.getValue()));
+ }
+
+ /**
* Return true if this instance is a shard ResultReporter and should propagate
* certain events to the master.
*/
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
index 8d6fbf5..c9d9cbe 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
@@ -27,6 +27,7 @@
import com.android.compatibility.common.tradefed.result.ChecksumReporterTest;
import com.android.compatibility.common.tradefed.result.ConsoleReporterTest;
import com.android.compatibility.common.tradefed.result.MetadataReporterTest;
+import com.android.compatibility.common.tradefed.result.ResultReporterBuildInfoTest;
import com.android.compatibility.common.tradefed.result.ResultReporterTest;
import com.android.compatibility.common.tradefed.result.SubPlanHelperTest;
import com.android.compatibility.common.tradefed.targetprep.PropertyCheckTest;
@@ -78,6 +79,7 @@
ChecksumReporterTest.class,
ConsoleReporterTest.class,
MetadataReporterTest.class,
+ ResultReporterBuildInfoTest.class,
ResultReporterTest.class,
SubPlanHelperTest.class,
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterBuildInfoTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterBuildInfoTest.java
new file mode 100644
index 0000000..21154ff
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterBuildInfoTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.tradefed.result;
+
+
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.InvocationResult;
+import junit.framework.TestCase;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for {@link ResultReporter}, focused on ability to override build info.
+ */
+public class ResultReporterBuildInfoTest extends TestCase {
+
+ public void testOverrideBuildProperties() {
+ ResultReporterBuildInfoTester tester = new ResultReporterBuildInfoTester();
+ String manufacture = "custom_manufacture";
+ String brand = "google";
+ String product = "gProduct";
+ String device = "gDevice";
+ String version = "gVersion";
+ String buildId = "123";
+ String fingerprint = brand + "/" + product + "/" + device + ":" +
+ version + "/" + buildId + "/userdebug-keys";
+
+ IInvocationResult result = tester.testBuildInfoOverride(fingerprint, manufacture);
+ Map<String, String> invocationInfo = result.getInvocationInfo();
+ assertEquals(invocationInfo.get(ResultReporter.BUILD_ID), buildId);
+ assertEquals(invocationInfo.get(ResultReporter.BUILD_BRAND), brand);
+ assertEquals(invocationInfo.get(ResultReporter.BUILD_DEVICE), device);
+ assertEquals(invocationInfo.get(ResultReporter.BUILD_PRODUCT), product);
+ assertEquals(invocationInfo.get(ResultReporter.BUILD_VERSION_RELEASE), version);
+ assertEquals(invocationInfo.get(ResultReporter.BUILD_FINGERPRINT), fingerprint);
+ assertEquals(invocationInfo.get(ResultReporter.BUILD_MANUFACTURER), manufacture);
+ }
+
+ public static class ResultReporterBuildInfoTester extends ResultReporter {
+
+ public ResultReporterBuildInfoTester() {
+ mResult = new InvocationResult();
+ }
+
+ public IInvocationResult testBuildInfoOverride(String buildFingerprintOverride,
+ String manufactureOverride) {
+ addDeviceBuildInfoToResult(buildFingerprintOverride, manufactureOverride);
+ return mResult;
+ }
+
+ @Override
+ protected Map<String, String> mapBuildInfo() {
+ Map<String, String> buildProperties = new HashMap<>();
+ buildProperties.put(BUILD_ID, BUILD_ID);
+ buildProperties.put(BUILD_BRAND, BUILD_BRAND);
+ buildProperties.put(BUILD_DEVICE, BUILD_DEVICE);
+ buildProperties.put(BUILD_PRODUCT, BUILD_PRODUCT);
+ buildProperties.put(BUILD_VERSION_RELEASE, BUILD_VERSION_RELEASE);
+ buildProperties.put(BUILD_FINGERPRINT, BUILD_FINGERPRINT);
+ buildProperties.put(BUILD_MANUFACTURER, BUILD_MANUFACTURER);
+ return buildProperties;
+ }
+ }
+}