1 /* 2 * Copyright (C) 2014 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 com.android.cts.runner; 18 19 import android.app.Instrumentation; 20 import android.app.KeyguardManager; 21 import android.content.Context; 22 import android.content.pm.PackageManager; 23 import android.support.test.internal.runner.listener.InstrumentationRunListener; 24 import android.util.Log; 25 26 import junit.framework.TestCase; 27 28 import org.junit.runner.Description; 29 import org.junit.runner.notification.RunListener; 30 31 import java.io.File; 32 import java.lang.reflect.Field; 33 import java.lang.reflect.Modifier; 34 import java.net.Authenticator; 35 import java.net.CookieHandler; 36 import java.net.ResponseCache; 37 import java.util.Locale; 38 import java.util.TimeZone; 39 40 import javax.net.ssl.HostnameVerifier; 41 import javax.net.ssl.HttpsURLConnection; 42 import javax.net.ssl.SSLSocketFactory; 43 44 /** 45 * A {@link RunListener} for CTS. Sets the system properties necessary for many 46 * core tests to run. This is needed because there are some core tests that need 47 * writing access to the file system. 48 * Finally, we add a means to free memory allocated by a TestCase after its 49 * execution. 50 */ 51 public class CtsTestRunListener extends InstrumentationRunListener { 52 53 private static final String TAG = "CtsTestRunListener"; 54 55 private TestEnvironment mEnvironment; 56 private Class<?> lastClass; 57 58 @Override testRunStarted(Description description)59 public void testRunStarted(Description description) throws Exception { 60 mEnvironment = new TestEnvironment(); 61 62 // We might want to move this to /sdcard, if is is mounted/writable. 63 File cacheDir = getInstrumentation().getTargetContext().getCacheDir(); 64 System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath()); 65 66 // attempt to disable keyguard, if current test has permission to do so 67 // TODO: move this to a better place, such as InstrumentationTestRunner 68 // ? 69 if (getInstrumentation().getContext().checkCallingOrSelfPermission( 70 android.Manifest.permission.DISABLE_KEYGUARD) 71 == PackageManager.PERMISSION_GRANTED) { 72 Log.i(TAG, "Disabling keyguard"); 73 KeyguardManager keyguardManager = 74 (KeyguardManager) getInstrumentation().getContext().getSystemService( 75 Context.KEYGUARD_SERVICE); 76 keyguardManager.newKeyguardLock("cts").disableKeyguard(); 77 } else { 78 Log.i(TAG, "Test lacks permission to disable keyguard. " + 79 "UI based tests may fail if keyguard is up"); 80 } 81 } 82 83 @Override testStarted(Description description)84 public void testStarted(Description description) throws Exception { 85 if (description.getTestClass() != lastClass) { 86 lastClass = description.getTestClass(); 87 printMemory(description.getTestClass()); 88 } 89 90 mEnvironment.reset(); 91 } 92 93 @Override testFinished(Description description)94 public void testFinished(Description description) { 95 // no way to implement this in JUnit4... 96 // offending test cases that need this logic should probably be cleaned 97 // up individually 98 // if (test instanceof TestCase) { 99 // cleanup((TestCase) test); 100 // } 101 } 102 103 /** 104 * Dumps some memory info. 105 */ printMemory(Class<?> testClass)106 private void printMemory(Class<?> testClass) { 107 Runtime runtime = Runtime.getRuntime(); 108 109 long total = runtime.totalMemory(); 110 long free = runtime.freeMemory(); 111 long used = total - free; 112 113 Log.d(TAG, "Total memory : " + total); 114 Log.d(TAG, "Used memory : " + used); 115 Log.d(TAG, "Free memory : " + free); 116 Log.d(TAG, "Now executing : " + testClass.getName()); 117 } 118 119 /** 120 * Nulls all non-static reference fields in the given test class. This 121 * method helps us with those test classes that don't have an explicit 122 * tearDown() method. Normally the garbage collector should take care of 123 * everything, but since JUnit keeps references to all test cases, a little 124 * help might be a good idea. 125 */ cleanup(TestCase test)126 private void cleanup(TestCase test) { 127 Class<?> clazz = test.getClass(); 128 129 while (clazz != TestCase.class) { 130 Field[] fields = clazz.getDeclaredFields(); 131 for (int i = 0; i < fields.length; i++) { 132 Field f = fields[i]; 133 if (!f.getType().isPrimitive() && 134 !Modifier.isStatic(f.getModifiers())) { 135 try { 136 f.setAccessible(true); 137 f.set(test, null); 138 } catch (Exception ignored) { 139 // Nothing we can do about it. 140 } 141 } 142 } 143 144 clazz = clazz.getSuperclass(); 145 } 146 } 147 148 // http://code.google.com/p/vogar/source/browse/trunk/src/vogar/target/TestEnvironment.java 149 static class TestEnvironment { 150 private final Locale mDefaultLocale; 151 private final TimeZone mDefaultTimeZone; 152 private final String mJavaIoTmpDir; 153 private final HostnameVerifier mHostnameVerifier; 154 private final SSLSocketFactory mSslSocketFactory; 155 TestEnvironment()156 TestEnvironment() { 157 mDefaultLocale = Locale.getDefault(); 158 mDefaultTimeZone = TimeZone.getDefault(); 159 mJavaIoTmpDir = System.getProperty("java.io.tmpdir"); 160 mHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); 161 mSslSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory(); 162 } 163 reset()164 void reset() { 165 System.setProperties(null); 166 System.setProperty("java.io.tmpdir", mJavaIoTmpDir); 167 Locale.setDefault(mDefaultLocale); 168 TimeZone.setDefault(mDefaultTimeZone); 169 Authenticator.setDefault(null); 170 CookieHandler.setDefault(null); 171 ResponseCache.setDefault(null); 172 HttpsURLConnection.setDefaultHostnameVerifier(mHostnameVerifier); 173 HttpsURLConnection.setDefaultSSLSocketFactory(mSslSocketFactory); 174 } 175 } 176 177 } 178