blob: 9bd4c966496d260b8c5e73d287b67660d9d6a300 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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 android.test;
18
Jack Wangff1df692009-08-26 17:19:13 -070019import com.android.internal.util.Predicate;
Brett Chabot88e03a92010-02-19 09:57:11 -080020import com.android.internal.util.Predicates;
Jack Wangff1df692009-08-26 17:19:13 -070021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.app.Activity;
23import android.app.Instrumentation;
24import android.os.Bundle;
25import android.os.Debug;
26import android.os.Looper;
Jack Wangff1df692009-08-26 17:19:13 -070027import android.os.Parcelable;
28import android.os.PerformanceCollector;
Jack Wangff1df692009-08-26 17:19:13 -070029import android.os.PerformanceCollector.PerformanceResultsWriter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.test.suitebuilder.TestMethod;
31import android.test.suitebuilder.TestPredicates;
32import android.test.suitebuilder.TestSuiteBuilder;
Brett Chabot88e03a92010-02-19 09:57:11 -080033import android.test.suitebuilder.annotation.HasAnnotation;
Doug Zongker0375fa12010-02-23 12:36:06 -080034import android.test.suitebuilder.annotation.LargeTest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.util.Log;
36
Jack Wangff1df692009-08-26 17:19:13 -070037import java.io.ByteArrayOutputStream;
38import java.io.File;
39import java.io.PrintStream;
Brett Chabot88e03a92010-02-19 09:57:11 -080040import java.lang.annotation.Annotation;
Jack Wangff1df692009-08-26 17:19:13 -070041import java.lang.reflect.InvocationTargetException;
42import java.lang.reflect.Method;
43import java.util.ArrayList;
44import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045
46import junit.framework.AssertionFailedError;
47import junit.framework.Test;
48import junit.framework.TestCase;
49import junit.framework.TestListener;
50import junit.framework.TestResult;
51import junit.framework.TestSuite;
52import junit.runner.BaseTestRunner;
53import junit.textui.ResultPrinter;
54
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055/**
56 * An {@link Instrumentation} that runs various types of {@link junit.framework.TestCase}s against
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080057 * an Android package (application).
58 *
59 * <div class="special reference">
60 * <h3>Developer Guides</h3>
61 * <p>For more information about application testing, read the
62 * <a href="{@docRoot}guide/topics/testing/index.html">Testing</a> developer guide.</p>
63 * </div>
64 *
65 * <h3>Typical Usage</h3>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066 * <ol>
67 * <li>Write {@link junit.framework.TestCase}s that perform unit, functional, or performance tests
68 * against the classes in your package. Typically these are subclassed from:
Jack Wangff1df692009-08-26 17:19:13 -070069 * <ul><li>{@link android.test.ActivityInstrumentationTestCase2}</li>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 * <li>{@link android.test.ActivityUnitTestCase}</li>
71 * <li>{@link android.test.AndroidTestCase}</li>
72 * <li>{@link android.test.ApplicationTestCase}</li>
73 * <li>{@link android.test.InstrumentationTestCase}</li>
74 * <li>{@link android.test.ProviderTestCase}</li>
75 * <li>{@link android.test.ServiceTestCase}</li>
76 * <li>{@link android.test.SingleLaunchActivityTestCase}</li></ul>
quddusce8df6f42014-01-06 16:28:03 -080077 * <li>Set the <code>android:targetPackage</code> attribute of the <code>&lt;instrumentation&gt;</code>
78 * element in the test package's manifest. You should set the attribute value
79 * to the package name of the target application under test.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 * <li>Run the instrumentation using "adb shell am instrument -w",
81 * with no optional arguments, to run all tests (except performance tests).
82 * <li>Run the instrumentation using "adb shell am instrument -w",
83 * with the argument '-e func true' to run all functional tests. These are tests that derive from
84 * {@link android.test.InstrumentationTestCase}.
85 * <li>Run the instrumentation using "adb shell am instrument -w",
86 * with the argument '-e unit true' to run all unit tests. These are tests that <i>do not</i>derive
87 * from {@link android.test.InstrumentationTestCase} (and are not performance tests).
88 * <li>Run the instrumentation using "adb shell am instrument -w",
89 * with the argument '-e class' set to run an individual {@link junit.framework.TestCase}.
90 * </ol>
91 * <p/>
92 * <b>Running all tests:</b> adb shell am instrument -w
93 * com.android.foo/android.test.InstrumentationTestRunner
94 * <p/>
95 * <b>Running all small tests:</b> adb shell am instrument -w
96 * -e size small
97 * com.android.foo/android.test.InstrumentationTestRunner
98 * <p/>
99 * <b>Running all medium tests:</b> adb shell am instrument -w
100 * -e size medium
101 * com.android.foo/android.test.InstrumentationTestRunner
102 * <p/>
103 * <b>Running all large tests:</b> adb shell am instrument -w
104 * -e size large
105 * com.android.foo/android.test.InstrumentationTestRunner
106 * <p/>
Brett Chabot88e03a92010-02-19 09:57:11 -0800107 * <b>Filter test run to tests with given annotation:</b> adb shell am instrument -w
108 * -e annotation com.android.foo.MyAnnotation
109 * com.android.foo/android.test.InstrumentationTestRunner
110 * <p/>
111 * If used with other options, the resulting test run will contain the union of the two options.
112 * e.g. "-e size large -e annotation com.android.foo.MyAnnotation" will run only tests with both
113 * the {@link LargeTest} and "com.android.foo.MyAnnotation" annotations.
114 * <p/>
115 * <b>Filter test run to tests <i>without</i> given annotation:</b> adb shell am instrument -w
116 * -e notAnnotation com.android.foo.MyAnnotation
117 * com.android.foo/android.test.InstrumentationTestRunner
118 * <p/>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 * <b>Running a single testcase:</b> adb shell am instrument -w
120 * -e class com.android.foo.FooTest
121 * com.android.foo/android.test.InstrumentationTestRunner
122 * <p/>
123 * <b>Running a single test:</b> adb shell am instrument -w
124 * -e class com.android.foo.FooTest#testFoo
125 * com.android.foo/android.test.InstrumentationTestRunner
126 * <p/>
127 * <b>Running multiple tests:</b> adb shell am instrument -w
128 * -e class com.android.foo.FooTest,com.android.foo.TooTest
129 * com.android.foo/android.test.InstrumentationTestRunner
130 * <p/>
Brett Chabot89c0ef42010-03-18 20:03:31 -0700131 * <b>Running all tests in a java package:</b> adb shell am instrument -w
132 * -e package com.android.foo.subpkg
133 * com.android.foo/android.test.InstrumentationTestRunner
134 * <p/>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 * <b>Including performance tests:</b> adb shell am instrument -w
136 * -e perf true
137 * com.android.foo/android.test.InstrumentationTestRunner
138 * <p/>
139 * <b>To debug your tests, set a break point in your code and pass:</b>
140 * -e debug true
141 * <p/>
142 * <b>To run in 'log only' mode</b>
143 * -e log true
Jack Wangff1df692009-08-26 17:19:13 -0700144 * This option will load and iterate through all test classes and methods, but will bypass actual
145 * test execution. Useful for quickly obtaining info on the tests to be executed by an
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 * instrumentation command.
147 * <p/>
148 * <b>To generate EMMA code coverage:</b>
149 * -e coverage true
Jack Wangff1df692009-08-26 17:19:13 -0700150 * Note: this requires an emma instrumented build. By default, the code coverage results file
Brett Chabot51e03642009-05-28 18:18:15 -0700151 * will be saved in a /data/<app>/coverage.ec file, unless overridden by coverageFile flag (see
152 * below)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 * <p/>
154 * <b> To specify EMMA code coverage results file path:</b>
155 * -e coverageFile /sdcard/myFile.ec
156 * <br/>
157 * in addition to the other arguments.
Stephan Linznerb51617f2016-01-27 18:09:50 -0800158 * @deprecated Use
159 * <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
160 * AndroidJUnitRunner</a> instead. New tests should be written using the
161 * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 */
163
164/* (not JavaDoc)
165 * Although not necessary in most case, another way to use this class is to extend it and have the
Jack Wangff1df692009-08-26 17:19:13 -0700166 * derived class return the desired test suite from the {@link #getTestSuite()} method. The test
167 * suite returned from this method will be used if no target class is defined in the meta-data or
168 * command line argument parameters. If a derived class is used it needs to be added as an
169 * instrumentation to the AndroidManifest.xml and the command to run it would look like:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 * <p/>
171 * adb shell am instrument -w com.android.foo/<i>com.android.FooInstrumentationTestRunner</i>
172 * <p/>
173 * Where <i>com.android.FooInstrumentationTestRunner</i> is the derived class.
174 *
175 * This model is used by many existing app tests, but can probably be deprecated.
176 */
Stephan Linznerb51617f2016-01-27 18:09:50 -0800177@Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178public class InstrumentationTestRunner extends Instrumentation implements TestSuiteProvider {
179
180 /** @hide */
181 public static final String ARGUMENT_TEST_CLASS = "class";
182 /** @hide */
183 public static final String ARGUMENT_TEST_PACKAGE = "package";
184 /** @hide */
185 public static final String ARGUMENT_TEST_SIZE_PREDICATE = "size";
186 /** @hide */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 public static final String ARGUMENT_DELAY_MSEC = "delay_msec";
188
189 private static final String SMALL_SUITE = "small";
Jack Wangff1df692009-08-26 17:19:13 -0700190 private static final String MEDIUM_SUITE = "medium";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 private static final String LARGE_SUITE = "large";
Jack Wangff1df692009-08-26 17:19:13 -0700192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 private static final String ARGUMENT_LOG_ONLY = "log";
Brett Chabot88e03a92010-02-19 09:57:11 -0800194 /** @hide */
195 static final String ARGUMENT_ANNOTATION = "annotation";
196 /** @hide */
197 static final String ARGUMENT_NOT_ANNOTATION = "notAnnotation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 /**
Jack Wangff1df692009-08-26 17:19:13 -0700200 * This constant defines the maximum allowed runtime (in ms) for a test included in the "small"
201 * suite. It is used to make an educated guess at what suite an unlabeled test belongs.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 */
203 private static final float SMALL_SUITE_MAX_RUNTIME = 100;
Jack Wangff1df692009-08-26 17:19:13 -0700204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 /**
Jack Wangff1df692009-08-26 17:19:13 -0700206 * This constant defines the maximum allowed runtime (in ms) for a test included in the
207 * "medium" suite. It is used to make an educated guess at what suite an unlabeled test belongs.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 */
209 private static final float MEDIUM_SUITE_MAX_RUNTIME = 1000;
Jack Wangff1df692009-08-26 17:19:13 -0700210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 /**
Jack Wangff1df692009-08-26 17:19:13 -0700212 * The following keys are used in the status bundle to provide structured reports to
213 * an IInstrumentationWatcher.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 */
215
216 /**
Jack Wangff1df692009-08-26 17:19:13 -0700217 * This value, if stored with key {@link android.app.Instrumentation#REPORT_KEY_IDENTIFIER},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 * identifies InstrumentationTestRunner as the source of the report. This is sent with all
219 * status messages.
220 */
221 public static final String REPORT_VALUE_ID = "InstrumentationTestRunner";
222 /**
Jack Wangff1df692009-08-26 17:19:13 -0700223 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 * identifies the total number of tests that are being run. This is sent with all status
225 * messages.
226 */
227 public static final String REPORT_KEY_NUM_TOTAL = "numtests";
228 /**
Jack Wangff1df692009-08-26 17:19:13 -0700229 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 * identifies the sequence number of the current test. This is sent with any status message
231 * describing a specific test being started or completed.
232 */
233 public static final String REPORT_KEY_NUM_CURRENT = "current";
234 /**
Jack Wangff1df692009-08-26 17:19:13 -0700235 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 * identifies the name of the current test class. This is sent with any status message
237 * describing a specific test being started or completed.
238 */
239 public static final String REPORT_KEY_NAME_CLASS = "class";
240 /**
Jack Wangff1df692009-08-26 17:19:13 -0700241 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 * identifies the name of the current test. This is sent with any status message
243 * describing a specific test being started or completed.
244 */
245 public static final String REPORT_KEY_NAME_TEST = "test";
246 /**
Jack Wangff1df692009-08-26 17:19:13 -0700247 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 * reports the run time in seconds of the current test.
249 */
250 private static final String REPORT_KEY_RUN_TIME = "runtime";
251 /**
Jack Wangff1df692009-08-26 17:19:13 -0700252 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
Jack Wang3fc03e62010-10-19 15:13:07 -0700253 * reports the number of total iterations of the current test.
254 */
255 private static final String REPORT_KEY_NUM_ITERATIONS = "numiterations";
256 /**
257 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 * reports the guessed suite assignment for the current test.
259 */
260 private static final String REPORT_KEY_SUITE_ASSIGNMENT = "suiteassignment";
261 /**
Brett Chabot51e03642009-05-28 18:18:15 -0700262 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
263 * identifies the path to the generated code coverage file.
264 */
265 private static final String REPORT_KEY_COVERAGE_PATH = "coverageFilePath";
Jack Wangff1df692009-08-26 17:19:13 -0700266
267 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 * The test is starting.
269 */
270 public static final int REPORT_VALUE_RESULT_START = 1;
271 /**
272 * The test completed successfully.
273 */
274 public static final int REPORT_VALUE_RESULT_OK = 0;
275 /**
276 * The test completed with an error.
277 */
278 public static final int REPORT_VALUE_RESULT_ERROR = -1;
279 /**
280 * The test completed with a failure.
281 */
282 public static final int REPORT_VALUE_RESULT_FAILURE = -2;
283 /**
Jack Wangff1df692009-08-26 17:19:13 -0700284 * If included in the status bundle sent to an IInstrumentationWatcher, this key
285 * identifies a stack trace describing an error or failure. This is sent with any status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 * message describing a specific test being completed.
287 */
288 public static final String REPORT_KEY_STACK = "stack";
289
Brett Chabot51e03642009-05-28 18:18:15 -0700290 // Default file name for code coverage
291 private static final String DEFAULT_COVERAGE_FILE_NAME = "coverage.ec";
Jack Wangff1df692009-08-26 17:19:13 -0700292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 private static final String LOG_TAG = "InstrumentationTestRunner";
294
295 private final Bundle mResults = new Bundle();
David Hucbc584d2011-09-16 18:08:35 -0700296 private Bundle mArguments;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 private AndroidTestRunner mTestRunner;
298 private boolean mDebug;
299 private boolean mJustCount;
300 private boolean mSuiteAssignmentMode;
301 private int mTestCount;
302 private String mPackageOfTests;
303 private boolean mCoverage;
304 private String mCoverageFilePath;
305 private int mDelayMsec;
306
307 @Override
308 public void onCreate(Bundle arguments) {
309 super.onCreate(arguments);
David Hucbc584d2011-09-16 18:08:35 -0700310 mArguments = arguments;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311
312 // Apk paths used to search for test classes when using TestSuiteBuilders.
313 String[] apkPaths =
314 {getTargetContext().getPackageCodePath(), getContext().getPackageCodePath()};
315 ClassPathPackageInfoSource.setApkPaths(apkPaths);
316
317 Predicate<TestMethod> testSizePredicate = null;
Brett Chabot88e03a92010-02-19 09:57:11 -0800318 Predicate<TestMethod> testAnnotationPredicate = null;
319 Predicate<TestMethod> testNotAnnotationPredicate = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 String testClassesArg = null;
321 boolean logOnly = false;
322
323 if (arguments != null) {
324 // Test class name passed as an argument should override any meta-data declaration.
325 testClassesArg = arguments.getString(ARGUMENT_TEST_CLASS);
326 mDebug = getBooleanArgument(arguments, "debug");
327 mJustCount = getBooleanArgument(arguments, "count");
328 mSuiteAssignmentMode = getBooleanArgument(arguments, "suiteAssignment");
329 mPackageOfTests = arguments.getString(ARGUMENT_TEST_PACKAGE);
330 testSizePredicate = getSizePredicateFromArg(
331 arguments.getString(ARGUMENT_TEST_SIZE_PREDICATE));
Brett Chabot88e03a92010-02-19 09:57:11 -0800332 testAnnotationPredicate = getAnnotationPredicate(
333 arguments.getString(ARGUMENT_ANNOTATION));
334 testNotAnnotationPredicate = getNotAnnotationPredicate(
335 arguments.getString(ARGUMENT_NOT_ANNOTATION));
336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 logOnly = getBooleanArgument(arguments, ARGUMENT_LOG_ONLY);
338 mCoverage = getBooleanArgument(arguments, "coverage");
339 mCoverageFilePath = arguments.getString("coverageFile");
340
341 try {
342 Object delay = arguments.get(ARGUMENT_DELAY_MSEC); // Accept either string or int
343 if (delay != null) mDelayMsec = Integer.parseInt(delay.toString());
344 } catch (NumberFormatException e) {
345 Log.e(LOG_TAG, "Invalid delay_msec parameter", e);
346 }
347 }
348
349 TestSuiteBuilder testSuiteBuilder = new TestSuiteBuilder(getClass().getName(),
350 getTargetContext().getClassLoader());
351
352 if (testSizePredicate != null) {
353 testSuiteBuilder.addRequirements(testSizePredicate);
354 }
Brett Chabot88e03a92010-02-19 09:57:11 -0800355 if (testAnnotationPredicate != null) {
356 testSuiteBuilder.addRequirements(testAnnotationPredicate);
357 }
358 if (testNotAnnotationPredicate != null) {
359 testSuiteBuilder.addRequirements(testNotAnnotationPredicate);
360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
362 if (testClassesArg == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 if (mPackageOfTests != null) {
364 testSuiteBuilder.includePackages(mPackageOfTests);
365 } else {
Brett Chabot61b10ac2009-03-31 17:04:34 -0700366 TestSuite testSuite = getTestSuite();
367 if (testSuite != null) {
368 testSuiteBuilder.addTestSuite(testSuite);
369 } else {
Jack Wangff1df692009-08-26 17:19:13 -0700370 // no package or class bundle arguments were supplied, and no test suite
Brett Chabot61b10ac2009-03-31 17:04:34 -0700371 // provided so add all tests in application
372 testSuiteBuilder.includePackages("");
373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 }
375 } else {
376 parseTestClasses(testClassesArg, testSuiteBuilder);
377 }
Jack Wangff1df692009-08-26 17:19:13 -0700378
Urs Grobda13ef52009-04-17 11:30:14 -0700379 testSuiteBuilder.addRequirements(getBuilderRequirements());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380
381 mTestRunner = getAndroidTestRunner();
382 mTestRunner.setContext(getTargetContext());
Jack Wang7aba54b2009-08-20 19:20:54 -0700383 mTestRunner.setInstrumentation(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 mTestRunner.setSkipExecution(logOnly);
385 mTestRunner.setTest(testSuiteBuilder.build());
386 mTestCount = mTestRunner.getTestCases().size();
387 if (mSuiteAssignmentMode) {
388 mTestRunner.addTestListener(new SuiteAssignmentPrinter());
389 } else {
Jack Wangff1df692009-08-26 17:19:13 -0700390 WatcherResultPrinter resultPrinter = new WatcherResultPrinter(mTestCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 mTestRunner.addTestListener(new TestPrinter("TestRunner", false));
Jack Wangff1df692009-08-26 17:19:13 -0700392 mTestRunner.addTestListener(resultPrinter);
393 mTestRunner.setPerformanceResultsWriter(resultPrinter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 }
395 start();
396 }
397
David Hucbc584d2011-09-16 18:08:35 -0700398 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800399 * Get the arguments passed to this instrumentation.
David Hucbc584d2011-09-16 18:08:35 -0700400 *
401 * @return the Bundle object
David Hucbc584d2011-09-16 18:08:35 -0700402 */
Svetoslav3a34d172013-01-28 19:55:35 -0800403 public Bundle getArguments() {
David Hucbc584d2011-09-16 18:08:35 -0700404 return mArguments;
405 }
406
David Hu8cc9a8e2011-12-13 15:57:42 -0800407 /**
408 * Add a {@link TestListener}
409 * @hide
410 */
411 protected void addTestListener(TestListener listener){
412 if(mTestRunner!=null && listener!=null){
413 mTestRunner.addTestListener(listener);
414 }
415 }
416
Urs Grobda13ef52009-04-17 11:30:14 -0700417 List<Predicate<TestMethod>> getBuilderRequirements() {
418 return new ArrayList<Predicate<TestMethod>>();
419 }
420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 /**
Jack Wangff1df692009-08-26 17:19:13 -0700422 * Parses and loads the specified set of test classes
423 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 * @param testClassArg - comma-separated list of test classes and methods
425 * @param testSuiteBuilder - builder to add tests to
426 */
427 private void parseTestClasses(String testClassArg, TestSuiteBuilder testSuiteBuilder) {
428 String[] testClasses = testClassArg.split(",");
429 for (String testClass : testClasses) {
430 parseTestClass(testClass, testSuiteBuilder);
431 }
432 }
433
434 /**
435 * Parse and load the given test class and, optionally, method
Jack Wangff1df692009-08-26 17:19:13 -0700436 *
437 * @param testClassName - full package name of test class and optionally method to add.
438 * Expected format: com.android.TestClass#testMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 * @param testSuiteBuilder - builder to add tests to
440 */
441 private void parseTestClass(String testClassName, TestSuiteBuilder testSuiteBuilder) {
442 int methodSeparatorIndex = testClassName.indexOf('#');
443 String testMethodName = null;
444
445 if (methodSeparatorIndex > 0) {
446 testMethodName = testClassName.substring(methodSeparatorIndex + 1);
447 testClassName = testClassName.substring(0, methodSeparatorIndex);
448 }
Jack Wangff1df692009-08-26 17:19:13 -0700449 testSuiteBuilder.addTestClassByName(testClassName, testMethodName, getTargetContext());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 }
451
452 protected AndroidTestRunner getAndroidTestRunner() {
453 return new AndroidTestRunner();
454 }
455
456 private boolean getBooleanArgument(Bundle arguments, String tag) {
457 String tagString = arguments.getString(tag);
458 return tagString != null && Boolean.parseBoolean(tagString);
459 }
Jack Wangff1df692009-08-26 17:19:13 -0700460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 /*
462 * Returns the size predicate object, corresponding to the "size" argument value.
463 */
464 private Predicate<TestMethod> getSizePredicateFromArg(String sizeArg) {
Jack Wangff1df692009-08-26 17:19:13 -0700465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 if (SMALL_SUITE.equals(sizeArg)) {
467 return TestPredicates.SELECT_SMALL;
468 } else if (MEDIUM_SUITE.equals(sizeArg)) {
469 return TestPredicates.SELECT_MEDIUM;
470 } else if (LARGE_SUITE.equals(sizeArg)) {
471 return TestPredicates.SELECT_LARGE;
472 } else {
473 return null;
474 }
475 }
Jack Wangff1df692009-08-26 17:19:13 -0700476
Brett Chabot88e03a92010-02-19 09:57:11 -0800477 /**
478 * Returns the test predicate object, corresponding to the annotation class value provided via
479 * the {@link ARGUMENT_ANNOTATION} argument.
480 *
481 * @return the predicate or <code>null</code>
482 */
483 private Predicate<TestMethod> getAnnotationPredicate(String annotationClassName) {
484 Class<? extends Annotation> annotationClass = getAnnotationClass(annotationClassName);
485 if (annotationClass != null) {
486 return new HasAnnotation(annotationClass);
487 }
488 return null;
489 }
490
491 /**
492 * Returns the negative test predicate object, corresponding to the annotation class value
493 * provided via the {@link ARGUMENT_NOT_ANNOTATION} argument.
494 *
495 * @return the predicate or <code>null</code>
496 */
497 private Predicate<TestMethod> getNotAnnotationPredicate(String annotationClassName) {
498 Class<? extends Annotation> annotationClass = getAnnotationClass(annotationClassName);
499 if (annotationClass != null) {
500 return Predicates.not(new HasAnnotation(annotationClass));
501 }
502 return null;
503 }
504
505 /**
506 * Helper method to return the annotation class with specified name
507 *
508 * @param annotationClassName the fully qualified name of the class
509 * @return the annotation class or <code>null</code>
510 */
511 private Class<? extends Annotation> getAnnotationClass(String annotationClassName) {
512 if (annotationClassName == null) {
513 return null;
514 }
515 try {
516 Class<?> annotationClass = Class.forName(annotationClassName);
517 if (annotationClass.isAnnotation()) {
518 return (Class<? extends Annotation>)annotationClass;
519 } else {
520 Log.e(LOG_TAG, String.format("Provided annotation value %s is not an Annotation",
521 annotationClassName));
522 }
523 } catch (ClassNotFoundException e) {
524 Log.e(LOG_TAG, String.format("Could not find class for specified annotation %s",
525 annotationClassName));
526 }
527 return null;
528 }
529
Brett Chabot31e7ce72010-07-07 17:19:08 -0700530 /**
531 * Initialize the current thread as a looper.
532 * <p/>
533 * Exposed for unit testing.
534 */
535 void prepareLooper() {
536 Looper.prepare();
537 }
538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 @Override
540 public void onStart() {
Brett Chabot31e7ce72010-07-07 17:19:08 -0700541 prepareLooper();
Jack Wangff1df692009-08-26 17:19:13 -0700542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 if (mJustCount) {
544 mResults.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
545 mResults.putInt(REPORT_KEY_NUM_TOTAL, mTestCount);
546 finish(Activity.RESULT_OK, mResults);
547 } else {
548 if (mDebug) {
549 Debug.waitForDebugger();
550 }
Jack Wangff1df692009-08-26 17:19:13 -0700551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
553 PrintStream writer = new PrintStream(byteArrayOutputStream);
554 try {
555 StringResultPrinter resultPrinter = new StringResultPrinter(writer);
Jack Wangff1df692009-08-26 17:19:13 -0700556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 mTestRunner.addTestListener(resultPrinter);
Jack Wangff1df692009-08-26 17:19:13 -0700558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 long startTime = System.currentTimeMillis();
560 mTestRunner.runTest();
561 long runTime = System.currentTimeMillis() - startTime;
Jack Wangff1df692009-08-26 17:19:13 -0700562
Brett Chabot41e173d2012-10-24 14:34:07 -0700563 resultPrinter.printResult(mTestRunner.getTestResult(), runTime);
Brett Chabot31e7ce72010-07-07 17:19:08 -0700564 } catch (Throwable t) {
565 // catch all exceptions so a more verbose error message can be outputted
566 writer.println(String.format("Test run aborted due to unexpected exception: %s",
567 t.getMessage()));
568 t.printStackTrace(writer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 } finally {
Jack Wangff1df692009-08-26 17:19:13 -0700570 mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
571 String.format("\nTest results for %s=%s",
572 mTestRunner.getTestClassName(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 byteArrayOutputStream.toString()));
574
575 if (mCoverage) {
576 generateCoverageReport();
577 }
578 writer.close();
Jack Wangff1df692009-08-26 17:19:13 -0700579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 finish(Activity.RESULT_OK, mResults);
581 }
582 }
583 }
584
585 public TestSuite getTestSuite() {
586 return getAllTests();
587 }
588
589 /**
590 * Override this to define all of the tests to run in your package.
591 */
592 public TestSuite getAllTests() {
593 return null;
594 }
595
596 /**
597 * Override this to provide access to the class loader of your package.
598 */
599 public ClassLoader getLoader() {
600 return null;
601 }
Jack Wangff1df692009-08-26 17:19:13 -0700602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 private void generateCoverageReport() {
604 // use reflection to call emma dump coverage method, to avoid
605 // always statically compiling against emma jar
Brett Chabot51e03642009-05-28 18:18:15 -0700606 String coverageFilePath = getCoverageFilePath();
607 java.io.File coverageFile = new java.io.File(coverageFilePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 try {
Brett Chabot88e03a92010-02-19 09:57:11 -0800609 Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
Jack Wangff1df692009-08-26 17:19:13 -0700610 Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 coverageFile.getClass(), boolean.class, boolean.class);
Jack Wangff1df692009-08-26 17:19:13 -0700612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 dumpCoverageMethod.invoke(null, coverageFile, false, false);
Brett Chabot51e03642009-05-28 18:18:15 -0700614 // output path to generated coverage file so it can be parsed by a test harness if
615 // needed
616 mResults.putString(REPORT_KEY_COVERAGE_PATH, coverageFilePath);
617 // also output a more user friendly msg
Brett Chabot08d13c32010-02-18 15:42:13 -0800618 final String currentStream = mResults.getString(
619 Instrumentation.REPORT_KEY_STREAMRESULT);
Brett Chabot51e03642009-05-28 18:18:15 -0700620 mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
Brett Chabot08d13c32010-02-18 15:42:13 -0800621 String.format("%s\nGenerated code coverage data to %s", currentStream,
622 coverageFilePath));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 } catch (ClassNotFoundException e) {
624 reportEmmaError("Is emma jar on classpath?", e);
625 } catch (SecurityException e) {
626 reportEmmaError(e);
627 } catch (NoSuchMethodException e) {
628 reportEmmaError(e);
629 } catch (IllegalArgumentException e) {
630 reportEmmaError(e);
631 } catch (IllegalAccessException e) {
632 reportEmmaError(e);
633 } catch (InvocationTargetException e) {
634 reportEmmaError(e);
635 }
636 }
637
638 private String getCoverageFilePath() {
639 if (mCoverageFilePath == null) {
Brett Chabot51e03642009-05-28 18:18:15 -0700640 return getTargetContext().getFilesDir().getAbsolutePath() + File.separator +
Jack Wangff1df692009-08-26 17:19:13 -0700641 DEFAULT_COVERAGE_FILE_NAME;
642 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 return mCoverageFilePath;
644 }
645 }
646
647 private void reportEmmaError(Exception e) {
Jack Wangff1df692009-08-26 17:19:13 -0700648 reportEmmaError("", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 }
650
651 private void reportEmmaError(String hint, Exception e) {
652 String msg = "Failed to generate emma coverage. " + hint;
653 Log.e(LOG_TAG, msg, e);
654 mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "\nError: " + msg);
655 }
656
657 // TODO kill this, use status() and prettyprint model for better output
658 private class StringResultPrinter extends ResultPrinter {
659
660 public StringResultPrinter(PrintStream writer) {
661 super(writer);
662 }
663
Brett Chabot41e173d2012-10-24 14:34:07 -0700664 public synchronized void printResult(TestResult result, long runTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 printHeader(runTime);
666 printFooter(result);
667 }
668 }
Jack Wangff1df692009-08-26 17:19:13 -0700669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 /**
Jack Wangff1df692009-08-26 17:19:13 -0700671 * This class sends status reports back to the IInstrumentationWatcher about
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 * which suite each test belongs.
673 */
Jack Wangff1df692009-08-26 17:19:13 -0700674 private class SuiteAssignmentPrinter implements TestListener {
675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 private Bundle mTestResult;
677 private long mStartTime;
678 private long mEndTime;
679 private boolean mTimingValid;
Jack Wangff1df692009-08-26 17:19:13 -0700680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 public SuiteAssignmentPrinter() {
682 }
Jack Wangff1df692009-08-26 17:19:13 -0700683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 /**
685 * send a status for the start of a each test, so long tests can be seen as "running"
686 */
687 public void startTest(Test test) {
688 mTimingValid = true;
Jack Wangff1df692009-08-26 17:19:13 -0700689 mStartTime = System.currentTimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 }
Jack Wangff1df692009-08-26 17:19:13 -0700691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 /**
693 * @see junit.framework.TestListener#addError(Test, Throwable)
694 */
695 public void addError(Test test, Throwable t) {
696 mTimingValid = false;
697 }
698
699 /**
700 * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
701 */
702 public void addFailure(Test test, AssertionFailedError t) {
703 mTimingValid = false;
704 }
705
706 /**
707 * @see junit.framework.TestListener#endTest(Test)
708 */
709 public void endTest(Test test) {
710 float runTime;
711 String assignmentSuite;
712 mEndTime = System.currentTimeMillis();
713 mTestResult = new Bundle();
714
715 if (!mTimingValid || mStartTime < 0) {
716 assignmentSuite = "NA";
717 runTime = -1;
718 } else {
719 runTime = mEndTime - mStartTime;
Jack Wangff1df692009-08-26 17:19:13 -0700720 if (runTime < SMALL_SUITE_MAX_RUNTIME
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 && !InstrumentationTestCase.class.isAssignableFrom(test.getClass())) {
722 assignmentSuite = SMALL_SUITE;
723 } else if (runTime < MEDIUM_SUITE_MAX_RUNTIME) {
724 assignmentSuite = MEDIUM_SUITE;
725 } else {
726 assignmentSuite = LARGE_SUITE;
727 }
728 }
729 // Clear mStartTime so that we can verify that it gets set next time.
730 mStartTime = -1;
731
Jack Wangff1df692009-08-26 17:19:13 -0700732 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
733 test.getClass().getName() + "#" + ((TestCase) test).getName()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 + "\nin " + assignmentSuite + " suite\nrunTime: "
735 + String.valueOf(runTime) + "\n");
736 mTestResult.putFloat(REPORT_KEY_RUN_TIME, runTime);
737 mTestResult.putString(REPORT_KEY_SUITE_ASSIGNMENT, assignmentSuite);
738
739 sendStatus(0, mTestResult);
740 }
741 }
Jack Wangff1df692009-08-26 17:19:13 -0700742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 /**
744 * This class sends status reports back to the IInstrumentationWatcher
745 */
Jack Wangff1df692009-08-26 17:19:13 -0700746 private class WatcherResultPrinter implements TestListener, PerformanceResultsWriter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 private final Bundle mResultTemplate;
748 Bundle mTestResult;
749 int mTestNum = 0;
750 int mTestResultCode = 0;
751 String mTestClass = null;
Jack Wang4f414bd2009-11-06 20:53:47 -0800752 PerformanceCollector mPerfCollector = new PerformanceCollector();
Jack Wangff1df692009-08-26 17:19:13 -0700753 boolean mIsTimedTest = false;
Jack Wang4f414bd2009-11-06 20:53:47 -0800754 boolean mIncludeDetailedStats = false;
Jack Wangff1df692009-08-26 17:19:13 -0700755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 public WatcherResultPrinter(int numTests) {
757 mResultTemplate = new Bundle();
758 mResultTemplate.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
759 mResultTemplate.putInt(REPORT_KEY_NUM_TOTAL, numTests);
760 }
Jack Wangff1df692009-08-26 17:19:13 -0700761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 /**
Jack Wangff1df692009-08-26 17:19:13 -0700763 * send a status for the start of a each test, so long tests can be seen
764 * as "running"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 */
766 public void startTest(Test test) {
767 String testClass = test.getClass().getName();
Jack Wangff1df692009-08-26 17:19:13 -0700768 String testName = ((TestCase)test).getName();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 mTestResult = new Bundle(mResultTemplate);
770 mTestResult.putString(REPORT_KEY_NAME_CLASS, testClass);
Jack Wangff1df692009-08-26 17:19:13 -0700771 mTestResult.putString(REPORT_KEY_NAME_TEST, testName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 mTestResult.putInt(REPORT_KEY_NUM_CURRENT, ++mTestNum);
773 // pretty printing
774 if (testClass != null && !testClass.equals(mTestClass)) {
Jack Wangff1df692009-08-26 17:19:13 -0700775 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 String.format("\n%s:", testClass));
777 mTestClass = testClass;
778 } else {
779 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "");
780 }
781
Jack Wang3fc03e62010-10-19 15:13:07 -0700782 Method testMethod = null;
783 try {
784 testMethod = test.getClass().getMethod(testName);
785 // Report total number of iterations, if test is repetitive
786 if (testMethod.isAnnotationPresent(RepetitiveTest.class)) {
787 int numIterations = testMethod.getAnnotation(
788 RepetitiveTest.class).numIterations();
789 mTestResult.putInt(REPORT_KEY_NUM_ITERATIONS, numIterations);
790 }
791 } catch (NoSuchMethodException e) {
792 // ignore- the test with given name does not exist. Will be handled during test
793 // execution
794 }
795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 // The delay_msec parameter is normally used to provide buffers of idle time
Jack Wangff1df692009-08-26 17:19:13 -0700797 // for power measurement purposes. To make sure there is a delay before and after
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 // every test in a suite, we delay *after* every test (see endTest below) and also
Jack Wangff1df692009-08-26 17:19:13 -0700799 // delay *before* the first test. So, delay test1 delay test2 delay.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800
801 try {
802 if (mTestNum == 1) Thread.sleep(mDelayMsec);
803 } catch (InterruptedException e) {
804 throw new IllegalStateException(e);
805 }
806
807 sendStatus(REPORT_VALUE_RESULT_START, mTestResult);
808 mTestResultCode = 0;
Jack Wangff1df692009-08-26 17:19:13 -0700809
810 mIsTimedTest = false;
Jack Wang4f414bd2009-11-06 20:53:47 -0800811 mIncludeDetailedStats = false;
Jack Wangff1df692009-08-26 17:19:13 -0700812 try {
Jack Wang4f414bd2009-11-06 20:53:47 -0800813 // Look for TimedTest annotation on both test class and test method
Brian Muramatsu48983952010-11-17 12:28:51 -0800814 if (testMethod != null && testMethod.isAnnotationPresent(TimedTest.class)) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800815 mIsTimedTest = true;
Jack Wang3fc03e62010-10-19 15:13:07 -0700816 mIncludeDetailedStats = testMethod.getAnnotation(
Jack Wang4f414bd2009-11-06 20:53:47 -0800817 TimedTest.class).includeDetailedStats();
818 } else if (test.getClass().isAnnotationPresent(TimedTest.class)) {
819 mIsTimedTest = true;
820 mIncludeDetailedStats = test.getClass().getAnnotation(
821 TimedTest.class).includeDetailedStats();
822 }
Jack Wangff1df692009-08-26 17:19:13 -0700823 } catch (SecurityException e) {
Brett Chabot31e7ce72010-07-07 17:19:08 -0700824 // ignore - the test with given name cannot be accessed. Will be handled during
825 // test execution
Jack Wangff1df692009-08-26 17:19:13 -0700826 }
827
Jack Wang4f414bd2009-11-06 20:53:47 -0800828 if (mIsTimedTest && mIncludeDetailedStats) {
829 mPerfCollector.beginSnapshot("");
830 } else if (mIsTimedTest) {
831 mPerfCollector.startTiming("");
Jack Wangff1df692009-08-26 17:19:13 -0700832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 }
Jack Wangff1df692009-08-26 17:19:13 -0700834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 /**
836 * @see junit.framework.TestListener#addError(Test, Throwable)
837 */
838 public void addError(Test test, Throwable t) {
839 mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
840 mTestResultCode = REPORT_VALUE_RESULT_ERROR;
841 // pretty printing
Jack Wangff1df692009-08-26 17:19:13 -0700842 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
843 String.format("\nError in %s:\n%s",
844 ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 }
846
847 /**
848 * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
849 */
850 public void addFailure(Test test, AssertionFailedError t) {
851 mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
852 mTestResultCode = REPORT_VALUE_RESULT_FAILURE;
853 // pretty printing
Jack Wangff1df692009-08-26 17:19:13 -0700854 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
855 String.format("\nFailure in %s:\n%s",
856 ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857 }
858
859 /**
860 * @see junit.framework.TestListener#endTest(Test)
861 */
862 public void endTest(Test test) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800863 if (mIsTimedTest && mIncludeDetailedStats) {
864 mTestResult.putAll(mPerfCollector.endSnapshot());
865 } else if (mIsTimedTest) {
866 writeStopTiming(mPerfCollector.stopTiming(""));
Jack Wangff1df692009-08-26 17:19:13 -0700867 }
868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 if (mTestResultCode == 0) {
870 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, ".");
871 }
872 sendStatus(mTestResultCode, mTestResult);
873
Jack Wangff1df692009-08-26 17:19:13 -0700874 try { // Sleep after every test, if specified
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 Thread.sleep(mDelayMsec);
876 } catch (InterruptedException e) {
877 throw new IllegalStateException(e);
878 }
879 }
880
Jack Wangff1df692009-08-26 17:19:13 -0700881 public void writeBeginSnapshot(String label) {
882 // Do nothing
883 }
884
885 public void writeEndSnapshot(Bundle results) {
Jack Wang075997f2009-10-27 22:01:09 -0700886 // Copy all snapshot data fields into mResults, which is outputted
887 // via Instrumentation.finish
888 mResults.putAll(results);
Jack Wangff1df692009-08-26 17:19:13 -0700889 }
890
891 public void writeStartTiming(String label) {
892 // Do nothing
893 }
894
895 public void writeStopTiming(Bundle results) {
896 // Copy results into mTestResult by flattening list of iterations,
897 // which is outputted via WatcherResultPrinter.endTest
898 int i = 0;
899 for (Parcelable p :
900 results.getParcelableArrayList(PerformanceCollector.METRIC_KEY_ITERATIONS)) {
901 Bundle iteration = (Bundle)p;
Jack Wang4f414bd2009-11-06 20:53:47 -0800902 String index = "iteration" + i + ".";
Jack Wangff1df692009-08-26 17:19:13 -0700903 mTestResult.putString(index + PerformanceCollector.METRIC_KEY_LABEL,
904 iteration.getString(PerformanceCollector.METRIC_KEY_LABEL));
905 mTestResult.putLong(index + PerformanceCollector.METRIC_KEY_CPU_TIME,
906 iteration.getLong(PerformanceCollector.METRIC_KEY_CPU_TIME));
907 mTestResult.putLong(index + PerformanceCollector.METRIC_KEY_EXECUTION_TIME,
908 iteration.getLong(PerformanceCollector.METRIC_KEY_EXECUTION_TIME));
909 i++;
910 }
911 }
912
Jack Wang075997f2009-10-27 22:01:09 -0700913 public void writeMeasurement(String label, long value) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800914 mTestResult.putLong(label, value);
Jack Wang075997f2009-10-27 22:01:09 -0700915 }
916
917 public void writeMeasurement(String label, float value) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800918 mTestResult.putFloat(label, value);
Jack Wang075997f2009-10-27 22:01:09 -0700919 }
920
921 public void writeMeasurement(String label, String value) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800922 mTestResult.putString(label, value);
Jack Wang075997f2009-10-27 22:01:09 -0700923 }
924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 // TODO report the end of the cycle
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 }
927}