AndroidTestCase.java revision bedf9df706ef1fe352c1ba0734f50f9e8ad2533e
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.test;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaenimport android.content.ContentValues;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
21bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaenimport android.content.Intent;
22bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaenimport android.net.Uri;
23bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaenimport junit.framework.TestCase;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Field;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Extend this if you need to access Resources or other things that depend on Activity Context.
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class AndroidTestCase extends TestCase {
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected Context mContext;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void setUp() throws Exception {
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.setUp();
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void tearDown() throws Exception {
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.tearDown();
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void testAndroidTestCaseSetupProperly() {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assertNotNull("Context is null. setContext should be called before tests are run",
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mContext);
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setContext(Context context) {
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getContext() {
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
58bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * Asserts that launching a given activity is protected by a particular permission by
59bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * attempting to start the activity and validating that a {@link SecurityException}
60bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * is thrown that mentions the permission in its error message.
61bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     *
62bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * Note that an instrumentation isn't needed because all we are looking for is a security error
63bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * and we don't need to wait for the activity to launch and get a handle to the activity.
64bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     *
65bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * @param packageName The package name of the activity to launch.
66bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * @param className The class of the activity to launch.
67bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * @param permission The name of the permission.
68bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     */
69bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen    public void assertActivityRequiresPermission(
70bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            String packageName, String className, String permission) {
71bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        final Intent intent = new Intent();
72bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        intent.setClassName(packageName, className);
73bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
74bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen
75bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        try {
76bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            getContext().startActivity(intent);
77bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            fail("expected security exception for " + permission);
78bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        } catch (SecurityException expected) {
79bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            assertNotNull("security exception's error message.", expected.getMessage());
80bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            assertTrue("error message should contain " + permission + ".",
81bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen                    expected.getMessage().contains(permission));
82bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        }
83bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen    }
84bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen
85bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen
86bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen    /**
87bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * Asserts that reading from the content uri requires a particular permission by querying the
88bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * uri and ensuring a {@link SecurityException} is thrown mentioning the particular permission.
89bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     *
90bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * @param uri The uri that requires a permission to query.
91bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * @param permission The permission that should be required.
92bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     */
93bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen    public void assertReadingContentUriRequiresPermission(Uri uri, String permission) {
94bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        try {
95bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            getContext().getContentResolver().query(uri, null, null, null, null);
96bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            fail("expected SecurityException requiring " + permission);
97bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        } catch (SecurityException expected) {
98bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            assertNotNull("security exception's error message.", expected.getMessage());
99bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            assertTrue("error message should contain " + permission + ".",
100bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen                    expected.getMessage().contains(permission));
101bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        }
102bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen    }
103bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen
104bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen    /**
105bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * Asserts that writing to the content uri requires a particular permission by inserting into
106bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * the uri and ensuring a {@link SecurityException} is thrown mentioning the particular
107bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * permission.
108bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     *
109bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * @param uri The uri that requires a permission to query.
110bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     * @param permission The permission that should be required.
111bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen     */
112bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen    public void assertWritingContentUriRequiresPermission(Uri uri, String permission) {
113bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        try {
114bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            getContext().getContentResolver().insert(uri, new ContentValues());
115bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            fail("expected SecurityException requiring " + permission);
116bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        } catch (SecurityException expected) {
117bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            assertNotNull("security exception's error message.", expected.getMessage());
118bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen            assertTrue("error message should contain " + permission + ".",
119bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen                    expected.getMessage().contains(permission));
120bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen        }
121bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen    }
122bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen
123bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen    /**
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This function is called by various TestCase implementations, at tearDown() time, in order
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to scrub out any class variables.  This protects against memory leaks in the case where a
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * test case creates a non-static inner class (thus referencing the test case) and gives it to
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * someone else to hold onto.
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param testCaseClass The class of the derived TestCase implementation.
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalAccessException
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void scrubClass(final Class<?> testCaseClass)
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    throws IllegalAccessException {
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Field[] fields = getClass().getDeclaredFields();
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Field field : fields) {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Class<?> fieldClass = field.getDeclaringClass();
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (testCaseClass.isAssignableFrom(fieldClass) && !field.getType().isPrimitive()) {
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    field.setAccessible(true);
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    field.set(this, null);
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (Exception e) {
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    android.util.Log.d("TestCase", "Error: Could not nullify field!");
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (field.get(this) != null) {
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    android.util.Log.d("TestCase", "Error: Could not nullify field!");
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
155