summaryrefslogtreecommitdiffstats
path: root/tests/SmokeTest
diff options
context:
space:
mode:
authorOmari Stephens <xsdg@android.com>2012-03-08 18:27:33 -0800
committerOmari Stephens <xsdg@android.com>2012-03-12 15:26:11 -0700
commit5ae3dfe59d22457fb232853990ba4131385ff3f6 (patch)
treedab5bc5fcc884a3dfd36962ca2166504642ddc7e /tests/SmokeTest
parent583e885bef9891f582d19b06d575fc0cd96620a0 (diff)
downloadframeworks_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/SmokeTest')
-rw-r--r--tests/SmokeTest/tests/AndroidManifest.xml22
-rw-r--r--tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java130
-rw-r--r--tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java94
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;
+ }
+}
+