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