blob: 91d04da05930b3c42c7426a6259a745d13d9132b [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>
77 * <li>In an appropriate AndroidManifest.xml, define the this instrumentation with
78 * the appropriate android:targetPackage set.
79 * <li>Run the instrumentation using "adb shell am instrument -w",
80 * with no optional arguments, to run all tests (except performance tests).
81 * <li>Run the instrumentation using "adb shell am instrument -w",
82 * with the argument '-e func true' to run all functional tests. These are tests that derive from
83 * {@link android.test.InstrumentationTestCase}.
84 * <li>Run the instrumentation using "adb shell am instrument -w",
85 * with the argument '-e unit true' to run all unit tests. These are tests that <i>do not</i>derive
86 * from {@link android.test.InstrumentationTestCase} (and are not performance tests).
87 * <li>Run the instrumentation using "adb shell am instrument -w",
88 * with the argument '-e class' set to run an individual {@link junit.framework.TestCase}.
89 * </ol>
90 * <p/>
91 * <b>Running all tests:</b> adb shell am instrument -w
92 * com.android.foo/android.test.InstrumentationTestRunner
93 * <p/>
94 * <b>Running all small tests:</b> adb shell am instrument -w
95 * -e size small
96 * com.android.foo/android.test.InstrumentationTestRunner
97 * <p/>
98 * <b>Running all medium tests:</b> adb shell am instrument -w
99 * -e size medium
100 * com.android.foo/android.test.InstrumentationTestRunner
101 * <p/>
102 * <b>Running all large tests:</b> adb shell am instrument -w
103 * -e size large
104 * com.android.foo/android.test.InstrumentationTestRunner
105 * <p/>
Brett Chabot88e03a92010-02-19 09:57:11 -0800106 * <b>Filter test run to tests with given annotation:</b> adb shell am instrument -w
107 * -e annotation com.android.foo.MyAnnotation
108 * com.android.foo/android.test.InstrumentationTestRunner
109 * <p/>
110 * If used with other options, the resulting test run will contain the union of the two options.
111 * e.g. "-e size large -e annotation com.android.foo.MyAnnotation" will run only tests with both
112 * the {@link LargeTest} and "com.android.foo.MyAnnotation" annotations.
113 * <p/>
114 * <b>Filter test run to tests <i>without</i> given annotation:</b> adb shell am instrument -w
115 * -e notAnnotation com.android.foo.MyAnnotation
116 * com.android.foo/android.test.InstrumentationTestRunner
117 * <p/>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 * <b>Running a single testcase:</b> adb shell am instrument -w
119 * -e class com.android.foo.FooTest
120 * com.android.foo/android.test.InstrumentationTestRunner
121 * <p/>
122 * <b>Running a single test:</b> adb shell am instrument -w
123 * -e class com.android.foo.FooTest#testFoo
124 * com.android.foo/android.test.InstrumentationTestRunner
125 * <p/>
126 * <b>Running multiple tests:</b> adb shell am instrument -w
127 * -e class com.android.foo.FooTest,com.android.foo.TooTest
128 * com.android.foo/android.test.InstrumentationTestRunner
129 * <p/>
Brett Chabot89c0ef42010-03-18 20:03:31 -0700130 * <b>Running all tests in a java package:</b> adb shell am instrument -w
131 * -e package com.android.foo.subpkg
132 * com.android.foo/android.test.InstrumentationTestRunner
133 * <p/>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 * <b>Including performance tests:</b> adb shell am instrument -w
135 * -e perf true
136 * com.android.foo/android.test.InstrumentationTestRunner
137 * <p/>
138 * <b>To debug your tests, set a break point in your code and pass:</b>
139 * -e debug true
140 * <p/>
141 * <b>To run in 'log only' mode</b>
142 * -e log true
Jack Wangff1df692009-08-26 17:19:13 -0700143 * This option will load and iterate through all test classes and methods, but will bypass actual
144 * 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 -0800145 * instrumentation command.
146 * <p/>
147 * <b>To generate EMMA code coverage:</b>
148 * -e coverage true
Jack Wangff1df692009-08-26 17:19:13 -0700149 * Note: this requires an emma instrumented build. By default, the code coverage results file
Brett Chabot51e03642009-05-28 18:18:15 -0700150 * will be saved in a /data/<app>/coverage.ec file, unless overridden by coverageFile flag (see
151 * below)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 * <p/>
153 * <b> To specify EMMA code coverage results file path:</b>
154 * -e coverageFile /sdcard/myFile.ec
155 * <br/>
156 * in addition to the other arguments.
157 */
158
159/* (not JavaDoc)
160 * 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 -0700161 * derived class return the desired test suite from the {@link #getTestSuite()} method. The test
162 * suite returned from this method will be used if no target class is defined in the meta-data or
163 * command line argument parameters. If a derived class is used it needs to be added as an
164 * instrumentation to the AndroidManifest.xml and the command to run it would look like:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 * <p/>
166 * adb shell am instrument -w com.android.foo/<i>com.android.FooInstrumentationTestRunner</i>
167 * <p/>
168 * Where <i>com.android.FooInstrumentationTestRunner</i> is the derived class.
169 *
170 * This model is used by many existing app tests, but can probably be deprecated.
171 */
172public class InstrumentationTestRunner extends Instrumentation implements TestSuiteProvider {
173
174 /** @hide */
175 public static final String ARGUMENT_TEST_CLASS = "class";
176 /** @hide */
177 public static final String ARGUMENT_TEST_PACKAGE = "package";
178 /** @hide */
179 public static final String ARGUMENT_TEST_SIZE_PREDICATE = "size";
180 /** @hide */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 public static final String ARGUMENT_DELAY_MSEC = "delay_msec";
182
183 private static final String SMALL_SUITE = "small";
Jack Wangff1df692009-08-26 17:19:13 -0700184 private static final String MEDIUM_SUITE = "medium";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 private static final String LARGE_SUITE = "large";
Jack Wangff1df692009-08-26 17:19:13 -0700186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 private static final String ARGUMENT_LOG_ONLY = "log";
Brett Chabot88e03a92010-02-19 09:57:11 -0800188 /** @hide */
189 static final String ARGUMENT_ANNOTATION = "annotation";
190 /** @hide */
191 static final String ARGUMENT_NOT_ANNOTATION = "notAnnotation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 /**
Jack Wangff1df692009-08-26 17:19:13 -0700194 * This constant defines the maximum allowed runtime (in ms) for a test included in the "small"
195 * 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 -0800196 */
197 private static final float SMALL_SUITE_MAX_RUNTIME = 100;
Jack Wangff1df692009-08-26 17:19:13 -0700198
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
201 * "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 -0800202 */
203 private static final float MEDIUM_SUITE_MAX_RUNTIME = 1000;
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 * The following keys are used in the status bundle to provide structured reports to
207 * an IInstrumentationWatcher.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 */
209
210 /**
Jack Wangff1df692009-08-26 17:19:13 -0700211 * This value, if stored with key {@link android.app.Instrumentation#REPORT_KEY_IDENTIFIER},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 * identifies InstrumentationTestRunner as the source of the report. This is sent with all
213 * status messages.
214 */
215 public static final String REPORT_VALUE_ID = "InstrumentationTestRunner";
216 /**
Jack Wangff1df692009-08-26 17:19:13 -0700217 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 * identifies the total number of tests that are being run. This is sent with all status
219 * messages.
220 */
221 public static final String REPORT_KEY_NUM_TOTAL = "numtests";
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 sequence number of the current test. This is sent with any status message
225 * describing a specific test being started or completed.
226 */
227 public static final String REPORT_KEY_NUM_CURRENT = "current";
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 name of the current test class. This is sent with any status message
231 * describing a specific test being started or completed.
232 */
233 public static final String REPORT_KEY_NAME_CLASS = "class";
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. 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_TEST = "test";
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 * reports the run time in seconds of the current test.
243 */
244 private static final String REPORT_KEY_RUN_TIME = "runtime";
245 /**
Jack Wangff1df692009-08-26 17:19:13 -0700246 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
Jack Wang3fc03e62010-10-19 15:13:07 -0700247 * reports the number of total iterations of the current test.
248 */
249 private static final String REPORT_KEY_NUM_ITERATIONS = "numiterations";
250 /**
251 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 * reports the guessed suite assignment for the current test.
253 */
254 private static final String REPORT_KEY_SUITE_ASSIGNMENT = "suiteassignment";
255 /**
Brett Chabot51e03642009-05-28 18:18:15 -0700256 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
257 * identifies the path to the generated code coverage file.
258 */
259 private static final String REPORT_KEY_COVERAGE_PATH = "coverageFilePath";
Jack Wangff1df692009-08-26 17:19:13 -0700260
261 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 * The test is starting.
263 */
264 public static final int REPORT_VALUE_RESULT_START = 1;
265 /**
266 * The test completed successfully.
267 */
268 public static final int REPORT_VALUE_RESULT_OK = 0;
269 /**
270 * The test completed with an error.
271 */
272 public static final int REPORT_VALUE_RESULT_ERROR = -1;
273 /**
274 * The test completed with a failure.
275 */
276 public static final int REPORT_VALUE_RESULT_FAILURE = -2;
277 /**
Jack Wangff1df692009-08-26 17:19:13 -0700278 * If included in the status bundle sent to an IInstrumentationWatcher, this key
279 * 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 -0800280 * message describing a specific test being completed.
281 */
282 public static final String REPORT_KEY_STACK = "stack";
283
Brett Chabot51e03642009-05-28 18:18:15 -0700284 // Default file name for code coverage
285 private static final String DEFAULT_COVERAGE_FILE_NAME = "coverage.ec";
Jack Wangff1df692009-08-26 17:19:13 -0700286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 private static final String LOG_TAG = "InstrumentationTestRunner";
288
289 private final Bundle mResults = new Bundle();
David Hucbc584d2011-09-16 18:08:35 -0700290 private Bundle mArguments;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 private AndroidTestRunner mTestRunner;
292 private boolean mDebug;
293 private boolean mJustCount;
294 private boolean mSuiteAssignmentMode;
295 private int mTestCount;
296 private String mPackageOfTests;
297 private boolean mCoverage;
298 private String mCoverageFilePath;
299 private int mDelayMsec;
300
301 @Override
302 public void onCreate(Bundle arguments) {
303 super.onCreate(arguments);
David Hucbc584d2011-09-16 18:08:35 -0700304 mArguments = arguments;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
306 // Apk paths used to search for test classes when using TestSuiteBuilders.
307 String[] apkPaths =
308 {getTargetContext().getPackageCodePath(), getContext().getPackageCodePath()};
309 ClassPathPackageInfoSource.setApkPaths(apkPaths);
310
311 Predicate<TestMethod> testSizePredicate = null;
Brett Chabot88e03a92010-02-19 09:57:11 -0800312 Predicate<TestMethod> testAnnotationPredicate = null;
313 Predicate<TestMethod> testNotAnnotationPredicate = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 String testClassesArg = null;
315 boolean logOnly = false;
316
317 if (arguments != null) {
318 // Test class name passed as an argument should override any meta-data declaration.
319 testClassesArg = arguments.getString(ARGUMENT_TEST_CLASS);
320 mDebug = getBooleanArgument(arguments, "debug");
321 mJustCount = getBooleanArgument(arguments, "count");
322 mSuiteAssignmentMode = getBooleanArgument(arguments, "suiteAssignment");
323 mPackageOfTests = arguments.getString(ARGUMENT_TEST_PACKAGE);
324 testSizePredicate = getSizePredicateFromArg(
325 arguments.getString(ARGUMENT_TEST_SIZE_PREDICATE));
Brett Chabot88e03a92010-02-19 09:57:11 -0800326 testAnnotationPredicate = getAnnotationPredicate(
327 arguments.getString(ARGUMENT_ANNOTATION));
328 testNotAnnotationPredicate = getNotAnnotationPredicate(
329 arguments.getString(ARGUMENT_NOT_ANNOTATION));
330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 logOnly = getBooleanArgument(arguments, ARGUMENT_LOG_ONLY);
332 mCoverage = getBooleanArgument(arguments, "coverage");
333 mCoverageFilePath = arguments.getString("coverageFile");
334
335 try {
336 Object delay = arguments.get(ARGUMENT_DELAY_MSEC); // Accept either string or int
337 if (delay != null) mDelayMsec = Integer.parseInt(delay.toString());
338 } catch (NumberFormatException e) {
339 Log.e(LOG_TAG, "Invalid delay_msec parameter", e);
340 }
341 }
342
343 TestSuiteBuilder testSuiteBuilder = new TestSuiteBuilder(getClass().getName(),
344 getTargetContext().getClassLoader());
345
346 if (testSizePredicate != null) {
347 testSuiteBuilder.addRequirements(testSizePredicate);
348 }
Brett Chabot88e03a92010-02-19 09:57:11 -0800349 if (testAnnotationPredicate != null) {
350 testSuiteBuilder.addRequirements(testAnnotationPredicate);
351 }
352 if (testNotAnnotationPredicate != null) {
353 testSuiteBuilder.addRequirements(testNotAnnotationPredicate);
354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355
356 if (testClassesArg == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 if (mPackageOfTests != null) {
358 testSuiteBuilder.includePackages(mPackageOfTests);
359 } else {
Brett Chabot61b10ac2009-03-31 17:04:34 -0700360 TestSuite testSuite = getTestSuite();
361 if (testSuite != null) {
362 testSuiteBuilder.addTestSuite(testSuite);
363 } else {
Jack Wangff1df692009-08-26 17:19:13 -0700364 // no package or class bundle arguments were supplied, and no test suite
Brett Chabot61b10ac2009-03-31 17:04:34 -0700365 // provided so add all tests in application
366 testSuiteBuilder.includePackages("");
367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 }
369 } else {
370 parseTestClasses(testClassesArg, testSuiteBuilder);
371 }
Jack Wangff1df692009-08-26 17:19:13 -0700372
Urs Grobda13ef52009-04-17 11:30:14 -0700373 testSuiteBuilder.addRequirements(getBuilderRequirements());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374
375 mTestRunner = getAndroidTestRunner();
376 mTestRunner.setContext(getTargetContext());
Jack Wang7aba54b2009-08-20 19:20:54 -0700377 mTestRunner.setInstrumentation(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 mTestRunner.setSkipExecution(logOnly);
379 mTestRunner.setTest(testSuiteBuilder.build());
380 mTestCount = mTestRunner.getTestCases().size();
381 if (mSuiteAssignmentMode) {
382 mTestRunner.addTestListener(new SuiteAssignmentPrinter());
383 } else {
Jack Wangff1df692009-08-26 17:19:13 -0700384 WatcherResultPrinter resultPrinter = new WatcherResultPrinter(mTestCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 mTestRunner.addTestListener(new TestPrinter("TestRunner", false));
Jack Wangff1df692009-08-26 17:19:13 -0700386 mTestRunner.addTestListener(resultPrinter);
387 mTestRunner.setPerformanceResultsWriter(resultPrinter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 }
389 start();
390 }
391
David Hucbc584d2011-09-16 18:08:35 -0700392 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800393 * Get the arguments passed to this instrumentation.
David Hucbc584d2011-09-16 18:08:35 -0700394 *
395 * @return the Bundle object
David Hucbc584d2011-09-16 18:08:35 -0700396 */
Svetoslav3a34d172013-01-28 19:55:35 -0800397 public Bundle getArguments() {
David Hucbc584d2011-09-16 18:08:35 -0700398 return mArguments;
399 }
400
David Hu8cc9a8e2011-12-13 15:57:42 -0800401 /**
402 * Add a {@link TestListener}
403 * @hide
404 */
405 protected void addTestListener(TestListener listener){
406 if(mTestRunner!=null && listener!=null){
407 mTestRunner.addTestListener(listener);
408 }
409 }
410
Urs Grobda13ef52009-04-17 11:30:14 -0700411 List<Predicate<TestMethod>> getBuilderRequirements() {
412 return new ArrayList<Predicate<TestMethod>>();
413 }
414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 /**
Jack Wangff1df692009-08-26 17:19:13 -0700416 * Parses and loads the specified set of test classes
417 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 * @param testClassArg - comma-separated list of test classes and methods
419 * @param testSuiteBuilder - builder to add tests to
420 */
421 private void parseTestClasses(String testClassArg, TestSuiteBuilder testSuiteBuilder) {
422 String[] testClasses = testClassArg.split(",");
423 for (String testClass : testClasses) {
424 parseTestClass(testClass, testSuiteBuilder);
425 }
426 }
427
428 /**
429 * Parse and load the given test class and, optionally, method
Jack Wangff1df692009-08-26 17:19:13 -0700430 *
431 * @param testClassName - full package name of test class and optionally method to add.
432 * Expected format: com.android.TestClass#testMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 * @param testSuiteBuilder - builder to add tests to
434 */
435 private void parseTestClass(String testClassName, TestSuiteBuilder testSuiteBuilder) {
436 int methodSeparatorIndex = testClassName.indexOf('#');
437 String testMethodName = null;
438
439 if (methodSeparatorIndex > 0) {
440 testMethodName = testClassName.substring(methodSeparatorIndex + 1);
441 testClassName = testClassName.substring(0, methodSeparatorIndex);
442 }
Jack Wangff1df692009-08-26 17:19:13 -0700443 testSuiteBuilder.addTestClassByName(testClassName, testMethodName, getTargetContext());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 }
445
446 protected AndroidTestRunner getAndroidTestRunner() {
447 return new AndroidTestRunner();
448 }
449
450 private boolean getBooleanArgument(Bundle arguments, String tag) {
451 String tagString = arguments.getString(tag);
452 return tagString != null && Boolean.parseBoolean(tagString);
453 }
Jack Wangff1df692009-08-26 17:19:13 -0700454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 /*
456 * Returns the size predicate object, corresponding to the "size" argument value.
457 */
458 private Predicate<TestMethod> getSizePredicateFromArg(String sizeArg) {
Jack Wangff1df692009-08-26 17:19:13 -0700459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 if (SMALL_SUITE.equals(sizeArg)) {
461 return TestPredicates.SELECT_SMALL;
462 } else if (MEDIUM_SUITE.equals(sizeArg)) {
463 return TestPredicates.SELECT_MEDIUM;
464 } else if (LARGE_SUITE.equals(sizeArg)) {
465 return TestPredicates.SELECT_LARGE;
466 } else {
467 return null;
468 }
469 }
Jack Wangff1df692009-08-26 17:19:13 -0700470
Brett Chabot88e03a92010-02-19 09:57:11 -0800471 /**
472 * Returns the test predicate object, corresponding to the annotation class value provided via
473 * the {@link ARGUMENT_ANNOTATION} argument.
474 *
475 * @return the predicate or <code>null</code>
476 */
477 private Predicate<TestMethod> getAnnotationPredicate(String annotationClassName) {
478 Class<? extends Annotation> annotationClass = getAnnotationClass(annotationClassName);
479 if (annotationClass != null) {
480 return new HasAnnotation(annotationClass);
481 }
482 return null;
483 }
484
485 /**
486 * Returns the negative test predicate object, corresponding to the annotation class value
487 * provided via the {@link ARGUMENT_NOT_ANNOTATION} argument.
488 *
489 * @return the predicate or <code>null</code>
490 */
491 private Predicate<TestMethod> getNotAnnotationPredicate(String annotationClassName) {
492 Class<? extends Annotation> annotationClass = getAnnotationClass(annotationClassName);
493 if (annotationClass != null) {
494 return Predicates.not(new HasAnnotation(annotationClass));
495 }
496 return null;
497 }
498
499 /**
500 * Helper method to return the annotation class with specified name
501 *
502 * @param annotationClassName the fully qualified name of the class
503 * @return the annotation class or <code>null</code>
504 */
505 private Class<? extends Annotation> getAnnotationClass(String annotationClassName) {
506 if (annotationClassName == null) {
507 return null;
508 }
509 try {
510 Class<?> annotationClass = Class.forName(annotationClassName);
511 if (annotationClass.isAnnotation()) {
512 return (Class<? extends Annotation>)annotationClass;
513 } else {
514 Log.e(LOG_TAG, String.format("Provided annotation value %s is not an Annotation",
515 annotationClassName));
516 }
517 } catch (ClassNotFoundException e) {
518 Log.e(LOG_TAG, String.format("Could not find class for specified annotation %s",
519 annotationClassName));
520 }
521 return null;
522 }
523
Brett Chabot31e7ce72010-07-07 17:19:08 -0700524 /**
525 * Initialize the current thread as a looper.
526 * <p/>
527 * Exposed for unit testing.
528 */
529 void prepareLooper() {
530 Looper.prepare();
531 }
532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 @Override
534 public void onStart() {
Brett Chabot31e7ce72010-07-07 17:19:08 -0700535 prepareLooper();
Jack Wangff1df692009-08-26 17:19:13 -0700536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 if (mJustCount) {
538 mResults.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
539 mResults.putInt(REPORT_KEY_NUM_TOTAL, mTestCount);
540 finish(Activity.RESULT_OK, mResults);
541 } else {
542 if (mDebug) {
543 Debug.waitForDebugger();
544 }
Jack Wangff1df692009-08-26 17:19:13 -0700545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
547 PrintStream writer = new PrintStream(byteArrayOutputStream);
548 try {
549 StringResultPrinter resultPrinter = new StringResultPrinter(writer);
Jack Wangff1df692009-08-26 17:19:13 -0700550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 mTestRunner.addTestListener(resultPrinter);
Jack Wangff1df692009-08-26 17:19:13 -0700552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 long startTime = System.currentTimeMillis();
554 mTestRunner.runTest();
555 long runTime = System.currentTimeMillis() - startTime;
Jack Wangff1df692009-08-26 17:19:13 -0700556
Brett Chabot41e173d2012-10-24 14:34:07 -0700557 resultPrinter.printResult(mTestRunner.getTestResult(), runTime);
Brett Chabot31e7ce72010-07-07 17:19:08 -0700558 } catch (Throwable t) {
559 // catch all exceptions so a more verbose error message can be outputted
560 writer.println(String.format("Test run aborted due to unexpected exception: %s",
561 t.getMessage()));
562 t.printStackTrace(writer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 } finally {
Jack Wangff1df692009-08-26 17:19:13 -0700564 mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
565 String.format("\nTest results for %s=%s",
566 mTestRunner.getTestClassName(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 byteArrayOutputStream.toString()));
568
569 if (mCoverage) {
570 generateCoverageReport();
571 }
572 writer.close();
Jack Wangff1df692009-08-26 17:19:13 -0700573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 finish(Activity.RESULT_OK, mResults);
575 }
576 }
577 }
578
579 public TestSuite getTestSuite() {
580 return getAllTests();
581 }
582
583 /**
584 * Override this to define all of the tests to run in your package.
585 */
586 public TestSuite getAllTests() {
587 return null;
588 }
589
590 /**
591 * Override this to provide access to the class loader of your package.
592 */
593 public ClassLoader getLoader() {
594 return null;
595 }
Jack Wangff1df692009-08-26 17:19:13 -0700596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 private void generateCoverageReport() {
598 // use reflection to call emma dump coverage method, to avoid
599 // always statically compiling against emma jar
Brett Chabot51e03642009-05-28 18:18:15 -0700600 String coverageFilePath = getCoverageFilePath();
601 java.io.File coverageFile = new java.io.File(coverageFilePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 try {
Brett Chabot88e03a92010-02-19 09:57:11 -0800603 Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
Jack Wangff1df692009-08-26 17:19:13 -0700604 Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 coverageFile.getClass(), boolean.class, boolean.class);
Jack Wangff1df692009-08-26 17:19:13 -0700606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 dumpCoverageMethod.invoke(null, coverageFile, false, false);
Brett Chabot51e03642009-05-28 18:18:15 -0700608 // output path to generated coverage file so it can be parsed by a test harness if
609 // needed
610 mResults.putString(REPORT_KEY_COVERAGE_PATH, coverageFilePath);
611 // also output a more user friendly msg
Brett Chabot08d13c32010-02-18 15:42:13 -0800612 final String currentStream = mResults.getString(
613 Instrumentation.REPORT_KEY_STREAMRESULT);
Brett Chabot51e03642009-05-28 18:18:15 -0700614 mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
Brett Chabot08d13c32010-02-18 15:42:13 -0800615 String.format("%s\nGenerated code coverage data to %s", currentStream,
616 coverageFilePath));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 } catch (ClassNotFoundException e) {
618 reportEmmaError("Is emma jar on classpath?", e);
619 } catch (SecurityException e) {
620 reportEmmaError(e);
621 } catch (NoSuchMethodException e) {
622 reportEmmaError(e);
623 } catch (IllegalArgumentException e) {
624 reportEmmaError(e);
625 } catch (IllegalAccessException e) {
626 reportEmmaError(e);
627 } catch (InvocationTargetException e) {
628 reportEmmaError(e);
629 }
630 }
631
632 private String getCoverageFilePath() {
633 if (mCoverageFilePath == null) {
Brett Chabot51e03642009-05-28 18:18:15 -0700634 return getTargetContext().getFilesDir().getAbsolutePath() + File.separator +
Jack Wangff1df692009-08-26 17:19:13 -0700635 DEFAULT_COVERAGE_FILE_NAME;
636 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 return mCoverageFilePath;
638 }
639 }
640
641 private void reportEmmaError(Exception e) {
Jack Wangff1df692009-08-26 17:19:13 -0700642 reportEmmaError("", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 }
644
645 private void reportEmmaError(String hint, Exception e) {
646 String msg = "Failed to generate emma coverage. " + hint;
647 Log.e(LOG_TAG, msg, e);
648 mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "\nError: " + msg);
649 }
650
651 // TODO kill this, use status() and prettyprint model for better output
652 private class StringResultPrinter extends ResultPrinter {
653
654 public StringResultPrinter(PrintStream writer) {
655 super(writer);
656 }
657
Brett Chabot41e173d2012-10-24 14:34:07 -0700658 public synchronized void printResult(TestResult result, long runTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 printHeader(runTime);
660 printFooter(result);
661 }
662 }
Jack Wangff1df692009-08-26 17:19:13 -0700663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 /**
Jack Wangff1df692009-08-26 17:19:13 -0700665 * This class sends status reports back to the IInstrumentationWatcher about
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 * which suite each test belongs.
667 */
Jack Wangff1df692009-08-26 17:19:13 -0700668 private class SuiteAssignmentPrinter implements TestListener {
669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 private Bundle mTestResult;
671 private long mStartTime;
672 private long mEndTime;
673 private boolean mTimingValid;
Jack Wangff1df692009-08-26 17:19:13 -0700674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 public SuiteAssignmentPrinter() {
676 }
Jack Wangff1df692009-08-26 17:19:13 -0700677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 /**
679 * send a status for the start of a each test, so long tests can be seen as "running"
680 */
681 public void startTest(Test test) {
682 mTimingValid = true;
Jack Wangff1df692009-08-26 17:19:13 -0700683 mStartTime = System.currentTimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 }
Jack Wangff1df692009-08-26 17:19:13 -0700685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 /**
687 * @see junit.framework.TestListener#addError(Test, Throwable)
688 */
689 public void addError(Test test, Throwable t) {
690 mTimingValid = false;
691 }
692
693 /**
694 * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
695 */
696 public void addFailure(Test test, AssertionFailedError t) {
697 mTimingValid = false;
698 }
699
700 /**
701 * @see junit.framework.TestListener#endTest(Test)
702 */
703 public void endTest(Test test) {
704 float runTime;
705 String assignmentSuite;
706 mEndTime = System.currentTimeMillis();
707 mTestResult = new Bundle();
708
709 if (!mTimingValid || mStartTime < 0) {
710 assignmentSuite = "NA";
711 runTime = -1;
712 } else {
713 runTime = mEndTime - mStartTime;
Jack Wangff1df692009-08-26 17:19:13 -0700714 if (runTime < SMALL_SUITE_MAX_RUNTIME
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 && !InstrumentationTestCase.class.isAssignableFrom(test.getClass())) {
716 assignmentSuite = SMALL_SUITE;
717 } else if (runTime < MEDIUM_SUITE_MAX_RUNTIME) {
718 assignmentSuite = MEDIUM_SUITE;
719 } else {
720 assignmentSuite = LARGE_SUITE;
721 }
722 }
723 // Clear mStartTime so that we can verify that it gets set next time.
724 mStartTime = -1;
725
Jack Wangff1df692009-08-26 17:19:13 -0700726 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
727 test.getClass().getName() + "#" + ((TestCase) test).getName()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 + "\nin " + assignmentSuite + " suite\nrunTime: "
729 + String.valueOf(runTime) + "\n");
730 mTestResult.putFloat(REPORT_KEY_RUN_TIME, runTime);
731 mTestResult.putString(REPORT_KEY_SUITE_ASSIGNMENT, assignmentSuite);
732
733 sendStatus(0, mTestResult);
734 }
735 }
Jack Wangff1df692009-08-26 17:19:13 -0700736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 /**
738 * This class sends status reports back to the IInstrumentationWatcher
739 */
Jack Wangff1df692009-08-26 17:19:13 -0700740 private class WatcherResultPrinter implements TestListener, PerformanceResultsWriter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 private final Bundle mResultTemplate;
742 Bundle mTestResult;
743 int mTestNum = 0;
744 int mTestResultCode = 0;
745 String mTestClass = null;
Jack Wang4f414bd2009-11-06 20:53:47 -0800746 PerformanceCollector mPerfCollector = new PerformanceCollector();
Jack Wangff1df692009-08-26 17:19:13 -0700747 boolean mIsTimedTest = false;
Jack Wang4f414bd2009-11-06 20:53:47 -0800748 boolean mIncludeDetailedStats = false;
Jack Wangff1df692009-08-26 17:19:13 -0700749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 public WatcherResultPrinter(int numTests) {
751 mResultTemplate = new Bundle();
752 mResultTemplate.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
753 mResultTemplate.putInt(REPORT_KEY_NUM_TOTAL, numTests);
754 }
Jack Wangff1df692009-08-26 17:19:13 -0700755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 /**
Jack Wangff1df692009-08-26 17:19:13 -0700757 * send a status for the start of a each test, so long tests can be seen
758 * as "running"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 */
760 public void startTest(Test test) {
761 String testClass = test.getClass().getName();
Jack Wangff1df692009-08-26 17:19:13 -0700762 String testName = ((TestCase)test).getName();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 mTestResult = new Bundle(mResultTemplate);
764 mTestResult.putString(REPORT_KEY_NAME_CLASS, testClass);
Jack Wangff1df692009-08-26 17:19:13 -0700765 mTestResult.putString(REPORT_KEY_NAME_TEST, testName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 mTestResult.putInt(REPORT_KEY_NUM_CURRENT, ++mTestNum);
767 // pretty printing
768 if (testClass != null && !testClass.equals(mTestClass)) {
Jack Wangff1df692009-08-26 17:19:13 -0700769 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 String.format("\n%s:", testClass));
771 mTestClass = testClass;
772 } else {
773 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "");
774 }
775
Jack Wang3fc03e62010-10-19 15:13:07 -0700776 Method testMethod = null;
777 try {
778 testMethod = test.getClass().getMethod(testName);
779 // Report total number of iterations, if test is repetitive
780 if (testMethod.isAnnotationPresent(RepetitiveTest.class)) {
781 int numIterations = testMethod.getAnnotation(
782 RepetitiveTest.class).numIterations();
783 mTestResult.putInt(REPORT_KEY_NUM_ITERATIONS, numIterations);
784 }
785 } catch (NoSuchMethodException e) {
786 // ignore- the test with given name does not exist. Will be handled during test
787 // execution
788 }
789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 // The delay_msec parameter is normally used to provide buffers of idle time
Jack Wangff1df692009-08-26 17:19:13 -0700791 // for power measurement purposes. To make sure there is a delay before and after
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 // every test in a suite, we delay *after* every test (see endTest below) and also
Jack Wangff1df692009-08-26 17:19:13 -0700793 // delay *before* the first test. So, delay test1 delay test2 delay.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794
795 try {
796 if (mTestNum == 1) Thread.sleep(mDelayMsec);
797 } catch (InterruptedException e) {
798 throw new IllegalStateException(e);
799 }
800
801 sendStatus(REPORT_VALUE_RESULT_START, mTestResult);
802 mTestResultCode = 0;
Jack Wangff1df692009-08-26 17:19:13 -0700803
804 mIsTimedTest = false;
Jack Wang4f414bd2009-11-06 20:53:47 -0800805 mIncludeDetailedStats = false;
Jack Wangff1df692009-08-26 17:19:13 -0700806 try {
Jack Wang4f414bd2009-11-06 20:53:47 -0800807 // Look for TimedTest annotation on both test class and test method
Brian Muramatsu48983952010-11-17 12:28:51 -0800808 if (testMethod != null && testMethod.isAnnotationPresent(TimedTest.class)) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800809 mIsTimedTest = true;
Jack Wang3fc03e62010-10-19 15:13:07 -0700810 mIncludeDetailedStats = testMethod.getAnnotation(
Jack Wang4f414bd2009-11-06 20:53:47 -0800811 TimedTest.class).includeDetailedStats();
812 } else if (test.getClass().isAnnotationPresent(TimedTest.class)) {
813 mIsTimedTest = true;
814 mIncludeDetailedStats = test.getClass().getAnnotation(
815 TimedTest.class).includeDetailedStats();
816 }
Jack Wangff1df692009-08-26 17:19:13 -0700817 } catch (SecurityException e) {
Brett Chabot31e7ce72010-07-07 17:19:08 -0700818 // ignore - the test with given name cannot be accessed. Will be handled during
819 // test execution
Jack Wangff1df692009-08-26 17:19:13 -0700820 }
821
Jack Wang4f414bd2009-11-06 20:53:47 -0800822 if (mIsTimedTest && mIncludeDetailedStats) {
823 mPerfCollector.beginSnapshot("");
824 } else if (mIsTimedTest) {
825 mPerfCollector.startTiming("");
Jack Wangff1df692009-08-26 17:19:13 -0700826 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 }
Jack Wangff1df692009-08-26 17:19:13 -0700828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 /**
830 * @see junit.framework.TestListener#addError(Test, Throwable)
831 */
832 public void addError(Test test, Throwable t) {
833 mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
834 mTestResultCode = REPORT_VALUE_RESULT_ERROR;
835 // pretty printing
Jack Wangff1df692009-08-26 17:19:13 -0700836 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
837 String.format("\nError in %s:\n%s",
838 ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 }
840
841 /**
842 * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
843 */
844 public void addFailure(Test test, AssertionFailedError t) {
845 mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
846 mTestResultCode = REPORT_VALUE_RESULT_FAILURE;
847 // pretty printing
Jack Wangff1df692009-08-26 17:19:13 -0700848 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
849 String.format("\nFailure in %s:\n%s",
850 ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 }
852
853 /**
854 * @see junit.framework.TestListener#endTest(Test)
855 */
856 public void endTest(Test test) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800857 if (mIsTimedTest && mIncludeDetailedStats) {
858 mTestResult.putAll(mPerfCollector.endSnapshot());
859 } else if (mIsTimedTest) {
860 writeStopTiming(mPerfCollector.stopTiming(""));
Jack Wangff1df692009-08-26 17:19:13 -0700861 }
862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 if (mTestResultCode == 0) {
864 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, ".");
865 }
866 sendStatus(mTestResultCode, mTestResult);
867
Jack Wangff1df692009-08-26 17:19:13 -0700868 try { // Sleep after every test, if specified
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 Thread.sleep(mDelayMsec);
870 } catch (InterruptedException e) {
871 throw new IllegalStateException(e);
872 }
873 }
874
Jack Wangff1df692009-08-26 17:19:13 -0700875 public void writeBeginSnapshot(String label) {
876 // Do nothing
877 }
878
879 public void writeEndSnapshot(Bundle results) {
Jack Wang075997f2009-10-27 22:01:09 -0700880 // Copy all snapshot data fields into mResults, which is outputted
881 // via Instrumentation.finish
882 mResults.putAll(results);
Jack Wangff1df692009-08-26 17:19:13 -0700883 }
884
885 public void writeStartTiming(String label) {
886 // Do nothing
887 }
888
889 public void writeStopTiming(Bundle results) {
890 // Copy results into mTestResult by flattening list of iterations,
891 // which is outputted via WatcherResultPrinter.endTest
892 int i = 0;
893 for (Parcelable p :
894 results.getParcelableArrayList(PerformanceCollector.METRIC_KEY_ITERATIONS)) {
895 Bundle iteration = (Bundle)p;
Jack Wang4f414bd2009-11-06 20:53:47 -0800896 String index = "iteration" + i + ".";
Jack Wangff1df692009-08-26 17:19:13 -0700897 mTestResult.putString(index + PerformanceCollector.METRIC_KEY_LABEL,
898 iteration.getString(PerformanceCollector.METRIC_KEY_LABEL));
899 mTestResult.putLong(index + PerformanceCollector.METRIC_KEY_CPU_TIME,
900 iteration.getLong(PerformanceCollector.METRIC_KEY_CPU_TIME));
901 mTestResult.putLong(index + PerformanceCollector.METRIC_KEY_EXECUTION_TIME,
902 iteration.getLong(PerformanceCollector.METRIC_KEY_EXECUTION_TIME));
903 i++;
904 }
905 }
906
Jack Wang075997f2009-10-27 22:01:09 -0700907 public void writeMeasurement(String label, long value) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800908 mTestResult.putLong(label, value);
Jack Wang075997f2009-10-27 22:01:09 -0700909 }
910
911 public void writeMeasurement(String label, float value) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800912 mTestResult.putFloat(label, value);
Jack Wang075997f2009-10-27 22:01:09 -0700913 }
914
915 public void writeMeasurement(String label, String value) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800916 mTestResult.putString(label, value);
Jack Wang075997f2009-10-27 22:01:09 -0700917 }
918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 // TODO report the end of the cycle
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 }
921}