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