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.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 }