• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.test;
18 
19 import java.io.File;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Modifier;
22 import java.util.List;
23 import java.util.TimeZone;
24 
25 import com.android.internal.util.Predicate;
26 import com.android.internal.util.Predicates;
27 
28 import dalvik.annotation.BrokenTest;
29 import dalvik.annotation.SideEffect;
30 
31 import junit.framework.AssertionFailedError;
32 import junit.framework.Test;
33 import junit.framework.TestCase;
34 import junit.framework.TestListener;
35 import android.os.Bundle;
36 import android.test.suitebuilder.TestMethod;
37 import android.test.suitebuilder.annotation.HasAnnotation;
38 import android.util.Log;
39 
40 /**
41  * This test runner extends the default InstrumentationTestRunner. It overrides
42  * the {@code onCreate(Bundle)} method and sets the system properties necessary
43  * for many core tests to run. This is needed because there are some core tests
44  * that need writing access to the file system. We also need to set the harness
45  * Thread's context ClassLoader. Otherwise some classes and resources will not
46  * be found. Finally, we add a means to free memory allocated by a TestCase
47  * after its execution.
48  *
49  * @hide
50  */
51 public class InstrumentationCtsTestRunner extends InstrumentationTestRunner {
52 
53     /**
54      * Convenience definition of our log tag.
55      */
56     private static final String TAG = "InstrumentationCtsTestRunner";
57 
58     /**
59      * True if (and only if) we are running in single-test mode (as opposed to
60      * batch mode).
61      */
62     private boolean singleTest = false;
63 
64     @Override
onCreate(Bundle arguments)65     public void onCreate(Bundle arguments) {
66         // We might want to move this to /sdcard, if is is mounted/writable.
67         File cacheDir = getTargetContext().getCacheDir();
68 
69         // Set some properties that the core tests absolutely need.
70         System.setProperty("user.language", "en");
71         System.setProperty("user.region", "US");
72 
73         System.setProperty("java.home", cacheDir.getAbsolutePath());
74         System.setProperty("user.home", cacheDir.getAbsolutePath());
75         System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
76         System.setProperty("javax.net.ssl.trustStore",
77                 "/etc/security/cacerts.bks");
78 
79         TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
80 
81         if (arguments != null) {
82             String classArg = arguments.getString(ARGUMENT_TEST_CLASS);
83             singleTest = classArg != null && classArg.contains("#");
84         }
85 
86         super.onCreate(arguments);
87     }
88 
89     @Override
getAndroidTestRunner()90     protected AndroidTestRunner getAndroidTestRunner() {
91         AndroidTestRunner runner = super.getAndroidTestRunner();
92 
93         runner.addTestListener(new TestListener() {
94             /**
95              * The last test class we executed code from.
96              */
97             private Class<?> lastClass;
98 
99             /**
100              * The minimum time we expect a test to take.
101              */
102             private static final int MINIMUM_TIME = 100;
103 
104             /**
105              * The start time of our current test in System.currentTimeMillis().
106              */
107             private long startTime;
108 
109             public void startTest(Test test) {
110                 if (test.getClass() != lastClass) {
111                     lastClass = test.getClass();
112                     printMemory(test.getClass());
113                 }
114 
115                 Thread.currentThread().setContextClassLoader(
116                         test.getClass().getClassLoader());
117 
118                 startTime = System.currentTimeMillis();
119             }
120 
121             public void endTest(Test test) {
122                 if (test instanceof TestCase) {
123                     cleanup((TestCase)test);
124 
125                     /*
126                      * Make sure all tests take at least MINIMUM_TIME to
127                      * complete. If they don't, we wait a bit. The Cupcake
128                      * Binder can't handle too many operations in a very
129                      * short time, which causes headache for the CTS.
130                      */
131                     long timeTaken = System.currentTimeMillis() - startTime;
132 
133                     if (timeTaken < MINIMUM_TIME) {
134                         try {
135                             Thread.sleep(MINIMUM_TIME - timeTaken);
136                         } catch (InterruptedException ignored) {
137                             // We don't care.
138                         }
139                     }
140                 }
141             }
142 
143             public void addError(Test test, Throwable t) {
144                 // This space intentionally left blank.
145             }
146 
147             public void addFailure(Test test, AssertionFailedError t) {
148                 // This space intentionally left blank.
149             }
150 
151             /**
152              * Dumps some memory info.
153              */
154             private void printMemory(Class<? extends Test> testClass) {
155                 Runtime runtime = Runtime.getRuntime();
156 
157                 long total = runtime.totalMemory();
158                 long free = runtime.freeMemory();
159                 long used = total - free;
160 
161                 Log.d(TAG, "Total memory  : " + total);
162                 Log.d(TAG, "Used memory   : " + used);
163                 Log.d(TAG, "Free memory   : " + free);
164                 Log.d(TAG, "Now executing : " + testClass.getName());
165             }
166 
167             /**
168              * Nulls all non-static reference fields in the given test class.
169              * This method helps us with those test classes that don't have an
170              * explicit tearDown() method. Normally the garbage collector should
171              * take care of everything, but since JUnit keeps references to all
172              * test cases, a little help might be a good idea.
173              */
174             private void cleanup(TestCase test) {
175                 Class<?> clazz = test.getClass();
176 
177                 while (clazz != TestCase.class) {
178                     Field[] fields = clazz.getDeclaredFields();
179                     for (int i = 0; i < fields.length; i++) {
180                         Field f = fields[i];
181                         if (!f.getType().isPrimitive() &&
182                                 !Modifier.isStatic(f.getModifiers())) {
183                             try {
184                                 f.setAccessible(true);
185                                 f.set(test, null);
186                             } catch (Exception ignored) {
187                                 // Nothing we can do about it.
188                             }
189                         }
190                     }
191 
192                     clazz = clazz.getSuperclass();
193                 }
194             }
195 
196         });
197 
198         return runner;
199     }
200 
201     @Override
getBuilderRequirements()202     List<Predicate<TestMethod>> getBuilderRequirements() {
203         List<Predicate<TestMethod>> builderRequirements =
204                 super.getBuilderRequirements();
205         Predicate<TestMethod> brokenTestPredicate =
206                 Predicates.not(new HasAnnotation(BrokenTest.class));
207         builderRequirements.add(brokenTestPredicate);
208         if (!singleTest) {
209             Predicate<TestMethod> sideEffectPredicate =
210                     Predicates.not(new HasAnnotation(SideEffect.class));
211             builderRequirements.add(sideEffectPredicate);
212         }
213         return builderRequirements;
214     }
215 }
216