blob: 1baebc1bd69c022f505cf84ea6ee58fc3404f3df [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
[email protected]6bc1bda22013-07-19 22:08:3724from pylib.base import test_dispatcher
[email protected]6bc1bda22013-07-19 22:08:3725from pylib.gtest import gtest_config
[email protected]2a684222013-08-01 16:59:2226from pylib.gtest import setup as gtest_setup
27from pylib.gtest import test_options as gtest_test_options
[email protected]6b6abac6d2013-10-03 11:56:3828from pylib.linker import setup as linker_setup
[email protected]37ee0c792013-08-06 19:10:1329from pylib.host_driven import setup as host_driven_setup
[email protected]6bc1bda22013-07-19 22:08:3730from pylib.instrumentation import setup as instrumentation_setup
[email protected]2a684222013-08-01 16:59:2231from pylib.instrumentation import test_options as instrumentation_test_options
jbudorick9a6b7b332014-09-20 00:01:0732from pylib.junit import setup as junit_setup
33from pylib.junit import test_dispatcher as junit_dispatcher
[email protected]3dbdfa42013-08-08 01:08:1434from pylib.monkey import setup as monkey_setup
35from pylib.monkey import test_options as monkey_test_options
[email protected]ec3170b2013-08-14 14:39:4736from pylib.perf import setup as perf_setup
37from pylib.perf import test_options as perf_test_options
38from pylib.perf import test_runner as perf_test_runner
[email protected]6bc1bda22013-07-19 22:08:3739from pylib.uiautomator import setup as uiautomator_setup
[email protected]2a684222013-08-01 16:59:2240from pylib.uiautomator import test_options as uiautomator_test_options
[email protected]2eea4872014-07-28 23:06:1741from pylib.utils import apk_helper
[email protected]803f65a72013-08-20 19:11:3042from pylib.utils import command_option_parser
[email protected]6bc1bda22013-07-19 22:08:3743from pylib.utils import report_results
[email protected]71aec4b2013-11-20 00:35:2444from pylib.utils import reraiser_thread
[email protected]6bc1bda22013-07-19 22:08:3745from pylib.utils import run_tests_helper
[email protected]fbe29322013-07-09 09:03:2646
47
jbudorick256fd532014-10-24 01:50:1348HOST_TESTS = ['junit', 'python']
49
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.'))
[email protected]dfffbcbc2013-09-17 22:06:0181 option_parser.add_option_group(group)
[email protected]fbe29322013-07-09 09:03:2682
83
84def ProcessCommonOptions(options):
85 """Processes and handles all common options."""
[email protected]fbe29322013-07-09 09:03:2686 run_tests_helper.SetLogLevel(options.verbose_count)
[email protected]14b3b1202013-08-15 22:25:2887 constants.SetBuildType(options.build_type)
r.kasibhatla3d57cba2014-10-09 10:55:5788 if options.build_directory:
89 constants.SetBuildDirectory(options.build_directory)
[email protected]fbe29322013-07-09 09:03:2690
91
jbudorick256fd532014-10-24 01:50:1392def AddDeviceOptions(option_parser):
93 group = optparse.OptionGroup(option_parser, 'Device Options')
94 group.add_option('-c', dest='cleanup_test_files',
95 help='Cleanup test files on the device after run',
96 action='store_true')
97 group.add_option('--tool',
98 dest='tool',
99 help=('Run the test under a tool '
100 '(use --tool help to list them)'))
jbudorick256fd532014-10-24 01:50:13101 group.add_option('-d', '--device', dest='test_device',
102 help=('Target device for the test suite '
103 'to run on.'))
104 option_parser.add_option_group(group)
105
106
[email protected]fbe29322013-07-09 09:03:26107def AddGTestOptions(option_parser):
108 """Adds gtest options to |option_parser|."""
109
110 option_parser.usage = '%prog gtest [options]'
[email protected]dfffbcbc2013-09-17 22:06:01111 option_parser.commands_dict = {}
[email protected]fbe29322013-07-09 09:03:26112 option_parser.example = '%prog gtest -s base_unittests'
113
[email protected]6bc1bda22013-07-19 22:08:37114 # TODO(gkanwar): Make this option required
115 option_parser.add_option('-s', '--suite', dest='suite_name',
[email protected]fbe29322013-07-09 09:03:26116 help=('Executable name of the test suite to run '
117 '(use -s help to list them).'))
[email protected]c53dc4332013-11-20 04:38:03118 option_parser.add_option('-f', '--gtest_filter', '--gtest-filter',
119 dest='test_filter',
[email protected]9e689252013-07-30 20:14:36120 help='googletest-style filter string.')
[email protected]c53dc4332013-11-20 04:38:03121 option_parser.add_option('--gtest_also_run_disabled_tests',
122 '--gtest-also-run-disabled-tests',
[email protected]dfffbcbc2013-09-17 22:06:01123 dest='run_disabled', action='store_true',
124 help='Also run disabled tests if applicable.')
125 option_parser.add_option('-a', '--test-arguments', dest='test_arguments',
126 default='',
[email protected]9e689252013-07-30 20:14:36127 help='Additional arguments to pass to the test.')
128 option_parser.add_option('-t', dest='timeout',
129 help='Timeout to wait for each test',
130 type='int',
131 default=60)
[email protected]5b8b8742014-05-22 08:18:50132 option_parser.add_option('--isolate_file_path',
133 '--isolate-file-path',
134 dest='isolate_file_path',
135 help='.isolate file path to override the default '
136 'path')
[email protected]fbe29322013-07-09 09:03:26137 # TODO(gkanwar): Move these to Common Options once we have the plumbing
138 # in our other test types to handle these commands
[email protected]fbe29322013-07-09 09:03:26139 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13140 AddDeviceOptions(option_parser)
[email protected]fbe29322013-07-09 09:03:26141
142
[email protected]6b6abac6d2013-10-03 11:56:38143def AddLinkerTestOptions(option_parser):
144 option_parser.usage = '%prog linker'
145 option_parser.commands_dict = {}
146 option_parser.example = '%prog linker'
147
[email protected]98c4feef2013-10-08 01:19:05148 option_parser.add_option('-f', '--gtest-filter', dest='test_filter',
149 help='googletest-style filter string.')
[email protected]6b6abac6d2013-10-03 11:56:38150 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13151 AddDeviceOptions(option_parser)
[email protected]6b6abac6d2013-10-03 11:56:38152
153
[email protected]6bc1bda22013-07-19 22:08:37154def ProcessGTestOptions(options):
155 """Intercept test suite help to list test suites.
156
157 Args:
158 options: Command line options.
[email protected]6bc1bda22013-07-19 22:08:37159 """
160 if options.suite_name == 'help':
161 print 'Available test suites are:'
[email protected]9e689252013-07-30 20:14:36162 for test_suite in (gtest_config.STABLE_TEST_SUITES +
163 gtest_config.EXPERIMENTAL_TEST_SUITES):
164 print test_suite
[email protected]2a684222013-08-01 16:59:22165 sys.exit(0)
[email protected]6bc1bda22013-07-19 22:08:37166
167 # Convert to a list, assuming all test suites if nothing was specified.
168 # TODO(gkanwar): Require having a test suite
169 if options.suite_name:
170 options.suite_name = [options.suite_name]
171 else:
[email protected]9e689252013-07-30 20:14:36172 options.suite_name = [s for s in gtest_config.STABLE_TEST_SUITES]
[email protected]6bc1bda22013-07-19 22:08:37173
174
[email protected]fbe29322013-07-09 09:03:26175def AddJavaTestOptions(option_parser):
176 """Adds the Java test options to |option_parser|."""
177
[email protected]dfffbcbc2013-09-17 22:06:01178 option_parser.add_option('-f', '--test-filter', dest='test_filter',
[email protected]fbe29322013-07-09 09:03:26179 help=('Test filter (if not fully qualified, '
180 'will run all matches).'))
181 option_parser.add_option(
182 '-A', '--annotation', dest='annotation_str',
183 help=('Comma-separated list of annotations. Run only tests with any of '
184 'the given annotations. An annotation can be either a key or a '
185 'key-values pair. A test that has no annotation is considered '
186 '"SmallTest".'))
187 option_parser.add_option(
188 '-E', '--exclude-annotation', dest='exclude_annotation_str',
189 help=('Comma-separated list of annotations. Exclude tests with these '
190 'annotations.'))
jbudorickcbcc115d2014-09-18 17:50:59191 option_parser.add_option(
192 '--screenshot', dest='screenshot_failures', action='store_true',
193 help='Capture screenshots of test failures')
194 option_parser.add_option(
195 '--save-perf-json', action='store_true',
196 help='Saves the JSON file for each UI Perf test.')
197 option_parser.add_option(
198 '--official-build', action='store_true', help='Run official build tests.')
199 option_parser.add_option(
200 '--test_data', '--test-data', action='append', default=[],
201 help=('Each instance defines a directory of test data that should be '
202 'copied to the target(s) before running the tests. The argument '
203 'should be of the form <target>:<source>, <target> is relative to '
204 'the device data directory, and <source> is relative to the '
205 'chromium build directory.'))
[email protected]fbe29322013-07-09 09:03:26206
207
[email protected]7c53a602014-03-24 16:21:44208def ProcessJavaTestOptions(options):
[email protected]fbe29322013-07-09 09:03:26209 """Processes options/arguments and populates |options| with defaults."""
210
[email protected]fbe29322013-07-09 09:03:26211 if options.annotation_str:
212 options.annotations = options.annotation_str.split(',')
213 elif options.test_filter:
214 options.annotations = []
215 else:
[email protected]6bc1bda22013-07-19 22:08:37216 options.annotations = ['Smoke', 'SmallTest', 'MediumTest', 'LargeTest',
[email protected]4f777ca2014-08-08 01:45:59217 'EnormousTest', 'IntegrationTest']
[email protected]fbe29322013-07-09 09:03:26218
219 if options.exclude_annotation_str:
220 options.exclude_annotations = options.exclude_annotation_str.split(',')
221 else:
222 options.exclude_annotations = []
223
[email protected]fbe29322013-07-09 09:03:26224
225def AddInstrumentationTestOptions(option_parser):
226 """Adds Instrumentation test options to |option_parser|."""
227
228 option_parser.usage = '%prog instrumentation [options]'
[email protected]dfffbcbc2013-09-17 22:06:01229 option_parser.commands_dict = {}
[email protected]fb7ab5e82013-07-26 18:31:20230 option_parser.example = ('%prog instrumentation '
[email protected]efeb59e2014-03-12 01:31:26231 '--test-apk=ChromeShellTest')
[email protected]fbe29322013-07-09 09:03:26232
233 AddJavaTestOptions(option_parser)
234 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13235 AddDeviceOptions(option_parser)
[email protected]fbe29322013-07-09 09:03:26236
[email protected]dfffbcbc2013-09-17 22:06:01237 option_parser.add_option('-j', '--java-only', action='store_true',
[email protected]37ee0c792013-08-06 19:10:13238 default=False, help='Run only the Java tests.')
[email protected]dfffbcbc2013-09-17 22:06:01239 option_parser.add_option('-p', '--python-only', action='store_true',
[email protected]37ee0c792013-08-06 19:10:13240 default=False,
241 help='Run only the host-driven tests.')
[email protected]a69e85bc2013-08-16 18:07:26242 option_parser.add_option('--host-driven-root',
[email protected]37ee0c792013-08-06 19:10:13243 help='Root of the host-driven tests.')
[email protected]fbe29322013-07-09 09:03:26244 option_parser.add_option('-w', '--wait_debugger', dest='wait_for_debugger',
245 action='store_true',
246 help='Wait for debugger.')
[email protected]fbe29322013-07-09 09:03:26247 option_parser.add_option(
248 '--test-apk', dest='test_apk',
249 help=('The name of the apk containing the tests '
[email protected]ae68d4a2013-09-24 21:57:15250 '(without the .apk extension; e.g. "ContentShellTest").'))
[email protected]803f65a72013-08-20 19:11:30251 option_parser.add_option('--coverage-dir',
252 help=('Directory in which to place all generated '
253 'EMMA coverage files.'))
[email protected]4f777ca2014-08-08 01:45:59254 option_parser.add_option('--device-flags', dest='device_flags', default='',
255 help='The relative filepath to a file containing '
256 'command-line flags to set on the device')
[email protected]fbe29322013-07-09 09:03:26257
258
259def ProcessInstrumentationOptions(options, error_func):
[email protected]2a684222013-08-01 16:59:22260 """Processes options/arguments and populate |options| with defaults.
261
262 Args:
263 options: optparse.Options object.
264 error_func: Function to call with the error message in case of an error.
265
266 Returns:
267 An InstrumentationOptions named tuple which contains all options relevant to
268 instrumentation tests.
269 """
[email protected]fbe29322013-07-09 09:03:26270
[email protected]7c53a602014-03-24 16:21:44271 ProcessJavaTestOptions(options)
[email protected]fbe29322013-07-09 09:03:26272
[email protected]37ee0c792013-08-06 19:10:13273 if options.java_only and options.python_only:
274 error_func('Options java_only (-j) and python_only (-p) '
275 'are mutually exclusive.')
276 options.run_java_tests = True
277 options.run_python_tests = True
278 if options.java_only:
279 options.run_python_tests = False
280 elif options.python_only:
281 options.run_java_tests = False
282
[email protected]67954f822013-08-14 18:09:08283 if not options.host_driven_root:
[email protected]37ee0c792013-08-06 19:10:13284 options.run_python_tests = False
285
[email protected]fbe29322013-07-09 09:03:26286 if not options.test_apk:
287 error_func('--test-apk must be specified.')
288
[email protected]ae68d4a2013-09-24 21:57:15289
[email protected]2eea4872014-07-28 23:06:17290 options.test_apk_path = os.path.join(
291 constants.GetOutDirectory(),
292 constants.SDK_BUILD_APKS_DIR,
293 '%s.apk' % options.test_apk)
[email protected]ae68d4a2013-09-24 21:57:15294 options.test_apk_jar_path = os.path.join(
295 constants.GetOutDirectory(),
296 constants.SDK_BUILD_TEST_JAVALIB_DIR,
297 '%s.jar' % options.test_apk)
[email protected]5e2f3f62014-06-23 12:31:46298 options.test_support_apk_path = '%sSupport%s' % (
[email protected]2eea4872014-07-28 23:06:17299 os.path.splitext(options.test_apk_path))
[email protected]5e2f3f62014-06-23 12:31:46300
[email protected]2eea4872014-07-28 23:06:17301 options.test_runner = apk_helper.GetInstrumentationName(options.test_apk_path)
[email protected]5e2f3f62014-06-23 12:31:46302
[email protected]2a684222013-08-01 16:59:22303 return instrumentation_test_options.InstrumentationOptions(
[email protected]2a684222013-08-01 16:59:22304 options.tool,
305 options.cleanup_test_files,
[email protected]2a684222013-08-01 16:59:22306 options.annotations,
307 options.exclude_annotations,
308 options.test_filter,
309 options.test_data,
310 options.save_perf_json,
311 options.screenshot_failures,
[email protected]2a684222013-08-01 16:59:22312 options.wait_for_debugger,
[email protected]803f65a72013-08-20 19:11:30313 options.coverage_dir,
[email protected]2a684222013-08-01 16:59:22314 options.test_apk,
315 options.test_apk_path,
[email protected]5e2f3f62014-06-23 12:31:46316 options.test_apk_jar_path,
[email protected]65bd8fb2014-08-02 17:02:02317 options.test_runner,
[email protected]4f777ca2014-08-08 01:45:59318 options.test_support_apk_path,
319 options.device_flags
[email protected]5e2f3f62014-06-23 12:31:46320 )
[email protected]2a684222013-08-01 16:59:22321
[email protected]fbe29322013-07-09 09:03:26322
323def AddUIAutomatorTestOptions(option_parser):
324 """Adds UI Automator test options to |option_parser|."""
325
326 option_parser.usage = '%prog uiautomator [options]'
[email protected]dfffbcbc2013-09-17 22:06:01327 option_parser.commands_dict = {}
[email protected]fbe29322013-07-09 09:03:26328 option_parser.example = (
[email protected]efeb59e2014-03-12 01:31:26329 '%prog uiautomator --test-jar=chrome_shell_uiautomator_tests'
330 ' --package=chrome_shell')
[email protected]fbe29322013-07-09 09:03:26331 option_parser.add_option(
[email protected]a8886c8a92013-10-08 17:29:30332 '--package',
333 help=('Package under test. Possible values: %s' %
334 constants.PACKAGE_INFO.keys()))
[email protected]fbe29322013-07-09 09:03:26335 option_parser.add_option(
336 '--test-jar', dest='test_jar',
337 help=('The name of the dexed jar containing the tests (without the '
338 '.dex.jar extension). Alternatively, this can be a full path '
339 'to the jar.'))
340
341 AddJavaTestOptions(option_parser)
342 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13343 AddDeviceOptions(option_parser)
[email protected]fbe29322013-07-09 09:03:26344
345
346def ProcessUIAutomatorOptions(options, error_func):
[email protected]2a684222013-08-01 16:59:22347 """Processes UIAutomator options/arguments.
348
349 Args:
350 options: optparse.Options object.
351 error_func: Function to call with the error message in case of an error.
352
353 Returns:
354 A UIAutomatorOptions named tuple which contains all options relevant to
[email protected]3dbdfa42013-08-08 01:08:14355 uiautomator tests.
[email protected]2a684222013-08-01 16:59:22356 """
[email protected]fbe29322013-07-09 09:03:26357
[email protected]7c53a602014-03-24 16:21:44358 ProcessJavaTestOptions(options)
[email protected]fbe29322013-07-09 09:03:26359
[email protected]a8886c8a92013-10-08 17:29:30360 if not options.package:
361 error_func('--package is required.')
362
363 if options.package not in constants.PACKAGE_INFO:
364 error_func('Invalid package.')
[email protected]fbe29322013-07-09 09:03:26365
366 if not options.test_jar:
367 error_func('--test-jar must be specified.')
368
369 if os.path.exists(options.test_jar):
370 # The dexed JAR is fully qualified, assume the info JAR lives along side.
371 options.uiautomator_jar = options.test_jar
372 else:
373 options.uiautomator_jar = os.path.join(
[email protected]ae68d4a2013-09-24 21:57:15374 constants.GetOutDirectory(),
375 constants.SDK_BUILD_JAVALIB_DIR,
[email protected]fbe29322013-07-09 09:03:26376 '%s.dex.jar' % options.test_jar)
377 options.uiautomator_info_jar = (
378 options.uiautomator_jar[:options.uiautomator_jar.find('.dex.jar')] +
379 '_java.jar')
380
[email protected]2a684222013-08-01 16:59:22381 return uiautomator_test_options.UIAutomatorOptions(
[email protected]2a684222013-08-01 16:59:22382 options.tool,
383 options.cleanup_test_files,
[email protected]2a684222013-08-01 16:59:22384 options.annotations,
385 options.exclude_annotations,
386 options.test_filter,
387 options.test_data,
388 options.save_perf_json,
389 options.screenshot_failures,
[email protected]2a684222013-08-01 16:59:22390 options.uiautomator_jar,
391 options.uiautomator_info_jar,
[email protected]a8886c8a92013-10-08 17:29:30392 options.package)
[email protected]2a684222013-08-01 16:59:22393
[email protected]fbe29322013-07-09 09:03:26394
jbudorick9a6b7b332014-09-20 00:01:07395def AddJUnitTestOptions(option_parser):
396 """Adds junit test options to |option_parser|."""
397 option_parser.usage = '%prog junit -s [test suite name]'
398 option_parser.commands_dict = {}
399
400 option_parser.add_option(
401 '-s', '--test-suite', dest='test_suite',
402 help=('JUnit test suite to run.'))
403 option_parser.add_option(
404 '-f', '--test-filter', dest='test_filter',
405 help='Filters tests googletest-style.')
406 option_parser.add_option(
407 '--package-filter', dest='package_filter',
408 help='Filters tests by package.')
409 option_parser.add_option(
410 '--runner-filter', dest='runner_filter',
411 help='Filters tests by runner class. Must be fully qualified.')
412 option_parser.add_option(
413 '--sdk-version', dest='sdk_version', type="int",
414 help='The Android SDK version.')
415 AddCommonOptions(option_parser)
416
417
418def ProcessJUnitTestOptions(options, error_func):
419 """Processes all JUnit test options."""
420 if not options.test_suite:
421 error_func('No test suite specified.')
422 return options
423
424
[email protected]3dbdfa42013-08-08 01:08:14425def AddMonkeyTestOptions(option_parser):
426 """Adds monkey test options to |option_parser|."""
[email protected]fb81b982013-08-09 00:07:12427
428 option_parser.usage = '%prog monkey [options]'
[email protected]dfffbcbc2013-09-17 22:06:01429 option_parser.commands_dict = {}
[email protected]fb81b982013-08-09 00:07:12430 option_parser.example = (
[email protected]efeb59e2014-03-12 01:31:26431 '%prog monkey --package=chrome_shell')
[email protected]fb81b982013-08-09 00:07:12432
[email protected]3dbdfa42013-08-08 01:08:14433 option_parser.add_option(
[email protected]a8886c8a92013-10-08 17:29:30434 '--package',
435 help=('Package under test. Possible values: %s' %
436 constants.PACKAGE_INFO.keys()))
[email protected]3dbdfa42013-08-08 01:08:14437 option_parser.add_option(
438 '--event-count', default=10000, type='int',
439 help='Number of events to generate [default: %default].')
440 option_parser.add_option(
441 '--category', default='',
[email protected]fb81b982013-08-09 00:07:12442 help='A list of allowed categories.')
[email protected]3dbdfa42013-08-08 01:08:14443 option_parser.add_option(
444 '--throttle', default=100, type='int',
445 help='Delay between events (ms) [default: %default]. ')
446 option_parser.add_option(
447 '--seed', type='int',
448 help=('Seed value for pseudo-random generator. Same seed value generates '
449 'the same sequence of events. Seed is randomized by default.'))
450 option_parser.add_option(
451 '--extra-args', default='',
452 help=('String of other args to pass to the command verbatim '
453 '[default: "%default"].'))
454
455 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13456 AddDeviceOptions(option_parser)
[email protected]3dbdfa42013-08-08 01:08:14457
458
459def ProcessMonkeyTestOptions(options, error_func):
460 """Processes all monkey test options.
461
462 Args:
463 options: optparse.Options object.
464 error_func: Function to call with the error message in case of an error.
465
466 Returns:
467 A MonkeyOptions named tuple which contains all options relevant to
468 monkey tests.
469 """
[email protected]a8886c8a92013-10-08 17:29:30470 if not options.package:
471 error_func('--package is required.')
472
473 if options.package not in constants.PACKAGE_INFO:
474 error_func('Invalid package.')
[email protected]3dbdfa42013-08-08 01:08:14475
476 category = options.category
477 if category:
478 category = options.category.split(',')
479
480 return monkey_test_options.MonkeyOptions(
[email protected]3dbdfa42013-08-08 01:08:14481 options.verbose_count,
[email protected]a8886c8a92013-10-08 17:29:30482 options.package,
[email protected]3dbdfa42013-08-08 01:08:14483 options.event_count,
484 category,
485 options.throttle,
486 options.seed,
487 options.extra_args)
488
489
[email protected]ec3170b2013-08-14 14:39:47490def AddPerfTestOptions(option_parser):
491 """Adds perf test options to |option_parser|."""
492
493 option_parser.usage = '%prog perf [options]'
[email protected]dfffbcbc2013-09-17 22:06:01494 option_parser.commands_dict = {}
[email protected]def4bce2013-11-12 12:59:52495 option_parser.example = ('%prog perf '
[email protected]ad32f312013-11-13 04:03:29496 '[--single-step -- command args] or '
[email protected]def4bce2013-11-12 12:59:52497 '[--steps perf_steps.json] or '
[email protected]ad32f312013-11-13 04:03:29498 '[--print-step step]')
[email protected]ec3170b2013-08-14 14:39:47499
[email protected]181a5c92013-09-06 17:11:46500 option_parser.add_option(
[email protected]def4bce2013-11-12 12:59:52501 '--single-step',
[email protected]ad32f312013-11-13 04:03:29502 action='store_true',
[email protected]def4bce2013-11-12 12:59:52503 help='Execute the given command with retries, but only print the result '
504 'for the "most successful" round.')
505 option_parser.add_option(
[email protected]181a5c92013-09-06 17:11:46506 '--steps',
[email protected]def4bce2013-11-12 12:59:52507 help='JSON file containing the list of commands to run.')
[email protected]181a5c92013-09-06 17:11:46508 option_parser.add_option(
509 '--flaky-steps',
510 help=('A JSON file containing steps that are flaky '
511 'and will have its exit code ignored.'))
512 option_parser.add_option(
[email protected]61487ed2014-06-09 12:33:56513 '--output-json-list',
514 help='Write a simple list of names from --steps into the given file.')
515 option_parser.add_option(
[email protected]181a5c92013-09-06 17:11:46516 '--print-step',
517 help='The name of a previously executed perf step to print.')
518 option_parser.add_option(
519 '--no-timeout', action='store_true',
520 help=('Do not impose a timeout. Each perf step is responsible for '
521 'implementing the timeout logic.'))
[email protected]650487c2013-09-30 11:40:49522 option_parser.add_option(
523 '-f', '--test-filter',
524 help=('Test filter (will match against the names listed in --steps).'))
525 option_parser.add_option(
526 '--dry-run',
527 action='store_true',
528 help='Just print the steps without executing.')
[email protected]ec3170b2013-08-14 14:39:47529 AddCommonOptions(option_parser)
jbudorick256fd532014-10-24 01:50:13530 AddDeviceOptions(option_parser)
[email protected]ec3170b2013-08-14 14:39:47531
532
[email protected]ad32f312013-11-13 04:03:29533def ProcessPerfTestOptions(options, args, error_func):
[email protected]ec3170b2013-08-14 14:39:47534 """Processes all perf test options.
535
536 Args:
537 options: optparse.Options object.
538 error_func: Function to call with the error message in case of an error.
539
540 Returns:
541 A PerfOptions named tuple which contains all options relevant to
542 perf tests.
543 """
[email protected]def4bce2013-11-12 12:59:52544 # Only one of steps, print_step or single_step must be provided.
545 count = len(filter(None,
546 [options.steps, options.print_step, options.single_step]))
547 if count != 1:
548 error_func('Please specify one of: --steps, --print-step, --single-step.')
[email protected]ad32f312013-11-13 04:03:29549 single_step = None
550 if options.single_step:
551 single_step = ' '.join(args[2:])
[email protected]ec3170b2013-08-14 14:39:47552 return perf_test_options.PerfOptions(
[email protected]61487ed2014-06-09 12:33:56553 options.steps, options.flaky_steps, options.output_json_list,
554 options.print_step, options.no_timeout, options.test_filter,
555 options.dry_run, single_step)
[email protected]ec3170b2013-08-14 14:39:47556
557
jbudorick256fd532014-10-24 01:50:13558def AddPythonTestOptions(option_parser):
559 option_parser.add_option('-s', '--suite', dest='suite_name',
560 help=('Name of the test suite to run'
561 '(use -s help to list them).'))
562 AddCommonOptions(option_parser)
563
564
565def ProcessPythonTestOptions(options, error_func):
566 if options.suite_name not in constants.PYTHON_UNIT_TEST_SUITES:
567 available = ('Available test suites: [%s]' %
568 ', '.join(constants.PYTHON_UNIT_TEST_SUITES.iterkeys()))
569 if options.suite_name == 'help':
570 print available
571 else:
572 error_func('"%s" is not a valid suite. %s' %
573 (options.suite_name, available))
574
575
[email protected]7c53a602014-03-24 16:21:44576def _RunGTests(options, devices):
[email protected]6bc1bda22013-07-19 22:08:37577 """Subcommand of RunTestsCommands which runs gtests."""
[email protected]2a684222013-08-01 16:59:22578 ProcessGTestOptions(options)
[email protected]6bc1bda22013-07-19 22:08:37579
580 exit_code = 0
581 for suite_name in options.suite_name:
[email protected]2a684222013-08-01 16:59:22582 # TODO(gkanwar): Move this into ProcessGTestOptions once we require -s for
583 # the gtest command.
584 gtest_options = gtest_test_options.GTestOptions(
[email protected]2a684222013-08-01 16:59:22585 options.tool,
586 options.cleanup_test_files,
[email protected]2a684222013-08-01 16:59:22587 options.test_filter,
[email protected]dfffbcbc2013-09-17 22:06:01588 options.run_disabled,
[email protected]2a684222013-08-01 16:59:22589 options.test_arguments,
590 options.timeout,
[email protected]5b8b8742014-05-22 08:18:50591 options.isolate_file_path,
[email protected]2a684222013-08-01 16:59:22592 suite_name)
[email protected]f7148dd42013-08-20 14:24:57593 runner_factory, tests = gtest_setup.Setup(gtest_options, devices)
[email protected]6bc1bda22013-07-19 22:08:37594
595 results, test_exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57596 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]6bc1bda22013-07-19 22:08:37597 num_retries=options.num_retries)
598
599 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE:
600 exit_code = test_exit_code
601
602 report_results.LogFull(
603 results=results,
604 test_type='Unit test',
605 test_package=suite_name,
[email protected]6bc1bda22013-07-19 22:08:37606 flakiness_server=options.flakiness_dashboard_server)
607
608 if os.path.isdir(constants.ISOLATE_DEPS_DIR):
609 shutil.rmtree(constants.ISOLATE_DEPS_DIR)
610
611 return exit_code
612
613
[email protected]7c53a602014-03-24 16:21:44614def _RunLinkerTests(options, devices):
[email protected]6b6abac6d2013-10-03 11:56:38615 """Subcommand of RunTestsCommands which runs linker tests."""
616 runner_factory, tests = linker_setup.Setup(options, devices)
617
618 results, exit_code = test_dispatcher.RunTests(
619 tests, runner_factory, devices, shard=True, test_timeout=60,
620 num_retries=options.num_retries)
621
622 report_results.LogFull(
623 results=results,
624 test_type='Linker test',
[email protected]93c9f9b2014-02-10 16:19:22625 test_package='ChromiumLinkerTest')
[email protected]6b6abac6d2013-10-03 11:56:38626
627 return exit_code
628
629
[email protected]f7148dd42013-08-20 14:24:57630def _RunInstrumentationTests(options, error_func, devices):
[email protected]6bc1bda22013-07-19 22:08:37631 """Subcommand of RunTestsCommands which runs instrumentation tests."""
[email protected]2a684222013-08-01 16:59:22632 instrumentation_options = ProcessInstrumentationOptions(options, error_func)
[email protected]6bc1bda22013-07-19 22:08:37633
[email protected]f7148dd42013-08-20 14:24:57634 if len(devices) > 1 and options.wait_for_debugger:
635 logging.warning('Debugger can not be sharded, using first available device')
636 devices = devices[:1]
637
[email protected]6bc1bda22013-07-19 22:08:37638 results = base_test_result.TestRunResults()
639 exit_code = 0
640
641 if options.run_java_tests:
[email protected]2a684222013-08-01 16:59:22642 runner_factory, tests = instrumentation_setup.Setup(instrumentation_options)
[email protected]6bc1bda22013-07-19 22:08:37643
644 test_results, exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57645 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]6bc1bda22013-07-19 22:08:37646 num_retries=options.num_retries)
647
648 results.AddTestRunResults(test_results)
649
650 if options.run_python_tests:
[email protected]37ee0c792013-08-06 19:10:13651 runner_factory, tests = host_driven_setup.InstrumentationSetup(
[email protected]67954f822013-08-14 18:09:08652 options.host_driven_root, options.official_build,
[email protected]37ee0c792013-08-06 19:10:13653 instrumentation_options)
654
[email protected]34020022013-08-06 23:35:34655 if tests:
656 test_results, test_exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57657 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]34020022013-08-06 23:35:34658 num_retries=options.num_retries)
[email protected]6bc1bda22013-07-19 22:08:37659
[email protected]34020022013-08-06 23:35:34660 results.AddTestRunResults(test_results)
[email protected]6bc1bda22013-07-19 22:08:37661
[email protected]34020022013-08-06 23:35:34662 # Only allow exit code escalation
663 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE:
664 exit_code = test_exit_code
[email protected]6bc1bda22013-07-19 22:08:37665
[email protected]4f777ca2014-08-08 01:45:59666 if options.device_flags:
667 options.device_flags = os.path.join(constants.DIR_SOURCE_ROOT,
668 options.device_flags)
669
[email protected]6bc1bda22013-07-19 22:08:37670 report_results.LogFull(
671 results=results,
672 test_type='Instrumentation',
673 test_package=os.path.basename(options.test_apk),
674 annotation=options.annotations,
[email protected]6bc1bda22013-07-19 22:08:37675 flakiness_server=options.flakiness_dashboard_server)
676
677 return exit_code
678
679
[email protected]f7148dd42013-08-20 14:24:57680def _RunUIAutomatorTests(options, error_func, devices):
[email protected]6bc1bda22013-07-19 22:08:37681 """Subcommand of RunTestsCommands which runs uiautomator tests."""
[email protected]2a684222013-08-01 16:59:22682 uiautomator_options = ProcessUIAutomatorOptions(options, error_func)
[email protected]6bc1bda22013-07-19 22:08:37683
[email protected]37ee0c792013-08-06 19:10:13684 runner_factory, tests = uiautomator_setup.Setup(uiautomator_options)
[email protected]6bc1bda22013-07-19 22:08:37685
[email protected]37ee0c792013-08-06 19:10:13686 results, exit_code = test_dispatcher.RunTests(
[email protected]f7148dd42013-08-20 14:24:57687 tests, runner_factory, devices, shard=True, test_timeout=None,
[email protected]37ee0c792013-08-06 19:10:13688 num_retries=options.num_retries)
[email protected]6bc1bda22013-07-19 22:08:37689
690 report_results.LogFull(
691 results=results,
692 test_type='UIAutomator',
693 test_package=os.path.basename(options.test_jar),
694 annotation=options.annotations,
[email protected]6bc1bda22013-07-19 22:08:37695 flakiness_server=options.flakiness_dashboard_server)
696
697 return exit_code
698
699
jbudorick9a6b7b332014-09-20 00:01:07700def _RunJUnitTests(options, error_func):
701 """Subcommand of RunTestsCommand which runs junit tests."""
702 junit_options = ProcessJUnitTestOptions(options, error_func)
703 runner_factory, tests = junit_setup.Setup(junit_options)
704 _, exit_code = junit_dispatcher.RunTests(tests, runner_factory)
705
706 return exit_code
707
708
[email protected]f7148dd42013-08-20 14:24:57709def _RunMonkeyTests(options, error_func, devices):
[email protected]3dbdfa42013-08-08 01:08:14710 """Subcommand of RunTestsCommands which runs monkey tests."""
711 monkey_options = ProcessMonkeyTestOptions(options, error_func)
712
713 runner_factory, tests = monkey_setup.Setup(monkey_options)
714
715 results, exit_code = test_dispatcher.RunTests(
[email protected]181a5c92013-09-06 17:11:46716 tests, runner_factory, devices, shard=False, test_timeout=None,
717 num_retries=options.num_retries)
[email protected]3dbdfa42013-08-08 01:08:14718
719 report_results.LogFull(
720 results=results,
721 test_type='Monkey',
[email protected]14b3b1202013-08-15 22:25:28722 test_package='Monkey')
[email protected]3dbdfa42013-08-08 01:08:14723
724 return exit_code
725
726
[email protected]a72f0752014-06-03 23:52:34727def _RunPerfTests(options, args, error_func):
[email protected]ec3170b2013-08-14 14:39:47728 """Subcommand of RunTestsCommands which runs perf tests."""
[email protected]ad32f312013-11-13 04:03:29729 perf_options = ProcessPerfTestOptions(options, args, error_func)
[email protected]61487ed2014-06-09 12:33:56730
731 # Just save a simple json with a list of test names.
732 if perf_options.output_json_list:
733 return perf_test_runner.OutputJsonList(
734 perf_options.steps, perf_options.output_json_list)
735
[email protected]ad32f312013-11-13 04:03:29736 # Just print the results from a single previously executed step.
[email protected]ec3170b2013-08-14 14:39:47737 if perf_options.print_step:
738 return perf_test_runner.PrintTestOutput(perf_options.print_step)
739
[email protected]a72f0752014-06-03 23:52:34740 runner_factory, tests, devices = perf_setup.Setup(perf_options)
[email protected]ec3170b2013-08-14 14:39:47741
[email protected]a72f0752014-06-03 23:52:34742 # shard=False means that each device will get the full list of tests
743 # and then each one will decide their own affinity.
744 # shard=True means each device will pop the next test available from a queue,
745 # which increases throughput but have no affinity.
[email protected]86184c7b2013-08-15 15:06:57746 results, _ = test_dispatcher.RunTests(
[email protected]a72f0752014-06-03 23:52:34747 tests, runner_factory, devices, shard=False, test_timeout=None,
[email protected]181a5c92013-09-06 17:11:46748 num_retries=options.num_retries)
[email protected]ec3170b2013-08-14 14:39:47749
750 report_results.LogFull(
751 results=results,
752 test_type='Perf',
[email protected]865a47a2013-08-16 14:01:12753 test_package='Perf')
[email protected]def4bce2013-11-12 12:59:52754
755 if perf_options.single_step:
756 return perf_test_runner.PrintTestOutput('single_step')
757
[email protected]11ce8452014-02-17 10:55:03758 perf_test_runner.PrintSummary(tests)
759
[email protected]86184c7b2013-08-15 15:06:57760 # Always return 0 on the sharding stage. Individual tests exit_code
761 # will be returned on the print_step stage.
762 return 0
[email protected]ec3170b2013-08-14 14:39:47763
[email protected]3dbdfa42013-08-08 01:08:14764
jbudorick256fd532014-10-24 01:50:13765def _RunPythonTests(options, error_func):
766 """Subcommand of RunTestsCommand which runs python unit tests."""
767 ProcessPythonTestOptions(options, error_func)
768
769 suite_vars = constants.PYTHON_UNIT_TEST_SUITES[options.suite_name]
770 suite_path = suite_vars['path']
771 suite_test_modules = suite_vars['test_modules']
772
773 sys.path = [suite_path] + sys.path
774 try:
775 suite = unittest.TestSuite()
776 suite.addTests(unittest.defaultTestLoader.loadTestsFromName(m)
777 for m in suite_test_modules)
778 runner = unittest.TextTestRunner(verbosity=1+options.verbose_count)
779 return 0 if runner.run(suite).wasSuccessful() else 1
780 finally:
781 sys.path = sys.path[1:]
782
783
[email protected]f7148dd42013-08-20 14:24:57784def _GetAttachedDevices(test_device=None):
785 """Get all attached devices.
786
787 Args:
788 test_device: Name of a specific device to use.
789
790 Returns:
791 A list of attached devices.
792 """
793 attached_devices = []
794
795 attached_devices = android_commands.GetAttachedDevices()
796 if test_device:
797 assert test_device in attached_devices, (
798 'Did not find device %s among attached device. Attached devices: %s'
799 % (test_device, ', '.join(attached_devices)))
800 attached_devices = [test_device]
801
802 assert attached_devices, 'No devices attached.'
803
804 return sorted(attached_devices)
805
806
[email protected]fbe29322013-07-09 09:03:26807def RunTestsCommand(command, options, args, option_parser):
808 """Checks test type and dispatches to the appropriate function.
809
810 Args:
811 command: String indicating the command that was received to trigger
812 this function.
813 options: optparse options dictionary.
814 args: List of extra args from optparse.
815 option_parser: optparse.OptionParser object.
816
817 Returns:
818 Integer indicated exit code.
[email protected]b3873892013-07-10 04:57:10819
820 Raises:
821 Exception: Unknown command name passed in, or an exception from an
822 individual test runner.
[email protected]fbe29322013-07-09 09:03:26823 """
824
[email protected]d82f0252013-07-12 23:22:57825 # Check for extra arguments
[email protected]ad32f312013-11-13 04:03:29826 if len(args) > 2 and command != 'perf':
[email protected]d82f0252013-07-12 23:22:57827 option_parser.error('Unrecognized arguments: %s' % (' '.join(args[2:])))
828 return constants.ERROR_EXIT_CODE
[email protected]ad32f312013-11-13 04:03:29829 if command == 'perf':
830 if ((options.single_step and len(args) <= 2) or
831 (not options.single_step and len(args) > 2)):
832 option_parser.error('Unrecognized arguments: %s' % (' '.join(args)))
833 return constants.ERROR_EXIT_CODE
[email protected]d82f0252013-07-12 23:22:57834
[email protected]fbe29322013-07-09 09:03:26835 ProcessCommonOptions(options)
836
jbudorick256fd532014-10-24 01:50:13837 if command in HOST_TESTS:
838 devices = []
839 else:
840 devices = _GetAttachedDevices(options.test_device)
[email protected]f7148dd42013-08-20 14:24:57841
[email protected]c0662e092013-11-12 11:51:25842 forwarder.Forwarder.RemoveHostLog()
[email protected]6b11583b2013-11-21 16:18:40843 if not ports.ResetTestServerPortAllocation():
844 raise Exception('Failed to reset test server port.')
[email protected]c0662e092013-11-12 11:51:25845
[email protected]fbe29322013-07-09 09:03:26846 if command == 'gtest':
[email protected]7c53a602014-03-24 16:21:44847 return _RunGTests(options, devices)
[email protected]6b6abac6d2013-10-03 11:56:38848 elif command == 'linker':
[email protected]7c53a602014-03-24 16:21:44849 return _RunLinkerTests(options, devices)
[email protected]fbe29322013-07-09 09:03:26850 elif command == 'instrumentation':
[email protected]f7148dd42013-08-20 14:24:57851 return _RunInstrumentationTests(options, option_parser.error, devices)
[email protected]fbe29322013-07-09 09:03:26852 elif command == 'uiautomator':
[email protected]f7148dd42013-08-20 14:24:57853 return _RunUIAutomatorTests(options, option_parser.error, devices)
jbudorick9a6b7b332014-09-20 00:01:07854 elif command == 'junit':
855 return _RunJUnitTests(options, option_parser.error)
[email protected]3dbdfa42013-08-08 01:08:14856 elif command == 'monkey':
[email protected]f7148dd42013-08-20 14:24:57857 return _RunMonkeyTests(options, option_parser.error, devices)
[email protected]ec3170b2013-08-14 14:39:47858 elif command == 'perf':
[email protected]a72f0752014-06-03 23:52:34859 return _RunPerfTests(options, args, option_parser.error)
jbudorick256fd532014-10-24 01:50:13860 elif command == 'python':
861 return _RunPythonTests(options, option_parser.error)
[email protected]fbe29322013-07-09 09:03:26862 else:
[email protected]6bc1bda22013-07-19 22:08:37863 raise Exception('Unknown test type.')
[email protected]fbe29322013-07-09 09:03:26864
[email protected]fbe29322013-07-09 09:03:26865
[email protected]7c53a602014-03-24 16:21:44866def HelpCommand(command, _options, args, option_parser):
[email protected]fbe29322013-07-09 09:03:26867 """Display help for a certain command, or overall help.
868
869 Args:
870 command: String indicating the command that was received to trigger
871 this function.
[email protected]7c53a602014-03-24 16:21:44872 options: optparse options dictionary. unused.
[email protected]fbe29322013-07-09 09:03:26873 args: List of extra args from optparse.
874 option_parser: optparse.OptionParser object.
875
876 Returns:
877 Integer indicated exit code.
878 """
879 # If we don't have any args, display overall help
880 if len(args) < 3:
881 option_parser.print_help()
882 return 0
[email protected]d82f0252013-07-12 23:22:57883 # If we have too many args, print an error
884 if len(args) > 3:
885 option_parser.error('Unrecognized arguments: %s' % (' '.join(args[3:])))
886 return constants.ERROR_EXIT_CODE
[email protected]fbe29322013-07-09 09:03:26887
888 command = args[2]
889
890 if command not in VALID_COMMANDS:
891 option_parser.error('Unrecognized command.')
892
893 # Treat the help command as a special case. We don't care about showing a
894 # specific help page for itself.
895 if command == 'help':
896 option_parser.print_help()
897 return 0
898
899 VALID_COMMANDS[command].add_options_func(option_parser)
900 option_parser.usage = '%prog ' + command + ' [options]'
[email protected]dfffbcbc2013-09-17 22:06:01901 option_parser.commands_dict = {}
[email protected]fbe29322013-07-09 09:03:26902 option_parser.print_help()
903
904 return 0
905
906
907# Define a named tuple for the values in the VALID_COMMANDS dictionary so the
908# syntax is a bit prettier. The tuple is two functions: (add options, run
909# command).
910CommandFunctionTuple = collections.namedtuple(
911 'CommandFunctionTuple', ['add_options_func', 'run_command_func'])
912VALID_COMMANDS = {
913 'gtest': CommandFunctionTuple(AddGTestOptions, RunTestsCommand),
[email protected]fbe29322013-07-09 09:03:26914 'instrumentation': CommandFunctionTuple(
915 AddInstrumentationTestOptions, RunTestsCommand),
916 'uiautomator': CommandFunctionTuple(
917 AddUIAutomatorTestOptions, RunTestsCommand),
jbudorick9a6b7b332014-09-20 00:01:07918 'junit': CommandFunctionTuple(
919 AddJUnitTestOptions, RunTestsCommand),
[email protected]3dbdfa42013-08-08 01:08:14920 'monkey': CommandFunctionTuple(
921 AddMonkeyTestOptions, RunTestsCommand),
[email protected]ec3170b2013-08-14 14:39:47922 'perf': CommandFunctionTuple(
923 AddPerfTestOptions, RunTestsCommand),
jbudorick256fd532014-10-24 01:50:13924 'python': CommandFunctionTuple(
925 AddPythonTestOptions, RunTestsCommand),
[email protected]6b6abac6d2013-10-03 11:56:38926 'linker': CommandFunctionTuple(
927 AddLinkerTestOptions, RunTestsCommand),
[email protected]fbe29322013-07-09 09:03:26928 'help': CommandFunctionTuple(lambda option_parser: None, HelpCommand)
929 }
930
931
[email protected]7c53a602014-03-24 16:21:44932def DumpThreadStacks(_signal, _frame):
[email protected]71aec4b2013-11-20 00:35:24933 for thread in threading.enumerate():
934 reraiser_thread.LogThreadStack(thread)
[email protected]83bb8152013-11-19 15:02:21935
936
[email protected]7c53a602014-03-24 16:21:44937def main():
[email protected]83bb8152013-11-19 15:02:21938 signal.signal(signal.SIGUSR1, DumpThreadStacks)
[email protected]803f65a72013-08-20 19:11:30939 option_parser = command_option_parser.CommandOptionParser(
940 commands_dict=VALID_COMMANDS)
941 return command_option_parser.ParseAndExecute(option_parser)
[email protected]fbe29322013-07-09 09:03:26942
[email protected]fbe29322013-07-09 09:03:26943
944if __name__ == '__main__':
[email protected]7c53a602014-03-24 16:21:44945 sys.exit(main())