1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/*
2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2012 The Android Open Source Project
3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License");
5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License.
6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at
7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *      http://www.apache.org/licenses/LICENSE-2.0
9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software
11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS,
12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and
14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License.
15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */
16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupackage com.android.uiautomator.testrunner;
18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
19e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.app.Activity;
20e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.app.IInstrumentationWatcher;
21e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.app.Instrumentation;
22e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.content.ComponentName;
23e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.os.Bundle;
24e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.os.Debug;
25e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.os.IBinder;
26e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.test.RepetitiveTest;
27e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.util.Log;
28e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
29e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport com.android.uiautomator.core.UiDevice;
30e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
31e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.AssertionFailedError;
32e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.Test;
33e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.TestCase;
34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.TestListener;
35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.TestResult;
36e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.runner.BaseTestRunner;
37e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.textui.ResultPrinter;
38e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
39e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.io.ByteArrayOutputStream;
40e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.io.PrintStream;
41e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.lang.Thread.UncaughtExceptionHandler;
42e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.lang.reflect.Method;
43e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.util.ArrayList;
44e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.util.List;
45e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
46ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu/**
47ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu * @hide
48ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu */
49e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupublic class UiAutomatorTestRunner {
50e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
51e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private static final String LOGTAG = UiAutomatorTestRunner.class.getSimpleName();
52e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private static final int EXIT_OK = 0;
53e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private static final int EXIT_EXCEPTION = -1;
54e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
55e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private boolean mDebug;
56e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private Bundle mParams = null;
57e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private UiDevice mUiDevice;
58e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private List<String> mTestClasses = null;
59e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private FakeInstrumentationWatcher mWatcher = new FakeInstrumentationWatcher();
60e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private IAutomationSupport mAutomationSupport = new IAutomationSupport() {
61e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        @Override
62e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public void sendStatus(int resultCode, Bundle status) {
63e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mWatcher.instrumentationStatus(null, resultCode, status);
64e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
65e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    };
66e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private List<TestListener> mTestListeners = new ArrayList<TestListener>();
67e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
68e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    public void run(List<String> testClasses, Bundle params, boolean debug) {
69e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
70e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            @Override
71e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            public void uncaughtException(Thread thread, Throwable ex) {
72e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                Log.e(LOGTAG, "uncaught exception", ex);
73e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                Bundle results = new Bundle();
74e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                results.putString("shortMsg", ex.getClass().getName());
75e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                results.putString("longMsg", ex.getMessage());
76e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                mWatcher.instrumentationFinished(null, 0, results);
77e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                // bailing on uncaught exception
78e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                System.exit(EXIT_EXCEPTION);
79e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
80e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        });
81e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        mTestClasses = testClasses;
83e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        mParams = params;
84e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        mDebug = debug;
85e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        start();
86e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        System.exit(EXIT_OK);
87e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
88e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
89e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
90e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Called after all test classes are in place, ready to test
91e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
92e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    protected void start() {
93e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        TestCaseCollector collector = getTestCaseCollector(this.getClass().getClassLoader());
94e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        try {
95e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            collector.addTestClasses(mTestClasses);
96e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        } catch (ClassNotFoundException e) {
97e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            // will be caught by uncaught handler
98e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            throw new RuntimeException(e.getMessage(), e);
99e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
100e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if (mDebug) {
101e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            Debug.waitForDebugger();
102e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        mUiDevice = UiDevice.getInstance();
104e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        List<TestCase> testCases = collector.getTestCases();
105e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        Bundle testRunOutput = new Bundle();
106e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
107e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        PrintStream writer = new PrintStream(byteArrayOutputStream);
108e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        try {
109e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            StringResultPrinter resultPrinter = new StringResultPrinter(writer);
110e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
111e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            TestResult testRunResult = new TestResult();
112e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            // add test listeners
113e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            testRunResult.addListener(new WatcherResultPrinter(testCases.size()));
114e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            testRunResult.addListener(resultPrinter);
115e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            // add all custom listeners
116e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            for (TestListener listener : mTestListeners) {
117e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                testRunResult.addListener(listener);
118e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
119e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            long startTime = System.currentTimeMillis();
120e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
121e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            // run tests for realz!
122e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            for (TestCase testCase : testCases) {
123e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                prepareTestCase(testCase);
124e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                testCase.run(testRunResult);
125e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
126e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            long runTime = System.currentTimeMillis() - startTime;
127e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
128e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            resultPrinter.print2(testRunResult, runTime);
129e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        } catch (Throwable t) {
130e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            // catch all exceptions so a more verbose error message can be outputted
131e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            writer.println(String.format("Test run aborted due to unexpected exception: %s",
132e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                            t.getMessage()));
133e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            t.printStackTrace(writer);
134e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        } finally {
135e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            testRunOutput.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
136e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    String.format("\nTest results for %s=%s",
137e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    getClass().getSimpleName(),
138e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    byteArrayOutputStream.toString()));
139e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            writer.close();
140e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mAutomationSupport.sendStatus(Activity.RESULT_OK, testRunOutput);
141e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
142e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
143e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
144e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    // copy & pasted from com.android.commands.am.Am
145e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private class FakeInstrumentationWatcher implements IInstrumentationWatcher {
146e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
147e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private boolean mRawMode = true;
148e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
149e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        @Override
150e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public IBinder asBinder() {
151e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            throw new UnsupportedOperationException("I'm just a fake!");
152e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
153e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
154e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        @Override
155e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
156e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            synchronized (this) {
157e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                // pretty printer mode?
158e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                String pretty = null;
159e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (!mRawMode && results != null) {
160e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
161e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
162e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (pretty != null) {
163e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    System.out.print(pretty);
164e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                } else {
165e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    if (results != null) {
166e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        for (String key : results.keySet()) {
167e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                            System.out.println("INSTRUMENTATION_STATUS: " + key + "="
168e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                                    + results.get(key));
169e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        }
170e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    }
171e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode);
172e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
173e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                notifyAll();
174e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
175e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
176e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
177e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        @Override
178e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public void instrumentationFinished(ComponentName name, int resultCode, Bundle results) {
179e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            synchronized (this) {
180e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                // pretty printer mode?
181e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                String pretty = null;
182e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (!mRawMode && results != null) {
183e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
184e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
185e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (pretty != null) {
186e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    System.out.println(pretty);
187e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                } else {
188e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    if (results != null) {
189e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        for (String key : results.keySet()) {
190e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                            System.out.println("INSTRUMENTATION_RESULT: " + key + "="
191e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                                    + results.get(key));
192e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        }
193e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    }
194e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    System.out.println("INSTRUMENTATION_CODE: " + resultCode);
195e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
196e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                notifyAll();
197e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
198e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
199e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
200e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
201e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    // Copy & pasted from InstrumentationTestRunner.WatcherResultPrinter
202e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private class WatcherResultPrinter implements TestListener {
203e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
204e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final String REPORT_KEY_NUM_TOTAL = "numtests";
205e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final String REPORT_KEY_NAME_CLASS = "class";
206e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final String REPORT_KEY_NUM_CURRENT = "current";
207e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final String REPORT_KEY_NAME_TEST = "test";
208e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final String REPORT_KEY_NUM_ITERATIONS = "numiterations";
209e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final String REPORT_VALUE_ID = "UiAutomatorTestRunner";
210e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final String REPORT_KEY_STACK = "stack";
211e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
212e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final int REPORT_VALUE_RESULT_START = 1;
213e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final int REPORT_VALUE_RESULT_ERROR = -1;
214e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private static final int REPORT_VALUE_RESULT_FAILURE = -2;
215e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
216e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        private final Bundle mResultTemplate;
217e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        Bundle mTestResult;
218e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        int mTestNum = 0;
219e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        int mTestResultCode = 0;
220e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        String mTestClass = null;
221e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
222e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public WatcherResultPrinter(int numTests) {
223e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mResultTemplate = new Bundle();
224e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mResultTemplate.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
225e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mResultTemplate.putInt(REPORT_KEY_NUM_TOTAL, numTests);
226e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
227e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
228e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        /**
229e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         * send a status for the start of a each test, so long tests can be seen
230e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         * as "running"
231e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu         */
232e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        @Override
233e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public void startTest(Test test) {
234e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            String testClass = test.getClass().getName();
235e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            String testName = ((TestCase) test).getName();
236e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResult = new Bundle(mResultTemplate);
237e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResult.putString(REPORT_KEY_NAME_CLASS, testClass);
238e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResult.putString(REPORT_KEY_NAME_TEST, testName);
239e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResult.putInt(REPORT_KEY_NUM_CURRENT, ++mTestNum);
240e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            // pretty printing
241e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            if (testClass != null && !testClass.equals(mTestClass)) {
242e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
243e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        String.format("\n%s:", testClass));
244e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                mTestClass = testClass;
245e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            } else {
246e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "");
247e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
248e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
249e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            Method testMethod = null;
250e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            try {
251e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                testMethod = test.getClass().getMethod(testName);
252e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                // Report total number of iterations, if test is repetitive
253e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (testMethod.isAnnotationPresent(RepetitiveTest.class)) {
254e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    int numIterations = testMethod.getAnnotation(RepetitiveTest.class)
255e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                            .numIterations();
256e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    mTestResult.putInt(REPORT_KEY_NUM_ITERATIONS, numIterations);
257e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
258e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            } catch (NoSuchMethodException e) {
259e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                // ignore- the test with given name does not exist. Will be
260e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                // handled during test
261e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                // execution
262e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
263e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
264e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mAutomationSupport.sendStatus(REPORT_VALUE_RESULT_START, mTestResult);
265e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResultCode = 0;
266e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
267e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
268e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        @Override
269e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public void addError(Test test, Throwable t) {
270e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
271e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResultCode = REPORT_VALUE_RESULT_ERROR;
272e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            // pretty printing
273e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
274e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                String.format("\nError in %s:\n%s",
275e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
276e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
277e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
278e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        @Override
279e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public void addFailure(Test test, AssertionFailedError t) {
280e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
281e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResultCode = REPORT_VALUE_RESULT_FAILURE;
282e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            // pretty printing
283e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
284e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                String.format("\nFailure in %s:\n%s",
285e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
286e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
287e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
288e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        @Override
289e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public void endTest(Test test) {
290e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            if (mTestResultCode == 0) {
291e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, ".");
292e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
293e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mAutomationSupport.sendStatus(mTestResultCode, mTestResult);
294e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
295e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
296e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
297e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
298e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    // copy pasted from InstrumentationTestRunner
299e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private class StringResultPrinter extends ResultPrinter {
300e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
301e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        public StringResultPrinter(PrintStream writer) {
302e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            super(writer);
303e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
304e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
305e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        synchronized void print2(TestResult result, long runTime) {
306e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            printHeader(runTime);
307e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            printFooter(result);
308e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
309e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
310e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
311e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    protected TestCaseCollector getTestCaseCollector(ClassLoader classLoader) {
312e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return new TestCaseCollector(classLoader, new UiAutomatorTestCaseFilter());
313e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
314e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
315e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    protected void addTestListener(TestListener listener) {
316e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if (!mTestListeners.contains(listener)) {
317e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            mTestListeners.add(listener);
318e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
319e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
320e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
321e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    protected void removeTestListener(TestListener listener) {
322e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        mTestListeners.remove(listener);
323e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
324e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
325e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
326e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * subclass may override this method to perform further preparation
327e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     *
328e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @param testCase
329e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
330e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    protected void prepareTestCase(TestCase testCase) {
331e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        ((UiAutomatorTestCase)testCase).setAutomationSupport(mAutomationSupport);
332e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        ((UiAutomatorTestCase)testCase).setUiDevice(mUiDevice);
333e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        ((UiAutomatorTestCase)testCase).setParams(mParams);
334e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
335e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu}
336