1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.packagemanager.stats.host; 18 19 import static org.junit.Assert.assertNotNull; 20 import static org.junit.Assert.assertTrue; 21 22 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 23 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner; 24 import com.android.tradefed.build.IBuildInfo; 25 import com.android.tradefed.device.DeviceNotAvailableException; 26 import com.android.tradefed.device.ITestDevice; 27 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; 28 import com.android.tradefed.result.CollectingTestListener; 29 import com.android.tradefed.result.TestDescription; 30 import com.android.tradefed.result.TestResult; 31 import com.android.tradefed.result.TestRunResult; 32 33 import java.io.File; 34 import java.util.HashMap; 35 import java.util.Map; 36 37 public final class Utils { 38 public static final String SIGNATURE_FILE_SUFFIX = ".idsig"; 39 pushApkToRemote(String apkName, String remoteDirPath, IBuildInfo ctsBuild, ITestDevice device)40 public static String pushApkToRemote(String apkName, String remoteDirPath, IBuildInfo ctsBuild, 41 ITestDevice device) throws Exception { 42 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(ctsBuild); 43 final File apk = buildHelper.getTestFile(apkName); 44 final File signature = buildHelper.getTestFile(apkName + SIGNATURE_FILE_SUFFIX); 45 assertNotNull(apk); 46 assertNotNull(signature); 47 final String remoteApkPath = remoteDirPath + "/" + apk.getName(); 48 final String remoteSignaturePath = remoteApkPath + SIGNATURE_FILE_SUFFIX; 49 assertTrue(device.pushFile(apk, remoteApkPath)); 50 assertTrue(device.pushFile(signature, remoteSignaturePath)); 51 return remoteApkPath; 52 } 53 runDeviceTests(ITestDevice device, String packageName, String testClassName, String testMethodName, Map<String, String> testArgs)54 public static Map<String, String> runDeviceTests(ITestDevice device, String packageName, 55 String testClassName, String testMethodName, Map<String, String> testArgs) 56 throws DeviceNotAvailableException { 57 if (testClassName != null && testClassName.startsWith(".")) { 58 testClassName = packageName + testClassName; 59 } 60 RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName, 61 "androidx.test.runner.AndroidJUnitRunner", device.getIDevice()); 62 63 if (testClassName != null && testMethodName != null) { 64 testRunner.setMethodName(testClassName, testMethodName); 65 } else if (testClassName != null) { 66 testRunner.setClassName(testClassName); 67 } 68 69 if (testArgs != null && testArgs.size() > 0) { 70 for (String name : testArgs.keySet()) { 71 final String value = testArgs.get(name); 72 testRunner.addInstrumentationArg(name, value); 73 } 74 } 75 final TestResultListener listener = new TestResultListener(); 76 assertTrue(device.runInstrumentationTests(testRunner, listener)); 77 78 final TestRunResult result = listener.getCurrentRunResults(); 79 if (result.isRunFailure()) { 80 throw new Error("Failed to successfully run device tests for " 81 + result.getName() + ": " + result.getRunFailureMessage()); 82 } 83 if (result.getNumTests() == 0) { 84 throw new Error("No tests were run on the device"); 85 } 86 if (result.hasFailedTests()) { 87 StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n"); 88 for (Map.Entry<TestDescription, TestResult> resultEntry : 89 result.getTestResults().entrySet()) { 90 if (!resultEntry.getValue().getStatus().equals( 91 com.android.ddmlib.testrunner.TestResult.TestStatus.PASSED)) { 92 errorBuilder.append(resultEntry.getKey().toString()); 93 errorBuilder.append(":\n"); 94 errorBuilder.append(resultEntry.getValue().getStackTrace()); 95 } 96 } 97 throw new AssertionError(errorBuilder.toString()); 98 } 99 100 if (listener.mFailureStackTrace != null) { 101 throw new AssertionError("Failed to successfully run device tests: " 102 + listener.mFailureStackTrace); 103 } 104 return listener.mMetrics; 105 } 106 107 /* Special listener for collecting data from the test result */ 108 private static class TestResultListener extends CollectingTestListener { 109 private final Map<String, String> mMetrics = new HashMap<>(); 110 private String mFailureStackTrace = null; 111 112 @Override testEnded(TestDescription test, Map<String, String> metrics)113 public void testEnded(TestDescription test, Map<String, String> metrics) { 114 mMetrics.putAll(metrics); 115 } 116 117 @Override testEnded(TestDescription test, HashMap<String, Metric> metrics)118 public void testEnded(TestDescription test, HashMap<String, Metric> metrics) { 119 for (Map.Entry<String, Metric> e: metrics.entrySet()) { 120 mMetrics.put(e.getKey(), e.getValue().getMeasurements().getSingleString()); 121 } 122 } 123 124 @Override testFailed(TestDescription test, String trace)125 public void testFailed(TestDescription test, String trace) { 126 mFailureStackTrace = trace; 127 } 128 } 129 hasIncrementalFeature(ITestDevice device)130 public static boolean hasIncrementalFeature(ITestDevice device) throws Exception { 131 return "true\n".equals(device.executeShellCommand( 132 "pm has-feature android.software.incremental_delivery")); 133 } 134 } 135