summaryrefslogtreecommitdiffstats
path: root/test-runner
diff options
context:
space:
mode:
authorJean-Baptiste Queru <jbq@google.com>2009-11-15 12:06:20 -0800
committerJean-Baptiste Queru <jbq@google.com>2009-11-15 12:06:23 -0800
commit478de466ce0504b9af639c3338b883893670a8e8 (patch)
tree61aba455baf06a4821a65b82d1115929619b49bd /test-runner
parent2b63ff51d5202eb2b458e937d4b65b326238733e (diff)
parent9db3d07b9620b4269ab33f78604a36327e536ce1 (diff)
downloadframeworks_base-478de466ce0504b9af639c3338b883893670a8e8.zip
frameworks_base-478de466ce0504b9af639c3338b883893670a8e8.tar.gz
frameworks_base-478de466ce0504b9af639c3338b883893670a8e8.tar.bz2
merge from eclair
Diffstat (limited to 'test-runner')
-rw-r--r--test-runner/android/test/AndroidTestRunner.java37
-rw-r--r--test-runner/android/test/InstrumentationTestRunner.java291
-rw-r--r--test-runner/android/test/IsolatedContext.java25
-rw-r--r--test-runner/android/test/PerformanceTestBase.java98
-rw-r--r--test-runner/android/test/ProviderTestCase.java1
-rw-r--r--test-runner/android/test/RenamingDelegatingContext.java35
-rw-r--r--test-runner/android/test/SyncBaseInstrumentation.java33
-rw-r--r--test-runner/android/test/TestLocationProvider.java3
-rw-r--r--test-runner/android/test/TestRunner.java8
-rw-r--r--test-runner/android/test/TouchUtils.java1
-rw-r--r--test-runner/android/test/mock/MockContentProvider.java27
-rw-r--r--test-runner/android/test/mock/MockContext.java15
-rw-r--r--test-runner/android/test/mock/MockPackageManager.java19
13 files changed, 438 insertions, 155 deletions
diff --git a/test-runner/android/test/AndroidTestRunner.java b/test-runner/android/test/AndroidTestRunner.java
index 79cedb0..0f1599a 100644
--- a/test-runner/android/test/AndroidTestRunner.java
+++ b/test-runner/android/test/AndroidTestRunner.java
@@ -18,6 +18,8 @@ package android.test;
import android.app.Instrumentation;
import android.content.Context;
+import android.os.PerformanceCollector.PerformanceResultsWriter;
+
import com.google.android.collect.Lists;
import junit.framework.Test;
import junit.framework.TestCase;
@@ -39,6 +41,7 @@ public class AndroidTestRunner extends BaseTestRunner {
private List<TestListener> mTestListeners = Lists.newArrayList();
private Instrumentation mInstrumentation;
+ private PerformanceResultsWriter mPerfWriter;
@SuppressWarnings("unchecked")
public void setTestClassName(String testClassName, String testMethodName) {
@@ -158,16 +161,19 @@ public class AndroidTestRunner extends BaseTestRunner {
mTestResult.addListener(testListener);
}
+ Context testContext = mInstrumentation == null ? mContext : mInstrumentation.getContext();
for (TestCase testCase : mTestCases) {
- setContextIfAndroidTestCase(testCase, mContext);
+ setContextIfAndroidTestCase(testCase, mContext, testContext);
setInstrumentationIfInstrumentationTestCase(testCase, mInstrumentation);
+ setPerformanceWriterIfPerformanceTestCase(testCase, mPerfWriter);
testCase.run(mTestResult);
}
}
- private void setContextIfAndroidTestCase(Test test, Context context) {
+ private void setContextIfAndroidTestCase(Test test, Context context, Context testContext) {
if (AndroidTestCase.class.isAssignableFrom(test.getClass())) {
((AndroidTestCase) test).setContext(context);
+ ((AndroidTestCase) test).setTestContext(testContext);
}
}
@@ -178,14 +184,37 @@ public class AndroidTestRunner extends BaseTestRunner {
private void setInstrumentationIfInstrumentationTestCase(
Test test, Instrumentation instrumentation) {
if (InstrumentationTestCase.class.isAssignableFrom(test.getClass())) {
- ((InstrumentationTestCase) test).injectInsrumentation(instrumentation);
+ ((InstrumentationTestCase) test).injectInstrumentation(instrumentation);
}
}
- public void setInstrumentaiton(Instrumentation instrumentation) {
+ private void setPerformanceWriterIfPerformanceTestCase(
+ Test test, PerformanceResultsWriter writer) {
+ if (PerformanceTestBase.class.isAssignableFrom(test.getClass())) {
+ ((PerformanceTestBase) test).setPerformanceResultsWriter(writer);
+ }
+ }
+
+ public void setInstrumentation(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
}
+ /**
+ * @deprecated Incorrect spelling,
+ * use {@link #setInstrumentation(android.app.Instrumentation)} instead.
+ */
+ @Deprecated
+ public void setInstrumentaiton(Instrumentation instrumentation) {
+ setInstrumentation(instrumentation);
+ }
+
+ /**
+ * {@hide} Pending approval for public API.
+ */
+ public void setPerformanceResultsWriter(PerformanceResultsWriter writer) {
+ mPerfWriter = writer;
+ }
+
@Override
protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
return mContext.getClassLoader().loadClass(suiteClassName);
diff --git a/test-runner/android/test/InstrumentationTestRunner.java b/test-runner/android/test/InstrumentationTestRunner.java
index 6658fb0..773d7a9 100644
--- a/test-runner/android/test/InstrumentationTestRunner.java
+++ b/test-runner/android/test/InstrumentationTestRunner.java
@@ -17,17 +17,31 @@
package android.test;
import static android.test.suitebuilder.TestPredicates.REJECT_PERFORMANCE;
+
+import com.android.internal.util.Predicate;
+
import android.app.Activity;
import android.app.Instrumentation;
import android.os.Bundle;
import android.os.Debug;
import android.os.Looper;
+import android.os.Parcelable;
+import android.os.PerformanceCollector;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.PerformanceCollector.PerformanceResultsWriter;
import android.test.suitebuilder.TestMethod;
import android.test.suitebuilder.TestPredicates;
import android.test.suitebuilder.TestSuiteBuilder;
import android.util.Log;
-import com.android.internal.util.Predicate;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
@@ -38,22 +52,13 @@ import junit.framework.TestSuite;
import junit.runner.BaseTestRunner;
import junit.textui.ResultPrinter;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.PrintStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-
/**
* An {@link Instrumentation} that runs various types of {@link junit.framework.TestCase}s against
* an Android package (application). Typical usage:
* <ol>
* <li>Write {@link junit.framework.TestCase}s that perform unit, functional, or performance tests
* against the classes in your package. Typically these are subclassed from:
- * <ul><li>{@link android.test.ActivityInstrumentationTestCase}</li>
+ * <ul><li>{@link android.test.ActivityInstrumentationTestCase2}</li>
* <li>{@link android.test.ActivityUnitTestCase}</li>
* <li>{@link android.test.AndroidTestCase}</li>
* <li>{@link android.test.ApplicationTestCase}</li>
@@ -111,13 +116,13 @@ import java.util.List;
* <p/>
* <b>To run in 'log only' mode</b>
* -e log true
- * This option will load and iterate through all test classes and methods, but will bypass actual
- * test execution. Useful for quickly obtaining info on the tests to be executed by an
+ * This option will load and iterate through all test classes and methods, but will bypass actual
+ * test execution. Useful for quickly obtaining info on the tests to be executed by an
* instrumentation command.
* <p/>
* <b>To generate EMMA code coverage:</b>
* -e coverage true
- * Note: this requires an emma instrumented build. By default, the code coverage results file
+ * Note: this requires an emma instrumented build. By default, the code coverage results file
* will be saved in a /data/<app>/coverage.ec file, unless overridden by coverageFile flag (see
* below)
* <p/>
@@ -129,11 +134,10 @@ import java.util.List;
/* (not JavaDoc)
* Although not necessary in most case, another way to use this class is to extend it and have the
- * derived class return
- * the desired test suite from the {@link #getTestSuite()} method. The test suite returned from this
- * method will be used if no target class is defined in the meta-data or command line argument
- * parameters. If a derived class is used it needs to be added as an instrumentation to the
- * AndroidManifest.xml and the command to run it would look like:
+ * derived class return the desired test suite from the {@link #getTestSuite()} method. The test
+ * suite returned from this method will be used if no target class is defined in the meta-data or
+ * command line argument parameters. If a derived class is used it needs to be added as an
+ * instrumentation to the AndroidManifest.xml and the command to run it would look like:
* <p/>
* adb shell am instrument -w com.android.foo/<i>com.android.FooInstrumentationTestRunner</i>
* <p/>
@@ -155,66 +159,65 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
public static final String ARGUMENT_DELAY_MSEC = "delay_msec";
private static final String SMALL_SUITE = "small";
- private static final String MEDIUM_SUITE = "medium";
+ private static final String MEDIUM_SUITE = "medium";
private static final String LARGE_SUITE = "large";
-
+
private static final String ARGUMENT_LOG_ONLY = "log";
-
/**
- * This constant defines the maximum allowed runtime (in ms) for a test included in the "small" suite.
- * It is used to make an educated guess at what suite an unlabeled test belongs.
+ * This constant defines the maximum allowed runtime (in ms) for a test included in the "small"
+ * suite. It is used to make an educated guess at what suite an unlabeled test belongs.
*/
private static final float SMALL_SUITE_MAX_RUNTIME = 100;
-
+
/**
- * This constant defines the maximum allowed runtime (in ms) for a test included in the "medium" suite.
- * It is used to make an educated guess at what suite an unlabeled test belongs.
+ * This constant defines the maximum allowed runtime (in ms) for a test included in the
+ * "medium" suite. It is used to make an educated guess at what suite an unlabeled test belongs.
*/
private static final float MEDIUM_SUITE_MAX_RUNTIME = 1000;
-
+
/**
- * The following keys are used in the status bundle to provide structured reports to
- * an IInstrumentationWatcher.
+ * The following keys are used in the status bundle to provide structured reports to
+ * an IInstrumentationWatcher.
*/
/**
- * This value, if stored with key {@link android.app.Instrumentation#REPORT_KEY_IDENTIFIER},
+ * This value, if stored with key {@link android.app.Instrumentation#REPORT_KEY_IDENTIFIER},
* identifies InstrumentationTestRunner as the source of the report. This is sent with all
* status messages.
*/
public static final String REPORT_VALUE_ID = "InstrumentationTestRunner";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* identifies the total number of tests that are being run. This is sent with all status
* messages.
*/
public static final String REPORT_KEY_NUM_TOTAL = "numtests";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* identifies the sequence number of the current test. This is sent with any status message
* describing a specific test being started or completed.
*/
public static final String REPORT_KEY_NUM_CURRENT = "current";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* identifies the name of the current test class. This is sent with any status message
* describing a specific test being started or completed.
*/
public static final String REPORT_KEY_NAME_CLASS = "class";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* identifies the name of the current test. This is sent with any status message
* describing a specific test being started or completed.
*/
public static final String REPORT_KEY_NAME_TEST = "test";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* reports the run time in seconds of the current test.
*/
private static final String REPORT_KEY_RUN_TIME = "runtime";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* reports the guessed suite assignment for the current test.
*/
private static final String REPORT_KEY_SUITE_ASSIGNMENT = "suiteassignment";
@@ -224,6 +227,24 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
*/
private static final String REPORT_KEY_COVERAGE_PATH = "coverageFilePath";
/**
+ * If included at the start of reporting keys, this prefix marks the key as a performance
+ * metric.
+ */
+ private static final String REPORT_KEY_PREFIX = "performance.";
+ /**
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * reports the cpu time in milliseconds of the current test.
+ */
+ private static final String REPORT_KEY_PERF_CPU_TIME =
+ REPORT_KEY_PREFIX + PerformanceCollector.METRIC_KEY_CPU_TIME;
+ /**
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * reports the run time in milliseconds of the current test.
+ */
+ private static final String REPORT_KEY_PERF_EXECUTION_TIME =
+ REPORT_KEY_PREFIX + PerformanceCollector.METRIC_KEY_EXECUTION_TIME;
+
+ /**
* The test is starting.
*/
public static final int REPORT_VALUE_RESULT_START = 1;
@@ -240,15 +261,15 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
*/
public static final int REPORT_VALUE_RESULT_FAILURE = -2;
/**
- * If included in the status bundle sent to an IInstrumentationWatcher, this key
- * identifies a stack trace describing an error or failure. This is sent with any status
+ * If included in the status bundle sent to an IInstrumentationWatcher, this key
+ * identifies a stack trace describing an error or failure. This is sent with any status
* message describing a specific test being completed.
*/
public static final String REPORT_KEY_STACK = "stack";
// Default file name for code coverage
private static final String DEFAULT_COVERAGE_FILE_NAME = "coverage.ec";
-
+
private static final String LOG_TAG = "InstrumentationTestRunner";
private final Bundle mResults = new Bundle();
@@ -316,7 +337,7 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
if (testSuite != null) {
testSuiteBuilder.addTestSuite(testSuite);
} else {
- // no package or class bundle arguments were supplied, and no test suite
+ // no package or class bundle arguments were supplied, and no test suite
// provided so add all tests in application
testSuiteBuilder.includePackages("");
}
@@ -324,20 +345,22 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
} else {
parseTestClasses(testClassesArg, testSuiteBuilder);
}
-
+
testSuiteBuilder.addRequirements(getBuilderRequirements());
mTestRunner = getAndroidTestRunner();
mTestRunner.setContext(getTargetContext());
- mTestRunner.setInstrumentaiton(this);
+ mTestRunner.setInstrumentation(this);
mTestRunner.setSkipExecution(logOnly);
mTestRunner.setTest(testSuiteBuilder.build());
mTestCount = mTestRunner.getTestCases().size();
if (mSuiteAssignmentMode) {
mTestRunner.addTestListener(new SuiteAssignmentPrinter());
} else {
+ WatcherResultPrinter resultPrinter = new WatcherResultPrinter(mTestCount);
mTestRunner.addTestListener(new TestPrinter("TestRunner", false));
- mTestRunner.addTestListener(new WatcherResultPrinter(mTestCount));
+ mTestRunner.addTestListener(resultPrinter);
+ mTestRunner.setPerformanceResultsWriter(resultPrinter);
}
start();
}
@@ -347,7 +370,8 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
}
/**
- * Parses and loads the specified set of test classes
+ * Parses and loads the specified set of test classes
+ *
* @param testClassArg - comma-separated list of test classes and methods
* @param testSuiteBuilder - builder to add tests to
*/
@@ -360,8 +384,9 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
/**
* Parse and load the given test class and, optionally, method
- * @param testClassName - full package name of test class and optionally method to add. Expected
- * format: com.android.TestClass#testMethod
+ *
+ * @param testClassName - full package name of test class and optionally method to add.
+ * Expected format: com.android.TestClass#testMethod
* @param testSuiteBuilder - builder to add tests to
*/
private void parseTestClass(String testClassName, TestSuiteBuilder testSuiteBuilder) {
@@ -372,8 +397,7 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
testMethodName = testClassName.substring(methodSeparatorIndex + 1);
testClassName = testClassName.substring(0, methodSeparatorIndex);
}
- testSuiteBuilder.addTestClassByName(testClassName, testMethodName,
- getTargetContext());
+ testSuiteBuilder.addTestClassByName(testClassName, testMethodName, getTargetContext());
}
protected AndroidTestRunner getAndroidTestRunner() {
@@ -384,12 +408,12 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
String tagString = arguments.getString(tag);
return tagString != null && Boolean.parseBoolean(tagString);
}
-
+
/*
* Returns the size predicate object, corresponding to the "size" argument value.
*/
private Predicate<TestMethod> getSizePredicateFromArg(String sizeArg) {
-
+
if (SMALL_SUITE.equals(sizeArg)) {
return TestPredicates.SELECT_SMALL;
} else if (MEDIUM_SUITE.equals(sizeArg)) {
@@ -400,11 +424,11 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
return null;
}
}
-
+
@Override
public void onStart() {
Looper.prepare();
-
+
if (mJustCount) {
mResults.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
mResults.putInt(REPORT_KEY_NUM_TOTAL, mTestCount);
@@ -413,30 +437,30 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
if (mDebug) {
Debug.waitForDebugger();
}
-
+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PrintStream writer = new PrintStream(byteArrayOutputStream);
try {
StringResultPrinter resultPrinter = new StringResultPrinter(writer);
-
+
mTestRunner.addTestListener(resultPrinter);
-
+
long startTime = System.currentTimeMillis();
mTestRunner.runTest();
long runTime = System.currentTimeMillis() - startTime;
-
+
resultPrinter.print(mTestRunner.getTestResult(), runTime);
} finally {
- mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
- String.format("\nTest results for %s=%s",
- mTestRunner.getTestClassName(),
+ mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ String.format("\nTest results for %s=%s",
+ mTestRunner.getTestClassName(),
byteArrayOutputStream.toString()));
if (mCoverage) {
generateCoverageReport();
}
writer.close();
-
+
finish(Activity.RESULT_OK, mResults);
}
}
@@ -459,7 +483,7 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
public ClassLoader getLoader() {
return null;
}
-
+
private void generateCoverageReport() {
// use reflection to call emma dump coverage method, to avoid
// always statically compiling against emma jar
@@ -467,9 +491,9 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
java.io.File coverageFile = new java.io.File(coverageFilePath);
try {
Class emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
- Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",
+ Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",
coverageFile.getClass(), boolean.class, boolean.class);
-
+
dumpCoverageMethod.invoke(null, coverageFile, false, false);
// output path to generated coverage file so it can be parsed by a test harness if
// needed
@@ -495,15 +519,14 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
private String getCoverageFilePath() {
if (mCoverageFilePath == null) {
return getTargetContext().getFilesDir().getAbsolutePath() + File.separator +
- DEFAULT_COVERAGE_FILE_NAME;
- }
- else {
+ DEFAULT_COVERAGE_FILE_NAME;
+ } else {
return mCoverageFilePath;
}
}
private void reportEmmaError(Exception e) {
- reportEmmaError("", e);
+ reportEmmaError("", e);
}
private void reportEmmaError(String hint, Exception e) {
@@ -524,30 +547,29 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
printFooter(result);
}
}
-
+
/**
- * This class sends status reports back to the IInstrumentationWatcher about
+ * This class sends status reports back to the IInstrumentationWatcher about
* which suite each test belongs.
*/
- private class SuiteAssignmentPrinter implements TestListener
- {
-
+ private class SuiteAssignmentPrinter implements TestListener {
+
private Bundle mTestResult;
private long mStartTime;
private long mEndTime;
private boolean mTimingValid;
-
+
public SuiteAssignmentPrinter() {
}
-
+
/**
* send a status for the start of a each test, so long tests can be seen as "running"
*/
public void startTest(Test test) {
mTimingValid = true;
- mStartTime = System.currentTimeMillis();
+ mStartTime = System.currentTimeMillis();
}
-
+
/**
* @see junit.framework.TestListener#addError(Test, Throwable)
*/
@@ -576,7 +598,7 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
runTime = -1;
} else {
runTime = mEndTime - mStartTime;
- if (runTime < SMALL_SUITE_MAX_RUNTIME
+ if (runTime < SMALL_SUITE_MAX_RUNTIME
&& !InstrumentationTestCase.class.isAssignableFrom(test.getClass())) {
assignmentSuite = SMALL_SUITE;
} else if (runTime < MEDIUM_SUITE_MAX_RUNTIME) {
@@ -588,8 +610,8 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
// Clear mStartTime so that we can verify that it gets set next time.
mStartTime = -1;
- mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
- test.getClass().getName() + "#" + ((TestCase) test).getName()
+ mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ test.getClass().getName() + "#" + ((TestCase) test).getName()
+ "\nin " + assignmentSuite + " suite\nrunTime: "
+ String.valueOf(runTime) + "\n");
mTestResult.putFloat(REPORT_KEY_RUN_TIME, runTime);
@@ -598,36 +620,40 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
sendStatus(0, mTestResult);
}
}
-
+
/**
* This class sends status reports back to the IInstrumentationWatcher
*/
- private class WatcherResultPrinter implements TestListener
- {
+ private class WatcherResultPrinter implements TestListener, PerformanceResultsWriter {
private final Bundle mResultTemplate;
Bundle mTestResult;
int mTestNum = 0;
int mTestResultCode = 0;
String mTestClass = null;
-
+ boolean mIsTimedTest = false;
+ long mCpuTime = 0;
+ long mExecTime = 0;
+
public WatcherResultPrinter(int numTests) {
mResultTemplate = new Bundle();
mResultTemplate.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
mResultTemplate.putInt(REPORT_KEY_NUM_TOTAL, numTests);
}
-
+
/**
- * send a status for the start of a each test, so long tests can be seen as "running"
+ * send a status for the start of a each test, so long tests can be seen
+ * as "running"
*/
public void startTest(Test test) {
String testClass = test.getClass().getName();
+ String testName = ((TestCase)test).getName();
mTestResult = new Bundle(mResultTemplate);
mTestResult.putString(REPORT_KEY_NAME_CLASS, testClass);
- mTestResult.putString(REPORT_KEY_NAME_TEST, ((TestCase) test).getName());
+ mTestResult.putString(REPORT_KEY_NAME_TEST, testName);
mTestResult.putInt(REPORT_KEY_NUM_CURRENT, ++mTestNum);
// pretty printing
if (testClass != null && !testClass.equals(mTestClass)) {
- mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
String.format("\n%s:", testClass));
mTestClass = testClass;
} else {
@@ -635,9 +661,9 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
}
// The delay_msec parameter is normally used to provide buffers of idle time
- // for power measurement purposes. To make sure there is a delay before and after
+ // for power measurement purposes. To make sure there is a delay before and after
// every test in a suite, we delay *after* every test (see endTest below) and also
- // delay *before* the first test. So, delay test1 delay test2 delay.
+ // delay *before* the first test. So, delay test1 delay test2 delay.
try {
if (mTestNum == 1) Thread.sleep(mDelayMsec);
@@ -647,8 +673,25 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
sendStatus(REPORT_VALUE_RESULT_START, mTestResult);
mTestResultCode = 0;
+
+ mIsTimedTest = false;
+ try {
+ // Look for TimedTest annotation on both test class and test
+ // method
+ mIsTimedTest = test.getClass().isAnnotationPresent(TimedTest.class) ||
+ test.getClass().getMethod(testName).isAnnotationPresent(TimedTest.class);
+ } catch (SecurityException e) {
+ throw new IllegalStateException(e);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException(e);
+ }
+
+ if (mIsTimedTest) {
+ mExecTime = SystemClock.uptimeMillis();
+ mCpuTime = Process.getElapsedCpuTime();
+ }
}
-
+
/**
* @see junit.framework.TestListener#addError(Test, Throwable)
*/
@@ -656,9 +699,9 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
mTestResultCode = REPORT_VALUE_RESULT_ERROR;
// pretty printing
- mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
- String.format("\nError in %s:\n%s",
- ((TestCase) test).getName(), BaseTestRunner.getFilteredTrace(t)));
+ mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ String.format("\nError in %s:\n%s",
+ ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
}
/**
@@ -668,28 +711,78 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
mTestResultCode = REPORT_VALUE_RESULT_FAILURE;
// pretty printing
- mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
- String.format("\nFailure in %s:\n%s",
- ((TestCase) test).getName(), BaseTestRunner.getFilteredTrace(t)));
+ mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ String.format("\nFailure in %s:\n%s",
+ ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
}
/**
* @see junit.framework.TestListener#endTest(Test)
*/
public void endTest(Test test) {
+ if (mIsTimedTest) {
+ mCpuTime = Process.getElapsedCpuTime() - mCpuTime;
+ mExecTime = SystemClock.uptimeMillis() - mExecTime;
+ mTestResult.putLong(REPORT_KEY_PERF_CPU_TIME, mCpuTime);
+ mTestResult.putLong(REPORT_KEY_PERF_EXECUTION_TIME, mExecTime);
+ }
+
if (mTestResultCode == 0) {
mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, ".");
}
sendStatus(mTestResultCode, mTestResult);
- try { // Sleep after every test, if specified
+ try { // Sleep after every test, if specified
Thread.sleep(mDelayMsec);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
+ public void writeBeginSnapshot(String label) {
+ // Do nothing
+ }
+
+ public void writeEndSnapshot(Bundle results) {
+ // Copy all snapshot data fields into mResults, which is outputted
+ // via Instrumentation.finish
+ mResults.putAll(results);
+ }
+
+ public void writeStartTiming(String label) {
+ // Do nothing
+ }
+
+ public void writeStopTiming(Bundle results) {
+ // Copy results into mTestResult by flattening list of iterations,
+ // which is outputted via WatcherResultPrinter.endTest
+ int i = 0;
+ for (Parcelable p :
+ results.getParcelableArrayList(PerformanceCollector.METRIC_KEY_ITERATIONS)) {
+ Bundle iteration = (Bundle)p;
+ String index = "performance.iteration" + i + ".";
+ mTestResult.putString(index + PerformanceCollector.METRIC_KEY_LABEL,
+ iteration.getString(PerformanceCollector.METRIC_KEY_LABEL));
+ mTestResult.putLong(index + PerformanceCollector.METRIC_KEY_CPU_TIME,
+ iteration.getLong(PerformanceCollector.METRIC_KEY_CPU_TIME));
+ mTestResult.putLong(index + PerformanceCollector.METRIC_KEY_EXECUTION_TIME,
+ iteration.getLong(PerformanceCollector.METRIC_KEY_EXECUTION_TIME));
+ i++;
+ }
+ }
+
+ public void writeMeasurement(String label, long value) {
+ mTestResult.putLong(REPORT_KEY_PREFIX + label, value);
+ }
+
+ public void writeMeasurement(String label, float value) {
+ mTestResult.putFloat(REPORT_KEY_PREFIX + label, value);
+ }
+
+ public void writeMeasurement(String label, String value) {
+ mTestResult.putString(REPORT_KEY_PREFIX + label, value);
+ }
+
// TODO report the end of the cycle
- // TODO report runtime for each test
}
}
diff --git a/test-runner/android/test/IsolatedContext.java b/test-runner/android/test/IsolatedContext.java
index 859b2e5..485e45c 100644
--- a/test-runner/android/test/IsolatedContext.java
+++ b/test-runner/android/test/IsolatedContext.java
@@ -2,6 +2,9 @@ package android.test;
import com.google.android.collect.Lists;
+import android.accounts.AccountManager;
+import android.accounts.OnAccountsUpdateListener;
+import android.accounts.Account;
import android.content.ContextWrapper;
import android.content.ContentResolver;
import android.content.Intent;
@@ -11,6 +14,7 @@ import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Handler;
import java.util.List;
import java.io.File;
@@ -22,6 +26,7 @@ import java.io.File;
public class IsolatedContext extends ContextWrapper {
private ContentResolver mResolver;
+ private final MockAccountManager mMockAccountManager;
private List<Intent> mBroadcastIntents = Lists.newArrayList();
@@ -29,6 +34,7 @@ public class IsolatedContext extends ContextWrapper {
ContentResolver resolver, Context targetContext) {
super(targetContext);
mResolver = resolver;
+ mMockAccountManager = new MockAccountManager();
}
/** Returns the list of intents that were broadcast since the last call to this method. */
@@ -79,10 +85,27 @@ public class IsolatedContext extends ContextWrapper {
@Override
public Object getSystemService(String name) {
- // No services exist in this context.
+ if (Context.ACCOUNT_SERVICE.equals(name)) {
+ return mMockAccountManager;
+ }
+ // No other services exist in this context.
return null;
}
+ private class MockAccountManager extends AccountManager {
+ public MockAccountManager() {
+ super(IsolatedContext.this, null /* IAccountManager */, null /* handler */);
+ }
+
+ public void addOnAccountsUpdatedListener(OnAccountsUpdateListener listener,
+ Handler handler, boolean updateImmediately) {
+ // do nothing
+ }
+
+ public Account[] getAccounts() {
+ return new Account[]{};
+ }
+ }
@Override
public File getFilesDir() {
return new File("/dev/null");
diff --git a/test-runner/android/test/PerformanceTestBase.java b/test-runner/android/test/PerformanceTestBase.java
index 93ac90c..572a9b8 100644
--- a/test-runner/android/test/PerformanceTestBase.java
+++ b/test-runner/android/test/PerformanceTestBase.java
@@ -16,13 +16,95 @@
package android.test;
-import android.test.PerformanceTestCase;
-import junit.framework.TestCase;
+import android.os.Bundle;
+import android.os.PerformanceCollector;
+import android.os.PerformanceCollector.PerformanceResultsWriter;
+
+import java.lang.reflect.Method;
/**
- * {@hide} Not needed for SDK.
+ * Provides hooks and wrappers to automatically and manually collect and report
+ * performance data in tests.
+ *
+ * {@hide} Pending approval for public API.
*/
-public abstract class PerformanceTestBase extends TestCase implements PerformanceTestCase {
+public class PerformanceTestBase extends InstrumentationTestCase implements PerformanceTestCase {
+
+ private static PerformanceCollector sPerfCollector = new PerformanceCollector();
+ private static int sNumTestMethods = 0;
+ private static int sNumTestMethodsLeft = 0;
+
+ // Count number of tests, used to emulate beforeClass and afterClass from JUnit4
+ public PerformanceTestBase() {
+ if (sNumTestMethods == 0) {
+ Method methods[] = getClass().getMethods();
+ for (Method m : methods) {
+ if (m.getName().startsWith("test")) {
+ sNumTestMethods ++;
+ sNumTestMethodsLeft ++;
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // @beforeClass
+ // Will skew timing measured by TestRunner, but not by PerformanceCollector
+ if (sNumTestMethodsLeft == sNumTestMethods) {
+ sPerfCollector.beginSnapshot(this.getClass().getName());
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // @afterClass
+ // Will skew timing measured by TestRunner, but not by PerformanceCollector
+ if (--sNumTestMethodsLeft == 0) {
+ sPerfCollector.endSnapshot();
+ }
+ super.tearDown();
+ }
+
+ public void setPerformanceResultsWriter(PerformanceResultsWriter writer) {
+ sPerfCollector.setPerformanceResultsWriter(writer);
+ }
+
+ /**
+ * @see PerformanceCollector#beginSnapshot(String)
+ */
+ protected void beginSnapshot(String label) {
+ sPerfCollector.beginSnapshot(label);
+ }
+
+ /**
+ * @see PerformanceCollector#endSnapshot()
+ */
+ protected Bundle endSnapshot() {
+ return sPerfCollector.endSnapshot();
+ }
+
+ /**
+ * @see PerformanceCollector#startTiming(String)
+ */
+ protected void startTiming(String label) {
+ sPerfCollector.startTiming(label);
+ }
+
+ /**
+ * @see PerformanceCollector#addIteration(String)
+ */
+ protected Bundle addIteration(String label) {
+ return sPerfCollector.addIteration(label);
+ }
+
+ /**
+ * @see PerformanceCollector#stopTiming(String)
+ */
+ protected Bundle stopTiming(String label) {
+ return sPerfCollector.stopTiming(label);
+ }
public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
return 0;
@@ -31,12 +113,4 @@ public abstract class PerformanceTestBase extends TestCase implements Performanc
public boolean isPerformanceOnly() {
return true;
}
-
- /*
- * Temporary hack to get some things working again.
- */
- public void testRun() {
- throw new RuntimeException("test implementation not provided");
- }
}
-
diff --git a/test-runner/android/test/ProviderTestCase.java b/test-runner/android/test/ProviderTestCase.java
index 445b4eb..668e9f7 100644
--- a/test-runner/android/test/ProviderTestCase.java
+++ b/test-runner/android/test/ProviderTestCase.java
@@ -15,6 +15,7 @@ import android.database.DatabaseUtils;
* @deprecated this class extends InstrumentationTestCase but should extend AndroidTestCase. Use
* ProviderTestCase2, which corrects this problem, instead.
*/
+@Deprecated
public abstract class ProviderTestCase<T extends ContentProvider>
extends InstrumentationTestCase {
diff --git a/test-runner/android/test/RenamingDelegatingContext.java b/test-runner/android/test/RenamingDelegatingContext.java
index 3f64340..0ea43ab 100644
--- a/test-runner/android/test/RenamingDelegatingContext.java
+++ b/test-runner/android/test/RenamingDelegatingContext.java
@@ -6,6 +6,8 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.content.ContentProvider;
import android.database.sqlite.SQLiteDatabase;
+import android.os.FileUtils;
+import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
@@ -22,6 +24,8 @@ public class RenamingDelegatingContext extends ContextWrapper {
private Context mFileContext;
private String mFilePrefix = null;
+ private File mCacheDir;
+ private final Object mSync = new Object();
private Set<String> mDatabaseNames = Sets.newHashSet();
private Set<String> mFileNames = Sets.newHashSet();
@@ -136,6 +140,11 @@ public class RenamingDelegatingContext extends ContextWrapper {
return false;
}
}
+
+ @Override
+ public File getDatabasePath(String name) {
+ return mFileContext.getDatabasePath(renamedFileName(name));
+ }
@Override
public String[] databaseList() {
@@ -179,6 +188,32 @@ public class RenamingDelegatingContext extends ContextWrapper {
public String[] fileList() {
return mFileNames.toArray(new String[]{});
}
+
+ /**
+ * In order to support calls to getCacheDir(), we create a temp cache dir (inside the real
+ * one) and return it instead. This code is basically getCacheDir(), except it uses the real
+ * cache dir as the parent directory and creates a test cache dir inside that.
+ */
+ @Override
+ public File getCacheDir() {
+ synchronized (mSync) {
+ if (mCacheDir == null) {
+ mCacheDir = new File(mFileContext.getCacheDir(), renamedFileName("cache"));
+ }
+ if (!mCacheDir.exists()) {
+ if(!mCacheDir.mkdirs()) {
+ Log.w("RenamingDelegatingContext", "Unable to create cache directory");
+ return null;
+ }
+ FileUtils.setPermissions(
+ mCacheDir.getPath(),
+ FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+ -1, -1);
+ }
+ }
+ return mCacheDir;
+ }
+
// /**
// * Given an array of files returns only those whose names indicate that they belong to this
diff --git a/test-runner/android/test/SyncBaseInstrumentation.java b/test-runner/android/test/SyncBaseInstrumentation.java
index 772d75c..e8d72d9 100644
--- a/test-runner/android/test/SyncBaseInstrumentation.java
+++ b/test-runner/android/test/SyncBaseInstrumentation.java
@@ -19,9 +19,9 @@ package android.test;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.net.Uri;
+import android.accounts.Account;
/**
* If you would like to test sync a single provider with an
@@ -44,12 +44,12 @@ public class SyncBaseInstrumentation extends InstrumentationTestCase {
* Syncs the specified provider.
* @throws Exception
*/
- protected void syncProvider(Uri uri, String account, String authority) throws Exception {
+ protected void syncProvider(Uri uri, String accountName, String authority) throws Exception {
Bundle extras = new Bundle();
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_FORCE, true);
- extras.putString(ContentResolver.SYNC_EXTRAS_ACCOUNT, account);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+ Account account = new Account(accountName, "com.google");
- mContentResolver.startSync(uri, extras);
+ ContentResolver.requestSync(account, authority, extras);
long startTimeInMillis = SystemClock.elapsedRealtime();
long endTimeInMillis = startTimeInMillis + MAX_TIME_FOR_SYNC_IN_MINS * 60000;
@@ -64,7 +64,7 @@ public class SyncBaseInstrumentation extends InstrumentationTestCase {
break;
}
- if (isSyncActive(account, authority)) {
+ if (ContentResolver.isSyncActive(account, authority)) {
counter = 0;
continue;
}
@@ -73,24 +73,7 @@ public class SyncBaseInstrumentation extends InstrumentationTestCase {
}
protected void cancelSyncsandDisableAutoSync() {
- try {
- ContentResolver.getContentService().setListenForNetworkTickles(false);
- } catch (RemoteException e) {
- }
- mContentResolver.cancelSync(null);
- }
-
- /**
- * This method tests if any sync is active or not. Sync is considered to be active if the
- * entry is in either the Pending or Active tables.
- * @return
- */
- private boolean isSyncActive(String account, String authority) {
- try {
- return ContentResolver.getContentService().isSyncActive(account,
- authority);
- } catch (RemoteException e) {
- return false;
- }
+ ContentResolver.setMasterSyncAutomatically(false);
+ ContentResolver.cancelSync(null /* all accounts */, null /* all authorities */);
}
}
diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java
index 2ea020e..dc07585 100644
--- a/test-runner/android/test/TestLocationProvider.java
+++ b/test-runner/android/test/TestLocationProvider.java
@@ -22,6 +22,7 @@ import android.location.ILocationManager;
import android.location.ILocationProvider;
import android.location.Location;
import android.location.LocationProvider;
+import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -156,7 +157,7 @@ public class TestLocationProvider extends ILocationProvider.Stub {
public void setMinTime(long minTime) {
}
- public void updateNetworkState(int state) {
+ public void updateNetworkState(int state, NetworkInfo info) {
}
public void updateLocation(Location location) {
diff --git a/test-runner/android/test/TestRunner.java b/test-runner/android/test/TestRunner.java
index efa2480..012df35 100644
--- a/test-runner/android/test/TestRunner.java
+++ b/test-runner/android/test/TestRunner.java
@@ -39,7 +39,7 @@ import com.google.android.collect.Lists;
* and you probably will not need to instantiate, extend, or call this
* class yourself. See the full {@link android.test} package description
* to learn more about testing Android applications.
- *
+ *
* {@hide} Not needed for 1.0 SDK.
*/
public class TestRunner implements PerformanceTestCase.Intermediates {
@@ -84,6 +84,7 @@ public class TestRunner implements PerformanceTestCase.Intermediates {
super();
}
+ @Override
public void run(TestResult result) {
result.addListener(this);
super.run(result);
@@ -301,7 +302,7 @@ public class TestRunner implements PerformanceTestCase.Intermediates {
if (mMode == PERFORMANCE) {
runInPerformanceMode(test, className, false, className);
} else if (mMode == PROFILING) {
- //Need a way to mark a test to be run in profiling mode or not.
+ //Need a way to mark a test to be run in profiling mode or not.
startProfiling();
test.run();
finishProfiling();
@@ -337,6 +338,7 @@ public class TestRunner implements PerformanceTestCase.Intermediates {
AndroidTestCase testcase = (AndroidTestCase) test;
try {
testcase.setContext(mContext);
+ testcase.setTestContext(mContext);
} catch (Exception ex) {
Log.i("TestHarness", ex.toString());
}
@@ -700,7 +702,7 @@ public class TestRunner implements PerformanceTestCase.Intermediates {
}
} catch (ClassNotFoundException e) {
return 1; // this gets the count right, because either this test
- // is missing, and it will fail when run or it is a single Junit test to be run.
+ // is missing, and it will fail when run or it is a single Junit test to be run.
}
return 0;
}
diff --git a/test-runner/android/test/TouchUtils.java b/test-runner/android/test/TouchUtils.java
index 52d2ee8..962b2f9 100644
--- a/test-runner/android/test/TouchUtils.java
+++ b/test-runner/android/test/TouchUtils.java
@@ -565,6 +565,7 @@ public class TouchUtils {
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
+ @Deprecated
public static int dragViewBy(InstrumentationTestCase test, View v, int gravity, int deltaX,
int deltaY) {
int[] xy = new int[2];
diff --git a/test-runner/android/test/mock/MockContentProvider.java b/test-runner/android/test/mock/MockContentProvider.java
index d04fc44..c3fe9c0 100644
--- a/test-runner/android/test/mock/MockContentProvider.java
+++ b/test-runner/android/test/mock/MockContentProvider.java
@@ -18,7 +18,11 @@ package android.test.mock;
import android.content.ContentValues;
import android.content.IContentProvider;
-import android.content.ISyncAdapter;
+import android.content.Entity;
+import android.content.EntityIterator;
+import android.content.ContentProviderResult;
+import android.content.ContentProviderOperation;
+import android.content.OperationApplicationException;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.CursorWindow;
@@ -30,6 +34,7 @@ import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import java.io.FileNotFoundException;
+import java.util.ArrayList;
/**
* Mock implementation of IContentProvider that does nothing. All methods are non-functional and
@@ -62,11 +67,6 @@ public class MockContentProvider implements IContentProvider {
}
@SuppressWarnings("unused")
- public ISyncAdapter getSyncAdapter() throws RemoteException {
- throw new UnsupportedOperationException("unimplemented mock method");
- }
-
- @SuppressWarnings("unused")
public String getType(Uri url) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -87,13 +87,26 @@ public class MockContentProvider implements IContentProvider {
throws FileNotFoundException {
throw new UnsupportedOperationException("unimplemented mock method");
}
-
+
+ public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
+ throws RemoteException, OperationApplicationException {
+ throw new UnsupportedOperationException("unimplemented mock method");
+ }
+
@SuppressWarnings("unused")
public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
String sortOrder) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ /**
+ * @hide
+ */
+ public EntityIterator queryEntities(Uri url, String selection, String[] selectionArgs,
+ String sortOrder) throws RemoteException {
+ throw new UnsupportedOperationException("unimplemented mock method");
+ }
+
@SuppressWarnings("unused")
public int update(Uri url, ContentValues values, String selection, String[] selectionArgs)
throws RemoteException {
diff --git a/test-runner/android/test/mock/MockContext.java b/test-runner/android/test/mock/MockContext.java
index 9fb1e61..57b22f8 100644
--- a/test-runner/android/test/mock/MockContext.java
+++ b/test-runner/android/test/mock/MockContext.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
+import android.content.IntentSender;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
@@ -228,6 +229,13 @@ public class MockContext extends Context {
}
@Override
+ public void startIntentSender(IntentSender intent,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
+ throws IntentSender.SendIntentException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public void sendBroadcast(Intent intent) {
throw new UnsupportedOperationException();
}
@@ -256,6 +264,13 @@ public class MockContext extends Context {
}
@Override
+ public void sendStickyOrderedBroadcast(Intent intent,
+ BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
+ Bundle initialExtras) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public void removeStickyBroadcast(Intent intent) {
throw new UnsupportedOperationException();
}
diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index d5cd6ef..2f313af 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -22,6 +22,7 @@ import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageInstallObserver;
@@ -139,6 +140,11 @@ public class MockPackageManager extends PackageManager {
}
@Override
+ public int checkSignatures(int uid1, int uid2) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public String[] getPackagesForUid(int uid) {
throw new UnsupportedOperationException();
}
@@ -292,9 +298,6 @@ public class MockPackageManager extends PackageManager {
throw new UnsupportedOperationException();
}
- /**
- * @hide - to match hiding in superclass
- */
@Override
public String getInstallerPackageName(String packageName) {
throw new UnsupportedOperationException();
@@ -422,6 +425,16 @@ public class MockPackageManager extends PackageManager {
}
@Override
+ public FeatureInfo[] getSystemAvailableFeatures() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean hasSystemFeature(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public boolean isSafeMode() {
throw new UnsupportedOperationException();
}