summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorAgatha Man <agathaman@google.com>2016-10-13 21:35:17 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-10-13 21:35:17 +0000
commitd5989e473319d3d523b6187760424a4d1cfb9119 (patch)
tree859de09572803a0a8b22e80c6e760c70099d2ad4 /common
parentee4149a0416f2682da0aaaa4bc8535a5203a8162 (diff)
parent4cc4075c19862d1c5245365de41b290983ed01ac (diff)
downloadplatform_cts-d5989e473319d3d523b6187760424a4d1cfb9119.tar.gz
platform_cts-d5989e473319d3d523b6187760424a4d1cfb9119.tar.bz2
platform_cts-d5989e473319d3d523b6187760424a4d1cfb9119.zip
CTS: Add host-side EDI
am: 4cc4075c19 Change-Id: Id313251b910108a9942286c83e3c525b8a56fa5f
Diffstat (limited to 'common')
-rw-r--r--common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java69
-rw-r--r--common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/CollectorUtil.java180
-rw-r--r--common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java2
-rw-r--r--common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/CollectorUtilTest.java51
-rw-r--r--common/host-side/util/src/com/android/compatibility/common/util/DeviceInfo.java55
5 files changed, 337 insertions, 20 deletions
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 dd91d11a685..08055a34360 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
@@ -18,6 +18,7 @@ package com.android.compatibility.common.tradefed.targetprep;
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.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -26,6 +27,7 @@ import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.targetprep.BuildError;
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.util.ArrayUtil;
+import com.android.tradefed.util.FileUtil;
import java.io.File;
import java.io.FileNotFoundException;
@@ -74,8 +76,17 @@ public class DeviceInfoCollector extends ApkInstrumentationPreparer {
@Option(name = "dest-dir", description = "The directory under the result to store the files")
private String mDestDir;
+ @Option(name = "temp-dir", description = "The directory containing host-side device info files")
+ private String mTempDir;
+
+ // Temp directory for host-side device info files.
+ private File mHostDir;
+
+ // Destination result directory for all device info files.
+ private File mResultDir;
+
public DeviceInfoCollector() {
- mWhen = When.BEFORE;
+ mWhen = When.BOTH;
}
@Override
@@ -88,39 +99,57 @@ public class DeviceInfoCollector extends ApkInstrumentationPreparer {
if (mSkipDeviceInfo) {
return;
}
+
+ createTempHostDir();
+ createResultDir(buildInfo);
run(device, buildInfo);
- getDeviceInfoFiles(device, buildInfo);
+ getDeviceInfoFiles(device);
+ }
+
+ @Override
+ public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e) {
+ if (mSkipDeviceInfo) {
+ return;
+ }
+ if (mHostDir != null && mHostDir.isDirectory() &&
+ mResultDir != null && mResultDir.isDirectory()) {
+ CollectorUtil.pullFromHost(mHostDir, mResultDir);
+ }
}
- private void getDeviceInfoFiles(ITestDevice device, IBuildInfo buildInfo) {
+ private void createTempHostDir() {
+ try {
+ mHostDir = FileUtil.createNamedTempDir(mTempDir);
+ if (!mHostDir.isDirectory()) {
+ CLog.e("%s is not a directory", mHostDir.getAbsolutePath());
+ return;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void createResultDir(IBuildInfo buildInfo) {
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
try {
- File resultDir = buildHelper.getResultDir();
+ mResultDir = buildHelper.getResultDir();
if (mDestDir != null) {
- resultDir = new File(resultDir, mDestDir);
+ mResultDir = new File(mResultDir, mDestDir);
}
- resultDir.mkdirs();
- if (!resultDir.isDirectory()) {
- CLog.e("%s is not a directory", resultDir.getAbsolutePath());
+ mResultDir.mkdirs();
+ if (!mResultDir.isDirectory()) {
+ CLog.e("%s is not a directory", mResultDir.getAbsolutePath());
return;
}
- String resultPath = resultDir.getAbsolutePath();
- pull(device, mSrcDir, resultPath);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
}
- private void pull(ITestDevice device, String src, String dest) {
- String command = String.format("adb -s %s pull %s %s", device.getSerialNumber(), src, dest);
- try {
- Process p = Runtime.getRuntime().exec(new String[] {"/bin/bash", "-c", command});
- if (p.waitFor() != 0) {
- CLog.e("Failed to run %s", command);
- }
- } catch (Exception e) {
- CLog.e("Caught exception during pull.");
- CLog.e(e);
+ private void getDeviceInfoFiles(ITestDevice device) {
+ if (mResultDir != null && mResultDir.isDirectory()) {
+ String mResultPath = mResultDir.getAbsolutePath();
+ CollectorUtil.pullFromDevice(device, mSrcDir, mResultPath);
}
}
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/CollectorUtil.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/CollectorUtil.java
new file mode 100644
index 00000000000..a6645155237
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/CollectorUtil.java
@@ -0,0 +1,180 @@
+/*
+ * 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.tradefed.util;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.util.FileUtil;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Util class for {@link ReportLogCollector} and {@link DeviceInfoCollector}.
+ */
+public class CollectorUtil {
+
+ private CollectorUtil() {
+ }
+
+ private static final String ADB_LS_PATTERN = "([^\\s]+)\\s*";
+ private static final String TEST_METRICS_PATTERN = "\\\"([a-z0-9_]*)\\\":(\\{[^{}]*\\})";
+
+ /**
+ * Copy files from device to host.
+ * @param device The device reference.
+ * @param src The source directory on the device.
+ * @param dest The destination directory.
+ */
+ public static void pullFromDevice(ITestDevice device, String src, String dest) {
+ try {
+ if (device.doesFileExist(src)) {
+ String listCommand = String.format("ls %s", src);
+ String fileList = device.executeShellCommand(listCommand);
+ Pattern p = Pattern.compile(ADB_LS_PATTERN);
+ Matcher m = p.matcher(fileList);
+ while (m.find()) {
+ String fileName = m.group(1);
+ String srcPath = String.format("%s%s", src, fileName);
+ File destFile = new File(String.format("%s/%s", dest, fileName));
+ device.pullFile(srcPath, destFile);
+ }
+ }
+ } catch (DeviceNotAvailableException e) {
+ CLog.e("Caught exception during pull.");
+ CLog.e(e);
+ }
+ }
+
+ /**
+ * Copy files from host and delete from source.
+ * @param src The source directory.
+ * @param dest The destination directory.
+ */
+ public static void pullFromHost(File src, File dest) {
+ try {
+ FileUtil.recursiveCopy(src, dest);
+ FileUtil.recursiveDelete(src);
+ } catch (IOException e) {
+ CLog.e("Caught exception during pull.");
+ CLog.e(e);
+ }
+ }
+
+ /**
+ * Reformat test metrics jsons to convert multiple json objects with identical stream names into
+ * arrays of objects (b/28790467).
+ *
+ * @param resultDir The directory containing test metrics.
+ */
+ public static void reformatRepeatedStreams(File resultDir) {
+ try {
+ File[] reportLogs = resultDir.listFiles();
+ for (File reportLog : reportLogs) {
+ writeFile(reportLog, reformatJsonString(readFile(reportLog)));
+ }
+ } catch (IOException e) {
+ CLog.e("Caught exception during reformatting.");
+ CLog.e(e);
+ }
+ }
+
+ /**
+ * Helper function to read a file.
+ *
+ * @throws IOException
+ */
+ private static String readFile(File file) throws IOException {
+ StringBuilder stringBuilder = new StringBuilder();
+ try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ stringBuilder.append(line);
+ }
+ }
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Helper function to write to a file.
+ *
+ * @param file {@link File} to write to.
+ * @param jsonString String to be written.
+ * @throws IOException
+ */
+ private static void writeFile(File file, String jsonString) throws IOException {
+ file.createNewFile();
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
+ writer.write(jsonString, 0, jsonString.length());
+ }
+ }
+
+ /**
+ * Helper function to reformat JSON string.
+ *
+ * @param jsonString
+ * @return
+ */
+ public static String reformatJsonString(String jsonString) {
+ StringBuilder newJsonBuilder = new StringBuilder();
+ // Create map of stream names and json objects.
+ HashMap<String, List<String>> jsonMap = new HashMap<>();
+ Pattern p = Pattern.compile(TEST_METRICS_PATTERN);
+ Matcher m = p.matcher(jsonString);
+ while (m.find()) {
+ String key = m.group(1);
+ String value = m.group(2);
+ if (!jsonMap.containsKey(key)) {
+ jsonMap.put(key, new ArrayList<String>());
+ }
+ jsonMap.get(key).add(value);
+ }
+ // Rewrite json string as arrays.
+ newJsonBuilder.append("{");
+ boolean firstLine = true;
+ for (String key : jsonMap.keySet()) {
+ if (!firstLine) {
+ newJsonBuilder.append(",");
+ } else {
+ firstLine = false;
+ }
+ newJsonBuilder.append("\"").append(key).append("\":[");
+ boolean firstValue = true;
+ for (String stream : jsonMap.get(key)) {
+ if (!firstValue) {
+ newJsonBuilder.append(",");
+ } else {
+ firstValue = false;
+ }
+ newJsonBuilder.append(stream);
+ }
+ newJsonBuilder.append("]");
+ }
+ newJsonBuilder.append("}");
+ return newJsonBuilder.toString();
+ }
+} \ No newline at end of file
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 b7101282a0c..dfe67c136c5 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
@@ -25,6 +25,7 @@ import com.android.compatibility.common.tradefed.testtype.CompatibilityTestTest;
import com.android.compatibility.common.tradefed.testtype.ModuleDefTest;
import com.android.compatibility.common.tradefed.testtype.ModuleRepoTest;
import com.android.compatibility.common.tradefed.util.OptionHelperTest;
+import com.android.compatibility.common.tradefed.util.CollectorUtilTest;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -45,6 +46,7 @@ public class UnitTests extends TestSuite {
addTestSuite(ResultReporterTest.class);
addTestSuite(CompatibilityTestTest.class);
addTestSuite(OptionHelperTest.class);
+ addTestSuite(CollectorUtilTest.class);
addTestSuite(ModuleDefTest.class);
addTestSuite(ModuleRepoTest.class);
addTestSuite(PropertyCheckTest.class);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/CollectorUtilTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/CollectorUtilTest.java
new file mode 100644
index 00000000000..d5b71fa6c01
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/CollectorUtilTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.tradefed.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link CollectorUtil}
+ */
+public class CollectorUtilTest extends TestCase {
+
+ String UNFORMATTED_JSON = "{"
+ + "\"stream_name_1\":"
+ + "{\"id\":1,\"key1\":\"value1\"},"
+ + "\"stream_name_2\":"
+ + "{\"id\":1,\"key1\":\"value3\"},"
+ + "\"stream_name_1\":"
+ + "{\"id\":2,\"key1\":\"value2\"},"
+ + "}";
+
+ String REFORMATTED_JSON = "{"
+ + "\"stream_name_2\":"
+ + "["
+ + "{\"id\":1,\"key1\":\"value3\"}"
+ + "],"
+ + "\"stream_name_1\":"
+ + "["
+ + "{\"id\":1,\"key1\":\"value1\"},"
+ + "{\"id\":2,\"key1\":\"value2\"}"
+ + "]"
+ + "}";
+
+ public void testReformatJsonString() throws Exception {
+ String reformattedJson = CollectorUtil.reformatJsonString(UNFORMATTED_JSON);
+ assertEquals(reformattedJson, REFORMATTED_JSON);
+ }
+
+} \ No newline at end of file
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/DeviceInfo.java b/common/host-side/util/src/com/android/compatibility/common/util/DeviceInfo.java
new file mode 100644
index 00000000000..ef05813361e
--- /dev/null
+++ b/common/host-side/util/src/com/android/compatibility/common/util/DeviceInfo.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.android.compatibility.common.util.HostInfoStore;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.util.FileUtil;
+
+import java.io.File;
+
+/**
+ * Collect device information from host and write to a JSON file.
+ */
+public abstract class DeviceInfo extends DeviceTestCase {
+
+ // Temporary folder must match the temp-dir value configured in DeviceInfoCollector target
+ // preparer in cts/tools/cts-tradefed/res/config/cts-preconditions.xml
+ private static final String TEMPORARY_REPORT_FOLDER = "temp-device-info-files/";
+
+ private HostInfoStore mStore;
+
+ public void testCollectDeviceInfo() throws Exception {
+ String collectionName = getClass().getSimpleName();
+ try {
+ final File dir = FileUtil.createNamedTempDir(TEMPORARY_REPORT_FOLDER);
+ File jsonFile = new File(dir, collectionName + ".deviceinfo.json");
+ mStore = new HostInfoStore(jsonFile);
+ mStore.open();
+ collectDeviceInfo(mStore);
+ mStore.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(String.format("Failed to collect device info (%s): %s",
+ collectionName, e.getMessage()));
+ }
+ }
+
+ /**
+ * Method to collect device information.
+ */
+ protected abstract void collectDeviceInfo(HostInfoStore store) throws Exception;
+} \ No newline at end of file