LoadTestsAutoTest.java revision f6d1b3f125b06fcc4847be3cfb35e8ce21905676
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 17package com.android.dumprendertree; 18 19import com.android.dumprendertree.forwarder.AdbUtils; 20import com.android.dumprendertree.forwarder.ForwardServer; 21 22import android.app.Instrumentation; 23import android.content.Context; 24import android.content.Intent; 25import android.os.Bundle; 26import android.os.Debug; 27import android.os.Environment; 28import android.os.Process; 29import android.test.ActivityInstrumentationTestCase2; 30import android.util.Log; 31 32import java.io.File; 33import java.io.FileOutputStream; 34import java.io.IOException; 35import java.io.InputStream; 36import java.io.OutputStream; 37import java.io.PrintStream; 38import java.util.concurrent.CountDownLatch; 39import java.util.concurrent.TimeUnit; 40import java.util.regex.Matcher; 41import java.util.regex.Pattern; 42 43public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShellActivity> { 44 45 private final static String LOGTAG = "LoadTest"; 46 private final static String LOAD_TEST_RESULT = 47 Environment.getExternalStorageDirectory() + "/load_test_result.txt"; 48 private final static int MAX_GC_WAIT_SEC = 10; 49 private final static int LOCAL_PORT = 17171; 50 private boolean mFinished; 51 static final String LOAD_TEST_RUNNER_FILES[] = { 52 "run_page_cycler.py" 53 }; 54 private ForwardServer mForwardServer; 55 56 public LoadTestsAutoTest() { 57 super(TestShellActivity.class); 58 } 59 60 // This function writes the result of the layout test to 61 // Am status so that it can be picked up from a script. 62 public void passOrFailCallback(String file, boolean result) { 63 Instrumentation inst = getInstrumentation(); 64 Bundle bundle = new Bundle(); 65 bundle.putBoolean(file, result); 66 inst.sendStatus(0, bundle); 67 } 68 69 private String setUpForwarding(String forwardInfo, String suite, String iteration) throws IOException { 70 // read forwarding information first 71 Pattern forwardPattern = Pattern.compile("(.*):(\\d+)/(.*)/"); 72 Matcher matcher = forwardPattern.matcher(forwardInfo); 73 if (!matcher.matches()) { 74 throw new RuntimeException("Invalid forward information"); 75 } 76 String host = matcher.group(1); 77 int port = Integer.parseInt(matcher.group(2)); 78 mForwardServer = new ForwardServer(LOCAL_PORT, AdbUtils.resolve(host), port); 79 mForwardServer.start(); 80 return String.format("http://127.0.0.1:%d/%s/%s/start.html?auto=1&iterations=%s", 81 LOCAL_PORT, matcher.group(3), suite, iteration); 82 } 83 84 // Invokes running of layout tests 85 // and waits till it has finished running. 86 public void runPageCyclerTest() throws IOException { 87 LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation(); 88 89 if (runner.mPageCyclerSuite != null) { 90 // start forwarder to use page cycler suites hosted on external web server 91 if (runner.mPageCyclerForwardHost == null) { 92 throw new RuntimeException("no forwarder information provided"); 93 } 94 runner.mTestPath = setUpForwarding(runner.mPageCyclerForwardHost, 95 runner.mPageCyclerSuite, runner.mPageCyclerIteration); 96 Log.d(LOGTAG, "using path: " + runner.mTestPath); 97 } 98 99 if (runner.mTestPath == null) { 100 throw new RuntimeException("No test specified"); 101 } 102 103 TestShellActivity activity = (TestShellActivity) getActivity(); 104 105 Log.v(LOGTAG, "About to run tests, calling gc first..."); 106 freeMem(); 107 108 // Run tests 109 runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis, 110 runner.mGetDrawTime, runner.mSaveImagePath); 111 112 activity.clearCache(); 113 if (mForwardServer != null) { 114 mForwardServer.stop(); 115 mForwardServer = null; 116 } 117 try { 118 Thread.sleep(5000); 119 } catch (InterruptedException e) { 120 } 121 dumpMemoryInfo(); 122 123 // Kill activity 124 activity.finish(); 125 } 126 127 private void freeMem() { 128 Log.v(LOGTAG, "freeMem: calling gc..."); 129 final CountDownLatch latch = new CountDownLatch(1); 130 @SuppressWarnings("unused") 131 Object dummy = new Object() { 132 // this object instance is used to track gc 133 @Override 134 protected void finalize() throws Throwable { 135 latch.countDown(); 136 super.finalize(); 137 } 138 }; 139 dummy = null; 140 System.gc(); 141 try { 142 if (!latch.await(MAX_GC_WAIT_SEC, TimeUnit.SECONDS)) { 143 Log.w(LOGTAG, "gc did not happen in 10s"); 144 } 145 } catch (InterruptedException e) { 146 //ignore 147 } 148 } 149 150 private void printRow(PrintStream ps, String format, Object...objs) { 151 ps.println(String.format(format, objs)); 152 } 153 154 private void dumpMemoryInfo() { 155 try { 156 freeMem(); 157 Log.v(LOGTAG, "Dumping memory information."); 158 159 FileOutputStream out = new FileOutputStream(LOAD_TEST_RESULT, true); 160 PrintStream ps = new PrintStream(out); 161 162 ps.print("\n\n\n"); 163 ps.println("** MEMINFO in pid " + Process.myPid() 164 + " [com.android.dumprendertree] **"); 165 String formatString = "%17s %8s %8s %8s %8s"; 166 167 long nativeMax = Debug.getNativeHeapSize() / 1024; 168 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; 169 long nativeFree = Debug.getNativeHeapFreeSize() / 1024; 170 Runtime runtime = Runtime.getRuntime(); 171 long dalvikMax = runtime.totalMemory() / 1024; 172 long dalvikFree = runtime.freeMemory() / 1024; 173 long dalvikAllocated = dalvikMax - dalvikFree; 174 175 176 Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); 177 Debug.getMemoryInfo(memInfo); 178 179 final int nativeShared = memInfo.nativeSharedDirty; 180 final int dalvikShared = memInfo.dalvikSharedDirty; 181 final int otherShared = memInfo.otherSharedDirty; 182 183 final int nativePrivate = memInfo.nativePrivateDirty; 184 final int dalvikPrivate = memInfo.dalvikPrivateDirty; 185 final int otherPrivate = memInfo.otherPrivateDirty; 186 187 printRow(ps, formatString, "", "native", "dalvik", "other", "total"); 188 printRow(ps, formatString, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax); 189 printRow(ps, formatString, "allocated:", nativeAllocated, dalvikAllocated, "N/A", 190 nativeAllocated + dalvikAllocated); 191 printRow(ps, formatString, "free:", nativeFree, dalvikFree, "N/A", 192 nativeFree + dalvikFree); 193 194 printRow(ps, formatString, "(Pss):", memInfo.nativePss, memInfo.dalvikPss, 195 memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); 196 197 printRow(ps, formatString, "(shared dirty):", nativeShared, dalvikShared, otherShared, 198 nativeShared + dalvikShared + otherShared); 199 printRow(ps, formatString, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate, 200 nativePrivate + dalvikPrivate + otherPrivate); 201 ps.print("\n\n\n"); 202 ps.flush(); 203 ps.close(); 204 out.flush(); 205 out.close(); 206 } catch (IOException e) { 207 Log.e(LOGTAG, e.getMessage()); 208 } 209 } 210 211 // A convenient method to be called by another activity. 212 private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout, 213 boolean getDrawTime, String saveImagePath) { 214 activity.setCallback(new TestShellCallback() { 215 public void finished() { 216 synchronized (LoadTestsAutoTest.this) { 217 mFinished = true; 218 LoadTestsAutoTest.this.notifyAll(); 219 } 220 } 221 222 public void timedOut(String url) { 223 } 224 }); 225 226 mFinished = false; 227 Intent intent = new Intent(Intent.ACTION_VIEW); 228 intent.setClass(activity, TestShellActivity.class); 229 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 230 intent.putExtra(TestShellActivity.TEST_URL, url); 231 intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout); 232 intent.putExtra(TestShellActivity.RESULT_FILE, LOAD_TEST_RESULT); 233 intent.putExtra(TestShellActivity.GET_DRAW_TIME, getDrawTime); 234 if (saveImagePath != null) 235 intent.putExtra(TestShellActivity.SAVE_IMAGE, saveImagePath); 236 activity.startActivity(intent); 237 238 // Wait until done. 239 synchronized (this) { 240 while(!mFinished) { 241 try { 242 this.wait(); 243 } catch (InterruptedException e) { } 244 } 245 } 246 } 247 248 public void copyRunnerAssetsToCache() { 249 try { 250 Context targetContext = getInstrumentation().getTargetContext(); 251 File cacheDir = targetContext.getCacheDir(); 252 253 for( int i=0; i< LOAD_TEST_RUNNER_FILES.length; i++) { 254 InputStream in = targetContext.getAssets().open( 255 LOAD_TEST_RUNNER_FILES[i]); 256 OutputStream out = new FileOutputStream( 257 new File(cacheDir, LOAD_TEST_RUNNER_FILES[i])); 258 259 byte[] buf = new byte[2048]; 260 int len; 261 262 while ((len = in.read(buf)) >= 0 ) { 263 out.write(buf, 0, len); 264 } 265 out.close(); 266 in.close(); 267 } 268 }catch (IOException e) { 269 e.printStackTrace(); 270 } 271 272 } 273 274} 275