1 /* 2 * Copyright (C) 2016 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 android.cts.statsdatom.statsd; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.truth.Truth.assertWithMessage; 21 22 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 23 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner; 24 import com.android.ddmlib.testrunner.TestResult.TestStatus; 25 import com.android.tradefed.build.IBuildInfo; 26 import com.android.tradefed.device.CollectingByteOutputReceiver; 27 import com.android.tradefed.device.DeviceNotAvailableException; 28 import com.android.tradefed.log.LogUtil.CLog; 29 import com.android.tradefed.result.CollectingTestListener; 30 import com.android.tradefed.result.TestDescription; 31 import com.android.tradefed.result.TestResult; 32 import com.android.tradefed.result.TestRunResult; 33 import com.android.tradefed.testtype.DeviceTestCase; 34 import com.android.tradefed.testtype.IBuildReceiver; 35 36 import com.google.protobuf.InvalidProtocolBufferException; 37 import com.google.protobuf.MessageLite; 38 import com.google.protobuf.Parser; 39 40 import java.io.FileNotFoundException; 41 import java.util.Map; 42 43 import javax.annotation.Nonnull; 44 import javax.annotation.Nullable; 45 46 // Largely copied from incident's ProtoDumpTestCase 47 public class BaseTestCase extends DeviceTestCase implements IBuildReceiver { 48 49 protected IBuildInfo mCtsBuild; 50 51 private static final String TEST_RUNNER = "androidx.test.runner.AndroidJUnitRunner"; 52 53 @Override setUp()54 protected void setUp() throws Exception { 55 super.setUp(); 56 assertThat(mCtsBuild).isNotNull(); 57 } 58 59 @Override setBuild(IBuildInfo buildInfo)60 public void setBuild(IBuildInfo buildInfo) { 61 mCtsBuild = buildInfo; 62 } 63 getBuild()64 public IBuildInfo getBuild() { 65 return mCtsBuild; 66 } 67 68 /** 69 * Call onto the device with an adb shell command and get the results of 70 * that as a proto of the given type. 71 * 72 * @param parser A protobuf parser object. e.g. MyProto.parser() 73 * @param command The adb shell command to run. e.g. "dumpsys fingerprint --proto" 74 * 75 * @throws DeviceNotAvailableException If there was a problem communicating with 76 * the test device. 77 * @throws InvalidProtocolBufferException If there was an error parsing 78 * the proto. Note that a 0 length buffer is not necessarily an error. 79 */ getDump(Parser<T> parser, String command)80 public <T extends MessageLite> T getDump(Parser<T> parser, String command) 81 throws DeviceNotAvailableException, InvalidProtocolBufferException { 82 final CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver(); 83 getDevice().executeShellCommand(command, receiver); 84 if (false) { 85 CLog.d("Command output while parsing " + parser.getClass().getCanonicalName() 86 + " for command: " + command + "\n" 87 + BufferDebug.debugString(receiver.getOutput(), -1)); 88 } 89 try { 90 return parser.parseFrom(receiver.getOutput()); 91 } catch (Exception ex) { 92 CLog.d("Error parsing " + parser.getClass().getCanonicalName() + " for command: " 93 + command 94 + BufferDebug.debugString(receiver.getOutput(), 16384)); 95 throw ex; 96 } 97 } 98 99 /** 100 * Install a device side test package. 101 * 102 * @param appFileName Apk file name, such as "CtsNetStatsApp.apk". 103 * @param grantPermissions whether to give runtime permissions. 104 */ installPackage(String appFileName, boolean grantPermissions)105 protected void installPackage(String appFileName, boolean grantPermissions) 106 throws FileNotFoundException, DeviceNotAvailableException { 107 CLog.d("Installing app " + appFileName); 108 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild); 109 final String result = getDevice().installPackage( 110 buildHelper.getTestFile(appFileName), true, grantPermissions); 111 assertWithMessage(String.format("Failed to install %s: %s", appFileName, result)) 112 .that(result).isNull(); 113 } 114 getBuildHelper()115 protected CompatibilityBuildHelper getBuildHelper() { 116 return new CompatibilityBuildHelper(mCtsBuild); 117 } 118 119 /** 120 * Run a device side test. 121 * 122 * @param pkgName Test package name, such as "com.android.server.cts.netstats". 123 * @param testClassName Test class name; either a fully qualified name, or "." + a class name. 124 * @param testMethodName Test method name. 125 * @return {@link TestRunResult} of this invocation. 126 * @throws DeviceNotAvailableException 127 */ 128 @Nonnull runDeviceTests(@onnull String pkgName, @Nullable String testClassName, @Nullable String testMethodName)129 protected TestRunResult runDeviceTests(@Nonnull String pkgName, 130 @Nullable String testClassName, @Nullable String testMethodName) 131 throws DeviceNotAvailableException { 132 if (testClassName != null && testClassName.startsWith(".")) { 133 testClassName = pkgName + testClassName; 134 } 135 136 RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner( 137 pkgName, TEST_RUNNER, getDevice().getIDevice()); 138 if (testClassName != null && testMethodName != null) { 139 testRunner.setMethodName(testClassName, testMethodName); 140 } else if (testClassName != null) { 141 testRunner.setClassName(testClassName); 142 } 143 144 CollectingTestListener listener = new CollectingTestListener(); 145 assertThat(getDevice().runInstrumentationTests(testRunner, listener)).isTrue(); 146 147 final TestRunResult result = listener.getCurrentRunResults(); 148 if (result.isRunFailure()) { 149 throw new Error("Failed to successfully run device tests for " 150 + result.getName() + ": " + result.getRunFailureMessage()); 151 } 152 if (result.getNumTests() == 0) { 153 throw new Error("No tests were run on the device"); 154 } 155 156 if (result.hasFailedTests()) { 157 // build a meaningful error message 158 StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n"); 159 for (Map.Entry<TestDescription, TestResult> resultEntry : 160 result.getTestResults().entrySet()) { 161 if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) { 162 errorBuilder.append(resultEntry.getKey().toString()); 163 errorBuilder.append(":\n"); 164 errorBuilder.append(resultEntry.getValue().getStackTrace()); 165 } 166 } 167 throw new AssertionError(errorBuilder.toString()); 168 } 169 170 return result; 171 } 172 } 173