blob: 5aa2c3b2ae60f1cb52d1a20e87c3a780b44acd1d [file] [log] [blame]
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17package android.test;
18
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070019import com.android.internal.util.Predicate;
20import com.android.internal.util.Predicates;
21
22import dalvik.annotation.BrokenTest;
23import dalvik.annotation.SideEffect;
24
Brett Chabot57441522010-04-21 11:17:14 -070025import android.app.KeyguardManager;
26import android.content.Context;
27import android.content.pm.PackageManager;
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070028import android.os.Bundle;
29import android.test.suitebuilder.TestMethod;
30import android.test.suitebuilder.annotation.HasAnnotation;
31import android.util.Log;
32
Brett Chabot57441522010-04-21 11:17:14 -070033import java.io.File;
34import java.lang.reflect.Field;
35import java.lang.reflect.Modifier;
36import java.util.List;
37import java.util.TimeZone;
38
39import junit.framework.AssertionFailedError;
40import junit.framework.Test;
41import junit.framework.TestCase;
42import junit.framework.TestListener;
43
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070044/**
45 * This test runner extends the default InstrumentationTestRunner. It overrides
46 * the {@code onCreate(Bundle)} method and sets the system properties necessary
47 * for many core tests to run. This is needed because there are some core tests
48 * that need writing access to the file system. We also need to set the harness
49 * Thread's context ClassLoader. Otherwise some classes and resources will not
50 * be found. Finally, we add a means to free memory allocated by a TestCase
51 * after its execution.
52 *
53 * @hide
54 */
55public class InstrumentationCtsTestRunner extends InstrumentationTestRunner {
56
57 /**
58 * Convenience definition of our log tag.
Brett Chabot57441522010-04-21 11:17:14 -070059 */
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070060 private static final String TAG = "InstrumentationCtsTestRunner";
Brett Chabot57441522010-04-21 11:17:14 -070061
Brian Muramatsu168beb02010-10-21 12:39:45 -070062 private static final String REPORT_VALUE_ID = "InstrumentationCtsTestRunner";
63
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070064 /**
65 * True if (and only if) we are running in single-test mode (as opposed to
66 * batch mode).
67 */
Brian Muramatsu7bc0e8e2010-08-24 12:24:18 -070068 private boolean mSingleTest = false;
Brett Chabot57441522010-04-21 11:17:14 -070069
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070070 @Override
71 public void onCreate(Bundle arguments) {
72 // We might want to move this to /sdcard, if is is mounted/writable.
73 File cacheDir = getTargetContext().getCacheDir();
74
Brett Chabot57441522010-04-21 11:17:14 -070075 // Set some properties that the core tests absolutely need.
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070076 System.setProperty("user.language", "en");
77 System.setProperty("user.region", "US");
Brett Chabot57441522010-04-21 11:17:14 -070078
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070079 System.setProperty("java.home", cacheDir.getAbsolutePath());
80 System.setProperty("user.home", cacheDir.getAbsolutePath());
81 System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
Brett Chabot40e5ac62010-11-09 19:47:41 -080082 System.setProperty("user.dir", cacheDir.getAbsolutePath());
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070083 System.setProperty("javax.net.ssl.trustStore",
84 "/etc/security/cacerts.bks");
Brett Chabot57441522010-04-21 11:17:14 -070085
Jorg Pleumann43ad2f62009-05-07 09:27:16 -070086 TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
Brett Chabot57441522010-04-21 11:17:14 -070087
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070088 if (arguments != null) {
89 String classArg = arguments.getString(ARGUMENT_TEST_CLASS);
Brian Muramatsu7bc0e8e2010-08-24 12:24:18 -070090 mSingleTest = classArg != null && classArg.contains("#");
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070091 }
Brett Chabot57441522010-04-21 11:17:14 -070092
93 // attempt to disable keyguard, if current test has permission to do so
94 // TODO: move this to a better place, such as InstrumentationTestRunner ?
95 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
96 == PackageManager.PERMISSION_GRANTED) {
97 Log.i(TAG, "Disabling keyguard");
98 KeyguardManager keyguardManager =
99 (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
100 keyguardManager.newKeyguardLock("cts").disableKeyguard();
101 } else {
102 Log.i(TAG, "Test lacks permission to disable keyguard. " +
103 "UI based tests may fail if keyguard is up");
104 }
105
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700106 super.onCreate(arguments);
107 }
108
109 @Override
110 protected AndroidTestRunner getAndroidTestRunner() {
111 AndroidTestRunner runner = super.getAndroidTestRunner();
112
113 runner.addTestListener(new TestListener() {
114 /**
Brett Chabot57441522010-04-21 11:17:14 -0700115 * The last test class we executed code from.
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700116 */
117 private Class<?> lastClass;
Brett Chabot57441522010-04-21 11:17:14 -0700118
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700119 /**
120 * The minimum time we expect a test to take.
121 */
122 private static final int MINIMUM_TIME = 100;
Brett Chabot57441522010-04-21 11:17:14 -0700123
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700124 /**
125 * The start time of our current test in System.currentTimeMillis().
126 */
127 private long startTime;
Brett Chabot57441522010-04-21 11:17:14 -0700128
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700129 public void startTest(Test test) {
130 if (test.getClass() != lastClass) {
131 lastClass = test.getClass();
132 printMemory(test.getClass());
133 }
Brett Chabot57441522010-04-21 11:17:14 -0700134
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700135 Thread.currentThread().setContextClassLoader(
136 test.getClass().getClassLoader());
Brett Chabot57441522010-04-21 11:17:14 -0700137
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700138 startTime = System.currentTimeMillis();
139 }
Brett Chabot57441522010-04-21 11:17:14 -0700140
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700141 public void endTest(Test test) {
142 if (test instanceof TestCase) {
143 cleanup((TestCase)test);
Brett Chabot57441522010-04-21 11:17:14 -0700144
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700145 /*
146 * Make sure all tests take at least MINIMUM_TIME to
147 * complete. If they don't, we wait a bit. The Cupcake
148 * Binder can't handle too many operations in a very
149 * short time, which causes headache for the CTS.
150 */
151 long timeTaken = System.currentTimeMillis() - startTime;
Brett Chabot57441522010-04-21 11:17:14 -0700152
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700153 if (timeTaken < MINIMUM_TIME) {
154 try {
155 Thread.sleep(MINIMUM_TIME - timeTaken);
156 } catch (InterruptedException ignored) {
157 // We don't care.
158 }
159 }
160 }
161 }
Brett Chabot57441522010-04-21 11:17:14 -0700162
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700163 public void addError(Test test, Throwable t) {
164 // This space intentionally left blank.
165 }
Brett Chabot57441522010-04-21 11:17:14 -0700166
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700167 public void addFailure(Test test, AssertionFailedError t) {
168 // This space intentionally left blank.
169 }
Brett Chabot57441522010-04-21 11:17:14 -0700170
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700171 /**
172 * Dumps some memory info.
173 */
174 private void printMemory(Class<? extends Test> testClass) {
175 Runtime runtime = Runtime.getRuntime();
176
177 long total = runtime.totalMemory();
178 long free = runtime.freeMemory();
179 long used = total - free;
Brett Chabot57441522010-04-21 11:17:14 -0700180
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700181 Log.d(TAG, "Total memory : " + total);
182 Log.d(TAG, "Used memory : " + used);
183 Log.d(TAG, "Free memory : " + free);
184 Log.d(TAG, "Now executing : " + testClass.getName());
185 }
186
187 /**
188 * Nulls all non-static reference fields in the given test class.
189 * This method helps us with those test classes that don't have an
190 * explicit tearDown() method. Normally the garbage collector should
191 * take care of everything, but since JUnit keeps references to all
192 * test cases, a little help might be a good idea.
193 */
194 private void cleanup(TestCase test) {
195 Class<?> clazz = test.getClass();
Brett Chabot57441522010-04-21 11:17:14 -0700196
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700197 while (clazz != TestCase.class) {
198 Field[] fields = clazz.getDeclaredFields();
199 for (int i = 0; i < fields.length; i++) {
200 Field f = fields[i];
201 if (!f.getType().isPrimitive() &&
202 !Modifier.isStatic(f.getModifiers())) {
203 try {
204 f.setAccessible(true);
205 f.set(test, null);
206 } catch (Exception ignored) {
207 // Nothing we can do about it.
208 }
209 }
210 }
Brett Chabot57441522010-04-21 11:17:14 -0700211
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700212 clazz = clazz.getSuperclass();
213 }
214 }
Brett Chabot57441522010-04-21 11:17:14 -0700215
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700216 });
Brett Chabot57441522010-04-21 11:17:14 -0700217
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700218 return runner;
Brett Chabot57441522010-04-21 11:17:14 -0700219 }
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700220
221 @Override
222 List<Predicate<TestMethod>> getBuilderRequirements() {
223 List<Predicate<TestMethod>> builderRequirements =
224 super.getBuilderRequirements();
Brian Muramatsu7bc0e8e2010-08-24 12:24:18 -0700225
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700226 Predicate<TestMethod> brokenTestPredicate =
227 Predicates.not(new HasAnnotation(BrokenTest.class));
228 builderRequirements.add(brokenTestPredicate);
Brian Muramatsu7bc0e8e2010-08-24 12:24:18 -0700229
Brian Muramatsu7bc0e8e2010-08-24 12:24:18 -0700230 if (!mSingleTest) {
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700231 Predicate<TestMethod> sideEffectPredicate =
232 Predicates.not(new HasAnnotation(SideEffect.class));
233 builderRequirements.add(sideEffectPredicate);
234 }
235 return builderRequirements;
236 }
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700237}