1 /* 2 * Copyright (C) 2015 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.compatibility.common.tradefed.targetprep; 18 19 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 20 import com.android.ddmlib.testrunner.TestResult.TestStatus; 21 import com.android.tradefed.config.IConfiguration; 22 import com.android.tradefed.config.IConfigurationReceiver; 23 import com.android.tradefed.config.Option; 24 import com.android.tradefed.config.OptionClass; 25 import com.android.tradefed.device.DeviceNotAvailableException; 26 import com.android.tradefed.device.ITestDevice; 27 import com.android.tradefed.invoker.TestInformation; 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.targetprep.BuildError; 34 import com.android.tradefed.targetprep.TargetSetupError; 35 import com.android.tradefed.testtype.AndroidJUnitTest; 36 37 import java.io.File; 38 import java.io.FileNotFoundException; 39 import java.util.Map.Entry; 40 41 /** Target preparer that instruments an APK. */ 42 @OptionClass(alias = "apk-instrumentation-preparer") 43 public class ApkInstrumentationPreparer extends PreconditionPreparer 44 implements IConfigurationReceiver { 45 46 @Option(name = "apk", description = "Name of the apk to instrument", mandatory = true) 47 protected String mApkFileName = null; 48 49 @Option(name = "package", description = "Name of the package", mandatory = true) 50 protected String mPackageName = null; 51 52 public enum When { 53 BEFORE, AFTER, BOTH; 54 } 55 56 @Option(name = "when", description = "When to instrument the apk", mandatory = true) 57 protected When mWhen = null; 58 59 @Option(name = "throw-error", description = "Whether to throw error for device test failure") 60 protected boolean mThrowError = true; 61 62 private IConfiguration mConfiguration = null; 63 64 /** {@inheritDoc} */ 65 @Override setConfiguration(IConfiguration configuration)66 public void setConfiguration(IConfiguration configuration) { 67 mConfiguration = configuration; 68 } 69 70 /** {@inheritDoc} */ 71 @Override run(TestInformation testInfo)72 public void run(TestInformation testInfo) 73 throws TargetSetupError, BuildError, DeviceNotAvailableException { 74 if (mWhen == When.AFTER) { 75 return; 76 } 77 ITestDevice device = testInfo.getDevice(); 78 try { 79 if (instrument(testInfo)) { 80 CLog.d("Target preparation successful"); 81 } else if (mThrowError) { 82 throw new TargetSetupError("Not all target preparation steps completed", 83 device.getDeviceDescriptor()); 84 } 85 } catch (FileNotFoundException e) { 86 throw new TargetSetupError("Couldn't find apk to instrument", e, 87 device.getDeviceDescriptor()); 88 } 89 } 90 91 /** {@inheritDoc} */ 92 @Override tearDown(TestInformation testInfo, Throwable e)93 public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException { 94 if (e instanceof DeviceNotAvailableException) { 95 return; 96 } 97 if (mWhen == When.BEFORE) { 98 return; 99 } 100 try { 101 instrument(testInfo); 102 } catch (FileNotFoundException e1) { 103 CLog.e("Couldn't find apk to instrument"); 104 CLog.e(e1); 105 } 106 } 107 instrument(TestInformation testInfo)108 private boolean instrument(TestInformation testInfo) 109 throws DeviceNotAvailableException, FileNotFoundException { 110 CompatibilityBuildHelper buildHelper = 111 new CompatibilityBuildHelper(testInfo.getBuildInfo()); 112 113 File apkFile = buildHelper.getTestFile(mApkFileName); 114 if (!apkFile.exists()) { 115 throw new FileNotFoundException(String.format("%s not found", mApkFileName)); 116 } 117 118 ITestDevice device = testInfo.getDevice(); 119 if (device.getAppPackageInfo(mPackageName) != null) { 120 CLog.i("Package %s already present on the device, uninstalling ...", mPackageName); 121 device.uninstallPackage(mPackageName); 122 } 123 124 CLog.i("Instrumenting package: %s", mPackageName); 125 CollectingTestListener listener = new CollectingTestListener(); 126 AndroidJUnitTest instrTest = new AndroidJUnitTest(); 127 instrTest.setConfiguration(mConfiguration); 128 instrTest.setDevice(device); 129 instrTest.setInstallFile(apkFile); 130 instrTest.setPackageName(mPackageName); 131 instrTest.setRerunMode(false); 132 instrTest.setReRunUsingTestFile(false); 133 // TODO: Make this configurable. 134 instrTest.setIsolatedStorage(false); 135 instrTest.run(testInfo, listener); 136 TestRunResult result = listener.getCurrentRunResults(); 137 138 for (Entry<TestDescription, TestResult> results : result.getTestResults().entrySet()) { 139 if (TestStatus.FAILURE.equals(results.getValue().getStatus())) { 140 if (mThrowError) { 141 CLog.e( 142 "Target preparation step %s failed.\n%s", 143 results.getKey(), results.getValue().getStackTrace()); 144 } else { 145 CLog.w( 146 "Target preparation step %s failed.\n%s", 147 results.getKey(), results.getValue().getStackTrace()); 148 } 149 } 150 } 151 // If any failure return false 152 return !(result.isRunFailure() || result.hasFailedTests()); 153 } 154 } 155