diff options
author | Agatha Man <agathaman@google.com> | 2016-10-13 21:35:17 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-10-13 21:35:17 +0000 |
commit | d5989e473319d3d523b6187760424a4d1cfb9119 (patch) | |
tree | 859de09572803a0a8b22e80c6e760c70099d2ad4 /common | |
parent | ee4149a0416f2682da0aaaa4bc8535a5203a8162 (diff) | |
parent | 4cc4075c19862d1c5245365de41b290983ed01ac (diff) | |
download | platform_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')
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 |