19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 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 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 20358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport java.lang.reflect.Field; 21358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport java.lang.reflect.Modifier; 22358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport java.util.List; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport com.android.internal.util.Predicate; 25358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport com.android.internal.util.Predicates; 26358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob 27358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport dalvik.annotation.BrokenTest; 28358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport dalvik.annotation.SideEffect; 29358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob 30358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport junit.framework.AssertionFailedError; 31358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport junit.framework.Test; 32358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport junit.framework.TestCase; 33358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport junit.framework.TestListener; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle; 35358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport android.test.suitebuilder.TestMethod; 36358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport android.test.suitebuilder.annotation.HasAnnotation; 37358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grobimport android.util.Log; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This test runner extends the default InstrumentationTestRunner. It overrides 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the {@code onCreate(Bundle)} method and sets the system properties necessary 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for many core tests to run. This is needed because there are some core tests 43358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob * that need writing access to the file system. We also need to set the harness 44358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob * Thread's context ClassLoader. Otherwise some classes and resources will not 45358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob * be found. Finally, we add a means to free memory allocated by a TestCase 46358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob * after its execution. 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class InstrumentationCoreTestRunner extends InstrumentationTestRunner { 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 52b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann /** 53b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * Convenience definition of our log tag. 54c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson */ 55358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob private static final String TAG = "InstrumentationCoreTestRunner"; 56c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 57b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann /** 58b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * True if (and only if) we are running in single-test mode (as opposed to 59b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * batch mode). 60b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann */ 61358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob private boolean singleTest = false; 62c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onCreate(Bundle arguments) { 65358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob // We might want to move this to /sdcard, if is is mounted/writable. 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File cacheDir = getTargetContext().getCacheDir(); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 68c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson // Set some properties that the core tests absolutely need. 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.setProperty("user.language", "en"); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.setProperty("user.region", "US"); 71c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 72358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob System.setProperty("java.home", cacheDir.getAbsolutePath()); 73358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob System.setProperty("user.home", cacheDir.getAbsolutePath()); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath()); 75c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 76358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob if (arguments != null) { 77358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob String classArg = arguments.getString(ARGUMENT_TEST_CLASS); 78c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson singleTest = classArg != null && classArg.contains("#"); 79358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 80c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 81358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob super.onCreate(arguments); 82358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 83358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob 84b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann @Override 85358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob protected AndroidTestRunner getAndroidTestRunner() { 86358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob AndroidTestRunner runner = super.getAndroidTestRunner(); 87358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob 88358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob runner.addTestListener(new TestListener() { 89b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann /** 90c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson * The last test class we executed code from. 91b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann */ 92358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob private Class<?> lastClass; 93c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 94b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann /** 95b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * The minimum time we expect a test to take. 96b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann */ 97b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann private static final int MINIMUM_TIME = 100; 98c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 99b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann /** 100b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * The start time of our current test in System.currentTimeMillis(). 101b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann */ 102b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann private long startTime; 103c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 104358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob public void startTest(Test test) { 105358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob if (test.getClass() != lastClass) { 106b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann lastClass = test.getClass(); 107358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob printMemory(test.getClass()); 108358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 109c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 110358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Thread.currentThread().setContextClassLoader( 111358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob test.getClass().getClassLoader()); 112c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 113b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann startTime = System.currentTimeMillis(); 114358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 115c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 116358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob public void endTest(Test test) { 117358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob if (test instanceof TestCase) { 118b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann cleanup((TestCase)test); 119c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 120b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann /* 121b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * Make sure all tests take at least MINIMUM_TIME to 122b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * complete. If they don't, we wait a bit. The Cupcake 123b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * Binder can't handle too many operations in a very 124b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * short time, which causes headache for the CTS. 125b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann */ 126b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann long timeTaken = System.currentTimeMillis() - startTime; 127c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 128b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann if (timeTaken < MINIMUM_TIME) { 129b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann try { 130b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann Thread.sleep(MINIMUM_TIME - timeTaken); 131b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann } catch (InterruptedException ignored) { 132b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann // We don't care. 133358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 134358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 135358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 136358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 137c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 138358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob public void addError(Test test, Throwable t) { 139b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann // This space intentionally left blank. 140358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 141c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 142358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob public void addFailure(Test test, AssertionFailedError t) { 143b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann // This space intentionally left blank. 144358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 145c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 146358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob /** 147358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob * Dumps some memory info. 148358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob */ 149358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob private void printMemory(Class<? extends Test> testClass) { 150358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Runtime runtime = Runtime.getRuntime(); 151358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob 152358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob long total = runtime.totalMemory(); 153358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob long free = runtime.freeMemory(); 154358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob long used = total - free; 155c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 156358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Log.d(TAG, "Total memory : " + total); 157358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Log.d(TAG, "Used memory : " + used); 158358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Log.d(TAG, "Free memory : " + free); 159358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Log.d(TAG, "Now executing : " + testClass.getName()); 160358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 161358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob 162358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob /** 163b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * Nulls all non-static reference fields in the given test class. 164b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann * This method helps us with those test classes that don't have an 165358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob * explicit tearDown() method. Normally the garbage collector should 166358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob * take care of everything, but since JUnit keeps references to all 167358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob * test cases, a little help might be a good idea. 168358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob */ 169b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann private void cleanup(TestCase test) { 170b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann Class<?> clazz = test.getClass(); 171c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 172b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann while (clazz != TestCase.class) { 173358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Field[] fields = clazz.getDeclaredFields(); 174358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob for (int i = 0; i < fields.length; i++) { 175358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Field f = fields[i]; 176358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob if (!f.getType().isPrimitive() && 177b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann !Modifier.isStatic(f.getModifiers())) { 178358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob try { 179358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob f.setAccessible(true); 180b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann f.set(test, null); 181358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } catch (Exception ignored) { 182358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob // Nothing we can do about it. 183358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 184358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 185358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 186c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 187b867019173d20cd4fd7ee79a3ce924096e95a241Jorg Pleumann clazz = clazz.getSuperclass(); 188358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 189358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 190c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 191358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob }); 192c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson 193358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob return runner; 194c69efa5efce6d9a820f8902ca62305cddea163e6Jesse Wilson } 195358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob 196358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob @Override 197358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob List<Predicate<TestMethod>> getBuilderRequirements() { 198358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob List<Predicate<TestMethod>> builderRequirements = 199358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob super.getBuilderRequirements(); 200358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Predicate<TestMethod> brokenTestPredicate = 201358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Predicates.not(new HasAnnotation(BrokenTest.class)); 202358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob builderRequirements.add(brokenTestPredicate); 203358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob if (!singleTest) { 204358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Predicate<TestMethod> sideEffectPredicate = 205358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob Predicates.not(new HasAnnotation(SideEffect.class)); 206358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob builderRequirements.add(sideEffectPredicate); 207358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob } 208358d23017d0d6c4636eb7599ae7a9b48108899a3Urs Grob return builderRequirements; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 211