Home | History | Annotate | Download | only in pm
      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 }