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; 3344a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov private Context mTestContext; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setUp() throws Exception { 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setUp(); 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void tearDown() throws Exception { 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.tearDown(); 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void testAndroidTestCaseSetupProperly() { 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assertNotNull("Context is null. setContext should be called before tests are run", 4744a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov mContext); 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setContext(Context context) { 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Context getContext() { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mContext; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5944a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov * Test context can be used to access resources from the test's own package 6044a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov * as opposed to the resources from the test target package. Access to the 6144a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov * latter is provided by the context set with the {@link #setContext} 6244a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov * method. 6344a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov * 6444a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov * @hide 6544a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov */ 6644a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov public void setTestContext(Context context) { 6744a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov mTestContext = context; 6844a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov } 6944a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov 7044a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov /** 7144a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov * @hide 7244a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov */ 7344a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov public Context getTestContext() { 7444a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov return mTestContext; 7544a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov } 7644a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov 7744a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov /** 78bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * Asserts that launching a given activity is protected by a particular permission by 79bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * attempting to start the activity and validating that a {@link SecurityException} 80bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * is thrown that mentions the permission in its error message. 81bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * 82bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * Note that an instrumentation isn't needed because all we are looking for is a security error 83bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * and we don't need to wait for the activity to launch and get a handle to the activity. 84bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * 85bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * @param packageName The package name of the activity to launch. 86bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * @param className The class of the activity to launch. 87bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * @param permission The name of the permission. 88bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen */ 89bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen public void assertActivityRequiresPermission( 90bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen String packageName, String className, String permission) { 91bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen final Intent intent = new Intent(); 92bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen intent.setClassName(packageName, className); 93bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 94bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen 95bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen try { 96bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen getContext().startActivity(intent); 97bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen fail("expected security exception for " + permission); 98bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen } catch (SecurityException expected) { 99bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen assertNotNull("security exception's error message.", expected.getMessage()); 100bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen assertTrue("error message should contain " + permission + ".", 101bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen expected.getMessage().contains(permission)); 102bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen } 103bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen } 104bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen 105bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen 106bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen /** 107bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * Asserts that reading from the content uri requires a particular permission by querying the 108bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * uri and ensuring a {@link SecurityException} is thrown mentioning the particular permission. 109bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * 110bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * @param uri The uri that requires a permission to query. 111bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * @param permission The permission that should be required. 112bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen */ 113bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen public void assertReadingContentUriRequiresPermission(Uri uri, String permission) { 114bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen try { 115bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen getContext().getContentResolver().query(uri, null, null, null, null); 116bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen fail("expected SecurityException requiring " + permission); 117bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen } catch (SecurityException expected) { 118bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen assertNotNull("security exception's error message.", expected.getMessage()); 119bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen assertTrue("error message should contain " + permission + ".", 120bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen expected.getMessage().contains(permission)); 121bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen } 122bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen } 123bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen 124bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen /** 125bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * Asserts that writing to the content uri requires a particular permission by inserting into 126bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * the uri and ensuring a {@link SecurityException} is thrown mentioning the particular 127bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * permission. 128bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * 129bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * @param uri The uri that requires a permission to query. 130bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen * @param permission The permission that should be required. 131bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen */ 132bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen public void assertWritingContentUriRequiresPermission(Uri uri, String permission) { 133bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen try { 134bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen getContext().getContentResolver().insert(uri, new ContentValues()); 135bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen fail("expected SecurityException requiring " + permission); 136bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen } catch (SecurityException expected) { 137bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen assertNotNull("security exception's error message.", expected.getMessage()); 138ff92aa74c133fd4abe30f97e6849e80db29af253Nick Kralevich assertTrue("error message should contain \"" + permission + "\". Got: \"" 139ff92aa74c133fd4abe30f97e6849e80db29af253Nick Kralevich + expected.getMessage() + "\".", 140bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen expected.getMessage().contains(permission)); 141bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen } 142bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen } 143bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen 144bedf9df706ef1fe352c1ba0734f50f9e8ad2533eKarl Rosaen /** 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This function is called by various TestCase implementations, at tearDown() time, in order 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to scrub out any class variables. This protects against memory leaks in the case where a 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * test case creates a non-static inner class (thus referencing the test case) and gives it to 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * someone else to hold onto. 14944a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov * 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param testCaseClass The class of the derived TestCase implementation. 15144a29dd097350e3050e44a2f64aa4c75d26ec695Dmitri Plotnikov * 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IllegalAccessException 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void scrubClass(final Class<?> testCaseClass) 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IllegalAccessException { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field[] fields = getClass().getDeclaredFields(); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Field field : fields) { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> fieldClass = field.getDeclaringClass(); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (testCaseClass.isAssignableFrom(fieldClass) && !field.getType().isPrimitive()) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field.setAccessible(true); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field.set(this, null); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.util.Log.d("TestCase", "Error: Could not nullify field!"); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field.get(this) != null) { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.util.Log.d("TestCase", "Error: Could not nullify field!"); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 176