implement instrumentation

This commit is contained in:
Mis012
2024-11-30 18:57:03 +01:00
parent f61f200d7b
commit d5bc4ea9a6
61 changed files with 8723 additions and 58 deletions

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Activity;
/**
* This class provides functional testing of a single activity. The activity under test will
* be created using the system infrastructure (by calling InstrumentationTestCase.launchActivity())
* and you will then be able to manipulate your Activity directly. Most of the work is handled
* automatically here by {@link #setUp} and {@link #tearDown}.
*
* <p>If you prefer an isolated unit test, see {@link android.test.ActivityUnitTestCase}.
*
* @deprecated new tests should be written using
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public abstract class ActivityInstrumentationTestCase<T extends Activity>
extends ActivityTestCase {
String mPackage;
Class<T> mActivityClass;
boolean mInitialTouchMode = false;
/**
* Creates an {@link ActivityInstrumentationTestCase} in non-touch mode.
*
* @param pkg ignored - no longer in use.
* @param activityClass The activity to test. This must be a class in the instrumentation
* targetPackage specified in the AndroidManifest.xml
*/
public ActivityInstrumentationTestCase(String pkg, Class<T> activityClass) {
this(pkg, activityClass, false);
}
/**
* Creates an {@link ActivityInstrumentationTestCase}.
*
* @param pkg ignored - no longer in use.
* @param activityClass The activity to test. This must be a class in the instrumentation
* targetPackage specified in the AndroidManifest.xml
* @param initialTouchMode true = in touch mode
*/
public ActivityInstrumentationTestCase(String pkg, Class<T> activityClass,
boolean initialTouchMode) {
mActivityClass = activityClass;
mInitialTouchMode = initialTouchMode;
}
@Override
public T getActivity() {
return (T) super.getActivity();
}
@Override
protected void setUp() throws Exception {
super.setUp();
// set initial touch mode
getInstrumentation().setInTouchMode(mInitialTouchMode);
final String targetPackageName = getInstrumentation().getTargetContext().getPackageName();
setActivity(launchActivity(targetPackageName, mActivityClass, null));
}
@Override
protected void tearDown() throws Exception {
getActivity().finish();
setActivity(null);
// Scrub out members - protects against memory leaks in the case where someone
// creates a non-static inner class (thus referencing the test case) and gives it to
// someone else to hold onto
scrubClass(ActivityInstrumentationTestCase.class);
super.tearDown();
}
public void testActivityTestCaseSetUpProperly() throws Exception {
assertNotNull("activity should be launched successfully", getActivity());
}
}

View File

@@ -0,0 +1,195 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Activity;
import android.content.Intent;
import java.lang.reflect.Method;
/**
* This class provides functional testing of a single activity. The activity under test will
* be created using the system infrastructure (by calling InstrumentationTestCase.launchActivity())
* and you will then be able to manipulate your Activity directly.
*
* <p>Other options supported by this test case include:
* <ul>
* <li>You can run any test method on the UI thread (see {@link android.test.UiThreadTest}).</li>
* <li>You can inject custom Intents into your Activity (see
* {@link #setActivityIntent(Intent)}).</li>
* </ul>
*
* <p>This class replaces {@link android.test.ActivityInstrumentationTestCase}, which is deprecated.
* New tests should be written using this base class.
*
* <p>If you prefer an isolated unit test, see {@link android.test.ActivityUnitTestCase}.
*
* @deprecated Use
* <a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">
* ActivityTestRule</a> instead. New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public abstract class ActivityInstrumentationTestCase2<T extends Activity>
extends ActivityTestCase {
Class<T> mActivityClass;
boolean mInitialTouchMode = false;
Intent mActivityIntent = null;
/**
* Creates an {@link ActivityInstrumentationTestCase2}.
*
* @param pkg ignored - no longer in use.
* @param activityClass The activity to test. This must be a class in the instrumentation
* targetPackage specified in the AndroidManifest.xml
*
* @deprecated use {@link #ActivityInstrumentationTestCase2(Class)} instead
*/
@Deprecated
public ActivityInstrumentationTestCase2(String pkg, Class<T> activityClass) {
this(activityClass);
}
/**
* Creates an {@link ActivityInstrumentationTestCase2}.
*
* @param activityClass The activity to test. This must be a class in the instrumentation
* targetPackage specified in the AndroidManifest.xml
*/
public ActivityInstrumentationTestCase2(Class<T> activityClass) {
mActivityClass = activityClass;
}
/**
* Get the Activity under test, starting it if necessary.
*
* For each test method invocation, the Activity will not actually be created until the first
* time this method is called.
*
* <p>If you wish to provide custom setup values to your Activity, you may call
* {@link #setActivityIntent(Intent)} and/or {@link #setActivityInitialTouchMode(boolean)}
* before your first call to getActivity(). Calling them after your Activity has
* started will have no effect.
*
* <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
* If your test method is annotated with {@link android.test.UiThreadTest}, then your Activity
* will be started automatically just before your test method is run. You still call this
* method in order to get the Activity under test.
*
* @return the Activity under test
*/
@Override
public T getActivity() {
Activity a = super.getActivity();
if (a == null) {
// set initial touch mode
getInstrumentation().setInTouchMode(mInitialTouchMode);
final String targetPackage = getInstrumentation().getTargetContext().getPackageName();
// inject custom intent, if provided
if (mActivityIntent == null) {
a = launchActivity(targetPackage, mActivityClass, null);
} else {
a = launchActivityWithIntent(targetPackage, mActivityClass, mActivityIntent);
}
setActivity(a);
}
return (T) a;
}
/**
* Call this method before the first call to {@link #getActivity} to inject a customized Intent
* into the Activity under test.
*
* <p>If you do not call this, the default intent will be provided. If you call this after
* your Activity has been started, it will have no effect.
*
* <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
* If your test method is annotated with {@link android.test.UiThreadTest}, then you must call
* {@link #setActivityIntent(Intent)} from {@link #setUp()}.
*
* <p>The default Intent (if this method is not called) is:
* action = {@link Intent#ACTION_MAIN}
* flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
* All other fields are null or empty.
*
* @param i The Intent to start the Activity with, or null to reset to the default Intent.
*/
public void setActivityIntent(Intent i) {
mActivityIntent = i;
}
/**
* Call this method before the first call to {@link #getActivity} to set the initial touch
* mode for the Activity under test.
*
* <p>If you do not call this, the touch mode will be false. If you call this after
* your Activity has been started, it will have no effect.
*
* <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
* If your test method is annotated with {@link android.test.UiThreadTest}, then you must call
* {@link #setActivityInitialTouchMode(boolean)} from {@link #setUp()}.
*
* @param initialTouchMode true if the Activity should be placed into "touch mode" when started
*/
public void setActivityInitialTouchMode(boolean initialTouchMode) {
mInitialTouchMode = initialTouchMode;
}
@Override
protected void setUp() throws Exception {
super.setUp();
mInitialTouchMode = false;
mActivityIntent = null;
}
@Override
protected void tearDown() throws Exception {
// Finish the Activity off (unless was never launched anyway)
Activity a = super.getActivity();
if (a != null) {
a.finish();
setActivity(null);
}
// Scrub out members - protects against memory leaks in the case where someone
// creates a non-static inner class (thus referencing the test case) and gives it to
// someone else to hold onto
scrubClass(ActivityInstrumentationTestCase2.class);
super.tearDown();
}
/**
* Runs the current unit test. If the unit test is annotated with
* {@link android.test.UiThreadTest}, force the Activity to be created before switching to
* the UI thread.
*/
@Override
protected void runTest() throws Throwable {
try {
Method method = getClass().getMethod(getName(), (Class[]) null);
if (method.isAnnotationPresent(UiThreadTest.class)) {
getActivity();
}
} catch (Exception e) {
// eat the exception here; super.runTest() will catch it again and handle it properly
}
super.runTest();
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Activity;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* This is common code used to support Activity test cases. For more useful classes, please see
* {@link android.test.ActivityUnitTestCase} and
* {@link android.test.ActivityInstrumentationTestCase}.
*
* @deprecated New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public abstract class ActivityTestCase extends InstrumentationTestCase {
/**
* The activity that will be set up for use in each test method.
*/
private Activity mActivity;
/**
* @return Returns the activity under test.
*/
protected Activity getActivity() {
return mActivity;
}
/**
* Set the activity under test.
* @param testActivity The activity under test
*/
protected void setActivity(Activity testActivity) {
mActivity = testActivity;
}
/**
* This function is called by various TestCase implementations, at tearDown() time, in order
* to scrub out any class variables. This protects against memory leaks in the case where a
* test case creates a non-static inner class (thus referencing the test case) and gives it to
* someone else to hold onto.
*
* @param testCaseClass The class of the derived TestCase implementation.
*
* @throws IllegalAccessException
*/
protected void scrubClass(final Class<?> testCaseClass)
throws IllegalAccessException {
final Field[] fields = getClass().getDeclaredFields();
for (Field field : fields) {
final Class<?> fieldClass = field.getDeclaringClass();
if (testCaseClass.isAssignableFrom(fieldClass) && !field.getType().isPrimitive()
&& (field.getModifiers() & Modifier.FINAL) == 0) {
try {
field.setAccessible(true);
field.set(this, null);
} catch (Exception e) {
android.util.Log.d("TestCase", "Error: Could not nullify field!");
}
if (field.get(this) != null) {
android.util.Log.d("TestCase", "Error: Could not nullify field!");
}
}
}
}
}

View File

@@ -0,0 +1,348 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Activity;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.IBinder;
//import android.test.mock.MockApplication;
import android.view.Window;
import android.util.Log;
/**
* This class provides isolated testing of a single activity. The activity under test will
* be created with minimal connection to the system infrastructure, and you can inject mocked or
* wrappered versions of many of Activity's dependencies. Most of the work is handled
* automatically here by {@link #setUp} and {@link #tearDown}.
*
* <p>If you prefer a functional test, see {@link android.test.ActivityInstrumentationTestCase}.
*
* <p>It must be noted that, as a true unit test, your Activity will not be running in the
* normal system and will not participate in the normal interactions with other Activities.
* The following methods should not be called in this configuration - most of them will throw
* exceptions:
* <ul>
* <li>{@link android.app.Activity#createPendingResult(int, Intent, int)}</li>
* <li>{@link android.app.Activity#startActivityIfNeeded(Intent, int)}</li>
* <li>{@link android.app.Activity#startActivityFromChild(Activity, Intent, int)}</li>
* <li>{@link android.app.Activity#startNextMatchingActivity(Intent)}</li>
* <li>{@link android.app.Activity#getCallingActivity()}</li>
* <li>{@link android.app.Activity#getCallingPackage()}</li>
* <li>{@link android.app.Activity#createPendingResult(int, Intent, int)}</li>
* <li>{@link android.app.Activity#getTaskId()}</li>
* <li>{@link android.app.Activity#isTaskRoot()}</li>
* <li>{@link android.app.Activity#moveTaskToBack(boolean)}</li>
* </ul>
*
* <p>The following methods may be called but will not do anything. For test purposes, you can use
* the methods {@link #getStartedActivityIntent()} and {@link #getStartedActivityRequest()} to
* inspect the parameters that they were called with.
* <ul>
* <li>{@link android.app.Activity#startActivity(Intent)}</li>
* <li>{@link android.app.Activity#startActivityForResult(Intent, int)}</li>
* </ul>
*
* <p>The following methods may be called but will not do anything. For test purposes, you can use
* the methods {@link #isFinishCalled()} and {@link #getFinishedActivityRequest()} to inspect the
* parameters that they were called with.
* <ul>
* <li>{@link android.app.Activity#finish()}</li>
* <li>{@link android.app.Activity#finishFromChild(Activity child)}</li>
* <li>{@link android.app.Activity#finishActivity(int requestCode)}</li>
* </ul>
*
* @deprecated Write
* <a href="{@docRoot}training/testing/unit-testing/local-unit-tests.html">Local Unit Tests</a>
* instead.
*/
@Deprecated
public abstract class ActivityUnitTestCase<T extends Activity>
extends ActivityTestCase {
private static final String TAG = "ActivityUnitTestCase";
private Class<T> mActivityClass;
private Context mActivityContext;
private Application mApplication;
private MockParent mMockParent;
private boolean mAttached = false;
private boolean mCreated = false;
public ActivityUnitTestCase(Class<T> activityClass) {
mActivityClass = activityClass;
}
@Override
public T getActivity() {
return (T) super.getActivity();
}
@Override
protected void setUp() throws Exception {
super.setUp();
// default value for target context, as a default
mActivityContext = getInstrumentation().getTargetContext();
}
/**
* Start the activity under test, in the same way as if it was started by
* {@link android.content.Context#startActivity Context.startActivity()}, providing the
* arguments it supplied. When you use this method to start the activity, it will automatically
* be stopped by {@link #tearDown}.
*
* <p>This method will call onCreate(), but if you wish to further exercise Activity life
* cycle methods, you must call them yourself from your test case.
*
* <p><i>Do not call from your setUp() method. You must call this method from each of your
* test methods.</i>
*
* @param intent The Intent as if supplied to {@link android.content.Context#startActivity}.
* @param savedInstanceState The instance state, if you are simulating this part of the life
* cycle. Typically null.
* @param lastNonConfigurationInstance This Object will be available to the
* Activity if it calls {@link android.app.Activity#getLastNonConfigurationInstance()}.
* Typically null.
* @return Returns the Activity that was created
*/
protected T startActivity(Intent intent, Bundle savedInstanceState,
Object lastNonConfigurationInstance) {
assertFalse("Activity already created", mCreated);
if (!mAttached) {
assertNotNull(mActivityClass);
setActivity(null);
T newActivity = null;
try {
IBinder token = null;
if (mApplication == null) {
setApplication(Context.this_application/*new MockApplication()*/);
}
ComponentName cn = new ComponentName(mActivityClass.getPackage().getName(),
mActivityClass.getName());
intent.setComponent(cn);
ActivityInfo info = new ActivityInfo();
CharSequence title = mActivityClass.getName();
mMockParent = new MockParent();
String id = null;
newActivity = (T) getInstrumentation().newActivity(mActivityClass, mActivityContext,
token, mApplication, intent, info, title, mMockParent, id,
lastNonConfigurationInstance);
} catch (Exception e) {
Log.w(TAG, "Catching exception", e);
assertNotNull(newActivity);
}
assertNotNull(newActivity);
setActivity(newActivity);
mAttached = true;
}
T result = getActivity();
if (result != null) {
getInstrumentation().callActivityOnCreate(getActivity(), savedInstanceState);
mCreated = true;
}
return result;
}
@Override
protected void tearDown() throws Exception {
setActivity(null);
// Scrub out members - protects against memory leaks in the case where someone
// creates a non-static inner class (thus referencing the test case) and gives it to
// someone else to hold onto
scrubClass(ActivityInstrumentationTestCase.class);
super.tearDown();
}
/**
* Set the application for use during the test. You must call this function before calling
* {@link #startActivity}. If your test does not call this method,
* @param application The Application object that will be injected into the Activity under test.
*/
public void setApplication(Application application) {
mApplication = application;
}
/**
* If you wish to inject a Mock, Isolated, or otherwise altered context, you can do so
* here. You must call this function before calling {@link #startActivity}. If you wish to
* obtain a real Context, as a building block, use getInstrumentation().getTargetContext().
*/
public void setActivityContext(Context activityContext) {
mActivityContext = activityContext;
}
/**
* This method will return the value if your Activity under test calls
* {@link android.app.Activity#setRequestedOrientation}.
*/
public int getRequestedOrientation() {
if (mMockParent != null) {
return mMockParent.mRequestedOrientation;
}
return 0;
}
/**
* This method will return the launch intent if your Activity under test calls
* {@link android.app.Activity#startActivity(Intent)} or
* {@link android.app.Activity#startActivityForResult(Intent, int)}.
* @return The Intent provided in the start call, or null if no start call was made.
*/
public Intent getStartedActivityIntent() {
if (mMockParent != null) {
return mMockParent.mStartedActivityIntent;
}
return null;
}
/**
* This method will return the launch request code if your Activity under test calls
* {@link android.app.Activity#startActivityForResult(Intent, int)}.
* @return The request code provided in the start call, or -1 if no start call was made.
*/
public int getStartedActivityRequest() {
if (mMockParent != null) {
return mMockParent.mStartedActivityRequest;
}
return 0;
}
/**
* This method will notify you if the Activity under test called
* {@link android.app.Activity#finish()},
* {@link android.app.Activity#finishFromChild(Activity)}, or
* {@link android.app.Activity#finishActivity(int)}.
* @return Returns true if one of the listed finish methods was called.
*/
public boolean isFinishCalled() {
if (mMockParent != null) {
return mMockParent.mFinished;
}
return false;
}
/**
* This method will return the request code if the Activity under test called
* {@link android.app.Activity#finishActivity(int)}.
* @return The request code provided in the start call, or -1 if no finish call was made.
*/
public int getFinishedActivityRequest() {
if (mMockParent != null) {
return mMockParent.mFinishedActivityRequest;
}
return 0;
}
/**
* This mock Activity represents the "parent" activity. By injecting this, we allow the user
* to call a few more Activity methods, including:
* <ul>
* <li>{@link android.app.Activity#getRequestedOrientation()}</li>
* <li>{@link android.app.Activity#setRequestedOrientation(int)}</li>
* <li>{@link android.app.Activity#finish()}</li>
* <li>{@link android.app.Activity#finishActivity(int requestCode)}</li>
* <li>{@link android.app.Activity#finishFromChild(Activity child)}</li>
* </ul>
*
* TODO: Make this overrideable, and the unit test can look for calls to other methods
*/
private static class MockParent extends Activity {
public int mRequestedOrientation = 0;
public Intent mStartedActivityIntent = null;
public int mStartedActivityRequest = -1;
public boolean mFinished = false;
public int mFinishedActivityRequest = -1;
/**
* Implementing in the parent allows the user to call this function on the tested activity.
*/
@Override
public void setRequestedOrientation(int requestedOrientation) {
mRequestedOrientation = requestedOrientation;
}
/**
* Implementing in the parent allows the user to call this function on the tested activity.
*/
@Override
public int getRequestedOrientation() {
return mRequestedOrientation;
}
/**
* By returning null here, we inhibit the creation of any "container" for the window.
*/
@Override
public Window getWindow() {
return null;
}
/**
* By defining this in the parent, we allow the tested activity to call
* <ul>
* <li>{@link android.app.Activity#startActivity(Intent)}</li>
* <li>{@link android.app.Activity#startActivityForResult(Intent, int)}</li>
* </ul>
*/
//@Override
public void startActivityFromChild(Activity child, Intent intent, int requestCode) {
mStartedActivityIntent = intent;
mStartedActivityRequest = requestCode;
}
/**
* By defining this in the parent, we allow the tested activity to call
* <ul>
* <li>{@link android.app.Activity#finish()}</li>
* <li>{@link android.app.Activity#finishFromChild(Activity child)}</li>
* </ul>
*/
//@Override
public void finishFromChild(Activity child) {
mFinished = true;
}
/**
* By defining this in the parent, we allow the tested activity to call
* <ul>
* <li>{@link android.app.Activity#finishActivity(int requestCode)}</li>
* </ul>
*/
//@Override
public void finishActivityFromChild(Activity child, int requestCode) {
mFinished = true;
mFinishedActivityRequest = requestCode;
}
}
}

View File

@@ -0,0 +1,182 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.test.suitebuilder.annotation.Suppress;
import junit.framework.TestCase;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* Extend this if you need to access Resources or other things that depend on Activity Context.
*
* @deprecated Use
* <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
* InstrumentationRegistry</a> instead. New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public class AndroidTestCase extends TestCase {
protected Context mContext;
private Context mTestContext;
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
@Suppress
public void testAndroidTestCaseSetupProperly() {
assertNotNull("Context is null. setContext should be called before tests are run",
mContext);
}
public void setContext(Context context) {
mContext = context;
}
public Context getContext() {
return mContext;
}
/**
* Test context can be used to access resources from the test's own package
* as opposed to the resources from the test target package. Access to the
* latter is provided by the context set with the {@link #setContext}
* method.
*
*/
public void setTestContext(Context context) {
mTestContext = context;
}
/**
* Returns the test context that was set via {@link #setTestContext(Context)}.
*/
public Context getTestContext() {
return mTestContext;
}
/**
* Asserts that launching a given activity is protected by a particular permission by
* attempting to start the activity and validating that a {@link SecurityException}
* is thrown that mentions the permission in its error message.
*
* Note that an instrumentation isn't needed because all we are looking for is a security error
* and we don't need to wait for the activity to launch and get a handle to the activity.
*
* @param packageName The package name of the activity to launch.
* @param className The class of the activity to launch.
* @param permission The name of the permission.
*/
public void assertActivityRequiresPermission(
String packageName, String className, String permission) {
final Intent intent = new Intent();
intent.setClassName(packageName, className);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
getContext().startActivity(intent);
fail("expected security exception for " + permission);
} catch (SecurityException expected) {
assertNotNull("security exception's error message.", expected.getMessage());
assertTrue("error message should contain " + permission + ".",
expected.getMessage().contains(permission));
}
}
/**
* Asserts that reading from the content uri requires a particular permission by querying the
* uri and ensuring a {@link SecurityException} is thrown mentioning the particular permission.
*
* @param uri The uri that requires a permission to query.
* @param permission The permission that should be required.
*/
public void assertReadingContentUriRequiresPermission(Uri uri, String permission) {
try {
getContext().getContentResolver().query(uri, null, null, null, null);
fail("expected SecurityException requiring " + permission);
} catch (SecurityException expected) {
assertNotNull("security exception's error message.", expected.getMessage());
assertTrue("error message should contain " + permission + ".",
expected.getMessage().contains(permission));
}
}
/**
* Asserts that writing to the content uri requires a particular permission by inserting into
* the uri and ensuring a {@link SecurityException} is thrown mentioning the particular
* permission.
*
* @param uri The uri that requires a permission to query.
* @param permission The permission that should be required.
*/
public void assertWritingContentUriRequiresPermission(Uri uri, String permission) {
try {
getContext().getContentResolver().insert(uri, new ContentValues());
fail("expected SecurityException requiring " + permission);
} catch (SecurityException expected) {
assertNotNull("security exception's error message.", expected.getMessage());
assertTrue("error message should contain \"" + permission + "\". Got: \""
+ expected.getMessage() + "\".",
expected.getMessage().contains(permission));
}
}
/**
* This function is called by various TestCase implementations, at tearDown() time, in order
* to scrub out any class variables. This protects against memory leaks in the case where a
* test case creates a non-static inner class (thus referencing the test case) and gives it to
* someone else to hold onto.
*
* @param testCaseClass The class of the derived TestCase implementation.
*
* @throws IllegalAccessException
*/
protected void scrubClass(final Class<?> testCaseClass)
throws IllegalAccessException {
final Field[] fields = getClass().getDeclaredFields();
for (Field field : fields) {
if (!field.getType().isPrimitive() &&
!Modifier.isStatic(field.getModifiers())) {
try {
field.setAccessible(true);
field.set(this, null);
} catch (Exception e) {
android.util.Log.d("TestCase", "Error: Could not nullify field!");
}
if (field.get(this) != null) {
android.util.Log.d("TestCase", "Error: Could not nullify field!");
}
}
}
}
}

View File

@@ -0,0 +1,251 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Instrumentation;
import android.content.Context;
import java.util.ArrayList;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestListener;
import junit.framework.TestResult;
import junit.framework.TestSuite;
import junit.runner.BaseTestRunner;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
/**
* @deprecated Use
* <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
* AndroidJUnitRunner</a> instead. New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public class AndroidTestRunner extends BaseTestRunner {
private TestResult mTestResult;
private String mTestClassName;
private List<TestCase> mTestCases;
private Context mContext;
private boolean mSkipExecution = false;
private List<TestListener> mTestListeners = new ArrayList<>();
private Instrumentation mInstrumentation;
@SuppressWarnings("unchecked")
public void setTestClassName(String testClassName, String testMethodName) {
Class testClass = loadTestClass(testClassName);
if (shouldRunSingleTestMethod(testMethodName, testClass)) {
TestCase testCase = buildSingleTestMethod(testClass, testMethodName);
mTestCases = new ArrayList<>();
mTestCases.add(testCase);
mTestClassName = testClass.getSimpleName();
} else {
setTest(getTest(testClass), testClass);
}
}
public void setTest(Test test) {
setTest(test, test.getClass());
}
private void setTest(Test test, Class<? extends Test> testClass) {
mTestCases = (List<TestCase>) TestCaseUtil.getTests(test, true);
if (TestSuite.class.isAssignableFrom(testClass)) {
mTestClassName = TestCaseUtil.getTestName(test);
} else {
mTestClassName = testClass.getSimpleName();
}
}
public void clearTestListeners() {
mTestListeners.clear();
}
public void addTestListener(TestListener testListener) {
if (testListener != null) {
mTestListeners.add(testListener);
}
}
@SuppressWarnings("unchecked")
private Class<? extends Test> loadTestClass(String testClassName) {
try {
return (Class<? extends Test>) mContext.getClassLoader().loadClass(testClassName);
} catch (ClassNotFoundException e) {
runFailed("Could not find test class. Class: " + testClassName, e);
}
return null;
}
private TestCase buildSingleTestMethod(Class testClass, String testMethodName) {
try {
Constructor c = testClass.getConstructor();
return newSingleTestMethod(testClass, testMethodName, c);
} catch (NoSuchMethodException e) {
}
try {
Constructor c = testClass.getConstructor(String.class);
return newSingleTestMethod(testClass, testMethodName, c, testMethodName);
} catch (NoSuchMethodException e) {
}
return null;
}
private TestCase newSingleTestMethod(Class testClass, String testMethodName,
Constructor constructor, Object... args) {
try {
TestCase testCase = (TestCase) constructor.newInstance(args);
testCase.setName(testMethodName);
return testCase;
} catch (IllegalAccessException e) {
runFailed("Could not access test class. Class: " + testClass.getName(), e);
} catch (InstantiationException e) {
runFailed("Could not instantiate test class. Class: " + testClass.getName(), e);
} catch (IllegalArgumentException e) {
runFailed("Illegal argument passed to constructor. Class: " + testClass.getName(), e);
} catch (InvocationTargetException e) {
runFailed("Constructor threw an exception. Class: " + testClass.getName(), e);
}
return null;
}
private boolean shouldRunSingleTestMethod(String testMethodName,
Class<? extends Test> testClass) {
return testMethodName != null && TestCase.class.isAssignableFrom(testClass);
}
private Test getTest(Class clazz) {
if (TestSuiteProvider.class.isAssignableFrom(clazz)) {
try {
TestSuiteProvider testSuiteProvider =
(TestSuiteProvider) clazz.getConstructor().newInstance();
return testSuiteProvider.getTestSuite();
} catch (InstantiationException e) {
runFailed("Could not instantiate test suite provider. Class: " + clazz.getName(), e);
} catch (IllegalAccessException e) {
runFailed("Illegal access of test suite provider. Class: " + clazz.getName(), e);
} catch (InvocationTargetException e) {
runFailed("Invocation exception test suite provider. Class: " + clazz.getName(), e);
} catch (NoSuchMethodException e) {
runFailed("No such method on test suite provider. Class: " + clazz.getName(), e);
}
}
return getTest(clazz.getName());
}
protected TestResult createTestResult() {
if (mSkipExecution) {
return new NoExecTestResult();
}
return new TestResult();
}
void setSkipExecution(boolean skip) {
mSkipExecution = skip;
}
public List<TestCase> getTestCases() {
return mTestCases;
}
public String getTestClassName() {
return mTestClassName;
}
public TestResult getTestResult() {
return mTestResult;
}
public void runTest() {
runTest(createTestResult());
}
public void runTest(TestResult testResult) {
mTestResult = testResult;
for (TestListener testListener : mTestListeners) {
mTestResult.addListener(testListener);
}
Context testContext = mInstrumentation == null ? mContext : mInstrumentation.getContext();
for (TestCase testCase : mTestCases) {
setContextIfAndroidTestCase(testCase, mContext, testContext);
setInstrumentationIfInstrumentationTestCase(testCase, mInstrumentation);
testCase.run(mTestResult);
}
}
private void setContextIfAndroidTestCase(Test test, Context context, Context testContext) {
if (AndroidTestCase.class.isAssignableFrom(test.getClass())) {
((AndroidTestCase) test).setContext(context);
((AndroidTestCase) test).setTestContext(testContext);
}
}
public void setContext(Context context) {
mContext = context;
}
private void setInstrumentationIfInstrumentationTestCase(
Test test, Instrumentation instrumentation) {
if (InstrumentationTestCase.class.isAssignableFrom(test.getClass())) {
((InstrumentationTestCase) test).injectInstrumentation(instrumentation);
}
}
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);
}
@Override
protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
return mContext.getClassLoader().loadClass(suiteClassName);
}
public void testStarted(String testName) {
}
public void testEnded(String testName) {
}
public void testFailed(int status, Test test, Throwable t) {
}
protected void runFailed(String message) {
throw new RuntimeException(message);
}
protected void runFailed(String message, Throwable cause) {
throw new RuntimeException(message, cause);
}
}

View File

@@ -0,0 +1,181 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Application;
import android.app.Instrumentation;
import android.content.Context;
/**
* This test case provides a framework in which you can test Application classes in
* a controlled environment. It provides basic support for the lifecycle of a
* Application, and hooks by which you can inject various dependencies and control
* the environment in which your Application is tested.
*
* <p><b>Lifecycle Support.</b>
* Every Application is designed to be accessed within a specific sequence of
* method calls (see {@link android.app.Application} for more details).
* In order to support the lifecycle of a Application, this test case will make the
* following calls at the following times.
*
* <ul><li>The test case will not call onCreate() until your test calls
* {@link #createApplication()}. This gives you a chance
* to set up or adjust any additional framework or test logic before
* onCreate().</li>
* <li>After your test completes, the test case {@link #tearDown} method is
* automatically called, and it will stop & destroy your application by calling its
* onDestroy() method.</li>
* </ul>
*
* <p><b>Dependency Injection.</b>
* Every Application has one inherent dependency, the {@link android.content.Context Context} in
* which it runs.
* This framework allows you to inject a modified, mock, or isolated replacement for this
* dependencies, and thus perform a true unit test.
*
* <p>If simply run your tests as-is, your Application will be injected with a fully-functional
* Context.
* You can create and inject alternative types of Contexts by calling
* {@link AndroidTestCase#setContext(Context) setContext()}. You must do this <i>before</i> calling
* {@link #createApplication()}. The test framework provides a
* number of alternatives for Context, including {@link android.test.mock.MockContext MockContext},
* {@link android.test.RenamingDelegatingContext RenamingDelegatingContext}, and
* {@link android.content.ContextWrapper ContextWrapper}.
*
* @deprecated Use
* <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
* InstrumentationRegistry</a> instead. New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public abstract class ApplicationTestCase<T extends Application> extends AndroidTestCase {
Class<T> mApplicationClass;
private Context mSystemContext;
public ApplicationTestCase(Class<T> applicationClass) {
mApplicationClass = applicationClass;
}
private T mApplication;
private boolean mAttached = false;
private boolean mCreated = false;
/**
* @return Returns the actual Application under test.
*/
public T getApplication() {
return mApplication;
}
/**
* This will do the work to instantiate the Application under test. After this, your test
* code must also start and stop the Application.
*/
@Override
protected void setUp() throws Exception {
super.setUp();
// get the real context, before the individual tests have a chance to muck with it
mSystemContext = getContext();
}
/**
* Load and attach the application under test.
*/
private void setupApplication() {
mApplication = null;
try {
mApplication = (T) Instrumentation.newApplication(mApplicationClass, getContext());
} catch (Exception e) {
assertNotNull(mApplication);
}
mAttached = true;
}
/**
* Start the Application under test, in the same way as if it was started by the system.
* If you use this method to start the Application, it will automatically
* be stopped by {@link #tearDown}. If you wish to inject a specialized Context for your
* test, by calling {@link AndroidTestCase#setContext(Context) setContext()},
* you must do so before calling this method.
*/
final protected void createApplication() {
assertFalse(mCreated);
if (!mAttached) {
setupApplication();
}
assertNotNull(mApplication);
mApplication.onCreate();
mCreated = true;
}
/**
* This will make the necessary calls to terminate the Application under test (it will
* call onTerminate(). Ordinarily this will be called automatically (by {@link #tearDown}, but
* you can call it directly from your test in order to check for proper shutdown behaviors.
*/
final protected void terminateApplication() {
if (mCreated) {
mApplication.onTerminate();
}
}
/**
* Shuts down the Application under test. Also makes sure all resources are cleaned up and
* garbage collected before moving on to the next
* test. Subclasses that override this method should make sure they call super.tearDown()
* at the end of the overriding method.
*
* @throws Exception
*/
@Override
protected void tearDown() throws Exception {
terminateApplication();
mApplication = null;
// Scrub out members - protects against memory leaks in the case where someone
// creates a non-static inner class (thus referencing the test case) and gives it to
// someone else to hold onto
scrubClass(ApplicationTestCase.class);
super.tearDown();
}
/**
* Return a real (not mocked or instrumented) system Context that can be used when generating
* Mock or other Context objects for your Application under test.
*
* @return Returns a reference to a normal Context.
*/
public Context getSystemContext() {
return mSystemContext;
}
/**
* This test simply confirms that the Application class can be instantiated properly.
*
* @throws Exception
*/
final public void testApplicationTestCaseSetUpProperly() throws Exception {
setupApplication();
assertNotNull("Application class could not be instantiated successfully", mApplication);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
/**
* Thrown when an assertion failed.
*
* @deprecated use junit.framework.AssertionFailedError
*/
@Deprecated
public class AssertionFailedError extends Error {
/**
* It is more typical to call {@link #AssertionFailedError(String)}.
*/
public AssertionFailedError() {
}
public AssertionFailedError(String errorMessage) {
super(errorMessage);
}
}

View File

@@ -0,0 +1,262 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.util.Log;
import dalvik.system.DexFile;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
/**
* Generate {@link ClassPathPackageInfo}s by scanning apk paths.
*
* {@hide} Not needed for 1.0 SDK.
*/
@Deprecated
public class ClassPathPackageInfoSource {
private static final ClassLoader CLASS_LOADER
= ClassPathPackageInfoSource.class.getClassLoader();
private static String[] apkPaths;
private static ClassPathPackageInfoSource classPathSource;
private final SimpleCache<String, ClassPathPackageInfo> cache =
new SimpleCache<String, ClassPathPackageInfo>() {
@Override
protected ClassPathPackageInfo load(String pkgName) {
return createPackageInfo(pkgName);
}
};
// The class path of the running application
private final String[] classPath;
private final ClassLoader classLoader;
private ClassPathPackageInfoSource(ClassLoader classLoader) {
this.classLoader = classLoader;
classPath = getClassPath();
}
static void setApkPaths(String[] apkPaths) {
ClassPathPackageInfoSource.apkPaths = apkPaths;
}
public static ClassPathPackageInfoSource forClassPath(ClassLoader classLoader) {
if (classPathSource == null) {
classPathSource = new ClassPathPackageInfoSource(classLoader);
}
return classPathSource;
}
public Set<Class<?>> getTopLevelClassesRecursive(String packageName) {
ClassPathPackageInfo packageInfo = cache.get(packageName);
return packageInfo.getTopLevelClassesRecursive();
}
private ClassPathPackageInfo createPackageInfo(String packageName) {
Set<String> subpackageNames = new TreeSet<String>();
Set<String> classNames = new TreeSet<String>();
Set<Class<?>> topLevelClasses = new HashSet<>();
findClasses(packageName, classNames, subpackageNames);
for (String className : classNames) {
if (className.endsWith(".R") || className.endsWith(".Manifest")) {
// Don't try to load classes that are generated. They usually aren't in test apks.
continue;
}
try {
// We get errors in the emulator if we don't use the caller's class loader.
topLevelClasses.add(Class.forName(className, false,
(classLoader != null) ? classLoader : CLASS_LOADER));
} catch (ClassNotFoundException | NoClassDefFoundError e) {
// Should not happen unless there is a generated class that is not included in
// the .apk.
Log.w("ClassPathPackageInfoSource", "Cannot load class. "
+ "Make sure it is in your apk. Class name: '" + className
+ "'. Message: " + e.getMessage(), e);
}
}
return new ClassPathPackageInfo(packageName, subpackageNames,
topLevelClasses);
}
/**
* Finds all classes and sub packages that are below the packageName and
* add them to the respective sets. Searches the package on the whole class
* path.
*/
private void findClasses(String packageName, Set<String> classNames,
Set<String> subpackageNames) {
for (String entryName : classPath) {
File classPathEntry = new File(entryName);
// Forge may not have brought over every item in the classpath. Be
// polite and ignore missing entries.
if (classPathEntry.exists()) {
try {
if (entryName.endsWith(".apk")) {
findClassesInApk(entryName, packageName, classNames, subpackageNames);
} else {
// scan the directories that contain apk files.
for (String apkPath : apkPaths) {
File file = new File(apkPath);
scanForApkFiles(file, packageName, classNames, subpackageNames);
}
}
} catch (IOException e) {
throw new AssertionError("Can't read classpath entry " +
entryName + ": " + e.getMessage());
}
}
}
}
private void scanForApkFiles(File source, String packageName,
Set<String> classNames, Set<String> subpackageNames) throws IOException {
if (source.getPath().endsWith(".apk")) {
findClassesInApk(source.getPath(), packageName, classNames, subpackageNames);
} else {
File[] files = source.listFiles();
if (files != null) {
for (File file : files) {
scanForApkFiles(file, packageName, classNames, subpackageNames);
}
}
}
}
/**
* Finds all classes and sub packages that are below the packageName and
* add them to the respective sets. Searches the package in a single apk file.
*/
private void findClassesInApk(String apkPath, String packageName,
Set<String> classNames, Set<String> subpackageNames)
throws IOException {
DexFile dexFile = null;
try {
dexFile = new DexFile(apkPath);
Enumeration<String> apkClassNames = dexFile.entries();
while (apkClassNames.hasMoreElements()) {
String className = apkClassNames.nextElement();
if (className.startsWith(packageName)) {
String subPackageName = packageName;
int lastPackageSeparator = className.lastIndexOf('.');
if (lastPackageSeparator > 0) {
subPackageName = className.substring(0, lastPackageSeparator);
}
if (subPackageName.length() > packageName.length()) {
subpackageNames.add(subPackageName);
} else if (isToplevelClass(className)) {
classNames.add(className);
}
}
}
} catch (IOException e) {
if (false) {
Log.w("ClassPathPackageInfoSource",
"Error finding classes at apk path: " + apkPath, e);
}
} finally {
if (dexFile != null) {
// Todo: figure out why closing causes a dalvik error resulting in vm shutdown.
// dexFile.close();
}
}
}
/**
* Checks if a given file name represents a toplevel class.
*/
private static boolean isToplevelClass(String fileName) {
return fileName.indexOf('$') < 0;
}
/**
* Gets the class path from the System Property "java.class.path" and splits
* it up into the individual elements.
*/
private static String[] getClassPath() {
String classPath = System.getProperty("java.class.path");
String separator = System.getProperty("path.separator", ":");
return classPath.split(Pattern.quote(separator));
}
/**
* The Package object doesn't allow you to iterate over the contained
* classes and subpackages of that package. This is a version that does.
*/
private class ClassPathPackageInfo {
private final String packageName;
private final Set<String> subpackageNames;
private final Set<Class<?>> topLevelClasses;
private ClassPathPackageInfo(String packageName,
Set<String> subpackageNames, Set<Class<?>> topLevelClasses) {
this.packageName = packageName;
this.subpackageNames = Collections.unmodifiableSet(subpackageNames);
this.topLevelClasses = Collections.unmodifiableSet(topLevelClasses);
}
private Set<ClassPathPackageInfo> getSubpackages() {
Set<ClassPathPackageInfo> info = new HashSet<>();
for (String name : subpackageNames) {
info.add(cache.get(name));
}
return info;
}
private Set<Class<?>> getTopLevelClassesRecursive() {
Set<Class<?>> set = new HashSet<>();
addTopLevelClassesTo(set);
return set;
}
private void addTopLevelClassesTo(Set<Class<?>> set) {
set.addAll(topLevelClasses);
for (ClassPathPackageInfo info : getSubpackages()) {
info.addTopLevelClassesTo(set);
}
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ClassPathPackageInfo) {
ClassPathPackageInfo that = (ClassPathPackageInfo) obj;
return (this.packageName).equals(that.packageName);
}
return false;
}
@Override
public int hashCode() {
return packageName.hashCode();
}
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
/**
* Thrown when an assert equals for Strings failed.
*
* @deprecated use org.junit.ComparisonFailure
*/
@Deprecated
public class ComparisonFailure extends AssertionFailedError {
private junit.framework.ComparisonFailure mComparison;
public ComparisonFailure(String message, String expected, String actual) {
mComparison = new junit.framework.ComparisonFailure(message, expected, actual);
}
public String getMessage() {
return mComparison.getMessage();
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
/**
* This annotation can be used on an {@link android.test.InstrumentationTestCase}'s
* test methods. When the annotation is present, the test method is re-executed if
* the test fails. The total number of executions is specified by the tolerance and
* defaults to 1.
*
* @deprecated Use
* <a href="{@docRoot}reference/android/support/test/filters/FlakyTest.html">
* FlakyTest</a> instead. New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FlakyTest {
/**
* Indicates how many times a test can run and fail before being reported
* as a failed test. If the tolerance factor is less than 1, the test runs
* only once.
*
* @return The total number of allowed run, the default is 1.
*/
int tolerance() default 1;
}

View File

@@ -0,0 +1,369 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import junit.framework.TestCase;
/**
* A test case that has access to {@link Instrumentation}.
*
* @deprecated Use
* <a href="{@docRoot}reference/androidx/test/platform/app/InstrumentationRegistry.html">
* InstrumentationRegistry</a> instead. New tests should be written using the
* <a href="{@docRoot}training/testing/index.html">AndroidX Test Library</a>.
*/
@Deprecated
public class InstrumentationTestCase extends TestCase {
private Instrumentation mInstrumentation;
/**
* Injects instrumentation into this test case. This method is
* called by the test runner during test setup.
*
* @param instrumentation the instrumentation to use with this instance
*/
public void injectInstrumentation(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
}
/**
* Injects instrumentation into this test case. This method is
* called by the test runner during test setup.
*
* @param instrumentation the instrumentation to use with this instance
*
* @deprecated Incorrect spelling,
* use {@link #injectInstrumentation(android.app.Instrumentation)} instead.
*/
@Deprecated
public void injectInsrumentation(Instrumentation instrumentation) {
injectInstrumentation(instrumentation);
}
/**
* Inheritors can access the instrumentation using this.
* @return instrumentation
*/
public Instrumentation getInstrumentation() {
return mInstrumentation;
}
/**
* Utility method for launching an activity.
*
* <p>The {@link Intent} used to launch the Activity is:
* action = {@link Intent#ACTION_MAIN}
* extras = null, unless a custom bundle is provided here
* All other fields are null or empty.
*
* <p><b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
* package hosting the activity to be launched, which is specified in the AndroidManifest.xml
* file. This is not necessarily the same as the java package name.
*
* @param pkg The package hosting the activity to be launched.
* @param activityCls The activity class to launch.
* @param extras Optional extra stuff to pass to the activity.
* @return The activity, or null if non launched.
*/
public final <T extends Activity> T launchActivity(
String pkg,
Class<T> activityCls,
Bundle extras) {
Intent intent = new Intent(Intent.ACTION_MAIN);
if (extras != null) {
intent.putExtras(extras);
}
return launchActivityWithIntent(pkg, activityCls, intent);
}
/**
* Utility method for launching an activity with a specific Intent.
*
* <p><b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
* package hosting the activity to be launched, which is specified in the AndroidManifest.xml
* file. This is not necessarily the same as the java package name.
*
* @param pkg The package hosting the activity to be launched.
* @param activityCls The activity class to launch.
* @param intent The intent to launch with
* @return The activity, or null if non launched.
*/
@SuppressWarnings("unchecked")
public final <T extends Activity> T launchActivityWithIntent(
String pkg,
Class<T> activityCls,
Intent intent) {
intent.setClassName(pkg, activityCls.getName());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
T activity = (T) getInstrumentation().startActivitySync(intent);
getInstrumentation().waitForIdleSync();
return activity;
}
/**
* Helper for running portions of a test on the UI thread.
*
* Note, in most cases it is simpler to annotate the test method with
* {@link android.test.UiThreadTest}, which will run the entire test method on the UI thread.
* Use this method if you need to switch in and out of the UI thread to perform your test.
*
* @param r runnable containing test code in the {@link Runnable#run()} method
*/
public void runTestOnUiThread(final Runnable r) throws Throwable {
final Throwable[] exceptions = new Throwable[1];
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
try {
r.run();
} catch (Throwable throwable) {
exceptions[0] = throwable;
}
}
});
if (exceptions[0] != null) {
throw exceptions[0];
}
}
/**
* Runs the current unit test. If the unit test is annotated with
* {@link android.test.UiThreadTest}, the test is run on the UI thread.
*/
@Override
protected void runTest() throws Throwable {
String fName = getName();
assertNotNull(fName);
Method method = null;
try {
// use getMethod to get all public inherited
// methods. getDeclaredMethods returns all
// methods of this class but excludes the
// inherited ones.
method = getClass().getMethod(fName, (Class[]) null);
} catch (NoSuchMethodException e) {
fail("Method \""+fName+"\" not found");
}
if (!Modifier.isPublic(method.getModifiers())) {
fail("Method \""+fName+"\" should be public");
}
int runCount = 1;
boolean isRepetitive = false;
if (method.isAnnotationPresent(FlakyTest.class)) {
runCount = method.getAnnotation(FlakyTest.class).tolerance();
} else if (method.isAnnotationPresent(RepetitiveTest.class)) {
runCount = method.getAnnotation(RepetitiveTest.class).numIterations();
isRepetitive = true;
}
if (method.isAnnotationPresent(UiThreadTest.class)) {
final int tolerance = runCount;
final boolean repetitive = isRepetitive;
final Method testMethod = method;
final Throwable[] exceptions = new Throwable[1];
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
try {
runMethod(testMethod, tolerance, repetitive);
} catch (Throwable throwable) {
exceptions[0] = throwable;
}
}
});
if (exceptions[0] != null) {
throw exceptions[0];
}
} else {
runMethod(method, runCount, isRepetitive);
}
}
// For backwards-compatibility after adding isRepetitive
private void runMethod(Method runMethod, int tolerance) throws Throwable {
runMethod(runMethod, tolerance, false);
}
private void runMethod(Method runMethod, int tolerance, boolean isRepetitive) throws Throwable {
Throwable exception = null;
int runCount = 0;
do {
try {
runMethod.invoke(this, (Object[]) null);
exception = null;
} catch (InvocationTargetException e) {
e.fillInStackTrace();
exception = e.getTargetException();
} catch (IllegalAccessException e) {
e.fillInStackTrace();
exception = e;
} finally {
runCount++;
// Report current iteration number, if test is repetitive
if (isRepetitive) {
Bundle iterations = new Bundle();
iterations.putInt("currentiterations", runCount);
getInstrumentation().sendStatus(2, iterations);
}
}
} while ((runCount < tolerance) && (isRepetitive || exception != null));
if (exception != null) {
throw exception;
}
}
/**
* Sends a series of key events through instrumentation and waits for idle. The sequence
* of keys is a string containing the key names as specified in KeyEvent, without the
* KEYCODE_ prefix. For instance: sendKeys("DPAD_LEFT A B C DPAD_CENTER"). Each key can
* be repeated by using the N* prefix. For instance, to send two KEYCODE_DPAD_LEFT, use
* the following: sendKeys("2*DPAD_LEFT").
*
* @param keysSequence The sequence of keys.
*/
public void sendKeys(String keysSequence) {
final String[] keys = keysSequence.split(" ");
final int count = keys.length;
final Instrumentation instrumentation = getInstrumentation();
for (int i = 0; i < count; i++) {
String key = keys[i];
int repeater = key.indexOf('*');
int keyCount;
try {
keyCount = repeater == -1 ? 1 : Integer.parseInt(key.substring(0, repeater));
} catch (NumberFormatException e) {
Log.w("ActivityTestCase", "Invalid repeat count: " + key);
continue;
}
if (repeater != -1) {
key = key.substring(repeater + 1);
}
for (int j = 0; j < keyCount; j++) {
try {
final Field keyCodeField = KeyEvent.class.getField("KEYCODE_" + key);
final int keyCode = keyCodeField.getInt(null);
try {
instrumentation.sendKeyDownUpSync(keyCode);
} catch (SecurityException e) {
// Ignore security exceptions that are now thrown
// when trying to send to another app, to retain
// compatibility with existing tests.
}
} catch (NoSuchFieldException e) {
Log.w("ActivityTestCase", "Unknown keycode: KEYCODE_" + key);
break;
} catch (IllegalAccessException e) {
Log.w("ActivityTestCase", "Unknown keycode: KEYCODE_" + key);
break;
}
}
}
instrumentation.waitForIdleSync();
}
/**
* Sends a series of key events through instrumentation and waits for idle. For instance:
* sendKeys(KEYCODE_DPAD_LEFT, KEYCODE_DPAD_CENTER).
*
* @param keys The series of key codes to send through instrumentation.
*/
public void sendKeys(int... keys) {
final int count = keys.length;
final Instrumentation instrumentation = getInstrumentation();
for (int i = 0; i < count; i++) {
try {
instrumentation.sendKeyDownUpSync(keys[i]);
} catch (SecurityException e) {
// Ignore security exceptions that are now thrown
// when trying to send to another app, to retain
// compatibility with existing tests.
}
}
instrumentation.waitForIdleSync();
}
/**
* Sends a series of key events through instrumentation and waits for idle. Each key code
* must be preceded by the number of times the key code must be sent. For instance:
* sendRepeatedKeys(1, KEYCODE_DPAD_CENTER, 2, KEYCODE_DPAD_LEFT).
*
* @param keys The series of key repeats and codes to send through instrumentation.
*/
public void sendRepeatedKeys(int... keys) {
final int count = keys.length;
if ((count & 0x1) == 0x1) {
throw new IllegalArgumentException("The size of the keys array must "
+ "be a multiple of 2");
}
final Instrumentation instrumentation = getInstrumentation();
for (int i = 0; i < count; i += 2) {
final int keyCount = keys[i];
final int keyCode = keys[i + 1];
for (int j = 0; j < keyCount; j++) {
try {
instrumentation.sendKeyDownUpSync(keyCode);
} catch (SecurityException e) {
// Ignore security exceptions that are now thrown
// when trying to send to another app, to retain
// compatibility with existing tests.
}
}
}
instrumentation.waitForIdleSync();
}
/**
* Make sure all resources are cleaned up and garbage collected before moving on to the next
* test. Subclasses that override this method should make sure they call super.tearDown()
* at the end of the overriding method.
*
* @throws Exception
*/
@Override
protected void tearDown() throws Exception {
Runtime.getRuntime().gc();
Runtime.getRuntime().runFinalization();
Runtime.getRuntime().gc();
super.tearDown();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Instrumentation;
import junit.framework.TestSuite;
import junit.framework.Test;
import junit.framework.TestResult;
/**
* A {@link junit.framework.TestSuite} that injects {@link android.app.Instrumentation} into
* {@link InstrumentationTestCase} before running them.
*
* @deprecated Use
* <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
* InstrumentationRegistry</a> instead. New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public class InstrumentationTestSuite extends TestSuite {
private final Instrumentation mInstrumentation;
/**
* @param instr The instrumentation that will be injected into each
* test before running it.
*/
public InstrumentationTestSuite(Instrumentation instr) {
mInstrumentation = instr;
}
public InstrumentationTestSuite(String name, Instrumentation instr) {
super(name);
mInstrumentation = instr;
}
/**
* @param theClass Inspected for methods starting with 'test'
* @param instr The instrumentation to inject into each test before
* running.
*/
public InstrumentationTestSuite(final Class theClass, Instrumentation instr) {
super(theClass);
mInstrumentation = instr;
}
@Override
public void addTestSuite(Class testClass) {
addTest(new InstrumentationTestSuite(testClass, mInstrumentation));
}
@Override
public void runTest(Test test, TestResult result) {
if (test instanceof InstrumentationTestCase) {
((InstrumentationTestCase) test).injectInstrumentation(mInstrumentation);
}
// run the test as usual
super.runTest(test, result);
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.accounts.AccountManager;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Process;
import android.test.mock.MockAccountManager;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
/**
* A mock context which prevents its users from talking to the rest of the device while
* stubbing enough methods to satify code that tries to talk to other packages.
*
* @deprecated New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public class IsolatedContext extends ContextWrapper {
private ContentResolver mResolver;
private final AccountManager mMockAccountManager;
private List<Intent> mBroadcastIntents = new ArrayList<>();
public IsolatedContext(
ContentResolver resolver, Context targetContext) {
super(targetContext);
mResolver = resolver;
mMockAccountManager = MockAccountManager.newMockAccountManager(IsolatedContext.this);
}
/** Returns the list of intents that were broadcast since the last call to this method. */
public List<Intent> getAndClearBroadcastIntents() {
List<Intent> intents = mBroadcastIntents;
mBroadcastIntents = new ArrayList<>();
return intents;
}
@Override
public AttributionSource getAttributionSource() {
AttributionSource attributionSource = super.getAttributionSource();
if (attributionSource == null) {
return new AttributionSource.Builder(Process.myUid()).build();
}
return attributionSource;
}
@Override
public ContentResolver getContentResolver() {
// We need to return the real resolver so that MailEngine.makeRight can get to the
// subscribed feeds provider. TODO: mock out subscribed feeds too.
return mResolver;
}
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
return false;
}
@Override
public boolean bindService(Intent service, int flags, Executor executor,
ServiceConnection conn) {
return false;
}
@Override
public boolean bindIsolatedService(Intent service, int flags, String instanceName,
Executor executor, ServiceConnection conn) {
return false;
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return null;
}
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
// Ignore
}
@Override
public void sendBroadcast(Intent intent) {
mBroadcastIntents.add(intent);
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
mBroadcastIntents.add(intent);
}
@Override
public int checkUriPermission(
Uri uri, String readPermission, String writePermission, int pid,
int uid, int modeFlags) {
return PackageManager.PERMISSION_GRANTED;
}
@Override
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
return PackageManager.PERMISSION_GRANTED;
}
@Override
public Object getSystemService(String name) {
if (Context.ACCOUNT_SERVICE.equals(name)) {
return mMockAccountManager;
}
// No other services exist in this context.
return null;
}
@Override
public File getFilesDir() {
return new File("/dev/null");
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Instrumentation;
import android.content.Intent;
import android.os.Bundle;
/**
* Base class for all launch performance Instrumentation classes.
*/
@Deprecated
public class LaunchPerformanceBase extends Instrumentation {
/** @hide */
public static final String LOG_TAG = "Launch Performance";
protected Bundle mResults;
protected Intent mIntent;
public LaunchPerformanceBase() {
mResults = new Bundle();
mIntent = new Intent(Intent.ACTION_MAIN);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
setAutomaticPerformanceSnapshots();
}
/**
* Launches intent, and waits for idle before returning.
*/
protected void LaunchApp() {
startActivitySync(mIntent);
waitForIdleSync();
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.test;
import android.content.Loader;
import android.content.Loader.OnLoadCompleteListener;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.util.concurrent.ArrayBlockingQueue;
/**
* A convenience class for testing {@link Loader}s. This test case
* provides a simple way to synchronously get the result from a Loader making
* it easy to assert that the Loader returns the expected result.
*/
public class LoaderTestCase extends AndroidTestCase {
static {
// Force class loading of AsyncTask on the main thread so that it's handlers are tied to
// the main thread and responses from the worker thread get delivered on the main thread.
// The tests are run on another thread, allowing them to block waiting on a response from
// the code running on the main thread. The main thread can't block since the AysncTask
// results come in via the event loop.
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... args) {return null;}
@Override
protected void onPostExecute(Void result) {}
};
}
/**
* Runs a Loader synchronously and returns the result of the load. The loader will
* be started, stopped, and destroyed by this method so it cannot be reused.
*
* @param loader The loader to run synchronously
* @return The result from the loader
*/
public <T> T getLoaderResultSynchronously(final Loader<T> loader) {
// The test thread blocks on this queue until the loader puts it's result in
final ArrayBlockingQueue<T> queue = new ArrayBlockingQueue<T>(1);
// This callback runs on the "main" thread and unblocks the test thread
// when it puts the result into the blocking queue
final OnLoadCompleteListener<T> listener = new OnLoadCompleteListener<T>() {
@Override
public void onLoadComplete(Loader<T> completedLoader, T data) {
// Shut the loader down
completedLoader.unregisterListener(this);
completedLoader.stopLoading();
completedLoader.reset();
// Store the result, unblocking the test thread
queue.add(data);
}
};
// This handler runs on the "main" thread of the process since AsyncTask
// is documented as needing to run on the main thread and many Loaders use
// AsyncTask
final Handler mainThreadHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
loader.registerListener(0, listener);
loader.startLoading();
}
};
// Ask the main thread to start the loading process
mainThreadHandler.sendEmptyMessage(0);
// Block on the queue waiting for the result of the load to be inserted
T result;
while (true) {
try {
result = queue.take();
break;
} catch (InterruptedException e) {
throw new RuntimeException("waiting thread interrupted", e);
}
}
return result;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import junit.framework.TestCase;
import junit.framework.TestResult;
/**
* A benign test result that does no actually test execution, just runs
* through the motions
*
* {@hide} Not needed for SDK.
*/
@Deprecated
class NoExecTestResult extends TestResult {
/**
* Override parent to just inform listeners of test,
* and skip test execution.
*/
@Override
protected void run(final TestCase test) {
startTest(test);
endTest(test);
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
/**
* More complex interface performance for test cases.
*
* If you want your test to be used as a performance test, you must
* implement this interface.
*
* @deprecated Use
* <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
* AndroidJUnitRunner</a> instead. New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public interface PerformanceTestCase
{
/**
* Callbacks for {@link PerformanceTestCase}.
*/
public interface Intermediates
{
void setInternalIterations(int count);
void startTiming(boolean realTime);
void addIntermediate(String name);
void addIntermediate(String name, long timeInNS);
void finishTiming(boolean realTime);
}
/**
* Set up to begin performance tests. The 'intermediates' is a
* communication channel to send back intermediate performance numbers --
* if you use it, you will probably want to ensure your test is only
* executed once by returning 1. Otherwise, return 0 to allow the test
* harness to decide the number of iterations.
*
* <p>If you return a non-zero iteration count, you should call
* {@link Intermediates#startTiming intermediates.startTiming} and
* {@link Intermediates#finishTiming intermediates.endTiming} to report the
* duration of the test whose performance should actually be measured.
*
* @param intermediates Callback for sending intermediate results.
*
* @return int Maximum number of iterations to run, or 0 to let the caller
* decide.
*/
int startPerformance(Intermediates intermediates);
/**
* This method is used to determine what modes this test case can run in.
*
* @return true if this test case can only be run in performance mode.
*/
boolean isPerformanceOnly();
}

Some files were not shown because too many files have changed in this diff Show More