diff options
author | Omari Stephens <xsdg@android.com> | 2012-03-08 18:27:33 -0800 |
---|---|---|
committer | Omari Stephens <xsdg@android.com> | 2012-03-12 15:26:11 -0700 |
commit | 5ae3dfe59d22457fb232853990ba4131385ff3f6 (patch) | |
tree | dab5bc5fcc884a3dfd36962ca2166504642ddc7e /tests | |
parent | 583e885bef9891f582d19b06d575fc0cd96620a0 (diff) | |
download | frameworks_base-5ae3dfe59d22457fb232853990ba4131385ff3f6.zip frameworks_base-5ae3dfe59d22457fb232853990ba4131385ff3f6.tar.gz frameworks_base-5ae3dfe59d22457fb232853990ba4131385ff3f6.tar.bz2 |
Refactor smoke tests to enable one-app-per-testcase runs
Also creates a special TestRunner which runs one app per testcase. Note that
running the smoke tests with android.test.InstrumentationTestRunner will /also/
work, but will run all of the launchable activites in a single testcase called
testRunAllActivities.
Bug: 6128185
Change-Id: Iffedff7e6105bbca614778a4d294d3be421f19d6
Diffstat (limited to 'tests')
3 files changed, 193 insertions, 53 deletions
diff --git a/tests/SmokeTest/tests/AndroidManifest.xml b/tests/SmokeTest/tests/AndroidManifest.xml index 517eb1e..cad37c5 100644 --- a/tests/SmokeTest/tests/AndroidManifest.xml +++ b/tests/SmokeTest/tests/AndroidManifest.xml @@ -18,20 +18,30 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.smoketest.tests"> - <!-- We add an application tag here just so that we can indicate that - this package needs to link against the android.test library, - which is needed when building test cases. --> + <!-- + We add an application tag here just so that we can indicate that this package needs to link + against the android.test library, which is needed when building test cases. + --> <application> <uses-library android:name="android.test.runner" /> </application> <!-- - This declares that this app uses the instrumentation test runner targeting - the package of com.android.smoketest. To run the tests use the command: - "adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner" + This declares that this app uses the instrumentation test runner targeting the package of + com.android.smoketest. To run the tests use the command: + `adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner` --> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.android.smoketest" android:label="System Smoke Tests"/> + <!-- + This declares a method to run the instrumentation with a special runner, which will run each + app as a separate testcase. To do so, use the command: + `adb shell am instrument -w com.android.smoketest.tests/com.android.smoketest.SmokeTestRunner` + --> + <instrumentation android:name="com.android.smoketest.SmokeTestRunner" + android:targetPackage="com.android.smoketest" + android:label="System Smoke Tests"/> + </manifest> diff --git a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java index 1a2dcb9..3efd658 100644 --- a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java +++ b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java @@ -16,8 +16,6 @@ package com.android.smoketest; -import com.android.internal.os.RuntimeInit; - import android.app.ActivityManager; import android.app.ActivityManager.ProcessErrorStateInfo; import android.content.Context; @@ -42,10 +40,18 @@ import java.util.Set; public class ProcessErrorsTest extends AndroidTestCase { private static final String TAG = "ProcessErrorsTest"; - + + private final Intent mHomeIntent; + protected ActivityManager mActivityManager; protected PackageManager mPackageManager; + public ProcessErrorsTest() { + mHomeIntent = new Intent(Intent.ACTION_MAIN); + mHomeIntent.addCategory(Intent.CATEGORY_HOME); + mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + @Override public void setUp() throws Exception { super.setUp(); @@ -59,7 +65,7 @@ public class ProcessErrorsTest extends AndroidTestCase { assertNotNull(mPackageManager); } - public void testNoProcessErrors() throws Exception { + public void testNoProcessErrorsAfterBoot() throws Exception { final String reportMsg = checkForProcessErrors(); if (reportMsg != null) { Log.w(TAG, reportMsg); @@ -72,16 +78,80 @@ public class ProcessErrorsTest extends AndroidTestCase { private String checkForProcessErrors() throws Exception { List<ProcessErrorStateInfo> errList; errList = mActivityManager.getProcessesInErrorState(); - + // note: this contains information about each process that is currently in an error - // condition. if the list is empty (null) then "we're good". - + // condition. if the list is empty (null) then "we're good". + // if the list is non-empty, then it's useful to report the contents of the list final String reportMsg = reportListContents(errList); return reportMsg; } /** + * A helper function to query the provided {@link PackageManager} for a list of Activities that + * can be launched from Launcher. + */ + static List<ResolveInfo> getLauncherActivities(PackageManager pm) { + final Intent launchable = new Intent(Intent.ACTION_MAIN); + launchable.addCategory(Intent.CATEGORY_LAUNCHER); + final List<ResolveInfo> activities = pm.queryIntentActivities(launchable, 0); + return activities; + } + + /** + * A helper function to create an {@link Intent} to run, given a {@link ResolveInfo} specifying + * an activity to be launched. + */ + static Intent intentForActivity(ResolveInfo app) { + // build an Intent to launch the specified app + final ComponentName component = new ComponentName(app.activityInfo.packageName, + app.activityInfo.name); + final Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setComponent(component); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + return intent; + } + + /** + * A method to run the specified Activity and return a {@link Collection} of the Activities that + * were in an error state, as listed by {@link ActivityManager.getProcessesInErrorState()}. + * <p /> + * The method will launch the app, wait for 7 seconds, check for apps in the error state, send + * the Home intent, wait for 2 seconds, and then return. + */ + public Collection<ProcessErrorStateInfo> runOneActivity(ResolveInfo app) { + final long appLaunchWait = 7000; + final long homeLaunchWait = 2000; + + Log.i(TAG, String.format("Running activity %s/%s", app.activityInfo.packageName, + app.activityInfo.name)); + + // launch app, and wait 7 seconds for it to start/settle + final Intent intent = intentForActivity(app); + getContext().startActivity(intent); + try { + Thread.sleep(appLaunchWait); + } catch (InterruptedException e) { + // ignore + } + + // See if there are any errors + final Collection<ProcessErrorStateInfo> errProcs = + mActivityManager.getProcessesInErrorState(); + + // Send the "home" intent and wait 2 seconds for us to get there + getContext().startActivity(mHomeIntent); + try { + Thread.sleep(homeLaunchWait); + } catch (InterruptedException e) { + // ignore + } + + return errProcs; + } + + /** * A test that runs all Launcher-launchable activities and verifies that no ANRs or crashes * happened while doing so. * <p /> @@ -89,46 +159,12 @@ public class ProcessErrorsTest extends AndroidTestCase { * FIXME: first app doesn't go away. */ public void testRunAllActivities() throws Exception { - final Intent home = new Intent(Intent.ACTION_MAIN); - home.addCategory(Intent.CATEGORY_HOME); - home.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - - final Intent launchable = new Intent(Intent.ACTION_MAIN); - launchable.addCategory(Intent.CATEGORY_LAUNCHER); - final List<ResolveInfo> activities = mPackageManager.queryIntentActivities(launchable, 0); final Set<ProcessError> errSet = new HashSet<ProcessError>(); - for (ResolveInfo info : activities) { - Log.i(TAG, String.format("Got %s/%s", info.activityInfo.packageName, - info.activityInfo.name)); - - // build an Intent to launch the app - final ComponentName component = new ComponentName(info.activityInfo.packageName, - info.activityInfo.name); - final Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setComponent(component); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - - // launch app, and wait 7 seconds for it to start/settle - getContext().startActivity(intent); - try { - Thread.sleep(7000); - } catch (InterruptedException e) { - // ignore - } - - // See if there are any errors - Collection<ProcessErrorStateInfo> procs = mActivityManager.getProcessesInErrorState(); - if (procs != null) { - errSet.addAll(ProcessError.fromCollection(procs)); - } - - // Send the "home" intent and wait 2 seconds for us to get there - getContext().startActivity(home); - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - // ignore + for (ResolveInfo app : getLauncherActivities(mPackageManager)) { + final Collection<ProcessErrorStateInfo> errProcs = runOneActivity(app); + if (errProcs != null) { + errSet.addAll(ProcessError.fromCollection(errProcs)); } } @@ -138,7 +174,7 @@ public class ProcessErrorsTest extends AndroidTestCase { } } - private String reportWrappedListContents(Collection<ProcessError> errList) { + String reportWrappedListContents(Collection<ProcessError> errList) { List<ProcessErrorStateInfo> newList = new ArrayList<ProcessErrorStateInfo>(errList.size()); for (ProcessError err : errList) { newList.add(err.info); @@ -186,7 +222,7 @@ public class ProcessErrorsTest extends AndroidTestCase { * A {@link ProcessErrorStateInfo} wrapper class that hashes how we want (so that equivalent * crashes are considered equal). */ - private static class ProcessError { + static class ProcessError { public final ProcessErrorStateInfo info; public ProcessError(ProcessErrorStateInfo newInfo) { diff --git a/tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java b/tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java new file mode 100644 index 0000000..40b11c5 --- /dev/null +++ b/tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012 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 com.android.smoketest; + +import android.app.ActivityManager; +import android.app.ActivityManager.ProcessErrorStateInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.test.InstrumentationTestRunner; + +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * A special test runner which does a test-start for each app in a separate testcase + */ +public class SmokeTestRunner extends InstrumentationTestRunner { + + private static final String SUITE_NAME = "Smoke Test Suite"; + + /** + * Returns a single testcase for each app to launch + */ + @Override + public TestSuite getAllTests() { + final TestSuite suite = new TestSuite(SUITE_NAME); + + final PackageManager pm = getTargetContext().getPackageManager(); + final List<ResolveInfo> apps = ProcessErrorsTest.getLauncherActivities(pm); + + // FIXME: figure out some way to control the reported class names for these anonymous + // FIXME: class instances. + + final TestCase setupTest = new ProcessErrorsTest() { + @Override + public void runTest() throws Exception { + testSetUpConditions(); + } + }; + setupTest.setName("testSetUpConditions"); + suite.addTest(setupTest); + + final TestCase postBootTest = new ProcessErrorsTest() { + @Override + public void runTest() throws Exception { + testNoProcessErrorsAfterBoot(); + } + }; + postBootTest.setName("testNoProcessErrorsAfterBoot"); + suite.addTest(postBootTest); + + for (final ResolveInfo app : apps) { + final TestCase appTest = new ProcessErrorsTest() { + @Override + public void runTest() throws Exception { + final Set<ProcessError> errSet = new HashSet<ProcessError>(); + final Collection<ProcessErrorStateInfo> errProcs = runOneActivity(app); + if (errProcs != null) { + errSet.addAll(ProcessError.fromCollection(errProcs)); + } + + if (!errSet.isEmpty()) { + fail(String.format("Got %d errors: %s", errSet.size(), + reportWrappedListContents(errSet))); + } + } + }; + appTest.setName(app.activityInfo.name); + suite.addTest(appTest); + } + + return suite; + } +} + |