summaryrefslogtreecommitdiffstats
path: root/core/tests/hosttests/src/android/content/pm/PackageManagerStressHostTests.java
blob: a2a5dd3afe70258aaf46aa0a404721cdae637cf9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
/*
 * 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.AdbCommandRejectedException;
import com.android.ddmlib.InstallException;
import com.android.ddmlib.Log;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.TimeoutException;
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,
            InstallException, TimeoutException, AdbCommandRejectedException,
            ShellCommandUnresponsiveException {
        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,
            InstallException, TimeoutException, AdbCommandRejectedException,
            ShellCommandUnresponsiveException {
        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,
            InstallException, TimeoutException, AdbCommandRejectedException,
            ShellCommandUnresponsiveException {
        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,
            InstallException, TimeoutException, AdbCommandRejectedException,
            ShellCommandUnresponsiveException {
        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));
            }
        }
    }
}