1 /* 2 * Copyright (C) 2010 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.content.pm; 18 19 import com.android.ddmlib.AdbCommandRejectedException; 20 import com.android.ddmlib.InstallException; 21 import com.android.ddmlib.Log; 22 import com.android.ddmlib.ShellCommandUnresponsiveException; 23 import com.android.ddmlib.TimeoutException; 24 import com.android.hosttest.DeviceTestCase; 25 import com.android.hosttest.DeviceTestSuite; 26 27 import java.io.File; 28 import java.io.IOException; 29 30 import junit.framework.Test; 31 32 /** 33 * Set of tests that verify host side stress scenarios (large apps, multiple upgrades, etc.) 34 */ 35 public class PackageManagerStressHostTests extends DeviceTestCase { 36 37 private static final String LOG_TAG = "PackageManagerStressHostTests"; 38 private PackageManagerHostTestUtils mPMHostUtils = null; 39 40 // Path to the app repository and various subdirectories of it 41 // Note: These stress tests require large apks that cannot be checked into the tree. 42 // These variables define static locations that point to existing APKs (not built from 43 // the tree) which can be used by the the stress tests in this file. 44 private static final String LARGE_APPS_DIRECTORY_NAME = "largeApps"; 45 private static final String MISC_APPS_DIRECTORY_NAME = "miscApps"; 46 private static final String VERSIONED_APPS_DIRECTORY_NAME = "versionedApps"; 47 private static final String MANY_APPS_DIRECTORY_NAME = "manyApps"; 48 49 // Note: An external environment variable "ANDROID_TEST_APP_REPOSITORY" must be set 50 // which points to the root location of the app respository. 51 private static String AppRepositoryPath = null; 52 53 // Large apps (>1mb) - filenames and their corresponding package names: 54 private static enum APK { 55 FILENAME, 56 PACKAGENAME; 57 } 58 private static final String[][] LARGE_APPS = { 59 {"External1mb.apk", "com.appsonsd.mytests.External1mb"}, 60 {"External2mb.apk", "com.appsonsd.mytests.External2mb"}, 61 {"External3mb.apk", "com.appsonsd.mytests.External3mb"}, 62 {"External4mb.apk", "com.appsonsd.mytests.External4mb"}, 63 {"External5mb.apk", "com.appsonsd.mytests.External5mb"}, 64 {"External6mb.apk", "com.appsonsd.mytests.External6mb"}, 65 {"External7mb.apk", "com.appsonsd.mytests.External7mb"}, 66 {"External8mb.apk", "com.appsonsd.mytests.External8mb"}, 67 {"External9mb.apk", "com.appsonsd.mytests.External9mb"}, 68 {"External10mb.apk", "com.appsonsd.mytests.External10mb"}, 69 {"External16mb.apk", "com.appsonsd.mytests.External16mb"}, 70 {"External28mb.apk", "com.appsonsd.mytests.External28mb"}, 71 {"External34mb.apk", "com.appsonsd.mytests.External34mb"}, 72 {"External46mb.apk", "com.appsonsd.mytests.External46mb"}, 73 {"External58mb.apk", "com.appsonsd.mytests.External58mb"}, 74 {"External65mb.apk", "com.appsonsd.mytests.External65mb"}, 75 {"External72mb.apk", "com.appsonsd.mytests.External72mb"}, 76 {"External79mb.apk", "com.appsonsd.mytests.External79mb"}, 77 {"External86mb.apk", "com.appsonsd.mytests.External86mb"}, 78 {"External93mb.apk", "com.appsonsd.mytests.External93mb"}}; 79 80 // Various test files and their corresponding package names 81 private static final String AUTO_LOC_APK = "Auto241kb.apk"; 82 private static final String AUTO_LOC_PKG = "com.appsonsd.mytests.Auto241kb"; 83 private static final String INTERNAL_LOC_APK = "Internal781kb.apk"; 84 private static final String INTERNAL_LOC_PKG = "com.appsonsd.mytests.Internal781kb"; 85 private static final String EXTERNAL_LOC_APK = "External931kb.apk"; 86 private static final String EXTERNAL_LOC_PKG = "com.appsonsd.mytests.External931kb"; 87 private static final String NO_LOC_APK = "Internal751kb_EclairSDK.apk"; 88 private static final String NO_LOC_PKG = "com.appsonsd.mytests.Internal751kb_EclairSDK"; 89 // Versioned test apps 90 private static final String VERSIONED_APPS_FILENAME_PREFIX = "External455kb_v"; 91 private static final String VERSIONED_APPS_PKG = "com.appsonsd.mytests.External455kb"; 92 private static final int VERSIONED_APPS_START_VERSION = 1; // inclusive 93 private static final int VERSIONED_APPS_END_VERSION = 250; // inclusive 94 // Large number of app installs 95 // @TODO: increase the max when we can install more apps 96 private static final int MANY_APPS_START = 1; 97 private static final int MANY_APPS_END = 100; 98 private static final String MANY_APPS_PKG_PREFIX = "com.appsonsd.mytests.External49kb_"; 99 private static final String MANY_APPS_APK_PREFIX = "External49kb_"; 100 101 public static Test suite() { 102 return new DeviceTestSuite(PackageManagerStressHostTests.class); 103 } 104 105 @Override 106 protected void setUp() throws Exception { 107 super.setUp(); 108 109 // setup the PackageManager host tests utilities class, and get various paths we'll need... 110 mPMHostUtils = new PackageManagerHostTestUtils(getDevice()); 111 AppRepositoryPath = System.getenv("ANDROID_TEST_APP_REPOSITORY"); 112 assertNotNull(AppRepositoryPath); 113 114 // Make sure path ends with a separator 115 if (!AppRepositoryPath.endsWith(File.separator)) { 116 AppRepositoryPath += File.separator; 117 } 118 } 119 120 /** 121 * Get the absolute file system location of repository test app with given filename 122 * @param fileName the file name of the test app apk 123 * @return {@link String} of absolute file path 124 */ 125 private String getRepositoryTestAppFilePath(String fileDirectory, String fileName) { 126 return String.format("%s%s%s%s", AppRepositoryPath, fileDirectory, 127 File.separator, fileName); 128 } 129 130 /** 131 * Get the absolute file system location of test app with given filename 132 * @param fileName the file name of the test app apk 133 * @return {@link String} of absolute file path 134 */ 135 public String getTestAppFilePath(String fileName) { 136 return String.format("%s%s%s", getTestAppPath(), File.separator, fileName); 137 } 138 139 /** 140 * Stress test to verify that we can update an app multiple times on the SD card. 141 * <p/> 142 * Assumes adb is running as root in device under test. 143 */ 144 public void testUpdateAppManyTimesOnSD() throws IOException, InterruptedException, 145 InstallException, TimeoutException, AdbCommandRejectedException, 146 ShellCommandUnresponsiveException { 147 Log.i(LOG_TAG, "Test updating an app on SD numerous times"); 148 149 // cleanup test app just in case it already exists 150 mPMHostUtils.uninstallApp(VERSIONED_APPS_PKG); 151 // grep for package to make sure its not installed 152 assertFalse(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG)); 153 154 try { 155 for (int i = VERSIONED_APPS_START_VERSION; i <= VERSIONED_APPS_END_VERSION; ++i) { 156 String currentApkName = String.format("%s%d.apk", 157 VERSIONED_APPS_FILENAME_PREFIX, i); 158 159 Log.i(LOG_TAG, "Installing app " + currentApkName); 160 mPMHostUtils.installFile(getRepositoryTestAppFilePath(VERSIONED_APPS_DIRECTORY_NAME, 161 currentApkName), true); 162 mPMHostUtils.waitForPackageManager(); 163 assertTrue(mPMHostUtils.doesAppExistOnSDCard(VERSIONED_APPS_PKG)); 164 assertTrue(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG)); 165 } 166 } 167 finally { 168 // cleanup test app 169 mPMHostUtils.uninstallApp(VERSIONED_APPS_PKG); 170 // grep for package to make sure its not installed 171 assertFalse(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG)); 172 } 173 } 174 175 /** 176 * Stress test to verify that an app can be installed, uninstalled, and 177 * reinstalled on SD many times. 178 * <p/> 179 * Assumes adb is running as root in device under test. 180 */ 181 public void testUninstallReinstallAppOnSDManyTimes() throws IOException, InterruptedException, 182 InstallException, TimeoutException, AdbCommandRejectedException, 183 ShellCommandUnresponsiveException { 184 Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card"); 185 186 // cleanup test app just in case it was already exists 187 mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG); 188 // grep for package to make sure its not installed 189 assertFalse(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG)); 190 191 for (int i = 0; i <= 500; ++i) { 192 Log.i(LOG_TAG, "Installing app"); 193 194 try { 195 // install the app 196 mPMHostUtils.installFile(getRepositoryTestAppFilePath(MISC_APPS_DIRECTORY_NAME, 197 EXTERNAL_LOC_APK), false); 198 mPMHostUtils.waitForPackageManager(); 199 assertTrue(mPMHostUtils.doesAppExistOnSDCard(EXTERNAL_LOC_PKG)); 200 assertTrue(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG)); 201 } 202 finally { 203 // now uninstall the app 204 Log.i(LOG_TAG, "Uninstalling app"); 205 mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG); 206 mPMHostUtils.waitForPackageManager(); 207 assertFalse(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG)); 208 } 209 } 210 } 211 212 /** 213 * Stress test to verify that we can install, 20 large apps (>1mb each) 214 * <p/> 215 * Assumes adb is running as root in device under test. 216 */ 217 public void testInstallManyLargeAppsOnSD() throws IOException, InterruptedException, 218 InstallException, TimeoutException, AdbCommandRejectedException, 219 ShellCommandUnresponsiveException { 220 Log.i(LOG_TAG, "Test installing 20 large apps onto the sd card"); 221 222 try { 223 // Install all the large apps 224 for (int i=0; i < LARGE_APPS.length; ++i) { 225 String apkName = LARGE_APPS[i][APK.FILENAME.ordinal()]; 226 String pkgName = LARGE_APPS[i][APK.PACKAGENAME.ordinal()]; 227 228 // cleanup test app just in case it already exists 229 mPMHostUtils.uninstallApp(pkgName); 230 // grep for package to make sure its not installed 231 assertFalse(mPMHostUtils.doesPackageExist(pkgName)); 232 233 Log.i(LOG_TAG, "Installing app " + apkName); 234 // install the app 235 mPMHostUtils.installFile(getRepositoryTestAppFilePath(LARGE_APPS_DIRECTORY_NAME, 236 apkName), false); 237 mPMHostUtils.waitForPackageManager(); 238 assertTrue(mPMHostUtils.doesAppExistOnSDCard(pkgName)); 239 assertTrue(mPMHostUtils.doesPackageExist(pkgName)); 240 } 241 } 242 finally { 243 // Cleanup - ensure we uninstall all large apps if they were installed 244 for (int i=0; i < LARGE_APPS.length; ++i) { 245 String apkName = LARGE_APPS[i][APK.FILENAME.ordinal()]; 246 String pkgName = LARGE_APPS[i][APK.PACKAGENAME.ordinal()]; 247 248 Log.i(LOG_TAG, "Uninstalling app " + apkName); 249 // cleanup test app just in case it was accidently installed 250 mPMHostUtils.uninstallApp(pkgName); 251 // grep for package to make sure its not installed anymore 252 assertFalse(mPMHostUtils.doesPackageExist(pkgName)); 253 assertFalse(mPMHostUtils.doesAppExistOnSDCard(pkgName)); 254 } 255 } 256 } 257 258 /** 259 * Stress test to verify that we can install many small apps onto SD. 260 * <p/> 261 * Assumes adb is running as root in device under test. 262 */ 263 public void testInstallManyAppsOnSD() throws IOException, InterruptedException, 264 InstallException, TimeoutException, AdbCommandRejectedException, 265 ShellCommandUnresponsiveException { 266 Log.i(LOG_TAG, "Test installing 500 small apps onto SD"); 267 268 try { 269 for (int i = MANY_APPS_START; i <= MANY_APPS_END; ++i) { 270 String currentPkgName = String.format("%s%d", MANY_APPS_PKG_PREFIX, i); 271 272 // cleanup test app just in case it already exists 273 mPMHostUtils.uninstallApp(currentPkgName); 274 // grep for package to make sure its not installed 275 assertFalse(mPMHostUtils.doesPackageExist(currentPkgName)); 276 277 String currentApkName = String.format("%s%d.apk", MANY_APPS_APK_PREFIX, i); 278 Log.i(LOG_TAG, "Installing app " + currentApkName); 279 mPMHostUtils.installFile(getRepositoryTestAppFilePath(MANY_APPS_DIRECTORY_NAME, 280 currentApkName), true); 281 mPMHostUtils.waitForPackageManager(); 282 assertTrue(mPMHostUtils.doesAppExistOnSDCard(currentPkgName)); 283 assertTrue(mPMHostUtils.doesPackageExist(currentPkgName)); 284 } 285 } 286 finally { 287 for (int i = MANY_APPS_START; i <= MANY_APPS_END; ++i) { 288 String currentPkgName = String.format("%s%d", MANY_APPS_PKG_PREFIX, i); 289 290 // cleanup test app 291 mPMHostUtils.uninstallApp(currentPkgName); 292 // grep for package to make sure its not installed 293 assertFalse(mPMHostUtils.doesPackageExist(currentPkgName)); 294 } 295 } 296 } 297 }