Change CTS Verifier reporting to CTSv2 format.
Bug: 32723464
Test: CTS Verifier should make a report in the CTSv2 format. CTS results
should stay consistent.
Make and run compatibility-common-util-tests. The unit tests should pass.
Change-Id: If3cc9dbc83f7eda356d7dbe36dd28615f492bcfe
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java b/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java
index 33c9b62..64585f2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java
@@ -21,11 +21,21 @@
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
+import android.os.SystemClock;
+
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.InvocationResult;
+import com.android.compatibility.common.util.ResultHandler;
+
+import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+// import java.nio.file.Files;
+// import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
@@ -38,6 +48,21 @@
* Background task to generate a report and save it to external storage.
*/
class ReportExporter extends AsyncTask<Void, Void, String> {
+
+ private static final String COMMAND_LINE_ARGS = "CtsVerifier";
+ private static final String LOG_URL = null;
+ private static final String REFERENCE_URL = null;
+ private static final String SUITE_NAME = "ctsverifier";
+ private static final String SUITE_PLAN = "CTSVERIFIER";
+ private static final String SUITE_BUILD = "0";
+
+ private static final long START_MS = SystemClock.uptimeMillis();
+ private static final long END_MS = START_MS;
+
+ private static final int BUFFER_SIZE = 16 * 1024;
+ private static final String REPORT_DIRECTORY = "ctsVerifierReports";
+ private static final String ZIP_EXTENSION = ".zip";
+
protected static final Logger LOG = Logger.getLogger(ReportExporter.class.getName());
private final Context mContext;
@@ -54,50 +79,69 @@
LOG.log(Level.WARNING, "External storage is not writable.");
return mContext.getString(R.string.no_storage);
}
- byte[] contents;
+ IInvocationResult result;
try {
TestResultsReport report = new TestResultsReport(mContext, mAdapter);
- contents = report.getContents().getBytes();
+ result = report.generateResult();
} catch (Exception e) {
LOG.log(Level.WARNING, "Couldn't create test results report", e);
return mContext.getString(R.string.test_results_error);
}
- File reportPath = new File(Environment.getExternalStorageDirectory(), "ctsVerifierReports");
- reportPath.mkdirs();
+ // create a directory for CTS Verifier reports
+ File externalStorageDirectory = Environment.getExternalStorageDirectory();
+ File verifierReportsDir = new File(externalStorageDirectory, REPORT_DIRECTORY);
+ verifierReportsDir.mkdirs();
+ // create a temporary directory for this particular report
+ File tempDir = new File(verifierReportsDir, getReportName());
+ tempDir.mkdirs();
- String baseName = getReportBaseName();
- File reportFile = new File(reportPath, baseName + ".zip");
- ZipOutputStream out = null;
+ // create a File object for a report ZIP file
+ File reportZipFile = new File(verifierReportsDir, getReportName() + ZIP_EXTENSION);
+ // create a File object for the result XML file generated by ResultHandler
+ File tempXmlFile = new File(tempDir, ResultHandler.TEST_RESULT_FILE_NAME);
+
try {
- out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(reportFile)));
- ZipEntry entry = new ZipEntry(baseName + ".xml");
- out.putNextEntry(entry);
- out.write(contents);
- } catch (IOException e) {
+ // Serialize the report
+ String versionName = Version.getVersionName(mContext);
+ ResultHandler.writeResults(SUITE_NAME, versionName, SUITE_PLAN, SUITE_BUILD,
+ result, tempDir, START_MS, END_MS, REFERENCE_URL, LOG_URL,
+ COMMAND_LINE_ARGS);
+
+ // create a compressed ZIP file
+ FileOutputStream reportFileStream = new FileOutputStream(reportZipFile);
+ ZipOutputStream reportZipStream =
+ new ZipOutputStream(new BufferedOutputStream(reportFileStream));
+ ZipEntry entry = new ZipEntry(ResultHandler.TEST_RESULT_FILE_NAME);
+ reportZipStream.putNextEntry(entry);
+
+ // TODO: compress all results via tradefed ZipUtil or equivalent;
+ // the current implementation only saves the generated result XML
+
+ // write the report to the ZIP file and close the ZIP file
+ FileInputStream tempXmlStream = new FileInputStream(tempXmlFile);
+ int size = -1;
+ byte[] ioBuffer = new byte[BUFFER_SIZE];
+ while ((size = tempXmlStream.read(ioBuffer)) != -1) {
+ reportZipStream.write(ioBuffer, 0, size);
+ }
+ reportZipStream.close();
+
+ } catch (IOException | XmlPullParserException e) {
LOG.log(Level.WARNING, "I/O exception writing report to storage.", e);
return mContext.getString(R.string.no_storage);
} finally {
- try {
- if (out != null) {
- out.close();
- }
- } catch (IOException e) {
- LOG.log(Level.WARNING, "I/O exception closing report.", e);
- }
+ // delete the temporary results file and directory made for the reports
+ tempXmlFile.delete();
+ tempDir.delete();
}
-
- return mContext.getString(R.string.report_saved, reportFile.getPath());
+ return mContext.getString(R.string.report_saved, reportZipFile.getPath());
}
- private String getReportBaseName() {
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd-HH.mm.ss", Locale.ENGLISH);
+ private String getReportName() {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss", Locale.ENGLISH);
String date = dateFormat.format(new Date());
- return "ctsVerifierReport"
- + "-" + date
- + "-" + Build.MANUFACTURER
- + "-" + Build.PRODUCT
- + "-" + Build.DEVICE
- + "-" + Build.ID;
+ return String.format( "%s-%s-%s-%s-%s",
+ date, Build.MANUFACTURER, Build.PRODUCT, Build.DEVICE, Build.ID);
}
@Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
index 1e3f312..4dd7777 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
@@ -34,8 +34,6 @@
import android.view.Window;
import android.widget.Toast;
-import java.io.IOException;
-
/** Top-level {@link ListActivity} for launching tests and managing results. */
public class TestListActivity extends AbstractTestListActivity implements View.OnClickListener {
private static final int CTS_VERIFIER_PERMISSION_REQUEST = 1;
@@ -146,15 +144,10 @@
}
private void handleViewItemSelected() {
- try {
- TestResultsReport report = new TestResultsReport(this, mAdapter);
- Intent intent = new Intent(this, ReportViewerActivity.class);
- intent.putExtra(ReportViewerActivity.EXTRA_REPORT_CONTENTS, report.getContents());
- startActivity(intent);
- } catch (IOException e) {
- Toast.makeText(this, R.string.test_results_error, Toast.LENGTH_SHORT).show();
- Log.e(TAG, "Couldn't copy test results report", e);
- }
+ TestResultsReport report = new TestResultsReport(this, mAdapter);
+ Intent intent = new Intent(this, ReportViewerActivity.class);
+ intent.putExtra(ReportViewerActivity.EXTRA_REPORT_CONTENTS, report.getContents());
+ startActivity(intent);
}
private void handleExportItemSelected() {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
index 36be7f9..9d9739d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
@@ -21,8 +21,15 @@
import android.text.TextUtils;
import android.util.Xml;
+import com.android.compatibility.common.util.DevicePropertyInfo;
+import com.android.compatibility.common.util.ICaseResult;
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.IModuleResult;
+import com.android.compatibility.common.util.InvocationResult;
+import com.android.compatibility.common.util.ITestResult;
import com.android.compatibility.common.util.MetricsXmlSerializer;
import com.android.compatibility.common.util.ReportLog;
+import com.android.compatibility.common.util.TestStatus;
import com.android.cts.verifier.TestListAdapter.TestListItem;
import org.xmlpull.v1.XmlSerializer;
@@ -33,26 +40,10 @@
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
+import java.util.Map.Entry;
/**
- * XML text report of the current test results.
- * <p>
- * Sample:
- * <pre>
- * <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
- * <test-results-report report-version="1" creation-time="Tue Jun 28 11:04:10 PDT 2011">
- * <verifier-info version-name="2.3_r4" version-code="2" />
- * <device-info>
- * <build-info fingerprint="google/soju/crespo:2.3.4/GRJ22/121341:user/release-keys" />
- * </device-info>
- * <test-results>
- * <test title="Audio Quality Verifier" class-name="com.android.cts.verifier.audioquality.AudioQualityVerifierActivity" result="not-executed" />
- * <test title="Hardware/Software Feature Summary" class-name="com.android.cts.verifier.features.FeatureSummaryActivity" result="fail" />
- * <test title="Bluetooth Test" class-name="com.android.cts.verifier.bluetooth.BluetoothTestActivity" result="fail" />
- * <test title="Accelerometer Test" class-name="com.android.cts.verifier.sensors.AccelerometerTestActivity" result="pass" />
- * </test-results>
- * </test-results-report>
- * </pre>
+ * Helper class for creating an {@code InvocationResult} for CTS result generation.
*/
class TestResultsReport {
@@ -63,6 +54,7 @@
private static DateFormat DATE_FORMAT =
new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
+ private static final String PREFIX_TAG = "build_";
private static final String TEST_RESULTS_REPORT_TAG = "test-results-report";
private static final String VERIFIER_INFO_TAG = "verifier-info";
private static final String DEVICE_INFO_TAG = "device-info";
@@ -71,6 +63,9 @@
private static final String TEST_TAG = "test";
private static final String TEST_DETAILS_TAG = "details";
+ private static final String MODULE_ID = "noabi CtsVerifier";
+ private static final String TEST_CASE_NAME = "manualTests";
+
private final Context mContext;
private final TestListAdapter mAdapter;
@@ -80,83 +75,83 @@
this.mAdapter = adapter;
}
- String getContents() throws IllegalArgumentException, IllegalStateException, IOException {
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ IInvocationResult generateResult() {
+ String abis = null;
+ String abis32 = null;
+ String abis64 = null;
+ String versionBaseOs = null;
+ String versionSecurityPatch = null;
+ IInvocationResult result = new InvocationResult();
+ IModuleResult moduleResult = result.getOrCreateModule(MODULE_ID);
- XmlSerializer xml = Xml.newSerializer();
- xml.setOutput(outputStream, "utf-8");
- xml.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
- xml.startDocument("utf-8", true);
+ // Collect build fields available in API level 21
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ abis = TextUtils.join(",", Build.SUPPORTED_ABIS);
+ abis32 = TextUtils.join(",", Build.SUPPORTED_32_BIT_ABIS);
+ abis64 = TextUtils.join(",", Build.SUPPORTED_64_BIT_ABIS);
+ }
- xml.startTag(null, TEST_RESULTS_REPORT_TAG);
- xml.attribute(null, "report-version", Integer.toString(REPORT_VERSION));
- xml.attribute(null, "creation-time", DATE_FORMAT.format(new Date()));
+ // Collect build fields available in API level 23
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ versionBaseOs = Build.VERSION.BASE_OS;
+ versionSecurityPatch = Build.VERSION.SECURITY_PATCH;
+ }
- xml.startTag(null, VERIFIER_INFO_TAG);
- xml.attribute(null, "version-name", Version.getVersionName(mContext));
- xml.attribute(null, "version-code", Integer.toString(Version.getVersionCode(mContext)));
- xml.endTag(null, VERIFIER_INFO_TAG);
+ // at the time of writing, the build class has no REFERENCE_FINGERPRINT property
+ String referenceFingerprint = null;
- xml.startTag(null, DEVICE_INFO_TAG);
- xml.startTag(null, BUILD_INFO_TAG);
- xml.attribute(null, "board", Build.BOARD);
- xml.attribute(null, "brand", Build.BRAND);
- xml.attribute(null, "device", Build.DEVICE);
- xml.attribute(null, "display", Build.DISPLAY);
- xml.attribute(null, "fingerprint", Build.FINGERPRINT);
- xml.attribute(null, "id", Build.ID);
- xml.attribute(null, "model", Build.MODEL);
- xml.attribute(null, "product", Build.PRODUCT);
- xml.attribute(null, "release", Build.VERSION.RELEASE);
- xml.attribute(null, "sdk", Integer.toString(Build.VERSION.SDK_INT));
- xml.endTag(null, BUILD_INFO_TAG);
- xml.endTag(null, DEVICE_INFO_TAG);
+ DevicePropertyInfo devicePropertyInfo = new DevicePropertyInfo(Build.CPU_ABI,
+ Build.CPU_ABI2, abis, abis32, abis64, Build.BOARD, Build.BRAND, Build.DEVICE,
+ Build.FINGERPRINT, Build.ID, Build.MANUFACTURER, Build.MODEL, Build.PRODUCT,
+ referenceFingerprint, Build.SERIAL, Build.TAGS, Build.TYPE, versionBaseOs,
+ Build.VERSION.RELEASE, Integer.toString(Build.VERSION.SDK_INT),
+ versionSecurityPatch);
- xml.startTag(null, TEST_RESULTS_TAG);
+ // add device properties to the result with a prefix tag for each key
+ for (Entry<String, String> entry :
+ devicePropertyInfo.getPropertytMapWithPrefix(PREFIX_TAG).entrySet()) {
+ String entryValue = entry.getValue();
+ if (entryValue != null) {
+ result.addInvocationInfo(entry.getKey(), entry.getValue());
+ }
+ }
+
+ ICaseResult caseResult = moduleResult.getOrCreateResult(TEST_CASE_NAME);
int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
TestListItem item = mAdapter.getItem(i);
if (item.isTest()) {
- xml.startTag(null, TEST_TAG);
- xml.attribute(null, "title", item.title);
- xml.attribute(null, "class-name", item.testName);
- xml.attribute(null, "result", getTestResultString(mAdapter.getTestResult(i)));
+ ITestResult currentTestResult = caseResult.getOrCreateResult(item.testName);
+ currentTestResult.setResultStatus(getTestResultStatus(mAdapter.getTestResult(i)));
+ // TODO: report test details with Extended Device Info (EDI) or CTS metrics
+ // String details = mAdapter.getTestDetails(i);
- String details = mAdapter.getTestDetails(i);
- if (!TextUtils.isEmpty(details)) {
- xml.startTag(null, TEST_DETAILS_TAG);
- xml.text(details);
- xml.endTag(null, TEST_DETAILS_TAG);
- }
-
- // TODO(stuartscott): For v2: ReportLog.serialize(xml, mAdapter.getReportLog(i));
ReportLog reportLog = mAdapter.getReportLog(i);
if (reportLog != null) {
- MetricsXmlSerializer metricsXmlSerializer = new MetricsXmlSerializer(xml);
- metricsXmlSerializer.serialize(reportLog);
+ currentTestResult.setReportLog(reportLog);
}
-
- xml.endTag(null, TEST_TAG);
}
}
- xml.endTag(null, TEST_RESULTS_TAG);
+ moduleResult.setDone(true);
- xml.endTag(null, TEST_RESULTS_REPORT_TAG);
- xml.endDocument();
-
- return outputStream.toString("utf-8");
+ return result;
}
- private String getTestResultString(int testResult) {
+ String getContents() {
+ // TODO: remove getContents and everything that depends on it
+ return "Report viewing is deprecated. See contents on the SD Card.";
+ }
+
+ private TestStatus getTestResultStatus(int testResult) {
switch (testResult) {
case TestResult.TEST_RESULT_PASSED:
- return "pass";
+ return TestStatus.PASS;
case TestResult.TEST_RESULT_FAILED:
- return "fail";
+ return TestStatus.FAIL;
case TestResult.TEST_RESULT_NOT_EXECUTED:
- return "not-executed";
+ return null;
default:
throw new IllegalArgumentException("Unknown test result: " + testResult);
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
index cd1c911..0805b31 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
@@ -19,6 +19,7 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
import com.android.compatibility.common.tradefed.util.CollectorUtil;
+import com.android.compatibility.common.util.DevicePropertyInfo;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -39,30 +40,29 @@
*/
public class DeviceInfoCollector extends ApkInstrumentationPreparer {
- private static final Map<String, String> BUILD_KEYS = new HashMap<>();
- static {
- BUILD_KEYS.put("cts:build_id", "ro.build.id");
- BUILD_KEYS.put("cts:build_product", "ro.product.name");
- BUILD_KEYS.put("cts:build_device", "ro.product.device");
- BUILD_KEYS.put("cts:build_board", "ro.product.board");
- BUILD_KEYS.put("cts:build_manufacturer", "ro.product.manufacturer");
- BUILD_KEYS.put("cts:build_brand", "ro.product.brand");
- BUILD_KEYS.put("cts:build_model", "ro.product.model");
- BUILD_KEYS.put("cts:build_type", "ro.build.type");
- BUILD_KEYS.put("cts:build_tags", "ro.build.tags");
- BUILD_KEYS.put("cts:build_fingerprint", "ro.build.fingerprint");
- BUILD_KEYS.put("cts:build_abi", "ro.product.cpu.abi");
- BUILD_KEYS.put("cts:build_abi2", "ro.product.cpu.abi2");
- BUILD_KEYS.put("cts:build_abis", "ro.product.cpu.abilist");
- BUILD_KEYS.put("cts:build_abis_32", "ro.product.cpu.abilist32");
- BUILD_KEYS.put("cts:build_abis_64", "ro.product.cpu.abilist64");
- BUILD_KEYS.put("cts:build_serial", "ro.serialno");
- BUILD_KEYS.put("cts:build_version_release", "ro.build.version.release");
- BUILD_KEYS.put("cts:build_version_sdk", "ro.build.version.sdk");
- BUILD_KEYS.put("cts:build_version_base_os", "ro.build.version.base_os");
- BUILD_KEYS.put("cts:build_version_security_patch", "ro.build.version.security_patch");
- BUILD_KEYS.put("cts:build_reference_fingerprint", "ro.build.reference.fingerprint");
- }
+ private static final String ABI = "ro.product.cpu.abi";
+ private static final String ABI2 = "ro.product.cpu.abi2";
+ private static final String ABIS = "ro.product.cpu.abilist";
+ private static final String ABIS_32 = "ro.product.cpu.abilist32";
+ private static final String ABIS_64 = "ro.product.cpu.abilist64";
+ private static final String BOARD = "ro.product.board";
+ private static final String BRAND = "ro.product.brand";
+ private static final String DEVICE = "ro.product.device";
+ private static final String FINGERPRINT = "ro.build.fingerprint";
+ private static final String ID = "ro.build.id";
+ private static final String MANUFACTURER = "ro.product.manufacturer";
+ private static final String MODEL = "ro.product.model";
+ private static final String PRODUCT = "ro.product.name";
+ private static final String REFERENCE_FINGERPRINT = "ro.build.reference.fingerprint";
+ private static final String SERIAL = "ro.serialno";
+ private static final String TAGS = "ro.build.tags";
+ private static final String TYPE = "ro.build.type";
+ private static final String VERSION_BASE_OS = "ro.build.version.base_os";
+ private static final String VERSION_RELEASE = "ro.build.version.release";
+ private static final String VERSION_SDK = "ro.build.version.sdk";
+ private static final String VERSION_SECURITY_PATCH = "ro.build.version.security_patch";
+
+ private static final String PREFIX_TAG = "cts:build_";
@Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION,
shortName = 'd',
@@ -91,9 +91,16 @@
@Override
public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
BuildError, DeviceNotAvailableException {
- for (Entry<String, String> entry : BUILD_KEYS.entrySet()) {
- buildInfo.addBuildAttribute(
- entry.getKey(), nullToEmpty(device.getProperty(entry.getValue())));
+ DevicePropertyInfo devicePropertyInfo = new DevicePropertyInfo(ABI, ABI2, ABIS, ABIS_32,
+ ABIS_64, BOARD, BRAND, DEVICE, FINGERPRINT, ID, MANUFACTURER, MODEL, PRODUCT,
+ REFERENCE_FINGERPRINT, SERIAL, TAGS, TYPE, VERSION_BASE_OS, VERSION_RELEASE,
+ VERSION_SDK, VERSION_SECURITY_PATCH);
+
+ // add device properties to the result with a prefix tag for each key
+ for (Entry<String, String> entry :
+ devicePropertyInfo.getPropertytMapWithPrefix(PREFIX_TAG).entrySet()) {
+ buildInfo.addBuildAttribute(entry.getKey(),
+ nullToEmpty(device.getProperty(entry.getValue())));
}
if (mSkipDeviceInfo) {
return;
@@ -111,7 +118,7 @@
return;
}
if (mHostDir != null && mHostDir.isDirectory() &&
- mResultDir != null && mResultDir.isDirectory()) {
+ mResultDir != null && mResultDir.isDirectory()) {
CollectorUtil.pullFromHost(mHostDir, mResultDir);
}
}
diff --git a/common/util/Android.mk b/common/util/Android.mk
index c95508b..0d3754b 100644
--- a/common/util/Android.mk
+++ b/common/util/Android.mk
@@ -26,6 +26,8 @@
LOCAL_MODULE := compatibility-common-util-devicesidelib
+LOCAL_STATIC_JAVA_LIBRARIES := guava
+
LOCAL_SDK_VERSION := current
include $(BUILD_STATIC_JAVA_LIBRARY)
@@ -42,7 +44,10 @@
LOCAL_MODULE := compatibility-common-util-hostsidelib
-LOCAL_STATIC_JAVA_LIBRARIES := junit kxml2-2.3.0 platform-test-annotations-host
+LOCAL_STATIC_JAVA_LIBRARIES := guavalib \
+ junit \
+ kxml2-2.3.0 \
+ platform-test-annotations-host
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/ChecksumReporter.java b/common/util/src/com/android/compatibility/common/util/ChecksumReporter.java
similarity index 99%
rename from common/host-side/util/src/com/android/compatibility/common/util/ChecksumReporter.java
rename to common/util/src/com/android/compatibility/common/util/ChecksumReporter.java
index faac61f..32fa532 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/ChecksumReporter.java
+++ b/common/util/src/com/android/compatibility/common/util/ChecksumReporter.java
@@ -16,8 +16,6 @@
package com.android.compatibility.common.util;
-import com.android.annotations.Nullable;
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
@@ -316,7 +314,7 @@
}
private static String buildTestId(
- String suiteName, String caseName, String testName, @Nullable String abi) {
+ String suiteName, String caseName, String testName, String abi) {
String name = Joiner.on(NAME_SEPARATOR).skipNulls().join(
Strings.emptyToNull(suiteName),
Strings.emptyToNull(caseName),
diff --git a/common/util/src/com/android/compatibility/common/util/DevicePropertyInfo.java b/common/util/src/com/android/compatibility/common/util/DevicePropertyInfo.java
new file mode 100644
index 0000000..ec24b42
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/DevicePropertyInfo.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 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.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class for collecting device information. This is used to enforce
+ * consistent property collection host-side and device-side for CTS reports.
+ *
+ * Note that properties across sources can differ, e.g. {@code android.os.Build}
+ * properties sometimes deviate from the read-only properties that they're based
+ * on.
+ */
+public final class DevicePropertyInfo {
+
+ private final String mAbi;
+ private final String mAbi2;
+ private final String mAbis;
+ private final String mAbis32;
+ private final String mAbis64;
+ private final String mBoard;
+ private final String mBrand;
+ private final String mDevice;
+ private final String mFingerprint;
+ private final String mId;
+ private final String mManufacturer;
+ private final String mModel;
+ private final String mProduct;
+ private final String mReferenceFingerprint;
+ private final String mSerial;
+ private final String mTags;
+ private final String mType;
+ private final String mVersionBaseOs;
+ private final String mVersionRelease;
+ private final String mVersionSdk;
+ private final String mVersionSecurityPatch;
+
+ public DevicePropertyInfo(String abi, String abi2, String abis, String abis32, String abis64,
+ String board, String brand, String device, String fingerprint, String id,
+ String manufacturer, String model, String product, String referenceFigerprint,
+ String serial, String tags, String type, String versionBaseOs, String versionRelease,
+ String versionSdk, String versionSecurityPatch) {
+ mAbi = abi;
+ mAbi2 = abi2;
+ mAbis = abis;
+ mAbis32 = abis32;
+ mAbis64 = abis64;
+ mBoard = board;
+ mBrand = brand;
+ mDevice = device;
+ mFingerprint = fingerprint;
+ mId = id;
+ mManufacturer = manufacturer;
+ mModel = model;
+ mProduct = product;
+ mReferenceFingerprint = referenceFigerprint;
+ mSerial = serial;
+ mTags = tags;
+ mType = type;
+ mVersionBaseOs = versionBaseOs;
+ mVersionRelease = versionRelease;
+ mVersionSdk = versionSdk;
+ mVersionSecurityPatch = versionSecurityPatch;
+ }
+
+ /**
+ * Return a {@code Map} with property keys prepended with a given prefix
+ * string. This is intended to be used to generate entries for
+ * {@code} Build tag attributes in CTS test results.
+ */
+ public Map<String, String> getPropertytMapWithPrefix(String prefix) {
+ Map<String, String> propertyMap = new HashMap<>();
+
+ propertyMap.put(prefix + "abi", mAbi);
+ propertyMap.put(prefix + "abi2", mAbi2);
+ propertyMap.put(prefix + "abis", mAbis);
+ propertyMap.put(prefix + "abis_32", mAbis32);
+ propertyMap.put(prefix + "abis_64", mAbis64);
+ propertyMap.put(prefix + "board", mBoard);
+ propertyMap.put(prefix + "brand", mBrand);
+ propertyMap.put(prefix + "device", mDevice);
+ propertyMap.put(prefix + "fingerprint", mFingerprint);
+ propertyMap.put(prefix + "id", mId);
+ propertyMap.put(prefix + "manufacturer", mManufacturer);
+ propertyMap.put(prefix + "model", mModel);
+ propertyMap.put(prefix + "product", mProduct);
+ propertyMap.put(prefix + "reference_fingerprint", mReferenceFingerprint);
+ propertyMap.put(prefix + "serial", mSerial);
+ propertyMap.put(prefix + "tags", mTags);
+ propertyMap.put(prefix + "type", mType);
+ propertyMap.put(prefix + "version_base_os", mVersionBaseOs);
+ propertyMap.put(prefix + "version_release", mVersionRelease);
+ propertyMap.put(prefix + "version_sdk", mVersionSdk);
+ propertyMap.put(prefix + "version_security_patch", mVersionSecurityPatch);
+
+ return propertyMap;
+ }
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/ModuleResult.java b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
index 60038cf..16d8964 100644
--- a/common/util/src/com/android/compatibility/common/util/ModuleResult.java
+++ b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
@@ -168,7 +168,8 @@
*/
@Override
public String getName() {
- return AbiUtils.parseTestName(mId);
+ // TODO: switch to using AbiUtils#parseTestName when available
+ return parseId(mId)[1];
}
/**
@@ -176,7 +177,21 @@
*/
@Override
public String getAbi() {
- return AbiUtils.parseAbi(mId);
+ // TODO: switch to using AbiUtils#parseAbi when available
+ return parseId(mId)[0];
+ }
+
+ /**
+ * Parses a unique id into the ABI and name.
+ * @param id The id to parse.
+ * @return a string array containing the ABI and name.
+ */
+ private static String[] parseId(String id) {
+ // TODO: remove this when AbiUtils is available for getName and getAbi
+ if (id == null || !id.contains(" ")) {
+ return new String[] {"", ""};
+ }
+ return id.split(" ");
}
/**
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/ResultHandler.java b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
similarity index 96%
rename from common/host-side/util/src/com/android/compatibility/common/util/ResultHandler.java
rename to common/util/src/com/android/compatibility/common/util/ResultHandler.java
index 89ec2d4..1cdc38a 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/ResultHandler.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
@@ -25,6 +25,7 @@
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
@@ -33,9 +34,6 @@
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
@@ -60,7 +58,7 @@
private static final String TYPE = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer";
private static final String NS = null;
private static final String RESULT_FILE_VERSION = "5.0";
- /* package */ static final String TEST_RESULT_FILE_NAME = "test_result.xml";
+ public static final String TEST_RESULT_FILE_NAME = "test_result.xml";
private static final String FAILURE_REPORT_NAME = "test_result_failures.html";
private static final String FAILURE_XSL_FILE_NAME = "compatibility_failures.xsl";
@@ -182,7 +180,8 @@
parser.require(XmlPullParser.START_TAG, NS, MODULE_TAG);
String name = parser.getAttributeValue(NS, NAME_ATTR);
String abi = parser.getAttributeValue(NS, ABI_ATTR);
- String moduleId = AbiUtils.createId(abi, name);
+ // TODO: use AbiUtils#createId when available for use
+ String moduleId = String.format("%s %s", abi, name);
boolean done = Boolean.parseBoolean(parser.getAttributeValue(NS, DONE_ATTR));
IModuleResult module = invocation.getOrCreateModule(moduleId);
module.initializeDone(done);
@@ -451,18 +450,22 @@
// If the previous run has an invalid checksum file,
// copy it into current results folder for future troubleshooting
File retryDirectory = invocationResult.getRetryDirectory();
- Path retryChecksum = FileSystems.getDefault().getPath(
- retryDirectory.getAbsolutePath(), ChecksumReporter.NAME);
- if (!retryChecksum.toFile().exists()) {
+ File retryChecksum = new File(retryDirectory, ChecksumReporter.NAME);
+ if (!retryChecksum.exists()) {
// if no checksum file, check for a copy from a previous retry
- retryChecksum = FileSystems.getDefault().getPath(
- retryDirectory.getAbsolutePath(), ChecksumReporter.PREV_NAME);
+ retryChecksum = new File(retryDirectory, ChecksumReporter.PREV_NAME);
}
- if (retryChecksum.toFile().exists()) {
+ if (retryChecksum.exists()) {
File checksumCopy = new File(resultDir, ChecksumReporter.PREV_NAME);
- try (FileOutputStream stream = new FileOutputStream(checksumCopy)) {
- Files.copy(retryChecksum, stream);
+ try (OutputStream out = new FileOutputStream(checksumCopy);
+ InputStream in = new FileInputStream(retryChecksum)) {
+ // Copy the bits from input stream to output stream
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
} catch (IOException e) {
// Do not disrupt the process if there is a problem copying checksum
}
diff --git a/common/host-side/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
similarity index 97%
rename from common/host-side/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
rename to common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
index 0dfe3f3..4f89a78 100644
--- a/common/host-side/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
@@ -70,13 +70,8 @@
private static final String METHOD_3 = "testBlah3";
private static final String METHOD_4 = "testBlah4";
private static final String SUMMARY_SOURCE = String.format("%s#%s:20", CLASS_B, METHOD_4);
- private static final String DETAILS_SOURCE = String.format("%s#%s:18", CLASS_B, METHOD_4);
private static final String SUMMARY_MESSAGE = "Headline";
private static final double SUMMARY_VALUE = 9001;
- private static final String DETAILS_MESSAGE = "Deats";
- private static final double DETAILS_VALUE_1 = 14;
- private static final double DETAILS_VALUE_2 = 18;
- private static final double DETAILS_VALUE_3 = 17;
private static final String MESSAGE = "Something small is not alright";
private static final String STACK_TRACE = "Something small is not alright\n " +
"at four.big.insects.Marley.sing(Marley.java:10)";
diff --git a/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java b/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java
index e6c6a87..faa4690 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java
@@ -34,6 +34,7 @@
addTestSuite(ModuleResultTest.class);
addTestSuite(MultipartFormTest.class);
addTestSuite(ReportLogTest.class);
+ addTestSuite(ResultHandlerTest.class);
addTestSuite(StatTest.class);
addTestSuite(TestFilterTest.class);
addTestSuite(TestResultTest.class);
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index a22d539..d901926 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -23,7 +23,15 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctsdeviceutil ctstestrunner services.core
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 \
+ android-support-multidex \
+ ctsdeviceutil \
+ ctstestrunner \
+ services.core
+
+# Use multi-dex as the compatibility-common-util-devicesidelib dependency
+# on ctsdeviceutil pushes us beyond 64k methods.
+LOCAL_JACK_FLAGS := --multi-dex legacy
# Resource unit tests use a private locale and some densities
LOCAL_AAPT_FLAGS = -c xx_YY -c cs -c small -c normal -c large -c xlarge \