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