2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Modifier;
22 import java.util.List;
24 import com.android.internal.util.Predicate;
25 import com.android.internal.util.Predicates;
27 import dalvik.annotation.BrokenTest;
28 import dalvik.annotation.SideEffect;
30 import junit.framework.AssertionFailedError;
31 import junit.framework.Test;
32 import junit.framework.TestCase;
33 import junit.framework.TestListener;
34 import android.os.Bundle;
35 import android.test.suitebuilder.TestMethod;
36 import android.test.suitebuilder.annotation.HasAnnotation;
37 import android.util.Log;
40 * This test runner extends the default InstrumentationTestRunner. It overrides
41 * the {@code onCreate(Bundle)} method and sets the system properties necessary
42 * for many core tests to run. This is needed because there are some core tests
43 * that need writing access to the file system. We also need to set the harness
44 * Thread's context ClassLoader. Otherwise some classes and resources will not
45 * be found. Finally, we add a means to free memory allocated by a TestCase
46 * after its execution.
50 public class InstrumentationCoreTestRunner extends InstrumentationTestRunner {
53 * Convenience definition of our log tag.
55 private static final String TAG = "InstrumentationCoreTestRunner";
58 * True if (and only if) we are running in single-test mode (as opposed to
61 private boolean singleTest = false;
64 public void onCreate(Bundle arguments) {
65 // We might want to move this to /sdcard, if is is mounted/writable.
66 File cacheDir = getTargetContext().getCacheDir();
68 // Set some properties that the core tests absolutely need.
69 System.setProperty("user.language", "en");
70 System.setProperty("user.region", "US");
72 System.setProperty("java.home", cacheDir.getAbsolutePath());
73 System.setProperty("user.home", cacheDir.getAbsolutePath());
74 System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
75 System.setProperty("javax.net.ssl.trustStore",
76 "/etc/security/cacerts.bks");
78 if (arguments != null) {
79 String classArg = arguments.getString(ARGUMENT_TEST_CLASS);
80 singleTest = classArg != null && classArg.contains("#");
83 super.onCreate(arguments);
87 protected AndroidTestRunner getAndroidTestRunner() {
88 AndroidTestRunner runner = super.getAndroidTestRunner();
90 runner.addTestListener(new TestListener() {
92 * The last test class we executed code from.
94 private Class<?> lastClass;
97 * The minimum time we expect a test to take.
99 private static final int MINIMUM_TIME = 100;
102 * The start time of our current test in System.currentTimeMillis().
104 private long startTime;
106 public void startTest(Test test) {
107 if (test.getClass() != lastClass) {
108 lastClass = test.getClass();
109 printMemory(test.getClass());
112 Thread.currentThread().setContextClassLoader(
113 test.getClass().getClassLoader());
115 startTime = System.currentTimeMillis();
118 public void endTest(Test test) {
119 if (test instanceof TestCase) {
120 cleanup((TestCase)test);
123 * Make sure all tests take at least MINIMUM_TIME to
124 * complete. If they don't, we wait a bit. The Cupcake
125 * Binder can't handle too many operations in a very
126 * short time, which causes headache for the CTS.
128 long timeTaken = System.currentTimeMillis() - startTime;
130 if (timeTaken < MINIMUM_TIME) {
132 Thread.sleep(MINIMUM_TIME - timeTaken);
133 } catch (InterruptedException ignored) {
140 public void addError(Test test, Throwable t) {
141 // This space intentionally left blank.
144 public void addFailure(Test test, AssertionFailedError t) {
145 // This space intentionally left blank.
149 * Dumps some memory info.
151 private void printMemory(Class<? extends Test> testClass) {
152 Runtime runtime = Runtime.getRuntime();
154 long total = runtime.totalMemory();
155 long free = runtime.freeMemory();
156 long used = total - free;
158 Log.d(TAG, "Total memory : " + total);
159 Log.d(TAG, "Used memory : " + used);
160 Log.d(TAG, "Free memory : " + free);
161 Log.d(TAG, "Now executing : " + testClass.getName());
165 * Nulls all non-static reference fields in the given test class.
166 * This method helps us with those test classes that don't have an
167 * explicit tearDown() method. Normally the garbage collector should
168 * take care of everything, but since JUnit keeps references to all
169 * test cases, a little help might be a good idea.
171 private void cleanup(TestCase test) {
172 Class<?> clazz = test.getClass();
174 while (clazz != TestCase.class) {
175 Field[] fields = clazz.getDeclaredFields();
176 for (int i = 0; i < fields.length; i++) {
178 if (!f.getType().isPrimitive() &&
179 !Modifier.isStatic(f.getModifiers())) {
181 f.setAccessible(true);
183 } catch (Exception ignored) {
184 // Nothing we can do about it.
189 clazz = clazz.getSuperclass();
199 List<Predicate<TestMethod>> getBuilderRequirements() {
200 List<Predicate<TestMethod>> builderRequirements =
201 super.getBuilderRequirements();
202 Predicate<TestMethod> brokenTestPredicate =
203 Predicates.not(new HasAnnotation(BrokenTest.class));
204 builderRequirements.add(brokenTestPredicate);
206 Predicate<TestMethod> sideEffectPredicate =
207 Predicates.not(new HasAnnotation(SideEffect.class));
208 builderRequirements.add(sideEffectPredicate);
210 return builderRequirements;