blob: 2e39c3c3e31f44d42cf6985ae05de614a0ee3115 [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]83bb8152013-11-19 15:02:2114import signal
[email protected]fbe29322013-07-09 09:03:2615import sys
[email protected]83bb8152013-11-19 15:02:2116import threading
jbudorick256fd532014-10-24 01:50:1317import unittest
[email protected]fbe29322013-07-09 09:03:2618
[email protected]f7148dd42013-08-20 14:24:5719from pylib import android_commands
[email protected]fbe29322013-07-09 09:03:2620from pylib import constants
[email protected]c0662e092013-11-12 11:51:2521from pylib import forwarder
[email protected]fbe29322013-07-09 09:03:2622from pylib import ports
23from pylib.base import base_test_result
jbudorick66dc3722014-11-06 21:33:5124from pylib.base import environment_factory
[email protected]6bc1bda22013-07-19 22:08:3725from pylib.base import test_dispatcher
jbudorick66dc3722014-11-06 21:33:5126from pylib.base import test_instance_factory
27from pylib.base import test_run_factory
[email protected]6bc1bda22013-07-19 22:08:3728from pylib.gtest import gtest_config
[email protected]2a684222013-08-01 16:59:2229from pylib.gtest import setup as gtest_setup
30from pylib.gtest import test_options as gtest_test_options
[email protected]6b6abac6d2013-10-03 11:56:3831from pylib.linker import setup as linker_setup
[email protected]37ee0c792013-08-06 19:10:1332from pylib.host_driven import setup as host_driven_setup
[email protected]6bc1bda22013-07-19 22:08:3733from pylib.instrumentation import setup as instrumentation_setup
[email protected]2a684222013-08-01 16:59:2234from pylib.instrumentation import test_options as instrumentation_test_options
jbudorick9a6b7b332014-09-20 00:01:0735from pylib.junit import setup as junit_setup
36from pylib.junit import test_dispatcher as junit_dispatcher
[email protected]3dbdfa42013-08-08 01:08:1437from pylib.monkey import setup as monkey_setup
38from pylib.monkey import test_options as monkey_test_options
[email protected]ec3170b2013-08-14 14:39:4739from pylib.perf import setup as perf_setup
40from pylib.perf import test_options as perf_test_options
41from pylib.perf import test_runner as perf_test_runner
[email protected]6bc1bda22013-07-19 22:08:3742from pylib.uiautomator import setup as uiautomator_setup
[email protected]2a684222013-08-01 16:59:2243from pylib.uiautomator import test_options as uiautomator_test_options
[email protected]2eea4872014-07-28 23:06:1744from pylib.utils import apk_helper
[email protected]803f65a72013-08-20 19:11:3045from pylib.utils import command_option_parser
[email protected]6bc1bda22013-07-19 22:08:3746from pylib.utils import report_results
[email protected]71aec4b2013-11-20 00:35:2447from pylib.utils import reraiser_thread
[email protected]6bc1bda22013-07-19 22:08:3748from pylib.utils import run_tests_helper
[email protected]fbe29322013-07-09 09:03:2649
50
[email protected]fbe29322013-07-09 09:03:2651def AddCommonOptions(option_parser):
52 """Adds all common options to |option_parser|."""
53
[email protected]dfffbcbc2013-09-17 22:06:0154 group = optparse.OptionGroup(option_parser, 'Common Options')
55 default_build_type = os.environ.get('BUILDTYPE', 'Debug')
56 group.add_option('--debug', action='store_const', const='Debug',
57 dest='build_type', default=default_build_type,
58 help=('If set, run test suites under out/Debug. '
59 'Default is env var BUILDTYPE or Debug.'))
60 group.add_option('--release', action='store_const',
61 const='Release', dest='build_type',
62 help=('If set, run test suites under out/Release.'
63 ' Default is env var BUILDTYPE or Debug.'))
r.kasibhatla3d57cba2014-10-09 10:55:5764 group.add_option('--build-directory', dest='build_directory',
65 help=('Path to the directory in which build files are'
66 ' located (should not include build type)'))
[email protected]dfffbcbc2013-09-17 22:06:0167 group.add_option('--num_retries', dest='num_retries', type='int',
68 default=2,
69 help=('Number of retries for a test before '
70 'giving up.'))
71 group.add_option('-v',
72 '--verbose',
73 dest='verbose_count',
74 default=0,
75 action='count',
76 help='Verbose level (multiple times for more)')
[email protected]dfffbcbc2013-09-17 22:06:0177 group.add_option('--flakiness-dashboard-server',
78 dest='flakiness_dashboard_server',
79 help=('Address of the server that is hosting the '
80 'Chrome for Android flakiness dashboard.'))
jbudorick66dc3722014-11-06 21:33:5181 group.add_option('--enable-platform-mode', action='store_true',
82 help=('Run the test scripts in platform mode, which '
83 'conceptually separates the test runner from the '
84 '"device" (local or remote, real or emulated) on '
85 'which the tests are running. [experimental]'))
86 group.add_option('-e', '--environment', default='local',
87 help=('Test environment to run in. Must be one of: %s' %
88 ', '.join(constants.VALID_ENVIRONMENTS)))
[email protected]dfffbcbc2013-09-17 22:06:0189 option_parser.add_option_group(group)
[email protected]fbe29322013-07-09 09:03:2690
91
jbudorick66dc3722014-11-06 21:33:5192def ProcessCommonOptions(options, error_func):
[email protected]fbe29322013-07-09 09:03:2693 """Processes and handles all common options."""
[email protected]fbe29322013-07-09 09:03:2694 run_tests_helper.SetLogLevel(options.verbose_count)
[email protected]14b3b1202013-08-15 22:25:2895 constants.SetBuildType(options.build_type)
r.kasibhatla3d57cba2014-10-09 10:55:5796 if options.build_directory:
97 constants.SetBuildDirectory(options.build_directory)
jbudorick66dc3722014-11-06 21:33:5198 if options.environment not in constants.VALID_ENVIRONMENTS:
99 error_func('--environment must be one of: %s' %
100 ', '.join(constants.VALID_ENVIRONMENTS))
[email protected]fbe29322013-07-09 09:03:26101
102
jbudorick256fd532014-10-24 01:50:13103def AddDeviceOptions(option_parser):
104 group = optparse.OptionGroup(option_parser, 'Device Options')
105 group.add_option('-c', dest='cleanup_test_files',
106 help='Cleanup test files on the device after run',
107 action='store_true')
108 group.add_option('--tool',
109 dest='tool',
110 help=('Run the test under a tool '
111 '(use --tool help to list them)'))
jbudorick256fd532014-10-24 01:50:13112 group.add_option('-d', '--device', dest='test_device',
113 help=('Target device for the test suite '
114 'to run on.'))
115 option_parser.add_option_group(group)
116
117
[email protected]fbe29322013-07-09 09:03:26118def AddGTestOptions(option_parser):
119 """Adds gtest options to |option_parser|."""
120
121 option_parser.usage = '%prog gtest [options]'
[email protected]dfffbcbc2013-09-17 22:06:01122 option_parser.commands_dict = {}
[email protected]fbe29322013-07-09 09:03:26123 option_parser.example = '%prog gtest -s base_unittests'
124
[email protected]6bc1bda22013-07-19 22:08:37125 # TODO(gkanwar): Make this option required
126 option_parser.add_option('-s', '--suite', dest='suite_name',
[email protected]fbe29322013-07-09 09:03:26127 help=('Executable name of the test suite to run '
128 '(use -s help to list them).'))
[email protected]c53dc4332013-11-20 04:38:03129 option_parser.add_option('-f', '--gtest_filter', '--gtest-filter',
130 dest='test_filter',
[email protected]9e689252013-07-30 20:14:36131 help='googletest-style filter string.')
[email protected]c53dc4332013-11-20 04:38:03132 option_parser.add_option('--gtest_also_run_disabled_tests',
133 '--gtest-also-run-disabled-tests',
[email protected]dfffbcbc2013-09-17 22:06:01134 dest='run_disabled', action='store_true',
135 help='Also run disabled tests if applicable.')
136 option_parser.add_option('-a', '--test-arguments', dest='test_arguments',
137 default='',
[email protected]9e689252013-07-30 20:14:36138 help='Additional arguments to pass to the test.')
139 option_parser.add_option('-t', dest='timeout',
140 help='Timeout to wait for each test',
141 type='int',
142 default=60)
[email protected]5b8b8742014-05-22 08:18:50143 option_parser.add_option('--isolate_file_path',
144 '--isolate-file-path',
145 dest='isolate_file_path',
146 help='.isolate file path to override the default '
147 'path')
[email protected]fbe29322013-07-09 09:03:26148 # TODO(gkanwar): Move these to Common Options once we have the plumbing
149 # in our other test types to handle these commands
[email protected]fbe29322013-07-09 09:03:26150 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13151 AddDeviceOptions(option_parser)
[email protected]fbe29322013-07-09 09:03:26152
153
[email protected]6b6abac6d2013-10-03 11:56:38154def AddLinkerTestOptions(option_parser):
155 option_parser.usage = '%prog linker'
156 option_parser.commands_dict = {}
157 option_parser.example = '%prog linker'
158
[email protected]98c4feef2013-10-08 01:19:05159 option_parser.add_option('-f', '--gtest-filter', dest='test_filter',
160 help='googletest-style filter string.')
[email protected]6b6abac6d2013-10-03 11:56:38161 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13162 AddDeviceOptions(option_parser)
[email protected]6b6abac6d2013-10-03 11:56:38163
164
[email protected]6bc1bda22013-07-19 22:08:37165def ProcessGTestOptions(options):
166 """Intercept test suite help to list test suites.
167
168 Args:
169 options: Command line options.
[email protected]6bc1bda22013-07-19 22:08:37170 """
171 if options.suite_name == 'help':
172 print 'Available test suites are:'
[email protected]9e689252013-07-30 20:14:36173 for test_suite in (gtest_config.STABLE_TEST_SUITES +
174 gtest_config.EXPERIMENTAL_TEST_SUITES):
175 print test_suite
[email protected]2a684222013-08-01 16:59:22176 sys.exit(0)
[email protected]6bc1bda22013-07-19 22:08:37177
178 # Convert to a list, assuming all test suites if nothing was specified.
179 # TODO(gkanwar): Require having a test suite
180 if options.suite_name:
181 options.suite_name = [options.suite_name]
182 else:
[email protected]9e689252013-07-30 20:14:36183 options.suite_name = [s for s in gtest_config.STABLE_TEST_SUITES]
[email protected]6bc1bda22013-07-19 22:08:37184
185
[email protected]fbe29322013-07-09 09:03:26186def AddJavaTestOptions(option_parser):
187 """Adds the Java test options to |option_parser|."""
188
[email protected]dfffbcbc2013-09-17 22:06:01189 option_parser.add_option('-f', '--test-filter', dest='test_filter',
[email protected]fbe29322013-07-09 09:03:26190 help=('Test filter (if not fully qualified, '
191 'will run all matches).'))
192 option_parser.add_option(
193 '-A', '--annotation', dest='annotation_str',
194 help=('Comma-separated list of annotations. Run only tests with any of '
195 'the given annotations. An annotation can be either a key or a '
196 'key-values pair. A test that has no annotation is considered '
197 '"SmallTest".'))
198 option_parser.add_option(
199 '-E', '--exclude-annotation', dest='exclude_annotation_str',
200 help=('Comma-separated list of annotations. Exclude tests with these '
201 'annotations.'))
jbudorickcbcc115d2014-09-18 17:50:59202 option_parser.add_option(
203 '--screenshot', dest='screenshot_failures', action='store_true',
204 help='Capture screenshots of test failures')
205 option_parser.add_option(
206 '--save-perf-json', action='store_true',
207 help='Saves the JSON file for each UI Perf test.')
208 option_parser.add_option(
209 '--official-build', action='store_true', help='Run official build tests.')
210 option_parser.add_option(
211 '--test_data', '--test-data', action='append', default=[],
212 help=('Each instance defines a directory of test data that should be '
213 'copied to the target(s) before running the tests. The argument '
214 'should be of the form <target>:<source>, <target> is relative to '
215 'the device data directory, and <source> is relative to the '
216 'chromium build directory.'))
[email protected]fbe29322013-07-09 09:03:26217
218
[email protected]7c53a602014-03-24 16:21:44219def ProcessJavaTestOptions(options):
[email protected]fbe29322013-07-09 09:03:26220 """Processes options/arguments and populates |options| with defaults."""
221
[email protected]fbe29322013-07-09 09:03:26222 if options.annotation_str:
223 options.annotations = options.annotation_str.split(',')
224 elif options.test_filter:
225 options.annotations = []
226 else:
[email protected]6bc1bda22013-07-19 22:08:37227 options.annotations = ['Smoke', 'SmallTest', 'MediumTest', 'LargeTest',
[email protected]4f777ca2014-08-08 01:45:59228 'EnormousTest', 'IntegrationTest']
[email protected]fbe29322013-07-09 09:03:26229
230 if options.exclude_annotation_str:
231 options.exclude_annotations = options.exclude_annotation_str.split(',')
232 else:
233 options.exclude_annotations = []
234
[email protected]fbe29322013-07-09 09:03:26235
236def AddInstrumentationTestOptions(option_parser):
237 """Adds Instrumentation test options to |option_parser|."""
238
239 option_parser.usage = '%prog instrumentation [options]'
[email protected]dfffbcbc2013-09-17 22:06:01240 option_parser.commands_dict = {}
[email protected]fb7ab5e82013-07-26 18:31:20241 option_parser.example = ('%prog instrumentation '
[email protected]efeb59e2014-03-12 01:31:26242 '--test-apk=ChromeShellTest')
[email protected]fbe29322013-07-09 09:03:26243
244 AddJavaTestOptions(option_parser)
245 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13246 AddDeviceOptions(option_parser)
[email protected]fbe29322013-07-09 09:03:26247
[email protected]dfffbcbc2013-09-17 22:06:01248 option_parser.add_option('-j', '--java-only', action='store_true',
[email protected]37ee0c792013-08-06 19:10:13249 default=False, help='Run only the Java tests.')
[email protected]dfffbcbc2013-09-17 22:06:01250 option_parser.add_option('-p', '--python-only', action='store_true',
[email protected]37ee0c792013-08-06 19:10:13251 default=False,
252 help='Run only the host-driven tests.')
[email protected]a69e85bc2013-08-16 18:07:26253 option_parser.add_option('--host-driven-root',
[email protected]37ee0c792013-08-06 19:10:13254 help='Root of the host-driven tests.')
[email protected]fbe29322013-07-09 09:03:26255 option_parser.add_option('-w', '--wait_debugger', dest='wait_for_debugger',
256 action='store_true',
257 help='Wait for debugger.')
[email protected]fbe29322013-07-09 09:03:26258 option_parser.add_option(
259 '--test-apk', dest='test_apk',
260 help=('The name of the apk containing the tests '
[email protected]ae68d4a2013-09-24 21:57:15261 '(without the .apk extension; e.g. "ContentShellTest").'))
[email protected]803f65a72013-08-20 19:11:30262 option_parser.add_option('--coverage-dir',
263 help=('Directory in which to place all generated '
264 'EMMA coverage files.'))
[email protected]4f777ca2014-08-08 01:45:59265 option_parser.add_option('--device-flags', dest='device_flags', default='',
266 help='The relative filepath to a file containing '
267 'command-line flags to set on the device')
[email protected]fbe29322013-07-09 09:03:26268
269
270def ProcessInstrumentationOptions(options, error_func):
[email protected]2a684222013-08-01 16:59:22271 """Processes options/arguments and populate |options| with defaults.
272
273 Args:
274 options: optparse.Options object.
275 error_func: Function to call with the error message in case of an error.
276
277 Returns:
278 An InstrumentationOptions named tuple which contains all options relevant to
279 instrumentation tests.
280 """
[email protected]fbe29322013-07-09 09:03:26281
[email protected]7c53a602014-03-24 16:21:44282 ProcessJavaTestOptions(options)
[email protected]fbe29322013-07-09 09:03:26283
[email protected]37ee0c792013-08-06 19:10:13284 if options.java_only and options.python_only:
285 error_func('Options java_only (-j) and python_only (-p) '
286 'are mutually exclusive.')
287 options.run_java_tests = True
288 options.run_python_tests = True
289 if options.java_only:
290 options.run_python_tests = False
291 elif options.python_only:
292 options.run_java_tests = False
293
[email protected]67954f822013-08-14 18:09:08294 if not options.host_driven_root:
[email protected]37ee0c792013-08-06 19:10:13295 options.run_python_tests = False
296
[email protected]fbe29322013-07-09 09:03:26297 if not options.test_apk:
298 error_func('--test-apk must be specified.')
299
[email protected]ae68d4a2013-09-24 21:57:15300
[email protected]2eea4872014-07-28 23:06:17301 options.test_apk_path = os.path.join(
302 constants.GetOutDirectory(),
303 constants.SDK_BUILD_APKS_DIR,
304 '%s.apk' % options.test_apk)
[email protected]ae68d4a2013-09-24 21:57:15305 options.test_apk_jar_path = os.path.join(
306 constants.GetOutDirectory(),
307 constants.SDK_BUILD_TEST_JAVALIB_DIR,
308 '%s.jar' % options.test_apk)
[email protected]5e2f3f62014-06-23 12:31:46309 options.test_support_apk_path = '%sSupport%s' % (
[email protected]2eea4872014-07-28 23:06:17310 os.path.splitext(options.test_apk_path))
[email protected]5e2f3f62014-06-23 12:31:46311
[email protected]2eea4872014-07-28 23:06:17312 options.test_runner = apk_helper.GetInstrumentationName(options.test_apk_path)
[email protected]5e2f3f62014-06-23 12:31:46313
[email protected]2a684222013-08-01 16:59:22314 return instrumentation_test_options.InstrumentationOptions(
[email protected]2a684222013-08-01 16:59:22315 options.tool,
316 options.cleanup_test_files,
[email protected]2a684222013-08-01 16:59:22317 options.annotations,
318 options.exclude_annotations,
319 options.test_filter,
320 options.test_data,
321 options.save_perf_json,
322 options.screenshot_failures,
[email protected]2a684222013-08-01 16:59:22323 options.wait_for_debugger,
[email protected]803f65a72013-08-20 19:11:30324 options.coverage_dir,
[email protected]2a684222013-08-01 16:59:22325 options.test_apk,
326 options.test_apk_path,
[email protected]5e2f3f62014-06-23 12:31:46327 options.test_apk_jar_path,
[email protected]65bd8fb2014-08-02 17:02:02328 options.test_runner,
[email protected]4f777ca2014-08-08 01:45:59329 options.test_support_apk_path,
330 options.device_flags
[email protected]5e2f3f62014-06-23 12:31:46331 )
[email protected]2a684222013-08-01 16:59:22332
[email protected]fbe29322013-07-09 09:03:26333
334def AddUIAutomatorTestOptions(option_parser):
335 """Adds UI Automator test options to |option_parser|."""
336
337 option_parser.usage = '%prog uiautomator [options]'
[email protected]dfffbcbc2013-09-17 22:06:01338 option_parser.commands_dict = {}
[email protected]fbe29322013-07-09 09:03:26339 option_parser.example = (
[email protected]efeb59e2014-03-12 01:31:26340 '%prog uiautomator --test-jar=chrome_shell_uiautomator_tests'
341 ' --package=chrome_shell')
[email protected]fbe29322013-07-09 09:03:26342 option_parser.add_option(
[email protected]a8886c8a92013-10-08 17:29:30343 '--package',
344 help=('Package under test. Possible values: %s' %
345 constants.PACKAGE_INFO.keys()))
[email protected]fbe29322013-07-09 09:03:26346 option_parser.add_option(
347 '--test-jar', dest='test_jar',
348 help=('The name of the dexed jar containing the tests (without the '
349 '.dex.jar extension). Alternatively, this can be a full path '
350 'to the jar.'))
351
352 AddJavaTestOptions(option_parser)
353 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13354 AddDeviceOptions(option_parser)
[email protected]fbe29322013-07-09 09:03:26355
356
357def ProcessUIAutomatorOptions(options, error_func):
[email protected]2a684222013-08-01 16:59:22358 """Processes UIAutomator options/arguments.
359
360 Args:
361 options: optparse.Options object.
362 error_func: Function to call with the error message in case of an error.
363
364 Returns:
365 A UIAutomatorOptions named tuple which contains all options relevant to
[email protected]3dbdfa42013-08-08 01:08:14366 uiautomator tests.
[email protected]2a684222013-08-01 16:59:22367 """
[email protected]fbe29322013-07-09 09:03:26368
[email protected]7c53a602014-03-24 16:21:44369 ProcessJavaTestOptions(options)
[email protected]fbe29322013-07-09 09:03:26370
[email protected]a8886c8a92013-10-08 17:29:30371 if not options.package:
372 error_func('--package is required.')
373
374 if options.package not in constants.PACKAGE_INFO:
375 error_func('Invalid package.')
[email protected]fbe29322013-07-09 09:03:26376
377 if not options.test_jar:
378 error_func('--test-jar must be specified.')
379
380 if os.path.exists(options.test_jar):
381 # The dexed JAR is fully qualified, assume the info JAR lives along side.
382 options.uiautomator_jar = options.test_jar
383 else:
384 options.uiautomator_jar = os.path.join(
[email protected]ae68d4a2013-09-24 21:57:15385 constants.GetOutDirectory(),
386 constants.SDK_BUILD_JAVALIB_DIR,
[email protected]fbe29322013-07-09 09:03:26387 '%s.dex.jar' % options.test_jar)
388 options.uiautomator_info_jar = (
389 options.uiautomator_jar[:options.uiautomator_jar.find('.dex.jar')] +
390 '_java.jar')
391
[email protected]2a684222013-08-01 16:59:22392 return uiautomator_test_options.UIAutomatorOptions(
[email protected]2a684222013-08-01 16:59:22393 options.tool,
394 options.cleanup_test_files,
[email protected]2a684222013-08-01 16:59:22395 options.annotations,
396 options.exclude_annotations,
397 options.test_filter,
398 options.test_data,
399 options.save_perf_json,
400 options.screenshot_failures,
[email protected]2a684222013-08-01 16:59:22401 options.uiautomator_jar,
402 options.uiautomator_info_jar,
[email protected]a8886c8a92013-10-08 17:29:30403 options.package)
[email protected]2a684222013-08-01 16:59:22404
[email protected]fbe29322013-07-09 09:03:26405
jbudorick9a6b7b332014-09-20 00:01:07406def AddJUnitTestOptions(option_parser):
407 """Adds junit test options to |option_parser|."""
408 option_parser.usage = '%prog junit -s [test suite name]'
409 option_parser.commands_dict = {}
410
411 option_parser.add_option(
412 '-s', '--test-suite', dest='test_suite',
413 help=('JUnit test suite to run.'))
414 option_parser.add_option(
415 '-f', '--test-filter', dest='test_filter',
416 help='Filters tests googletest-style.')
417 option_parser.add_option(
418 '--package-filter', dest='package_filter',
419 help='Filters tests by package.')
420 option_parser.add_option(
421 '--runner-filter', dest='runner_filter',
422 help='Filters tests by runner class. Must be fully qualified.')
423 option_parser.add_option(
424 '--sdk-version', dest='sdk_version', type="int",
425 help='The Android SDK version.')
426 AddCommonOptions(option_parser)
427
428
429def ProcessJUnitTestOptions(options, error_func):
430 """Processes all JUnit test options."""
431 if not options.test_suite:
432 error_func('No test suite specified.')
433 return options
434
435
[email protected]3dbdfa42013-08-08 01:08:14436def AddMonkeyTestOptions(option_parser):
437 """Adds monkey test options to |option_parser|."""
[email protected]fb81b982013-08-09 00:07:12438
439 option_parser.usage = '%prog monkey [options]'
[email protected]dfffbcbc2013-09-17 22:06:01440 option_parser.commands_dict = {}
[email protected]fb81b982013-08-09 00:07:12441 option_parser.example = (
[email protected]efeb59e2014-03-12 01:31:26442 '%prog monkey --package=chrome_shell')
[email protected]fb81b982013-08-09 00:07:12443
[email protected]3dbdfa42013-08-08 01:08:14444 option_parser.add_option(
[email protected]a8886c8a92013-10-08 17:29:30445 '--package',
446 help=('Package under test. Possible values: %s' %
447 constants.PACKAGE_INFO.keys()))
[email protected]3dbdfa42013-08-08 01:08:14448 option_parser.add_option(
449 '--event-count', default=10000, type='int',
450 help='Number of events to generate [default: %default].')
451 option_parser.add_option(
452 '--category', default='',
[email protected]fb81b982013-08-09 00:07:12453 help='A list of allowed categories.')
[email protected]3dbdfa42013-08-08 01:08:14454 option_parser.add_option(
455 '--throttle', default=100, type='int',
456 help='Delay between events (ms) [default: %default]. ')
457 option_parser.add_option(
458 '--seed', type='int',
459 help=('Seed value for pseudo-random generator. Same seed value generates '
460 'the same sequence of events. Seed is randomized by default.'))
461 option_parser.add_option(
462 '--extra-args', default='',
463 help=('String of other args to pass to the command verbatim '
464 '[default: "%default"].'))
465
466 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13467 AddDeviceOptions(option_parser)
[email protected]3dbdfa42013-08-08 01:08:14468
469
470def ProcessMonkeyTestOptions(options, error_func):
471 """Processes all monkey test options.
472
473 Args:
474 options: optparse.Options object.
475 error_func: Function to call with the error message in case of an error.
476
477 Returns:
478 A MonkeyOptions named tuple which contains all options relevant to
479 monkey tests.
480 """
[email protected]a8886c8a92013-10-08 17:29:30481 if not options.package:
482 error_func('--package is required.')
483
484 if options.package not in constants.PACKAGE_INFO:
485 error_func('Invalid package.')
[email protected]3dbdfa42013-08-08 01:08:14486
487 category = options.category
488 if category:
489 category = options.category.split(',')
490
491 return monkey_test_options.MonkeyOptions(
[email protected]3dbdfa42013-08-08 01:08:14492 options.verbose_count,
[email protected]a8886c8a92013-10-08 17:29:30493 options.package,
[email protected]3dbdfa42013-08-08 01:08:14494 options.event_count,
495 category,
496 options.throttle,
497 options.seed,
498 options.extra_args)
499
500
[email protected]ec3170b2013-08-14 14:39:47501def AddPerfTestOptions(option_parser):
502 """Adds perf test options to |option_parser|."""
503
504 option_parser.usage = '%prog perf [options]'
[email protected]dfffbcbc2013-09-17 22:06:01505 option_parser.commands_dict = {}
[email protected]def4bce2013-11-12 12:59:52506 option_parser.example = ('%prog perf '
[email protected]ad32f312013-11-13 04:03:29507 '[--single-step -- command args] or '
[email protected]def4bce2013-11-12 12:59:52508 '[--steps perf_steps.json] or '
[email protected]ad32f312013-11-13 04:03:29509 '[--print-step step]')
[email protected]ec3170b2013-08-14 14:39:47510
[email protected]181a5c92013-09-06 17:11:46511 option_parser.add_option(
[email protected]def4bce2013-11-12 12:59:52512 '--single-step',
[email protected]ad32f312013-11-13 04:03:29513 action='store_true',
[email protected]def4bce2013-11-12 12:59:52514 help='Execute the given command with retries, but only print the result '
515 'for the "most successful" round.')
516 option_parser.add_option(
[email protected]181a5c92013-09-06 17:11:46517 '--steps',
[email protected]def4bce2013-11-12 12:59:52518 help='JSON file containing the list of commands to run.')
[email protected]181a5c92013-09-06 17:11:46519 option_parser.add_option(
520 '--flaky-steps',
521 help=('A JSON file containing steps that are flaky '
522 'and will have its exit code ignored.'))
523 option_parser.add_option(
[email protected]61487ed2014-06-09 12:33:56524 '--output-json-list',
525 help='Write a simple list of names from --steps into the given file.')
526 option_parser.add_option(
[email protected]181a5c92013-09-06 17:11:46527 '--print-step',
528 help='The name of a previously executed perf step to print.')
529 option_parser.add_option(
530 '--no-timeout', action='store_true',
531 help=('Do not impose a timeout. Each perf step is responsible for '
532 'implementing the timeout logic.'))
[email protected]650487c2013-09-30 11:40:49533 option_parser.add_option(
534 '-f', '--test-filter',
535 help=('Test filter (will match against the names listed in --steps).'))
536 option_parser.add_option(
537 '--dry-run',
538 action='store_true',
539 help='Just print the steps without executing.')
[email protected]ec3170b2013-08-14 14:39:47540 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13541 AddDeviceOptions(option_parser)
[email protected]ec3170b2013-08-14 14:39:47542
543
[email protected]ad32f312013-11-13 04:03:29544def ProcessPerfTestOptions(options, args, error_func):
[email protected]ec3170b2013-08-14 14:39:47545 """Processes all perf test options.
546
547 Args:
548 options: optparse.Options object.
549 error_func: Function to call with the error message in case of an error.
550
551 Returns:
552 A PerfOptions named tuple which contains all options relevant to
553 perf tests.
554 """
[email protected]def4bce2013-11-12 12:59:52555 # Only one of steps, print_step or single_step must be provided.
556 count = len(filter(None,
557 [options.steps, options.print_step, options.single_step]))
558 if count != 1:
559 error_func('Please specify one of: --steps, --print-step, --single-step.')
[email protected]ad32f312013-11-13 04:03:29560 single_step = None
561 if options.single_step:
562 single_step = ' '.join(args[2:])
[email protected]ec3170b2013-08-14 14:39:47563 return perf_test_options.PerfOptions(
[email protected]61487ed2014-06-09 12:33:56564 options.steps, options.flaky_steps, options.output_json_list,
565 options.print_step, options.no_timeout, options.test_filter,
566 options.dry_run, single_step)
[email protected]ec3170b2013-08-14 14:39:47567
568
jbudorick256fd532014-10-24 01:50:13569def AddPythonTestOptions(option_parser):
570 option_parser.add_option('-s', '--suite', dest='suite_name',
571 help=('Name of the test suite to run'
572 '(use -s help to list them).'))
573 AddCommonOptions(option_parser)
574
575
576def ProcessPythonTestOptions(options, error_func):
577 if options.suite_name not in constants.PYTHON_UNIT_TEST_SUITES:
578 available = ('Available test suites: [%s]' %
579 ', '.join(constants.PYTHON_UNIT_TEST_SUITES.iterkeys()))
580 if options.suite_name == 'help':
581 print available
582 else:
583 error_func('"%s" is not a valid suite. %s' %
584 (options.suite_name, available))
585
586
[email protected]7c53a602014-03-24 16:21:44587def _RunGTests(options, devices):
[email protected]6bc1bda22013-07-19 22:08:37588 """Subcommand of RunTestsCommands which runs gtests."""
[email protected]2a684222013-08-01 16:59:22589 ProcessGTestOptions(options)
[email protected]6bc1bda22013-07-19 22:08:37590
591 exit_code = 0
592 for suite_name in options.suite_name:
[email protected]2a684222013-08-01 16:59:22593 # TODO(gkanwar): Move this into ProcessGTestOptions once we require -s for
594 # the gtest command.
595 gtest_options = gtest_test_options.GTestOptions(
[email protected]2a684222013-08-01 16:59:22596 options.tool,
597 options.cleanup_test_files,
[email protected]2a684222013-08-01 16:59:22598 options.test_filter,
[email protected]dfffbcbc2013-09-17 22:06:01599 options.run_disabled,
[email protected]2a684222013-08-01 16:59:22600 options.test_arguments,
601 options.timeout,
[email protected]5b8b8742014-05-22 08:18:50602 options.isolate_file_path,
[email protected]2a684222013-08-01 16:59:22603 suite_name)
[email protected]f7148dd42013-08-20 14:24:57604 runner_factory, tests = gtest_setup.Setup(gtest_options, devices)
[email protected]6bc1bda22013-07-19 22:08:37605
606 results, test_exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57607 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]6bc1bda22013-07-19 22:08:37608 num_retries=options.num_retries)
609
610 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE:
611 exit_code = test_exit_code
612
613 report_results.LogFull(
614 results=results,
615 test_type='Unit test',
616 test_package=suite_name,
[email protected]6bc1bda22013-07-19 22:08:37617 flakiness_server=options.flakiness_dashboard_server)
618
619 if os.path.isdir(constants.ISOLATE_DEPS_DIR):
620 shutil.rmtree(constants.ISOLATE_DEPS_DIR)
621
622 return exit_code
623
624
[email protected]7c53a602014-03-24 16:21:44625def _RunLinkerTests(options, devices):
[email protected]6b6abac6d2013-10-03 11:56:38626 """Subcommand of RunTestsCommands which runs linker tests."""
627 runner_factory, tests = linker_setup.Setup(options, devices)
628
629 results, exit_code = test_dispatcher.RunTests(
630 tests, runner_factory, devices, shard=True, test_timeout=60,
631 num_retries=options.num_retries)
632
633 report_results.LogFull(
634 results=results,
635 test_type='Linker test',
[email protected]93c9f9b2014-02-10 16:19:22636 test_package='ChromiumLinkerTest')
[email protected]6b6abac6d2013-10-03 11:56:38637
638 return exit_code
639
640
[email protected]f7148dd42013-08-20 14:24:57641def _RunInstrumentationTests(options, error_func, devices):
[email protected]6bc1bda22013-07-19 22:08:37642 """Subcommand of RunTestsCommands which runs instrumentation tests."""
[email protected]2a684222013-08-01 16:59:22643 instrumentation_options = ProcessInstrumentationOptions(options, error_func)
[email protected]6bc1bda22013-07-19 22:08:37644
[email protected]f7148dd42013-08-20 14:24:57645 if len(devices) > 1 and options.wait_for_debugger:
646 logging.warning('Debugger can not be sharded, using first available device')
647 devices = devices[:1]
648
[email protected]6bc1bda22013-07-19 22:08:37649 results = base_test_result.TestRunResults()
650 exit_code = 0
651
652 if options.run_java_tests:
[email protected]2a684222013-08-01 16:59:22653 runner_factory, tests = instrumentation_setup.Setup(instrumentation_options)
[email protected]6bc1bda22013-07-19 22:08:37654
655 test_results, exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57656 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]6bc1bda22013-07-19 22:08:37657 num_retries=options.num_retries)
658
659 results.AddTestRunResults(test_results)
660
661 if options.run_python_tests:
[email protected]37ee0c792013-08-06 19:10:13662 runner_factory, tests = host_driven_setup.InstrumentationSetup(
[email protected]67954f822013-08-14 18:09:08663 options.host_driven_root, options.official_build,
[email protected]37ee0c792013-08-06 19:10:13664 instrumentation_options)
665
[email protected]34020022013-08-06 23:35:34666 if tests:
667 test_results, test_exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57668 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]34020022013-08-06 23:35:34669 num_retries=options.num_retries)
[email protected]6bc1bda22013-07-19 22:08:37670
[email protected]34020022013-08-06 23:35:34671 results.AddTestRunResults(test_results)
[email protected]6bc1bda22013-07-19 22:08:37672
[email protected]34020022013-08-06 23:35:34673 # Only allow exit code escalation
674 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE:
675 exit_code = test_exit_code
[email protected]6bc1bda22013-07-19 22:08:37676
[email protected]4f777ca2014-08-08 01:45:59677 if options.device_flags:
678 options.device_flags = os.path.join(constants.DIR_SOURCE_ROOT,
679 options.device_flags)
680
[email protected]6bc1bda22013-07-19 22:08:37681 report_results.LogFull(
682 results=results,
683 test_type='Instrumentation',
684 test_package=os.path.basename(options.test_apk),
685 annotation=options.annotations,
[email protected]6bc1bda22013-07-19 22:08:37686 flakiness_server=options.flakiness_dashboard_server)
687
688 return exit_code
689
690
[email protected]f7148dd42013-08-20 14:24:57691def _RunUIAutomatorTests(options, error_func, devices):
[email protected]6bc1bda22013-07-19 22:08:37692 """Subcommand of RunTestsCommands which runs uiautomator tests."""
[email protected]2a684222013-08-01 16:59:22693 uiautomator_options = ProcessUIAutomatorOptions(options, error_func)
[email protected]6bc1bda22013-07-19 22:08:37694
[email protected]37ee0c792013-08-06 19:10:13695 runner_factory, tests = uiautomator_setup.Setup(uiautomator_options)
[email protected]6bc1bda22013-07-19 22:08:37696
[email protected]37ee0c792013-08-06 19:10:13697 results, exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57698 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]37ee0c792013-08-06 19:10:13699 num_retries=options.num_retries)
[email protected]6bc1bda22013-07-19 22:08:37700
701 report_results.LogFull(
702 results=results,
703 test_type='UIAutomator',
704 test_package=os.path.basename(options.test_jar),
705 annotation=options.annotations,
[email protected]6bc1bda22013-07-19 22:08:37706 flakiness_server=options.flakiness_dashboard_server)
707
708 return exit_code
709
710
jbudorick9a6b7b332014-09-20 00:01:07711def _RunJUnitTests(options, error_func):
712 """Subcommand of RunTestsCommand which runs junit tests."""
713 junit_options = ProcessJUnitTestOptions(options, error_func)
714 runner_factory, tests = junit_setup.Setup(junit_options)
715 _, exit_code = junit_dispatcher.RunTests(tests, runner_factory)
716
717 return exit_code
718
719
[email protected]f7148dd42013-08-20 14:24:57720def _RunMonkeyTests(options, error_func, devices):
[email protected]3dbdfa42013-08-08 01:08:14721 """Subcommand of RunTestsCommands which runs monkey tests."""
722 monkey_options = ProcessMonkeyTestOptions(options, error_func)
723
724 runner_factory, tests = monkey_setup.Setup(monkey_options)
725
726 results, exit_code = test_dispatcher.RunTests(
[email protected]181a5c92013-09-06 17:11:46727 tests, runner_factory, devices, shard=False, test_timeout=None,
728 num_retries=options.num_retries)
[email protected]3dbdfa42013-08-08 01:08:14729
730 report_results.LogFull(
731 results=results,
732 test_type='Monkey',
[email protected]14b3b1202013-08-15 22:25:28733 test_package='Monkey')
[email protected]3dbdfa42013-08-08 01:08:14734
735 return exit_code
736
737
[email protected]a72f0752014-06-03 23:52:34738def _RunPerfTests(options, args, error_func):
[email protected]ec3170b2013-08-14 14:39:47739 """Subcommand of RunTestsCommands which runs perf tests."""
[email protected]ad32f312013-11-13 04:03:29740 perf_options = ProcessPerfTestOptions(options, args, error_func)
[email protected]61487ed2014-06-09 12:33:56741
742 # Just save a simple json with a list of test names.
743 if perf_options.output_json_list:
744 return perf_test_runner.OutputJsonList(
745 perf_options.steps, perf_options.output_json_list)
746
[email protected]ad32f312013-11-13 04:03:29747 # Just print the results from a single previously executed step.
[email protected]ec3170b2013-08-14 14:39:47748 if perf_options.print_step:
749 return perf_test_runner.PrintTestOutput(perf_options.print_step)
750
[email protected]a72f0752014-06-03 23:52:34751 runner_factory, tests, devices = perf_setup.Setup(perf_options)
[email protected]ec3170b2013-08-14 14:39:47752
[email protected]a72f0752014-06-03 23:52:34753 # shard=False means that each device will get the full list of tests
754 # and then each one will decide their own affinity.
755 # shard=True means each device will pop the next test available from a queue,
756 # which increases throughput but have no affinity.
[email protected]86184c7b2013-08-15 15:06:57757 results, _ = test_dispatcher.RunTests(
[email protected]a72f0752014-06-03 23:52:34758 tests, runner_factory, devices, shard=False, test_timeout=None,
[email protected]181a5c92013-09-06 17:11:46759 num_retries=options.num_retries)
[email protected]ec3170b2013-08-14 14:39:47760
761 report_results.LogFull(
762 results=results,
763 test_type='Perf',
[email protected]865a47a2013-08-16 14:01:12764 test_package='Perf')
[email protected]def4bce2013-11-12 12:59:52765
766 if perf_options.single_step:
767 return perf_test_runner.PrintTestOutput('single_step')
768
[email protected]11ce8452014-02-17 10:55:03769 perf_test_runner.PrintSummary(tests)
770
[email protected]86184c7b2013-08-15 15:06:57771 # Always return 0 on the sharding stage. Individual tests exit_code
772 # will be returned on the print_step stage.
773 return 0
[email protected]ec3170b2013-08-14 14:39:47774
[email protected]3dbdfa42013-08-08 01:08:14775
jbudorick256fd532014-10-24 01:50:13776def _RunPythonTests(options, error_func):
777 """Subcommand of RunTestsCommand which runs python unit tests."""
778 ProcessPythonTestOptions(options, error_func)
779
780 suite_vars = constants.PYTHON_UNIT_TEST_SUITES[options.suite_name]
781 suite_path = suite_vars['path']
782 suite_test_modules = suite_vars['test_modules']
783
784 sys.path = [suite_path] + sys.path
785 try:
786 suite = unittest.TestSuite()
787 suite.addTests(unittest.defaultTestLoader.loadTestsFromName(m)
788 for m in suite_test_modules)
789 runner = unittest.TextTestRunner(verbosity=1+options.verbose_count)
790 return 0 if runner.run(suite).wasSuccessful() else 1
791 finally:
792 sys.path = sys.path[1:]
793
794
[email protected]f7148dd42013-08-20 14:24:57795def _GetAttachedDevices(test_device=None):
796 """Get all attached devices.
797
798 Args:
799 test_device: Name of a specific device to use.
800
801 Returns:
802 A list of attached devices.
803 """
804 attached_devices = []
805
806 attached_devices = android_commands.GetAttachedDevices()
807 if test_device:
808 assert test_device in attached_devices, (
809 'Did not find device %s among attached device. Attached devices: %s'
810 % (test_device, ', '.join(attached_devices)))
811 attached_devices = [test_device]
812
813 assert attached_devices, 'No devices attached.'
814
815 return sorted(attached_devices)
816
817
[email protected]fbe29322013-07-09 09:03:26818def RunTestsCommand(command, options, args, option_parser):
819 """Checks test type and dispatches to the appropriate function.
820
821 Args:
822 command: String indicating the command that was received to trigger
823 this function.
824 options: optparse options dictionary.
825 args: List of extra args from optparse.
826 option_parser: optparse.OptionParser object.
827
828 Returns:
829 Integer indicated exit code.
[email protected]b3873892013-07-10 04:57:10830
831 Raises:
832 Exception: Unknown command name passed in, or an exception from an
833 individual test runner.
[email protected]fbe29322013-07-09 09:03:26834 """
835
[email protected]d82f0252013-07-12 23:22:57836 # Check for extra arguments
[email protected]ad32f312013-11-13 04:03:29837 if len(args) > 2 and command != 'perf':
[email protected]d82f0252013-07-12 23:22:57838 option_parser.error('Unrecognized arguments: %s' % (' '.join(args[2:])))
839 return constants.ERROR_EXIT_CODE
[email protected]ad32f312013-11-13 04:03:29840 if command == 'perf':
841 if ((options.single_step and len(args) <= 2) or
842 (not options.single_step and len(args) > 2)):
843 option_parser.error('Unrecognized arguments: %s' % (' '.join(args)))
844 return constants.ERROR_EXIT_CODE
[email protected]d82f0252013-07-12 23:22:57845
jbudorick66dc3722014-11-06 21:33:51846 ProcessCommonOptions(options, option_parser.error)
[email protected]fbe29322013-07-09 09:03:26847
jbudorick66dc3722014-11-06 21:33:51848 if options.enable_platform_mode:
849 return RunTestsInPlatformMode(command, options, option_parser)
850
851 if command in constants.LOCAL_MACHINE_TESTS:
jbudorick256fd532014-10-24 01:50:13852 devices = []
853 else:
854 devices = _GetAttachedDevices(options.test_device)
[email protected]f7148dd42013-08-20 14:24:57855
[email protected]c0662e092013-11-12 11:51:25856 forwarder.Forwarder.RemoveHostLog()
[email protected]6b11583b2013-11-21 16:18:40857 if not ports.ResetTestServerPortAllocation():
858 raise Exception('Failed to reset test server port.')
[email protected]c0662e092013-11-12 11:51:25859
[email protected]fbe29322013-07-09 09:03:26860 if command == 'gtest':
[email protected]7c53a602014-03-24 16:21:44861 return _RunGTests(options, devices)
[email protected]6b6abac6d2013-10-03 11:56:38862 elif command == 'linker':
[email protected]7c53a602014-03-24 16:21:44863 return _RunLinkerTests(options, devices)
[email protected]fbe29322013-07-09 09:03:26864 elif command == 'instrumentation':
[email protected]f7148dd42013-08-20 14:24:57865 return _RunInstrumentationTests(options, option_parser.error, devices)
[email protected]fbe29322013-07-09 09:03:26866 elif command == 'uiautomator':
[email protected]f7148dd42013-08-20 14:24:57867 return _RunUIAutomatorTests(options, option_parser.error, devices)
jbudorick9a6b7b332014-09-20 00:01:07868 elif command == 'junit':
869 return _RunJUnitTests(options, option_parser.error)
[email protected]3dbdfa42013-08-08 01:08:14870 elif command == 'monkey':
[email protected]f7148dd42013-08-20 14:24:57871 return _RunMonkeyTests(options, option_parser.error, devices)
[email protected]ec3170b2013-08-14 14:39:47872 elif command == 'perf':
[email protected]a72f0752014-06-03 23:52:34873 return _RunPerfTests(options, args, option_parser.error)
jbudorick256fd532014-10-24 01:50:13874 elif command == 'python':
875 return _RunPythonTests(options, option_parser.error)
[email protected]fbe29322013-07-09 09:03:26876 else:
[email protected]6bc1bda22013-07-19 22:08:37877 raise Exception('Unknown test type.')
[email protected]fbe29322013-07-09 09:03:26878
[email protected]fbe29322013-07-09 09:03:26879
jbudorick66dc3722014-11-06 21:33:51880_SUPPORTED_IN_PLATFORM_MODE = [
881 # TODO(jbudorick): Add support for more test types.
882 'gtest',
883]
884
885
886def RunTestsInPlatformMode(command, options, option_parser):
887
888 if command not in _SUPPORTED_IN_PLATFORM_MODE:
889 option_parser.error('%s is not yet supported in platform mode' % command)
890
891 with environment_factory.CreateEnvironment(
892 command, options, option_parser.error) as env:
893 with test_instance_factory.CreateTestInstance(
894 command, options, option_parser.error) as test:
895 with test_run_factory.CreateTestRun(
896 options, env, test, option_parser.error) as test_run:
897 results = test_run.RunTests()
898
899 report_results.LogFull(
900 results=results,
901 test_type=test.TestType(),
902 test_package=test_run.TestPackage(),
903 annotation=options.annotations,
904 flakiness_server=options.flakiness_dashboard_server)
905
906 return results
907
908
[email protected]7c53a602014-03-24 16:21:44909def HelpCommand(command, _options, args, option_parser):
[email protected]fbe29322013-07-09 09:03:26910 """Display help for a certain command, or overall help.
911
912 Args:
913 command: String indicating the command that was received to trigger
914 this function.
[email protected]7c53a602014-03-24 16:21:44915 options: optparse options dictionary. unused.
[email protected]fbe29322013-07-09 09:03:26916 args: List of extra args from optparse.
917 option_parser: optparse.OptionParser object.
918
919 Returns:
920 Integer indicated exit code.
921 """
922 # If we don't have any args, display overall help
923 if len(args) < 3:
924 option_parser.print_help()
925 return 0
[email protected]d82f0252013-07-12 23:22:57926 # If we have too many args, print an error
927 if len(args) > 3:
928 option_parser.error('Unrecognized arguments: %s' % (' '.join(args[3:])))
929 return constants.ERROR_EXIT_CODE
[email protected]fbe29322013-07-09 09:03:26930
931 command = args[2]
932
933 if command not in VALID_COMMANDS:
934 option_parser.error('Unrecognized command.')
935
936 # Treat the help command as a special case. We don't care about showing a
937 # specific help page for itself.
938 if command == 'help':
939 option_parser.print_help()
940 return 0
941
942 VALID_COMMANDS[command].add_options_func(option_parser)
943 option_parser.usage = '%prog ' + command + ' [options]'
[email protected]dfffbcbc2013-09-17 22:06:01944 option_parser.commands_dict = {}
[email protected]fbe29322013-07-09 09:03:26945 option_parser.print_help()
946
947 return 0
948
949
950# Define a named tuple for the values in the VALID_COMMANDS dictionary so the
951# syntax is a bit prettier. The tuple is two functions: (add options, run
952# command).
953CommandFunctionTuple = collections.namedtuple(
954 'CommandFunctionTuple', ['add_options_func', 'run_command_func'])
955VALID_COMMANDS = {
956 'gtest': CommandFunctionTuple(AddGTestOptions, RunTestsCommand),
[email protected]fbe29322013-07-09 09:03:26957 'instrumentation': CommandFunctionTuple(
958 AddInstrumentationTestOptions, RunTestsCommand),
959 'uiautomator': CommandFunctionTuple(
960 AddUIAutomatorTestOptions, RunTestsCommand),
jbudorick9a6b7b332014-09-20 00:01:07961 'junit': CommandFunctionTuple(
962 AddJUnitTestOptions, RunTestsCommand),
[email protected]3dbdfa42013-08-08 01:08:14963 'monkey': CommandFunctionTuple(
964 AddMonkeyTestOptions, RunTestsCommand),
[email protected]ec3170b2013-08-14 14:39:47965 'perf': CommandFunctionTuple(
966 AddPerfTestOptions, RunTestsCommand),
jbudorick256fd532014-10-24 01:50:13967 'python': CommandFunctionTuple(
968 AddPythonTestOptions, RunTestsCommand),
[email protected]6b6abac6d2013-10-03 11:56:38969 'linker': CommandFunctionTuple(
970 AddLinkerTestOptions, RunTestsCommand),
[email protected]fbe29322013-07-09 09:03:26971 'help': CommandFunctionTuple(lambda option_parser: None, HelpCommand)
972 }
973
974
[email protected]7c53a602014-03-24 16:21:44975def DumpThreadStacks(_signal, _frame):
[email protected]71aec4b2013-11-20 00:35:24976 for thread in threading.enumerate():
977 reraiser_thread.LogThreadStack(thread)
[email protected]83bb8152013-11-19 15:02:21978
979
[email protected]7c53a602014-03-24 16:21:44980def main():
[email protected]83bb8152013-11-19 15:02:21981 signal.signal(signal.SIGUSR1, DumpThreadStacks)
[email protected]803f65a72013-08-20 19:11:30982 option_parser = command_option_parser.CommandOptionParser(
983 commands_dict=VALID_COMMANDS)
984 return command_option_parser.ParseAndExecute(option_parser)
[email protected]fbe29322013-07-09 09:03:26985
[email protected]fbe29322013-07-09 09:03:26986
987if __name__ == '__main__':
[email protected]7c53a602014-03-24 16:21:44988 sys.exit(main())