Loading tests/SmokeTest/tests/AndroidManifest.xml +16 −6 Original line number Diff line number Diff line Loading @@ -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> tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java +83 −47 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -43,9 +41,17 @@ 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(); Loading @@ -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); Loading @@ -82,54 +88,84 @@ public class ProcessErrorsTest extends AndroidTestCase { } /** * A test that runs all Launcher-launchable activities and verifies that no ANRs or crashes * happened while doing so. * <p /> * FIXME: Doesn't detect multiple crashing apps properly, since the crash dialog for the * FIXME: first app doesn't go away. * A helper function to query the provided {@link PackageManager} for a list of Activities that * can be launched from Launcher. */ 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); static List<ResolveInfo> getLauncherActivities(PackageManager pm) { 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)); final List<ResolveInfo> activities = pm.queryIntentActivities(launchable, 0); return activities; } // build an Intent to launch the app final ComponentName component = new ComponentName(info.activityInfo.packageName, info.activityInfo.name); /** * 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(7000); Thread.sleep(appLaunchWait); } catch (InterruptedException e) { // ignore } // See if there are any errors Collection<ProcessErrorStateInfo> procs = mActivityManager.getProcessesInErrorState(); if (procs != null) { errSet.addAll(ProcessError.fromCollection(procs)); } final Collection<ProcessErrorStateInfo> errProcs = mActivityManager.getProcessesInErrorState(); // Send the "home" intent and wait 2 seconds for us to get there getContext().startActivity(home); getContext().startActivity(mHomeIntent); try { Thread.sleep(2000); 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 /> * FIXME: Doesn't detect multiple crashing apps properly, since the crash dialog for the * FIXME: first app doesn't go away. */ public void testRunAllActivities() throws Exception { final Set<ProcessError> errSet = new HashSet<ProcessError>(); for (ResolveInfo app : getLauncherActivities(mPackageManager)) { final Collection<ProcessErrorStateInfo> errProcs = runOneActivity(app); if (errProcs != null) { errSet.addAll(ProcessError.fromCollection(errProcs)); } } if (!errSet.isEmpty()) { Loading @@ -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); Loading Loading @@ -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) { Loading tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java 0 → 100644 +94 −0 Original line number Diff line number Diff line /* * 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; } } Loading
tests/SmokeTest/tests/AndroidManifest.xml +16 −6 Original line number Diff line number Diff line Loading @@ -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>
tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java +83 −47 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -43,9 +41,17 @@ 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(); Loading @@ -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); Loading @@ -82,54 +88,84 @@ public class ProcessErrorsTest extends AndroidTestCase { } /** * A test that runs all Launcher-launchable activities and verifies that no ANRs or crashes * happened while doing so. * <p /> * FIXME: Doesn't detect multiple crashing apps properly, since the crash dialog for the * FIXME: first app doesn't go away. * A helper function to query the provided {@link PackageManager} for a list of Activities that * can be launched from Launcher. */ 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); static List<ResolveInfo> getLauncherActivities(PackageManager pm) { 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)); final List<ResolveInfo> activities = pm.queryIntentActivities(launchable, 0); return activities; } // build an Intent to launch the app final ComponentName component = new ComponentName(info.activityInfo.packageName, info.activityInfo.name); /** * 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(7000); Thread.sleep(appLaunchWait); } catch (InterruptedException e) { // ignore } // See if there are any errors Collection<ProcessErrorStateInfo> procs = mActivityManager.getProcessesInErrorState(); if (procs != null) { errSet.addAll(ProcessError.fromCollection(procs)); } final Collection<ProcessErrorStateInfo> errProcs = mActivityManager.getProcessesInErrorState(); // Send the "home" intent and wait 2 seconds for us to get there getContext().startActivity(home); getContext().startActivity(mHomeIntent); try { Thread.sleep(2000); 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 /> * FIXME: Doesn't detect multiple crashing apps properly, since the crash dialog for the * FIXME: first app doesn't go away. */ public void testRunAllActivities() throws Exception { final Set<ProcessError> errSet = new HashSet<ProcessError>(); for (ResolveInfo app : getLauncherActivities(mPackageManager)) { final Collection<ProcessErrorStateInfo> errProcs = runOneActivity(app); if (errProcs != null) { errSet.addAll(ProcessError.fromCollection(errProcs)); } } if (!errSet.isEmpty()) { Loading @@ -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); Loading Loading @@ -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) { Loading
tests/SmokeTest/tests/src/com/android/smoketest/SmokeTestRunner.java 0 → 100644 +94 −0 Original line number Diff line number Diff line /* * 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; } }