diff options
Diffstat (limited to 'test-runner/android')
-rw-r--r-- | test-runner/android/test/InstrumentationCoreTestRunner.java | 137 | ||||
-rw-r--r-- | test-runner/android/test/InstrumentationTestRunner.java | 8 |
2 files changed, 142 insertions, 3 deletions
diff --git a/test-runner/android/test/InstrumentationCoreTestRunner.java b/test-runner/android/test/InstrumentationCoreTestRunner.java index 6b1a4e4..3f77a60 100644 --- a/test-runner/android/test/InstrumentationCoreTestRunner.java +++ b/test-runner/android/test/InstrumentationCoreTestRunner.java @@ -17,27 +17,158 @@ package android.test; import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.List; +import com.android.internal.util.Predicate; +import com.android.internal.util.Predicates; + +import dalvik.annotation.BrokenTest; +import dalvik.annotation.SideEffect; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestListener; import android.os.Bundle; +import android.test.suitebuilder.TestMethod; +import android.test.suitebuilder.annotation.HasAnnotation; +import android.util.Log; /** * This test runner extends the default InstrumentationTestRunner. It overrides * the {@code onCreate(Bundle)} method and sets the system properties necessary * for many core tests to run. This is needed because there are some core tests - * that need writing access to the filesystem. + * that need writing access to the file system. We also need to set the harness + * Thread's context ClassLoader. Otherwise some classes and resources will not + * be found. Finally, we add a means to free memory allocated by a TestCase + * after its execution. * * @hide */ public class InstrumentationCoreTestRunner extends InstrumentationTestRunner { + private static final String TAG = "InstrumentationCoreTestRunner"; + private boolean singleTest = false; + @Override public void onCreate(Bundle arguments) { - super.onCreate(arguments); - + // We might want to move this to /sdcard, if is is mounted/writable. File cacheDir = getTargetContext().getCacheDir(); System.setProperty("user.language", "en"); System.setProperty("user.region", "US"); + + System.setProperty("java.home", cacheDir.getAbsolutePath()); + System.setProperty("user.home", cacheDir.getAbsolutePath()); System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath()); + System.setProperty("javax.net.ssl.trustStore", + "/etc/security/cacerts.bks"); + + if (arguments != null) { + String classArg = arguments.getString(ARGUMENT_TEST_CLASS); + singleTest = classArg != null && classArg.contains("#"); + } + + super.onCreate(arguments); + } + + protected AndroidTestRunner getAndroidTestRunner() { + AndroidTestRunner runner = super.getAndroidTestRunner(); + + runner.addTestListener(new TestListener() { + private Class<?> lastClass; + + public void startTest(Test test) { + if (test.getClass() != lastClass) { + printMemory(test.getClass()); + } + + Thread.currentThread().setContextClassLoader( + test.getClass().getClassLoader()); + } + + public void endTest(Test test) { + if (test instanceof TestCase) { + if (lastClass == null) { + lastClass = test.getClass(); + } else { + if (test.getClass() != lastClass) { + cleanup(lastClass); + lastClass = test.getClass(); + } + } + } + } + + public void addError(Test test, Throwable t) { + } + + public void addFailure(Test test, AssertionFailedError t) { + } + + /** + * Dumps some memory info. + */ + private void printMemory(Class<? extends Test> testClass) { + Runtime runtime = Runtime.getRuntime(); + + long total = runtime.totalMemory(); + long free = runtime.freeMemory(); + long used = total - free; + + Log.d(TAG, "Total memory : " + total); + Log.d(TAG, "Used memory : " + used); + Log.d(TAG, "Free memory : " + free); + Log.d(TAG, "Now executing : " + testClass.getName()); + } + + /** + * Nulls all static reference fields in the given test class. This + * method helps us with those test classes that don't have an + * explicit tearDown() method. Normally the garbage collector should + * take care of everything, but since JUnit keeps references to all + * test cases, a little help might be a good idea. + */ + private void cleanup(Class<?> clazz) { + if (clazz != TestCase.class) { + Field[] fields = clazz.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + Field f = fields[i]; + if (!f.getType().isPrimitive() && + Modifier.isStatic(f.getModifiers())) { + try { + f.setAccessible(true); + f.set(null, null); + } catch (Exception ignored) { + // Nothing we can do about it. + } + } + } + + // don't cleanup the superclass for now + //cleanup(clazz.getSuperclass()); + } + } + + }); + + return runner; + } + + @Override + List<Predicate<TestMethod>> getBuilderRequirements() { + List<Predicate<TestMethod>> builderRequirements = + super.getBuilderRequirements(); + Predicate<TestMethod> brokenTestPredicate = + Predicates.not(new HasAnnotation(BrokenTest.class)); + builderRequirements.add(brokenTestPredicate); + if (!singleTest) { + Predicate<TestMethod> sideEffectPredicate = + Predicates.not(new HasAnnotation(SideEffect.class)); + builderRequirements.add(sideEffectPredicate); + } + return builderRequirements; } } diff --git a/test-runner/android/test/InstrumentationTestRunner.java b/test-runner/android/test/InstrumentationTestRunner.java index 044f555..d5e6459 100644 --- a/test-runner/android/test/InstrumentationTestRunner.java +++ b/test-runner/android/test/InstrumentationTestRunner.java @@ -43,6 +43,8 @@ import java.io.File; import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; /** @@ -315,6 +317,8 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu } else { parseTestClasses(testClassesArg, testSuiteBuilder); } + + testSuiteBuilder.addRequirements(getBuilderRequirements()); mTestRunner = getAndroidTestRunner(); mTestRunner.setContext(getTargetContext()); @@ -331,6 +335,10 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu start(); } + List<Predicate<TestMethod>> getBuilderRequirements() { + return new ArrayList<Predicate<TestMethod>>(); + } + /** * Parses and loads the specified set of test classes * @param testClassArg - comma-separated list of test classes and methods |