blob: 715c55b9bbf4c440ebd21c997ae992206d8d4f35 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content.pm;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
import com.android.hosttest.DeviceTestCase;
import com.android.hosttest.DeviceTestSuite;
import java.io.File;
import java.io.IOException;
import junit.framework.Test;
/**
* Set of tests that verify host side stress scenarios (large apps, multiple upgrades, etc.)
*/
public class PackageManagerStressHostTests extends DeviceTestCase {
private static final String LOG_TAG = "PackageManagerStressHostTests";
private PackageManagerHostTestUtils mPMHostUtils = null;
// Path to the app repository and various subdirectories of it
// Note: These stress tests require large apks that cannot be checked into the tree.
// These variables define static locations that point to existing APKs (not built from
// the tree) which can be used by the the stress tests in this file.
private static final String LARGE_APPS_DIRECTORY_NAME = "largeApps";
private static final String MISC_APPS_DIRECTORY_NAME = "miscApps";
private static final String VERSIONED_APPS_DIRECTORY_NAME = "versionedApps";
private static final String MANY_APPS_DIRECTORY_NAME = "manyApps";
// Note: An external environment variable "ANDROID_TEST_APP_REPOSITORY" must be set
// which points to the root location of the app respository.
private static String AppRepositoryPath = null;
// Large apps (>1mb) - filenames and their corresponding package names:
private static enum APK {
FILENAME,
PACKAGENAME;
}
private static final String[][] LARGE_APPS = {
{"External1mb.apk", "com.appsonsd.mytests.External1mb"},
{"External2mb.apk", "com.appsonsd.mytests.External2mb"},
{"External3mb.apk", "com.appsonsd.mytests.External3mb"},
{"External4mb.apk", "com.appsonsd.mytests.External4mb"},
{"External5mb.apk", "com.appsonsd.mytests.External5mb"},
{"External6mb.apk", "com.appsonsd.mytests.External6mb"},
{"External7mb.apk", "com.appsonsd.mytests.External7mb"},
{"External8mb.apk", "com.appsonsd.mytests.External8mb"},
{"External9mb.apk", "com.appsonsd.mytests.External9mb"},
{"External10mb.apk", "com.appsonsd.mytests.External10mb"},
{"External16mb.apk", "com.appsonsd.mytests.External16mb"},
{"External28mb.apk", "com.appsonsd.mytests.External28mb"},
{"External34mb.apk", "com.appsonsd.mytests.External34mb"},
{"External46mb.apk", "com.appsonsd.mytests.External46mb"},
{"External58mb.apk", "com.appsonsd.mytests.External58mb"},
{"External65mb.apk", "com.appsonsd.mytests.External65mb"},
{"External72mb.apk", "com.appsonsd.mytests.External72mb"},
{"External79mb.apk", "com.appsonsd.mytests.External79mb"},
{"External86mb.apk", "com.appsonsd.mytests.External86mb"},
{"External93mb.apk", "com.appsonsd.mytests.External93mb"}};
// Various test files and their corresponding package names
private static final String AUTO_LOC_APK = "Auto241kb.apk";
private static final String AUTO_LOC_PKG = "com.appsonsd.mytests.Auto241kb";
private static final String INTERNAL_LOC_APK = "Internal781kb.apk";
private static final String INTERNAL_LOC_PKG = "com.appsonsd.mytests.Internal781kb";
private static final String EXTERNAL_LOC_APK = "External931kb.apk";
private static final String EXTERNAL_LOC_PKG = "com.appsonsd.mytests.External931kb";
private static final String NO_LOC_APK = "Internal751kb_EclairSDK.apk";
private static final String NO_LOC_PKG = "com.appsonsd.mytests.Internal751kb_EclairSDK";
// Versioned test apps
private static final String VERSIONED_APPS_FILENAME_PREFIX = "External455kb_v";
private static final String VERSIONED_APPS_PKG = "com.appsonsd.mytests.External455kb";
private static final int VERSIONED_APPS_START_VERSION = 1; // inclusive
private static final int VERSIONED_APPS_END_VERSION = 250; // inclusive
// Large number of app installs
// @TODO: increase the max when we can install more apps
private static final int MANY_APPS_START = 1;
private static final int MANY_APPS_END = 100;
private static final String MANY_APPS_PKG_PREFIX = "com.appsonsd.mytests.External49kb_";
private static final String MANY_APPS_APK_PREFIX = "External49kb_";
public static Test suite() {
return new DeviceTestSuite(PackageManagerStressHostTests.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
// setup the PackageManager host tests utilities class, and get various paths we'll need...
mPMHostUtils = new PackageManagerHostTestUtils(getDevice());
AppRepositoryPath = System.getenv("ANDROID_TEST_APP_REPOSITORY");
assertNotNull(AppRepositoryPath);
// Make sure path ends with a separator
if (!AppRepositoryPath.endsWith(File.separator)) {
AppRepositoryPath += File.separator;
}
}
/**
* Get the absolute file system location of repository test app with given filename
* @param fileName the file name of the test app apk
* @return {@link String} of absolute file path
*/
private String getRepositoryTestAppFilePath(String fileDirectory, String fileName) {
return String.format("%s%s%s%s", AppRepositoryPath, fileDirectory,
File.separator, fileName);
}
/**
* Get the absolute file system location of test app with given filename
* @param fileName the file name of the test app apk
* @return {@link String} of absolute file path
*/
public String getTestAppFilePath(String fileName) {
return String.format("%s%s%s", getTestAppPath(), File.separator, fileName);
}
/**
* Stress test to verify that we can update an app multiple times on the SD card.
* <p/>
* Assumes adb is running as root in device under test.
*/
public void testUpdateAppManyTimesOnSD() throws IOException, InterruptedException {
Log.i(LOG_TAG, "Test updating an app on SD numerous times");
// cleanup test app just in case it already exists
mPMHostUtils.uninstallApp(VERSIONED_APPS_PKG);
// grep for package to make sure its not installed
assertFalse(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG));
try {
for (int i = VERSIONED_APPS_START_VERSION; i <= VERSIONED_APPS_END_VERSION; ++i) {
String currentApkName = String.format("%s%d.apk",
VERSIONED_APPS_FILENAME_PREFIX, i);
Log.i(LOG_TAG, "Installing app " + currentApkName);
mPMHostUtils.installFile(getRepositoryTestAppFilePath(VERSIONED_APPS_DIRECTORY_NAME,
currentApkName), true);
mPMHostUtils.waitForPackageManager();
assertTrue(mPMHostUtils.doesAppExistOnSDCard(VERSIONED_APPS_PKG));
assertTrue(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG));
}
}
finally {
// cleanup test app
mPMHostUtils.uninstallApp(VERSIONED_APPS_PKG);
// grep for package to make sure its not installed
assertFalse(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG));
}
}
/**
* Stress test to verify that an app can be installed, uninstalled, and
* reinstalled on SD many times.
* <p/>
* Assumes adb is running as root in device under test.
*/
public void testUninstallReinstallAppOnSDManyTimes() throws IOException, InterruptedException {
Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card");
// cleanup test app just in case it was already exists
mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG);
// grep for package to make sure its not installed
assertFalse(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG));
for (int i = 0; i <= 500; ++i) {
Log.i(LOG_TAG, "Installing app");
try {
// install the app
mPMHostUtils.installFile(getRepositoryTestAppFilePath(MISC_APPS_DIRECTORY_NAME,
EXTERNAL_LOC_APK), false);
mPMHostUtils.waitForPackageManager();
assertTrue(mPMHostUtils.doesAppExistOnSDCard(EXTERNAL_LOC_PKG));
assertTrue(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG));
}
finally {
// now uninstall the app
Log.i(LOG_TAG, "Uninstalling app");
mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG);
mPMHostUtils.waitForPackageManager();
assertFalse(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG));
}
}
}
/**
* Stress test to verify that we can install, 20 large apps (>1mb each)
* <p/>
* Assumes adb is running as root in device under test.
*/
public void testInstallManyLargeAppsOnSD() throws IOException, InterruptedException {
Log.i(LOG_TAG, "Test installing 20 large apps onto the sd card");
try {
// Install all the large apps
for (int i=0; i < LARGE_APPS.length; ++i) {
String apkName = LARGE_APPS[i][APK.FILENAME.ordinal()];
String pkgName = LARGE_APPS[i][APK.PACKAGENAME.ordinal()];
// cleanup test app just in case it already exists
mPMHostUtils.uninstallApp(pkgName);
// grep for package to make sure its not installed
assertFalse(mPMHostUtils.doesPackageExist(pkgName));
Log.i(LOG_TAG, "Installing app " + apkName);
// install the app
mPMHostUtils.installFile(getRepositoryTestAppFilePath(LARGE_APPS_DIRECTORY_NAME,
apkName), false);
mPMHostUtils.waitForPackageManager();
assertTrue(mPMHostUtils.doesAppExistOnSDCard(pkgName));
assertTrue(mPMHostUtils.doesPackageExist(pkgName));
}
}
finally {
// Cleanup - ensure we uninstall all large apps if they were installed
for (int i=0; i < LARGE_APPS.length; ++i) {
String apkName = LARGE_APPS[i][APK.FILENAME.ordinal()];
String pkgName = LARGE_APPS[i][APK.PACKAGENAME.ordinal()];
Log.i(LOG_TAG, "Uninstalling app " + apkName);
// cleanup test app just in case it was accidently installed
mPMHostUtils.uninstallApp(pkgName);
// grep for package to make sure its not installed anymore
assertFalse(mPMHostUtils.doesPackageExist(pkgName));
assertFalse(mPMHostUtils.doesAppExistOnSDCard(pkgName));
}
}
}
/**
* Stress test to verify that we can install many small apps onto SD.
* <p/>
* Assumes adb is running as root in device under test.
*/
public void testInstallManyAppsOnSD() throws IOException, InterruptedException {
Log.i(LOG_TAG, "Test installing 500 small apps onto SD");
try {
for (int i = MANY_APPS_START; i <= MANY_APPS_END; ++i) {
String currentPkgName = String.format("%s%d", MANY_APPS_PKG_PREFIX, i);
// cleanup test app just in case it already exists
mPMHostUtils.uninstallApp(currentPkgName);
// grep for package to make sure its not installed
assertFalse(mPMHostUtils.doesPackageExist(currentPkgName));
String currentApkName = String.format("%s%d.apk", MANY_APPS_APK_PREFIX, i);
Log.i(LOG_TAG, "Installing app " + currentApkName);
mPMHostUtils.installFile(getRepositoryTestAppFilePath(MANY_APPS_DIRECTORY_NAME,
currentApkName), true);
mPMHostUtils.waitForPackageManager();
assertTrue(mPMHostUtils.doesAppExistOnSDCard(currentPkgName));
assertTrue(mPMHostUtils.doesPackageExist(currentPkgName));
}
}
finally {
for (int i = MANY_APPS_START; i <= MANY_APPS_END; ++i) {
String currentPkgName = String.format("%s%d", MANY_APPS_PKG_PREFIX, i);
// cleanup test app
mPMHostUtils.uninstallApp(currentPkgName);
// grep for package to make sure its not installed
assertFalse(mPMHostUtils.doesPackageExist(currentPkgName));
}
}
}
}