blob: 249fd313d359c0442f45f07b6e369797ad167bbc [file] [log] [blame]
[email protected]fbe29322013-07-09 09:03:261#!/usr/bin/env python
2#
3# Copyright 2013 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
[email protected]181a5c92013-09-06 17:11:467"""Runs all types of tests from one unified interface."""
[email protected]fbe29322013-07-09 09:03:268
9import collections
[email protected]f7148dd42013-08-20 14:24:5710import logging
[email protected]fbe29322013-07-09 09:03:2611import optparse
12import os
[email protected]6bc1bda22013-07-19 22:08:3713import shutil
[email protected]fbe29322013-07-09 09:03:2614import sys
15
[email protected]f7148dd42013-08-20 14:24:5716from pylib import android_commands
[email protected]fbe29322013-07-09 09:03:2617from pylib import constants
18from pylib import ports
19from pylib.base import base_test_result
[email protected]6bc1bda22013-07-19 22:08:3720from pylib.base import test_dispatcher
[email protected]6bc1bda22013-07-19 22:08:3721from pylib.gtest import gtest_config
[email protected]2a684222013-08-01 16:59:2222from pylib.gtest import setup as gtest_setup
23from pylib.gtest import test_options as gtest_test_options
[email protected]6b6abac6d2013-10-03 11:56:3824from pylib.linker import setup as linker_setup
[email protected]37ee0c792013-08-06 19:10:1325from pylib.host_driven import setup as host_driven_setup
[email protected]6bc1bda22013-07-19 22:08:3726from pylib.instrumentation import setup as instrumentation_setup
[email protected]2a684222013-08-01 16:59:2227from pylib.instrumentation import test_options as instrumentation_test_options
[email protected]3dbdfa42013-08-08 01:08:1428from pylib.monkey import setup as monkey_setup
29from pylib.monkey import test_options as monkey_test_options
[email protected]ec3170b2013-08-14 14:39:4730from pylib.perf import setup as perf_setup
31from pylib.perf import test_options as perf_test_options
32from pylib.perf import test_runner as perf_test_runner
[email protected]6bc1bda22013-07-19 22:08:3733from pylib.uiautomator import setup as uiautomator_setup
[email protected]2a684222013-08-01 16:59:2234from pylib.uiautomator import test_options as uiautomator_test_options
[email protected]803f65a72013-08-20 19:11:3035from pylib.utils import command_option_parser
[email protected]6bc1bda22013-07-19 22:08:3736from pylib.utils import report_results
37from pylib.utils import run_tests_helper
[email protected]fbe29322013-07-09 09:03:2638
39
[email protected]fbe29322013-07-09 09:03:2640def AddCommonOptions(option_parser):
41 """Adds all common options to |option_parser|."""
42
[email protected]dfffbcbc2013-09-17 22:06:0143 group = optparse.OptionGroup(option_parser, 'Common Options')
44 default_build_type = os.environ.get('BUILDTYPE', 'Debug')
45 group.add_option('--debug', action='store_const', const='Debug',
46 dest='build_type', default=default_build_type,
47 help=('If set, run test suites under out/Debug. '
48 'Default is env var BUILDTYPE or Debug.'))
49 group.add_option('--release', action='store_const',
50 const='Release', dest='build_type',
51 help=('If set, run test suites under out/Release.'
52 ' Default is env var BUILDTYPE or Debug.'))
53 group.add_option('-c', dest='cleanup_test_files',
54 help='Cleanup test files on the device after run',
55 action='store_true')
56 group.add_option('--num_retries', dest='num_retries', type='int',
57 default=2,
58 help=('Number of retries for a test before '
59 'giving up.'))
60 group.add_option('-v',
61 '--verbose',
62 dest='verbose_count',
63 default=0,
64 action='count',
65 help='Verbose level (multiple times for more)')
66 group.add_option('--tool',
67 dest='tool',
68 help=('Run the test under a tool '
69 '(use --tool help to list them)'))
70 group.add_option('--flakiness-dashboard-server',
71 dest='flakiness_dashboard_server',
72 help=('Address of the server that is hosting the '
73 'Chrome for Android flakiness dashboard.'))
74 group.add_option('--skip-deps-push', dest='push_deps',
75 action='store_false', default=True,
76 help=('Do not push dependencies to the device. '
77 'Use this at own risk for speeding up test '
78 'execution on local machine.'))
79 group.add_option('-d', '--device', dest='test_device',
80 help=('Target device for the test suite '
81 'to run on.'))
82 option_parser.add_option_group(group)
[email protected]fbe29322013-07-09 09:03:2683
84
85def ProcessCommonOptions(options):
86 """Processes and handles all common options."""
[email protected]fbe29322013-07-09 09:03:2687 run_tests_helper.SetLogLevel(options.verbose_count)
[email protected]14b3b1202013-08-15 22:25:2888 constants.SetBuildType(options.build_type)
[email protected]fbe29322013-07-09 09:03:2689
90
[email protected]fbe29322013-07-09 09:03:2691def AddGTestOptions(option_parser):
92 """Adds gtest options to |option_parser|."""
93
94 option_parser.usage = '%prog gtest [options]'
[email protected]dfffbcbc2013-09-17 22:06:0195 option_parser.commands_dict = {}
[email protected]fbe29322013-07-09 09:03:2696 option_parser.example = '%prog gtest -s base_unittests'
97
[email protected]6bc1bda22013-07-19 22:08:3798 # TODO(gkanwar): Make this option required
99 option_parser.add_option('-s', '--suite', dest='suite_name',
[email protected]fbe29322013-07-09 09:03:26100 help=('Executable name of the test suite to run '
101 '(use -s help to list them).'))
[email protected]dfffbcbc2013-09-17 22:06:01102 option_parser.add_option('-f', '--gtest-filter', dest='test_filter',
[email protected]9e689252013-07-30 20:14:36103 help='googletest-style filter string.')
[email protected]dfffbcbc2013-09-17 22:06:01104 option_parser.add_option('--gtest-also-run-disabled-tests',
105 dest='run_disabled', action='store_true',
106 help='Also run disabled tests if applicable.')
107 option_parser.add_option('-a', '--test-arguments', dest='test_arguments',
108 default='',
[email protected]9e689252013-07-30 20:14:36109 help='Additional arguments to pass to the test.')
110 option_parser.add_option('-t', dest='timeout',
111 help='Timeout to wait for each test',
112 type='int',
113 default=60)
[email protected]fbe29322013-07-09 09:03:26114 # TODO(gkanwar): Move these to Common Options once we have the plumbing
115 # in our other test types to handle these commands
[email protected]fbe29322013-07-09 09:03:26116 AddCommonOptions(option_parser)
117
118
[email protected]6b6abac6d2013-10-03 11:56:38119def AddLinkerTestOptions(option_parser):
120 option_parser.usage = '%prog linker'
121 option_parser.commands_dict = {}
122 option_parser.example = '%prog linker'
123
124 AddCommonOptions(option_parser)
125
126
[email protected]6bc1bda22013-07-19 22:08:37127def ProcessGTestOptions(options):
128 """Intercept test suite help to list test suites.
129
130 Args:
131 options: Command line options.
[email protected]6bc1bda22013-07-19 22:08:37132 """
133 if options.suite_name == 'help':
134 print 'Available test suites are:'
[email protected]9e689252013-07-30 20:14:36135 for test_suite in (gtest_config.STABLE_TEST_SUITES +
136 gtest_config.EXPERIMENTAL_TEST_SUITES):
137 print test_suite
[email protected]2a684222013-08-01 16:59:22138 sys.exit(0)
[email protected]6bc1bda22013-07-19 22:08:37139
140 # Convert to a list, assuming all test suites if nothing was specified.
141 # TODO(gkanwar): Require having a test suite
142 if options.suite_name:
143 options.suite_name = [options.suite_name]
144 else:
[email protected]9e689252013-07-30 20:14:36145 options.suite_name = [s for s in gtest_config.STABLE_TEST_SUITES]
[email protected]6bc1bda22013-07-19 22:08:37146
147
[email protected]fbe29322013-07-09 09:03:26148def AddJavaTestOptions(option_parser):
149 """Adds the Java test options to |option_parser|."""
150
[email protected]dfffbcbc2013-09-17 22:06:01151 option_parser.add_option('-f', '--test-filter', dest='test_filter',
[email protected]fbe29322013-07-09 09:03:26152 help=('Test filter (if not fully qualified, '
153 'will run all matches).'))
154 option_parser.add_option(
155 '-A', '--annotation', dest='annotation_str',
156 help=('Comma-separated list of annotations. Run only tests with any of '
157 'the given annotations. An annotation can be either a key or a '
158 'key-values pair. A test that has no annotation is considered '
159 '"SmallTest".'))
160 option_parser.add_option(
161 '-E', '--exclude-annotation', dest='exclude_annotation_str',
162 help=('Comma-separated list of annotations. Exclude tests with these '
163 'annotations.'))
[email protected]fbe29322013-07-09 09:03:26164 option_parser.add_option('--screenshot', dest='screenshot_failures',
165 action='store_true',
166 help='Capture screenshots of test failures')
167 option_parser.add_option('--save-perf-json', action='store_true',
168 help='Saves the JSON file for each UI Perf test.')
[email protected]37ee0c792013-08-06 19:10:13169 option_parser.add_option('--official-build', action='store_true',
170 help='Run official build tests.')
[email protected]fbe29322013-07-09 09:03:26171 option_parser.add_option('--keep_test_server_ports',
172 action='store_true',
173 help=('Indicates the test server ports must be '
174 'kept. When this is run via a sharder '
175 'the test server ports should be kept and '
176 'should not be reset.'))
[email protected]fbe29322013-07-09 09:03:26177 option_parser.add_option('--test_data', action='append', default=[],
178 help=('Each instance defines a directory of test '
179 'data that should be copied to the target(s) '
180 'before running the tests. The argument '
181 'should be of the form <target>:<source>, '
182 '<target> is relative to the device data'
183 'directory, and <source> is relative to the '
184 'chromium build directory.'))
185
186
187def ProcessJavaTestOptions(options, error_func):
188 """Processes options/arguments and populates |options| with defaults."""
189
[email protected]fbe29322013-07-09 09:03:26190 if options.annotation_str:
191 options.annotations = options.annotation_str.split(',')
192 elif options.test_filter:
193 options.annotations = []
194 else:
[email protected]6bc1bda22013-07-19 22:08:37195 options.annotations = ['Smoke', 'SmallTest', 'MediumTest', 'LargeTest',
196 'EnormousTest']
[email protected]fbe29322013-07-09 09:03:26197
198 if options.exclude_annotation_str:
199 options.exclude_annotations = options.exclude_annotation_str.split(',')
200 else:
201 options.exclude_annotations = []
202
203 if not options.keep_test_server_ports:
204 if not ports.ResetTestServerPortAllocation():
205 raise Exception('Failed to reset test server port.')
206
207
208def AddInstrumentationTestOptions(option_parser):
209 """Adds Instrumentation test options to |option_parser|."""
210
211 option_parser.usage = '%prog instrumentation [options]'
[email protected]dfffbcbc2013-09-17 22:06:01212 option_parser.commands_dict = {}
[email protected]fb7ab5e82013-07-26 18:31:20213 option_parser.example = ('%prog instrumentation '
[email protected]fbe29322013-07-09 09:03:26214 '--test-apk=ChromiumTestShellTest')
215
216 AddJavaTestOptions(option_parser)
217 AddCommonOptions(option_parser)
218
[email protected]dfffbcbc2013-09-17 22:06:01219 option_parser.add_option('-j', '--java-only', action='store_true',
[email protected]37ee0c792013-08-06 19:10:13220 default=False, help='Run only the Java tests.')
[email protected]dfffbcbc2013-09-17 22:06:01221 option_parser.add_option('-p', '--python-only', action='store_true',
[email protected]37ee0c792013-08-06 19:10:13222 default=False,
223 help='Run only the host-driven tests.')
[email protected]a69e85bc2013-08-16 18:07:26224 option_parser.add_option('--host-driven-root',
[email protected]37ee0c792013-08-06 19:10:13225 help='Root of the host-driven tests.')
[email protected]fbe29322013-07-09 09:03:26226 option_parser.add_option('-w', '--wait_debugger', dest='wait_for_debugger',
227 action='store_true',
228 help='Wait for debugger.')
[email protected]fbe29322013-07-09 09:03:26229 option_parser.add_option(
230 '--test-apk', dest='test_apk',
231 help=('The name of the apk containing the tests '
[email protected]ae68d4a2013-09-24 21:57:15232 '(without the .apk extension; e.g. "ContentShellTest").'))
[email protected]803f65a72013-08-20 19:11:30233 option_parser.add_option('--coverage-dir',
234 help=('Directory in which to place all generated '
235 'EMMA coverage files.'))
[email protected]fbe29322013-07-09 09:03:26236
237
238def ProcessInstrumentationOptions(options, error_func):
[email protected]2a684222013-08-01 16:59:22239 """Processes options/arguments and populate |options| with defaults.
240
241 Args:
242 options: optparse.Options object.
243 error_func: Function to call with the error message in case of an error.
244
245 Returns:
246 An InstrumentationOptions named tuple which contains all options relevant to
247 instrumentation tests.
248 """
[email protected]fbe29322013-07-09 09:03:26249
250 ProcessJavaTestOptions(options, error_func)
251
[email protected]37ee0c792013-08-06 19:10:13252 if options.java_only and options.python_only:
253 error_func('Options java_only (-j) and python_only (-p) '
254 'are mutually exclusive.')
255 options.run_java_tests = True
256 options.run_python_tests = True
257 if options.java_only:
258 options.run_python_tests = False
259 elif options.python_only:
260 options.run_java_tests = False
261
[email protected]67954f822013-08-14 18:09:08262 if not options.host_driven_root:
[email protected]37ee0c792013-08-06 19:10:13263 options.run_python_tests = False
264
[email protected]fbe29322013-07-09 09:03:26265 if not options.test_apk:
266 error_func('--test-apk must be specified.')
267
[email protected]ae68d4a2013-09-24 21:57:15268
269 options.test_apk_path = os.path.join(constants.GetOutDirectory(),
270 constants.SDK_BUILD_APKS_DIR,
271 '%s.apk' % options.test_apk)
272 options.test_apk_jar_path = os.path.join(
273 constants.GetOutDirectory(),
274 constants.SDK_BUILD_TEST_JAVALIB_DIR,
275 '%s.jar' % options.test_apk)
[email protected]fbe29322013-07-09 09:03:26276
[email protected]2a684222013-08-01 16:59:22277 return instrumentation_test_options.InstrumentationOptions(
[email protected]2a684222013-08-01 16:59:22278 options.tool,
279 options.cleanup_test_files,
280 options.push_deps,
281 options.annotations,
282 options.exclude_annotations,
283 options.test_filter,
284 options.test_data,
285 options.save_perf_json,
286 options.screenshot_failures,
[email protected]2a684222013-08-01 16:59:22287 options.wait_for_debugger,
[email protected]803f65a72013-08-20 19:11:30288 options.coverage_dir,
[email protected]2a684222013-08-01 16:59:22289 options.test_apk,
290 options.test_apk_path,
291 options.test_apk_jar_path)
292
[email protected]fbe29322013-07-09 09:03:26293
294def AddUIAutomatorTestOptions(option_parser):
295 """Adds UI Automator test options to |option_parser|."""
296
297 option_parser.usage = '%prog uiautomator [options]'
[email protected]dfffbcbc2013-09-17 22:06:01298 option_parser.commands_dict = {}
[email protected]fbe29322013-07-09 09:03:26299 option_parser.example = (
300 '%prog uiautomator --test-jar=chromium_testshell_uiautomator_tests'
301 ' --package-name=org.chromium.chrome.testshell')
302 option_parser.add_option(
303 '--package-name',
304 help='The package name used by the apk containing the application.')
305 option_parser.add_option(
306 '--test-jar', dest='test_jar',
307 help=('The name of the dexed jar containing the tests (without the '
308 '.dex.jar extension). Alternatively, this can be a full path '
309 'to the jar.'))
310
311 AddJavaTestOptions(option_parser)
312 AddCommonOptions(option_parser)
313
314
315def ProcessUIAutomatorOptions(options, error_func):
[email protected]2a684222013-08-01 16:59:22316 """Processes UIAutomator options/arguments.
317
318 Args:
319 options: optparse.Options object.
320 error_func: Function to call with the error message in case of an error.
321
322 Returns:
323 A UIAutomatorOptions named tuple which contains all options relevant to
[email protected]3dbdfa42013-08-08 01:08:14324 uiautomator tests.
[email protected]2a684222013-08-01 16:59:22325 """
[email protected]fbe29322013-07-09 09:03:26326
327 ProcessJavaTestOptions(options, error_func)
328
329 if not options.package_name:
330 error_func('--package-name must be specified.')
331
332 if not options.test_jar:
333 error_func('--test-jar must be specified.')
334
335 if os.path.exists(options.test_jar):
336 # The dexed JAR is fully qualified, assume the info JAR lives along side.
337 options.uiautomator_jar = options.test_jar
338 else:
339 options.uiautomator_jar = os.path.join(
[email protected]ae68d4a2013-09-24 21:57:15340 constants.GetOutDirectory(),
341 constants.SDK_BUILD_JAVALIB_DIR,
[email protected]fbe29322013-07-09 09:03:26342 '%s.dex.jar' % options.test_jar)
343 options.uiautomator_info_jar = (
344 options.uiautomator_jar[:options.uiautomator_jar.find('.dex.jar')] +
345 '_java.jar')
346
[email protected]2a684222013-08-01 16:59:22347 return uiautomator_test_options.UIAutomatorOptions(
[email protected]2a684222013-08-01 16:59:22348 options.tool,
349 options.cleanup_test_files,
350 options.push_deps,
351 options.annotations,
352 options.exclude_annotations,
353 options.test_filter,
354 options.test_data,
355 options.save_perf_json,
356 options.screenshot_failures,
[email protected]2a684222013-08-01 16:59:22357 options.uiautomator_jar,
358 options.uiautomator_info_jar,
359 options.package_name)
360
[email protected]fbe29322013-07-09 09:03:26361
[email protected]3dbdfa42013-08-08 01:08:14362def AddMonkeyTestOptions(option_parser):
363 """Adds monkey test options to |option_parser|."""
[email protected]fb81b982013-08-09 00:07:12364
365 option_parser.usage = '%prog monkey [options]'
[email protected]dfffbcbc2013-09-17 22:06:01366 option_parser.commands_dict = {}
[email protected]fb81b982013-08-09 00:07:12367 option_parser.example = (
368 '%prog monkey --package-name=org.chromium.content_shell_apk'
369 ' --activity-name=.ContentShellActivity')
370
[email protected]3dbdfa42013-08-08 01:08:14371 option_parser.add_option('--package-name', help='Allowed package.')
372 option_parser.add_option(
[email protected]fb81b982013-08-09 00:07:12373 '--activity-name', help='Name of the activity to start.')
[email protected]3dbdfa42013-08-08 01:08:14374 option_parser.add_option(
375 '--event-count', default=10000, type='int',
376 help='Number of events to generate [default: %default].')
377 option_parser.add_option(
378 '--category', default='',
[email protected]fb81b982013-08-09 00:07:12379 help='A list of allowed categories.')
[email protected]3dbdfa42013-08-08 01:08:14380 option_parser.add_option(
381 '--throttle', default=100, type='int',
382 help='Delay between events (ms) [default: %default]. ')
383 option_parser.add_option(
384 '--seed', type='int',
385 help=('Seed value for pseudo-random generator. Same seed value generates '
386 'the same sequence of events. Seed is randomized by default.'))
387 option_parser.add_option(
388 '--extra-args', default='',
389 help=('String of other args to pass to the command verbatim '
390 '[default: "%default"].'))
391
392 AddCommonOptions(option_parser)
393
394
395def ProcessMonkeyTestOptions(options, error_func):
396 """Processes all monkey test options.
397
398 Args:
399 options: optparse.Options object.
400 error_func: Function to call with the error message in case of an error.
401
402 Returns:
403 A MonkeyOptions named tuple which contains all options relevant to
404 monkey tests.
405 """
406 if not options.package_name:
407 error_func('Package name is required.')
408
409 category = options.category
410 if category:
411 category = options.category.split(',')
412
413 return monkey_test_options.MonkeyOptions(
[email protected]3dbdfa42013-08-08 01:08:14414 options.verbose_count,
415 options.package_name,
416 options.activity_name,
417 options.event_count,
418 category,
419 options.throttle,
420 options.seed,
421 options.extra_args)
422
423
[email protected]ec3170b2013-08-14 14:39:47424def AddPerfTestOptions(option_parser):
425 """Adds perf test options to |option_parser|."""
426
427 option_parser.usage = '%prog perf [options]'
[email protected]dfffbcbc2013-09-17 22:06:01428 option_parser.commands_dict = {}
[email protected]ec3170b2013-08-14 14:39:47429 option_parser.example = ('%prog perf --steps perf_steps.json')
430
[email protected]181a5c92013-09-06 17:11:46431 option_parser.add_option(
432 '--steps',
433 help='JSON file containing the list of perf steps to run.')
434 option_parser.add_option(
435 '--flaky-steps',
436 help=('A JSON file containing steps that are flaky '
437 'and will have its exit code ignored.'))
438 option_parser.add_option(
439 '--print-step',
440 help='The name of a previously executed perf step to print.')
441 option_parser.add_option(
442 '--no-timeout', action='store_true',
443 help=('Do not impose a timeout. Each perf step is responsible for '
444 'implementing the timeout logic.'))
[email protected]650487c2013-09-30 11:40:49445 option_parser.add_option(
446 '-f', '--test-filter',
447 help=('Test filter (will match against the names listed in --steps).'))
448 option_parser.add_option(
449 '--dry-run',
450 action='store_true',
451 help='Just print the steps without executing.')
[email protected]ec3170b2013-08-14 14:39:47452 AddCommonOptions(option_parser)
453
454
455def ProcessPerfTestOptions(options, error_func):
456 """Processes all perf test options.
457
458 Args:
459 options: optparse.Options object.
460 error_func: Function to call with the error message in case of an error.
461
462 Returns:
463 A PerfOptions named tuple which contains all options relevant to
464 perf tests.
465 """
466 if not options.steps and not options.print_step:
467 error_func('Please specify --steps or --print-step')
468 return perf_test_options.PerfOptions(
[email protected]181a5c92013-09-06 17:11:46469 options.steps, options.flaky_steps, options.print_step,
[email protected]650487c2013-09-30 11:40:49470 options.no_timeout, options.test_filter, options.dry_run)
[email protected]ec3170b2013-08-14 14:39:47471
472
[email protected]f7148dd42013-08-20 14:24:57473def _RunGTests(options, error_func, devices):
[email protected]6bc1bda22013-07-19 22:08:37474 """Subcommand of RunTestsCommands which runs gtests."""
[email protected]2a684222013-08-01 16:59:22475 ProcessGTestOptions(options)
[email protected]6bc1bda22013-07-19 22:08:37476
477 exit_code = 0
478 for suite_name in options.suite_name:
[email protected]2a684222013-08-01 16:59:22479 # TODO(gkanwar): Move this into ProcessGTestOptions once we require -s for
480 # the gtest command.
481 gtest_options = gtest_test_options.GTestOptions(
[email protected]2a684222013-08-01 16:59:22482 options.tool,
483 options.cleanup_test_files,
484 options.push_deps,
485 options.test_filter,
[email protected]dfffbcbc2013-09-17 22:06:01486 options.run_disabled,
[email protected]2a684222013-08-01 16:59:22487 options.test_arguments,
488 options.timeout,
489 suite_name)
[email protected]f7148dd42013-08-20 14:24:57490 runner_factory, tests = gtest_setup.Setup(gtest_options, devices)
[email protected]6bc1bda22013-07-19 22:08:37491
492 results, test_exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57493 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]6bc1bda22013-07-19 22:08:37494 num_retries=options.num_retries)
495
496 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE:
497 exit_code = test_exit_code
498
499 report_results.LogFull(
500 results=results,
501 test_type='Unit test',
502 test_package=suite_name,
[email protected]6bc1bda22013-07-19 22:08:37503 flakiness_server=options.flakiness_dashboard_server)
504
505 if os.path.isdir(constants.ISOLATE_DEPS_DIR):
506 shutil.rmtree(constants.ISOLATE_DEPS_DIR)
507
508 return exit_code
509
510
[email protected]6b6abac6d2013-10-03 11:56:38511def _RunLinkerTests(options, error_func, devices):
512 """Subcommand of RunTestsCommands which runs linker tests."""
513 runner_factory, tests = linker_setup.Setup(options, devices)
514
515 results, exit_code = test_dispatcher.RunTests(
516 tests, runner_factory, devices, shard=True, test_timeout=60,
517 num_retries=options.num_retries)
518
519 report_results.LogFull(
520 results=results,
521 test_type='Linker test',
522 test_package='ContentLinkerTest')
523
524 return exit_code
525
526
[email protected]f7148dd42013-08-20 14:24:57527def _RunInstrumentationTests(options, error_func, devices):
[email protected]6bc1bda22013-07-19 22:08:37528 """Subcommand of RunTestsCommands which runs instrumentation tests."""
[email protected]2a684222013-08-01 16:59:22529 instrumentation_options = ProcessInstrumentationOptions(options, error_func)
[email protected]6bc1bda22013-07-19 22:08:37530
[email protected]f7148dd42013-08-20 14:24:57531 if len(devices) > 1 and options.wait_for_debugger:
532 logging.warning('Debugger can not be sharded, using first available device')
533 devices = devices[:1]
534
[email protected]6bc1bda22013-07-19 22:08:37535 results = base_test_result.TestRunResults()
536 exit_code = 0
537
538 if options.run_java_tests:
[email protected]2a684222013-08-01 16:59:22539 runner_factory, tests = instrumentation_setup.Setup(instrumentation_options)
[email protected]6bc1bda22013-07-19 22:08:37540
541 test_results, exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57542 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]6bc1bda22013-07-19 22:08:37543 num_retries=options.num_retries)
544
545 results.AddTestRunResults(test_results)
546
547 if options.run_python_tests:
[email protected]37ee0c792013-08-06 19:10:13548 runner_factory, tests = host_driven_setup.InstrumentationSetup(
[email protected]67954f822013-08-14 18:09:08549 options.host_driven_root, options.official_build,
[email protected]37ee0c792013-08-06 19:10:13550 instrumentation_options)
551
[email protected]34020022013-08-06 23:35:34552 if tests:
553 test_results, test_exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57554 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]34020022013-08-06 23:35:34555 num_retries=options.num_retries)
[email protected]6bc1bda22013-07-19 22:08:37556
[email protected]34020022013-08-06 23:35:34557 results.AddTestRunResults(test_results)
[email protected]6bc1bda22013-07-19 22:08:37558
[email protected]34020022013-08-06 23:35:34559 # Only allow exit code escalation
560 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE:
561 exit_code = test_exit_code
[email protected]6bc1bda22013-07-19 22:08:37562
563 report_results.LogFull(
564 results=results,
565 test_type='Instrumentation',
566 test_package=os.path.basename(options.test_apk),
567 annotation=options.annotations,
[email protected]6bc1bda22013-07-19 22:08:37568 flakiness_server=options.flakiness_dashboard_server)
569
570 return exit_code
571
572
[email protected]f7148dd42013-08-20 14:24:57573def _RunUIAutomatorTests(options, error_func, devices):
[email protected]6bc1bda22013-07-19 22:08:37574 """Subcommand of RunTestsCommands which runs uiautomator tests."""
[email protected]2a684222013-08-01 16:59:22575 uiautomator_options = ProcessUIAutomatorOptions(options, error_func)
[email protected]6bc1bda22013-07-19 22:08:37576
[email protected]37ee0c792013-08-06 19:10:13577 runner_factory, tests = uiautomator_setup.Setup(uiautomator_options)
[email protected]6bc1bda22013-07-19 22:08:37578
[email protected]37ee0c792013-08-06 19:10:13579 results, exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57580 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]37ee0c792013-08-06 19:10:13581 num_retries=options.num_retries)
[email protected]6bc1bda22013-07-19 22:08:37582
583 report_results.LogFull(
584 results=results,
585 test_type='UIAutomator',
586 test_package=os.path.basename(options.test_jar),
587 annotation=options.annotations,
[email protected]6bc1bda22013-07-19 22:08:37588 flakiness_server=options.flakiness_dashboard_server)
589
590 return exit_code
591
592
[email protected]f7148dd42013-08-20 14:24:57593def _RunMonkeyTests(options, error_func, devices):
[email protected]3dbdfa42013-08-08 01:08:14594 """Subcommand of RunTestsCommands which runs monkey tests."""
595 monkey_options = ProcessMonkeyTestOptions(options, error_func)
596
597 runner_factory, tests = monkey_setup.Setup(monkey_options)
598
599 results, exit_code = test_dispatcher.RunTests(
[email protected]181a5c92013-09-06 17:11:46600 tests, runner_factory, devices, shard=False, test_timeout=None,
601 num_retries=options.num_retries)
[email protected]3dbdfa42013-08-08 01:08:14602
603 report_results.LogFull(
604 results=results,
605 test_type='Monkey',
[email protected]14b3b1202013-08-15 22:25:28606 test_package='Monkey')
[email protected]3dbdfa42013-08-08 01:08:14607
608 return exit_code
609
610
[email protected]f7148dd42013-08-20 14:24:57611def _RunPerfTests(options, error_func, devices):
[email protected]ec3170b2013-08-14 14:39:47612 """Subcommand of RunTestsCommands which runs perf tests."""
613 perf_options = ProcessPerfTestOptions(options, error_func)
614 # Just print the results from a single previously executed step.
615 if perf_options.print_step:
616 return perf_test_runner.PrintTestOutput(perf_options.print_step)
617
618 runner_factory, tests = perf_setup.Setup(perf_options)
619
[email protected]86184c7b2013-08-15 15:06:57620 results, _ = test_dispatcher.RunTests(
[email protected]181a5c92013-09-06 17:11:46621 tests, runner_factory, devices, shard=True, test_timeout=None,
622 num_retries=options.num_retries)
[email protected]ec3170b2013-08-14 14:39:47623
624 report_results.LogFull(
625 results=results,
626 test_type='Perf',
[email protected]865a47a2013-08-16 14:01:12627 test_package='Perf')
[email protected]86184c7b2013-08-15 15:06:57628 # Always return 0 on the sharding stage. Individual tests exit_code
629 # will be returned on the print_step stage.
630 return 0
[email protected]ec3170b2013-08-14 14:39:47631
[email protected]3dbdfa42013-08-08 01:08:14632
[email protected]f7148dd42013-08-20 14:24:57633def _GetAttachedDevices(test_device=None):
634 """Get all attached devices.
635
636 Args:
637 test_device: Name of a specific device to use.
638
639 Returns:
640 A list of attached devices.
641 """
642 attached_devices = []
643
644 attached_devices = android_commands.GetAttachedDevices()
645 if test_device:
646 assert test_device in attached_devices, (
647 'Did not find device %s among attached device. Attached devices: %s'
648 % (test_device, ', '.join(attached_devices)))
649 attached_devices = [test_device]
650
651 assert attached_devices, 'No devices attached.'
652
653 return sorted(attached_devices)
654
655
[email protected]fbe29322013-07-09 09:03:26656def RunTestsCommand(command, options, args, option_parser):
657 """Checks test type and dispatches to the appropriate function.
658
659 Args:
660 command: String indicating the command that was received to trigger
661 this function.
662 options: optparse options dictionary.
663 args: List of extra args from optparse.
664 option_parser: optparse.OptionParser object.
665
666 Returns:
667 Integer indicated exit code.
[email protected]b3873892013-07-10 04:57:10668
669 Raises:
670 Exception: Unknown command name passed in, or an exception from an
671 individual test runner.
[email protected]fbe29322013-07-09 09:03:26672 """
673
[email protected]d82f0252013-07-12 23:22:57674 # Check for extra arguments
675 if len(args) > 2:
676 option_parser.error('Unrecognized arguments: %s' % (' '.join(args[2:])))
677 return constants.ERROR_EXIT_CODE
678
[email protected]fbe29322013-07-09 09:03:26679 ProcessCommonOptions(options)
680
[email protected]f7148dd42013-08-20 14:24:57681 devices = _GetAttachedDevices(options.test_device)
682
[email protected]fbe29322013-07-09 09:03:26683 if command == 'gtest':
[email protected]f7148dd42013-08-20 14:24:57684 return _RunGTests(options, option_parser.error, devices)
[email protected]6b6abac6d2013-10-03 11:56:38685 elif command == 'linker':
686 return _RunLinkerTests(options, option_parser.error, devices)
[email protected]fbe29322013-07-09 09:03:26687 elif command == 'instrumentation':
[email protected]f7148dd42013-08-20 14:24:57688 return _RunInstrumentationTests(options, option_parser.error, devices)
[email protected]fbe29322013-07-09 09:03:26689 elif command == 'uiautomator':
[email protected]f7148dd42013-08-20 14:24:57690 return _RunUIAutomatorTests(options, option_parser.error, devices)
[email protected]3dbdfa42013-08-08 01:08:14691 elif command == 'monkey':
[email protected]f7148dd42013-08-20 14:24:57692 return _RunMonkeyTests(options, option_parser.error, devices)
[email protected]ec3170b2013-08-14 14:39:47693 elif command == 'perf':
[email protected]f7148dd42013-08-20 14:24:57694 return _RunPerfTests(options, option_parser.error, devices)
[email protected]fbe29322013-07-09 09:03:26695 else:
[email protected]6bc1bda22013-07-19 22:08:37696 raise Exception('Unknown test type.')
[email protected]fbe29322013-07-09 09:03:26697
[email protected]fbe29322013-07-09 09:03:26698
699def HelpCommand(command, options, args, option_parser):
700 """Display help for a certain command, or overall help.
701
702 Args:
703 command: String indicating the command that was received to trigger
704 this function.
705 options: optparse options dictionary.
706 args: List of extra args from optparse.
707 option_parser: optparse.OptionParser object.
708
709 Returns:
710 Integer indicated exit code.
711 """
712 # If we don't have any args, display overall help
713 if len(args) < 3:
714 option_parser.print_help()
715 return 0
[email protected]d82f0252013-07-12 23:22:57716 # If we have too many args, print an error
717 if len(args) > 3:
718 option_parser.error('Unrecognized arguments: %s' % (' '.join(args[3:])))
719 return constants.ERROR_EXIT_CODE
[email protected]fbe29322013-07-09 09:03:26720
721 command = args[2]
722
723 if command not in VALID_COMMANDS:
724 option_parser.error('Unrecognized command.')
725
726 # Treat the help command as a special case. We don't care about showing a
727 # specific help page for itself.
728 if command == 'help':
729 option_parser.print_help()
730 return 0
731
732 VALID_COMMANDS[command].add_options_func(option_parser)
733 option_parser.usage = '%prog ' + command + ' [options]'
[email protected]dfffbcbc2013-09-17 22:06:01734 option_parser.commands_dict = {}
[email protected]fbe29322013-07-09 09:03:26735 option_parser.print_help()
736
737 return 0
738
739
740# Define a named tuple for the values in the VALID_COMMANDS dictionary so the
741# syntax is a bit prettier. The tuple is two functions: (add options, run
742# command).
743CommandFunctionTuple = collections.namedtuple(
744 'CommandFunctionTuple', ['add_options_func', 'run_command_func'])
745VALID_COMMANDS = {
746 'gtest': CommandFunctionTuple(AddGTestOptions, RunTestsCommand),
[email protected]fbe29322013-07-09 09:03:26747 'instrumentation': CommandFunctionTuple(
748 AddInstrumentationTestOptions, RunTestsCommand),
749 'uiautomator': CommandFunctionTuple(
750 AddUIAutomatorTestOptions, RunTestsCommand),
[email protected]3dbdfa42013-08-08 01:08:14751 'monkey': CommandFunctionTuple(
752 AddMonkeyTestOptions, RunTestsCommand),
[email protected]ec3170b2013-08-14 14:39:47753 'perf': CommandFunctionTuple(
754 AddPerfTestOptions, RunTestsCommand),
[email protected]6b6abac6d2013-10-03 11:56:38755 'linker': CommandFunctionTuple(
756 AddLinkerTestOptions, RunTestsCommand),
[email protected]fbe29322013-07-09 09:03:26757 'help': CommandFunctionTuple(lambda option_parser: None, HelpCommand)
758 }
759
760
[email protected]fbe29322013-07-09 09:03:26761def main(argv):
[email protected]803f65a72013-08-20 19:11:30762 option_parser = command_option_parser.CommandOptionParser(
763 commands_dict=VALID_COMMANDS)
764 return command_option_parser.ParseAndExecute(option_parser)
[email protected]fbe29322013-07-09 09:03:26765
[email protected]fbe29322013-07-09 09:03:26766
767if __name__ == '__main__':
768 sys.exit(main(sys.argv))