xref: /aosp_15_r20/external/cronet/build/android/test_runner.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env vpython3
2*6777b538SAndroid Build Coastguard Worker#
3*6777b538SAndroid Build Coastguard Worker# Copyright 2013 The Chromium Authors
4*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
5*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker"""Runs all types of tests from one unified interface."""
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Workerfrom __future__ import absolute_import
10*6777b538SAndroid Build Coastguard Workerimport argparse
11*6777b538SAndroid Build Coastguard Workerimport collections
12*6777b538SAndroid Build Coastguard Workerimport contextlib
13*6777b538SAndroid Build Coastguard Workerimport io
14*6777b538SAndroid Build Coastguard Workerimport itertools
15*6777b538SAndroid Build Coastguard Workerimport logging
16*6777b538SAndroid Build Coastguard Workerimport os
17*6777b538SAndroid Build Coastguard Workerimport re
18*6777b538SAndroid Build Coastguard Workerimport shlex
19*6777b538SAndroid Build Coastguard Workerimport shutil
20*6777b538SAndroid Build Coastguard Workerimport signal
21*6777b538SAndroid Build Coastguard Workerimport sys
22*6777b538SAndroid Build Coastguard Workerimport tempfile
23*6777b538SAndroid Build Coastguard Workerimport threading
24*6777b538SAndroid Build Coastguard Workerimport traceback
25*6777b538SAndroid Build Coastguard Workerimport unittest
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker# Import _strptime before threaded code. datetime.datetime.strptime is
28*6777b538SAndroid Build Coastguard Worker# threadsafe except for the initial import of the _strptime module.
29*6777b538SAndroid Build Coastguard Worker# See http://crbug.com/724524 and https://bugs.python.org/issue7980.
30*6777b538SAndroid Build Coastguard Workerimport _strptime  # pylint: disable=unused-import
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker# pylint: disable=ungrouped-imports
33*6777b538SAndroid Build Coastguard Workerfrom pylib.constants import host_paths
34*6777b538SAndroid Build Coastguard Worker
35*6777b538SAndroid Build Coastguard Workerif host_paths.DEVIL_PATH not in sys.path:
36*6777b538SAndroid Build Coastguard Worker  sys.path.append(host_paths.DEVIL_PATH)
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Workerfrom devil import base_error
39*6777b538SAndroid Build Coastguard Workerfrom devil.utils import reraiser_thread
40*6777b538SAndroid Build Coastguard Workerfrom devil.utils import run_tests_helper
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Workerfrom pylib import constants
43*6777b538SAndroid Build Coastguard Workerfrom pylib.base import base_test_result
44*6777b538SAndroid Build Coastguard Workerfrom pylib.base import environment_factory
45*6777b538SAndroid Build Coastguard Workerfrom pylib.base import output_manager
46*6777b538SAndroid Build Coastguard Workerfrom pylib.base import output_manager_factory
47*6777b538SAndroid Build Coastguard Workerfrom pylib.base import test_instance_factory
48*6777b538SAndroid Build Coastguard Workerfrom pylib.base import test_run_factory
49*6777b538SAndroid Build Coastguard Workerfrom pylib.results import json_results
50*6777b538SAndroid Build Coastguard Workerfrom pylib.results import report_results
51*6777b538SAndroid Build Coastguard Workerfrom pylib.results.presentation import test_results_presentation
52*6777b538SAndroid Build Coastguard Workerfrom pylib.utils import local_utils
53*6777b538SAndroid Build Coastguard Workerfrom pylib.utils import logdog_helper
54*6777b538SAndroid Build Coastguard Workerfrom pylib.utils import logging_utils
55*6777b538SAndroid Build Coastguard Workerfrom pylib.utils import test_filter
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Workerfrom py_utils import contextlib_ext
58*6777b538SAndroid Build Coastguard Worker
59*6777b538SAndroid Build Coastguard Workerfrom lib.results import result_sink  # pylint: disable=import-error
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker_DEVIL_STATIC_CONFIG_FILE = os.path.abspath(os.path.join(
62*6777b538SAndroid Build Coastguard Worker    host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'devil_config.json'))
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker_RERUN_FAILED_TESTS_FILE = 'rerun_failed_tests.filter'
65*6777b538SAndroid Build Coastguard Worker
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Workerdef _RealPath(arg):
68*6777b538SAndroid Build Coastguard Worker  if arg.startswith('//'):
69*6777b538SAndroid Build Coastguard Worker    arg = os.path.abspath(os.path.join(host_paths.DIR_SOURCE_ROOT,
70*6777b538SAndroid Build Coastguard Worker                                       arg[2:].replace('/', os.sep)))
71*6777b538SAndroid Build Coastguard Worker  return os.path.realpath(arg)
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Workerdef AddTestLauncherOptions(parser):
75*6777b538SAndroid Build Coastguard Worker  """Adds arguments mirroring //base/test/launcher.
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker  Args:
78*6777b538SAndroid Build Coastguard Worker    parser: The parser to which arguments should be added.
79*6777b538SAndroid Build Coastguard Worker  Returns:
80*6777b538SAndroid Build Coastguard Worker    The given parser.
81*6777b538SAndroid Build Coastguard Worker  """
82*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
83*6777b538SAndroid Build Coastguard Worker      '--test-launcher-retry-limit',
84*6777b538SAndroid Build Coastguard Worker      '--test_launcher_retry_limit',
85*6777b538SAndroid Build Coastguard Worker      '--num_retries', '--num-retries',
86*6777b538SAndroid Build Coastguard Worker      '--isolated-script-test-launcher-retry-limit',
87*6777b538SAndroid Build Coastguard Worker      dest='num_retries', type=int, default=2,
88*6777b538SAndroid Build Coastguard Worker      help='Number of retries for a test before '
89*6777b538SAndroid Build Coastguard Worker           'giving up (default: %(default)s).')
90*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
91*6777b538SAndroid Build Coastguard Worker      '--test-launcher-summary-output',
92*6777b538SAndroid Build Coastguard Worker      '--json-results-file',
93*6777b538SAndroid Build Coastguard Worker      dest='json_results_file', type=os.path.realpath,
94*6777b538SAndroid Build Coastguard Worker      help='If set, will dump results in JSON form to the specified file. '
95*6777b538SAndroid Build Coastguard Worker           'Note that this will also trigger saving per-test logcats to '
96*6777b538SAndroid Build Coastguard Worker           'logdog.')
97*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
98*6777b538SAndroid Build Coastguard Worker      '--test-launcher-shard-index',
99*6777b538SAndroid Build Coastguard Worker      type=int, default=os.environ.get('GTEST_SHARD_INDEX', 0),
100*6777b538SAndroid Build Coastguard Worker      help='Index of the external shard to run.')
101*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
102*6777b538SAndroid Build Coastguard Worker      '--test-launcher-total-shards',
103*6777b538SAndroid Build Coastguard Worker      type=int, default=os.environ.get('GTEST_TOTAL_SHARDS', 1),
104*6777b538SAndroid Build Coastguard Worker      help='Total number of external shards.')
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker  test_filter.AddFilterOptions(parser)
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker  return parser
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Workerdef AddCommandLineOptions(parser):
112*6777b538SAndroid Build Coastguard Worker  """Adds arguments to support passing command-line flags to the device."""
113*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
114*6777b538SAndroid Build Coastguard Worker      '--device-flags-file',
115*6777b538SAndroid Build Coastguard Worker      type=os.path.realpath,
116*6777b538SAndroid Build Coastguard Worker      help='The relative filepath to a file containing '
117*6777b538SAndroid Build Coastguard Worker           'command-line flags to set on the device')
118*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
119*6777b538SAndroid Build Coastguard Worker      '--use-apk-under-test-flags-file',
120*6777b538SAndroid Build Coastguard Worker      action='store_true',
121*6777b538SAndroid Build Coastguard Worker      help='Wether to use the flags file for the apk under test. If set, '
122*6777b538SAndroid Build Coastguard Worker           "the filename will be looked up in the APK's PackageInfo.")
123*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--variations-test-seed-path',
124*6777b538SAndroid Build Coastguard Worker                      type=os.path.relpath,
125*6777b538SAndroid Build Coastguard Worker                      default=None,
126*6777b538SAndroid Build Coastguard Worker                      help='Path to variations seed file.')
127*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--webview-variations-test-seed-path',
128*6777b538SAndroid Build Coastguard Worker                      type=os.path.relpath,
129*6777b538SAndroid Build Coastguard Worker                      default=None,
130*6777b538SAndroid Build Coastguard Worker                      help='Path to variations seed file for WebView.')
131*6777b538SAndroid Build Coastguard Worker
132*6777b538SAndroid Build Coastguard Worker  parser.set_defaults(allow_unknown=True)
133*6777b538SAndroid Build Coastguard Worker  parser.set_defaults(command_line_flags=None)
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Worker
136*6777b538SAndroid Build Coastguard Workerdef AddTracingOptions(parser):
137*6777b538SAndroid Build Coastguard Worker  # TODO(shenghuazhang): Move this into AddCommonOptions once it's supported
138*6777b538SAndroid Build Coastguard Worker  # for all test types.
139*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
140*6777b538SAndroid Build Coastguard Worker      '--trace-output',
141*6777b538SAndroid Build Coastguard Worker      metavar='FILENAME', type=os.path.realpath,
142*6777b538SAndroid Build Coastguard Worker      help='Path to save test_runner trace json output to.')
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
145*6777b538SAndroid Build Coastguard Worker      '--trace-all',
146*6777b538SAndroid Build Coastguard Worker      action='store_true',
147*6777b538SAndroid Build Coastguard Worker      help='Whether to trace all function calls.')
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Workerdef AddCommonOptions(parser):
151*6777b538SAndroid Build Coastguard Worker  """Adds all common options to |parser|."""
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker  default_build_type = os.environ.get('BUILDTYPE', 'Debug')
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker  debug_or_release_group = parser.add_mutually_exclusive_group()
156*6777b538SAndroid Build Coastguard Worker  debug_or_release_group.add_argument(
157*6777b538SAndroid Build Coastguard Worker      '--debug',
158*6777b538SAndroid Build Coastguard Worker      action='store_const', const='Debug', dest='build_type',
159*6777b538SAndroid Build Coastguard Worker      default=default_build_type,
160*6777b538SAndroid Build Coastguard Worker      help='If set, run test suites under out/Debug. '
161*6777b538SAndroid Build Coastguard Worker           'Default is env var BUILDTYPE or Debug.')
162*6777b538SAndroid Build Coastguard Worker  debug_or_release_group.add_argument(
163*6777b538SAndroid Build Coastguard Worker      '--release',
164*6777b538SAndroid Build Coastguard Worker      action='store_const', const='Release', dest='build_type',
165*6777b538SAndroid Build Coastguard Worker      help='If set, run test suites under out/Release. '
166*6777b538SAndroid Build Coastguard Worker           'Default is env var BUILDTYPE or Debug.')
167*6777b538SAndroid Build Coastguard Worker
168*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
169*6777b538SAndroid Build Coastguard Worker      '--break-on-failure', '--break_on_failure',
170*6777b538SAndroid Build Coastguard Worker      dest='break_on_failure', action='store_true',
171*6777b538SAndroid Build Coastguard Worker      help='Whether to break on failure.')
172*6777b538SAndroid Build Coastguard Worker
173*6777b538SAndroid Build Coastguard Worker  # TODO(jbudorick): Remove this once everything has switched to platform
174*6777b538SAndroid Build Coastguard Worker  # mode.
175*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
176*6777b538SAndroid Build Coastguard Worker      '--enable-platform-mode',
177*6777b538SAndroid Build Coastguard Worker      action='store_true',
178*6777b538SAndroid Build Coastguard Worker      help='Run the test scripts in platform mode, which '
179*6777b538SAndroid Build Coastguard Worker           'conceptually separates the test runner from the '
180*6777b538SAndroid Build Coastguard Worker           '"device" (local or remote, real or emulated) on '
181*6777b538SAndroid Build Coastguard Worker           'which the tests are running. [experimental]')
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
184*6777b538SAndroid Build Coastguard Worker      '-e', '--environment',
185*6777b538SAndroid Build Coastguard Worker      default='local', choices=constants.VALID_ENVIRONMENTS,
186*6777b538SAndroid Build Coastguard Worker      help='Test environment to run in (default: %(default)s).')
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
189*6777b538SAndroid Build Coastguard Worker      '--local-output',
190*6777b538SAndroid Build Coastguard Worker      action='store_true',
191*6777b538SAndroid Build Coastguard Worker      help='Whether to archive test output locally and generate '
192*6777b538SAndroid Build Coastguard Worker           'a local results detail page.')
193*6777b538SAndroid Build Coastguard Worker
194*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--list-tests',
195*6777b538SAndroid Build Coastguard Worker                      action='store_true',
196*6777b538SAndroid Build Coastguard Worker                      help='List available tests and exit.')
197*6777b538SAndroid Build Coastguard Worker
198*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--wrapper-script-args',
199*6777b538SAndroid Build Coastguard Worker                      help='A string of args that were passed to the wrapper '
200*6777b538SAndroid Build Coastguard Worker                      'script. This should probably not be edited by a '
201*6777b538SAndroid Build Coastguard Worker                      'user as it is passed by the wrapper itself.')
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Worker  class FastLocalDevAction(argparse.Action):
204*6777b538SAndroid Build Coastguard Worker    def __call__(self, parser, namespace, values, option_string=None):
205*6777b538SAndroid Build Coastguard Worker      namespace.enable_concurrent_adb = True
206*6777b538SAndroid Build Coastguard Worker      namespace.enable_device_cache = True
207*6777b538SAndroid Build Coastguard Worker      namespace.extract_test_list_from_filter = True
208*6777b538SAndroid Build Coastguard Worker      namespace.local_output = True
209*6777b538SAndroid Build Coastguard Worker      namespace.num_retries = 0
210*6777b538SAndroid Build Coastguard Worker      namespace.skip_clear_data = True
211*6777b538SAndroid Build Coastguard Worker      namespace.use_persistent_shell = True
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
214*6777b538SAndroid Build Coastguard Worker      '--fast-local-dev',
215*6777b538SAndroid Build Coastguard Worker      type=bool,
216*6777b538SAndroid Build Coastguard Worker      nargs=0,
217*6777b538SAndroid Build Coastguard Worker      action=FastLocalDevAction,
218*6777b538SAndroid Build Coastguard Worker      help='Alias for: --num-retries=0 --enable-device-cache '
219*6777b538SAndroid Build Coastguard Worker      '--enable-concurrent-adb --skip-clear-data '
220*6777b538SAndroid Build Coastguard Worker      '--extract-test-list-from-filter --use-persistent-shell --local-output')
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Worker  # TODO(jbudorick): Remove this once downstream bots have switched to
223*6777b538SAndroid Build Coastguard Worker  # api.test_results.
224*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
225*6777b538SAndroid Build Coastguard Worker      '--flakiness-dashboard-server',
226*6777b538SAndroid Build Coastguard Worker      dest='flakiness_dashboard_server',
227*6777b538SAndroid Build Coastguard Worker      help=argparse.SUPPRESS)
228*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
229*6777b538SAndroid Build Coastguard Worker      '--gs-results-bucket',
230*6777b538SAndroid Build Coastguard Worker      help='Google Storage bucket to upload results to.')
231*6777b538SAndroid Build Coastguard Worker
232*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
233*6777b538SAndroid Build Coastguard Worker      '--output-directory',
234*6777b538SAndroid Build Coastguard Worker      dest='output_directory', type=os.path.realpath,
235*6777b538SAndroid Build Coastguard Worker      help='Path to the directory in which build files are'
236*6777b538SAndroid Build Coastguard Worker           ' located (must include build type). This will take'
237*6777b538SAndroid Build Coastguard Worker           ' precedence over --debug and --release')
238*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
239*6777b538SAndroid Build Coastguard Worker      '-v', '--verbose',
240*6777b538SAndroid Build Coastguard Worker      dest='verbose_count', default=0, action='count',
241*6777b538SAndroid Build Coastguard Worker      help='Verbose level (multiple times for more)')
242*6777b538SAndroid Build Coastguard Worker
243*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
244*6777b538SAndroid Build Coastguard Worker      '--repeat', '--gtest_repeat', '--gtest-repeat',
245*6777b538SAndroid Build Coastguard Worker      '--isolated-script-test-repeat',
246*6777b538SAndroid Build Coastguard Worker      dest='repeat', type=int, default=0,
247*6777b538SAndroid Build Coastguard Worker      help='Number of times to repeat the specified set of tests.')
248*6777b538SAndroid Build Coastguard Worker
249*6777b538SAndroid Build Coastguard Worker  # Not useful for junit tests.
250*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
251*6777b538SAndroid Build Coastguard Worker      '--use-persistent-shell',
252*6777b538SAndroid Build Coastguard Worker      action='store_true',
253*6777b538SAndroid Build Coastguard Worker      help='Uses a persistent shell connection for the adb connection.')
254*6777b538SAndroid Build Coastguard Worker
255*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--disable-test-server',
256*6777b538SAndroid Build Coastguard Worker                      action='store_true',
257*6777b538SAndroid Build Coastguard Worker                      help='Disables SpawnedTestServer which doesn'
258*6777b538SAndroid Build Coastguard Worker                      't work with remote adb. '
259*6777b538SAndroid Build Coastguard Worker                      'WARNING: Will break tests which require the server.')
260*6777b538SAndroid Build Coastguard Worker
261*6777b538SAndroid Build Coastguard Worker  # This is currently only implemented for gtests and instrumentation tests.
262*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
263*6777b538SAndroid Build Coastguard Worker      '--gtest_also_run_disabled_tests', '--gtest-also-run-disabled-tests',
264*6777b538SAndroid Build Coastguard Worker      '--isolated-script-test-also-run-disabled-tests',
265*6777b538SAndroid Build Coastguard Worker      dest='run_disabled', action='store_true',
266*6777b538SAndroid Build Coastguard Worker      help='Also run disabled tests if applicable.')
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker  # These are currently only implemented for gtests.
269*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--isolated-script-test-output',
270*6777b538SAndroid Build Coastguard Worker                      help='If present, store test results on this path.')
271*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--isolated-script-test-perf-output',
272*6777b538SAndroid Build Coastguard Worker                      help='If present, store chartjson results on this path.')
273*6777b538SAndroid Build Coastguard Worker
274*6777b538SAndroid Build Coastguard Worker  AddTestLauncherOptions(parser)
275*6777b538SAndroid Build Coastguard Worker
276*6777b538SAndroid Build Coastguard Worker
277*6777b538SAndroid Build Coastguard Workerdef ProcessCommonOptions(args):
278*6777b538SAndroid Build Coastguard Worker  """Processes and handles all common options."""
279*6777b538SAndroid Build Coastguard Worker  run_tests_helper.SetLogLevel(args.verbose_count, add_handler=False)
280*6777b538SAndroid Build Coastguard Worker  if args.verbose_count > 0:
281*6777b538SAndroid Build Coastguard Worker    handler = logging_utils.ColorStreamHandler()
282*6777b538SAndroid Build Coastguard Worker  else:
283*6777b538SAndroid Build Coastguard Worker    handler = logging.StreamHandler(sys.stdout)
284*6777b538SAndroid Build Coastguard Worker  handler.setFormatter(run_tests_helper.CustomFormatter())
285*6777b538SAndroid Build Coastguard Worker  logging.getLogger().addHandler(handler)
286*6777b538SAndroid Build Coastguard Worker
287*6777b538SAndroid Build Coastguard Worker  constants.SetBuildType(args.build_type)
288*6777b538SAndroid Build Coastguard Worker  if args.output_directory:
289*6777b538SAndroid Build Coastguard Worker    constants.SetOutputDirectory(args.output_directory)
290*6777b538SAndroid Build Coastguard Worker
291*6777b538SAndroid Build Coastguard Worker
292*6777b538SAndroid Build Coastguard Workerdef AddDeviceOptions(parser):
293*6777b538SAndroid Build Coastguard Worker  """Adds device options to |parser|."""
294*6777b538SAndroid Build Coastguard Worker
295*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group('device arguments')
296*6777b538SAndroid Build Coastguard Worker
297*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
298*6777b538SAndroid Build Coastguard Worker      '--adb-path',
299*6777b538SAndroid Build Coastguard Worker      type=os.path.realpath,
300*6777b538SAndroid Build Coastguard Worker      help='Specify the absolute path of the adb binary that '
301*6777b538SAndroid Build Coastguard Worker           'should be used.')
302*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
303*6777b538SAndroid Build Coastguard Worker      '--use-local-devil-tools',
304*6777b538SAndroid Build Coastguard Worker      action='store_true',
305*6777b538SAndroid Build Coastguard Worker      help='Use locally built versions of tools used by devil_chromium.')
306*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--denylist-file',
307*6777b538SAndroid Build Coastguard Worker                      type=os.path.realpath,
308*6777b538SAndroid Build Coastguard Worker                      help='Device denylist file.')
309*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
310*6777b538SAndroid Build Coastguard Worker      '-d', '--device', nargs='+',
311*6777b538SAndroid Build Coastguard Worker      dest='test_devices',
312*6777b538SAndroid Build Coastguard Worker      help='Target device(s) for the test suite to run on.')
313*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
314*6777b538SAndroid Build Coastguard Worker      '--enable-concurrent-adb',
315*6777b538SAndroid Build Coastguard Worker      action='store_true',
316*6777b538SAndroid Build Coastguard Worker      help='Run multiple adb commands at the same time, even '
317*6777b538SAndroid Build Coastguard Worker           'for the same device.')
318*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
319*6777b538SAndroid Build Coastguard Worker      '--enable-device-cache',
320*6777b538SAndroid Build Coastguard Worker      action='store_true',
321*6777b538SAndroid Build Coastguard Worker      help='Cache device state to disk between runs')
322*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
323*6777b538SAndroid Build Coastguard Worker      '--skip-clear-data',
324*6777b538SAndroid Build Coastguard Worker      action='store_true',
325*6777b538SAndroid Build Coastguard Worker      help='Do not wipe app data between tests. Use this to '
326*6777b538SAndroid Build Coastguard Worker           'speed up local development and never on bots '
327*6777b538SAndroid Build Coastguard Worker                     '(increases flakiness)')
328*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
329*6777b538SAndroid Build Coastguard Worker      '--recover-devices',
330*6777b538SAndroid Build Coastguard Worker      action='store_true',
331*6777b538SAndroid Build Coastguard Worker      help='Attempt to recover devices prior to the final retry. Warning: '
332*6777b538SAndroid Build Coastguard Worker           'this will cause all devices to reboot.')
333*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
334*6777b538SAndroid Build Coastguard Worker      '--tool',
335*6777b538SAndroid Build Coastguard Worker      dest='tool',
336*6777b538SAndroid Build Coastguard Worker      help='Run the test under a tool '
337*6777b538SAndroid Build Coastguard Worker           '(use --tool help to list them)')
338*6777b538SAndroid Build Coastguard Worker
339*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
340*6777b538SAndroid Build Coastguard Worker      '--upload-logcats-file',
341*6777b538SAndroid Build Coastguard Worker      action='store_true',
342*6777b538SAndroid Build Coastguard Worker      dest='upload_logcats_file',
343*6777b538SAndroid Build Coastguard Worker      help='Whether to upload logcat file to logdog.')
344*6777b538SAndroid Build Coastguard Worker
345*6777b538SAndroid Build Coastguard Worker  logcat_output_group = parser.add_mutually_exclusive_group()
346*6777b538SAndroid Build Coastguard Worker  logcat_output_group.add_argument(
347*6777b538SAndroid Build Coastguard Worker      '--logcat-output-dir', type=os.path.realpath,
348*6777b538SAndroid Build Coastguard Worker      help='If set, will dump logcats recorded during test run to directory. '
349*6777b538SAndroid Build Coastguard Worker           'File names will be the device ids with timestamps.')
350*6777b538SAndroid Build Coastguard Worker  logcat_output_group.add_argument(
351*6777b538SAndroid Build Coastguard Worker      '--logcat-output-file', type=os.path.realpath,
352*6777b538SAndroid Build Coastguard Worker      help='If set, will merge logcats recorded during test run and dump them '
353*6777b538SAndroid Build Coastguard Worker           'to the specified file.')
354*6777b538SAndroid Build Coastguard Worker
355*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
356*6777b538SAndroid Build Coastguard Worker      '--force-main-user',
357*6777b538SAndroid Build Coastguard Worker      action='store_true',
358*6777b538SAndroid Build Coastguard Worker      help='Force the applicable adb commands to run with "--user" param set '
359*6777b538SAndroid Build Coastguard Worker      'to the id of the main user on device. Only use when the main user is a '
360*6777b538SAndroid Build Coastguard Worker      'secondary user, e.g. Android Automotive OS.')
361*6777b538SAndroid Build Coastguard Worker
362*6777b538SAndroid Build Coastguard Worker
363*6777b538SAndroid Build Coastguard Workerdef AddEmulatorOptions(parser):
364*6777b538SAndroid Build Coastguard Worker  """Adds emulator-specific options to |parser|."""
365*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group('emulator arguments')
366*6777b538SAndroid Build Coastguard Worker
367*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
368*6777b538SAndroid Build Coastguard Worker      '--avd-config',
369*6777b538SAndroid Build Coastguard Worker      type=os.path.realpath,
370*6777b538SAndroid Build Coastguard Worker      help='Path to the avd config textpb. '
371*6777b538SAndroid Build Coastguard Worker      '(See //tools/android/avd/proto/ for message definition'
372*6777b538SAndroid Build Coastguard Worker      ' and existing textpb files.)')
373*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
374*6777b538SAndroid Build Coastguard Worker      '--emulator-count',
375*6777b538SAndroid Build Coastguard Worker      type=int,
376*6777b538SAndroid Build Coastguard Worker      default=1,
377*6777b538SAndroid Build Coastguard Worker      help='Number of emulators to use.')
378*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
379*6777b538SAndroid Build Coastguard Worker      '--emulator-window',
380*6777b538SAndroid Build Coastguard Worker      action='store_true',
381*6777b538SAndroid Build Coastguard Worker      default=False,
382*6777b538SAndroid Build Coastguard Worker      help='Enable graphical window display on the emulator.')
383*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
384*6777b538SAndroid Build Coastguard Worker      '--emulator-debug-tags',
385*6777b538SAndroid Build Coastguard Worker      help='Comma-separated list of debug tags. This can be used to enable or '
386*6777b538SAndroid Build Coastguard Worker      'disable debug messages from specific parts of the emulator, e.g. '
387*6777b538SAndroid Build Coastguard Worker      'init,snapshot. See "emulator -help-debug-tags" '
388*6777b538SAndroid Build Coastguard Worker      'for a full list of tags.')
389*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
390*6777b538SAndroid Build Coastguard Worker      '--emulator-enable-network',
391*6777b538SAndroid Build Coastguard Worker      action='store_true',
392*6777b538SAndroid Build Coastguard Worker      help='Enable the network (WiFi and mobile data) on the emulator.')
393*6777b538SAndroid Build Coastguard Worker
394*6777b538SAndroid Build Coastguard Worker
395*6777b538SAndroid Build Coastguard Workerdef AddGTestOptions(parser):
396*6777b538SAndroid Build Coastguard Worker  """Adds gtest options to |parser|."""
397*6777b538SAndroid Build Coastguard Worker
398*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group('gtest arguments')
399*6777b538SAndroid Build Coastguard Worker
400*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
401*6777b538SAndroid Build Coastguard Worker      '--additional-apk',
402*6777b538SAndroid Build Coastguard Worker      action='append', dest='additional_apks', default=[],
403*6777b538SAndroid Build Coastguard Worker      type=_RealPath,
404*6777b538SAndroid Build Coastguard Worker      help='Additional apk that must be installed on '
405*6777b538SAndroid Build Coastguard Worker           'the device when the tests are run.')
406*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
407*6777b538SAndroid Build Coastguard Worker      '--app-data-file',
408*6777b538SAndroid Build Coastguard Worker      action='append', dest='app_data_files',
409*6777b538SAndroid Build Coastguard Worker      help='A file path relative to the app data directory '
410*6777b538SAndroid Build Coastguard Worker           'that should be saved to the host.')
411*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
412*6777b538SAndroid Build Coastguard Worker      '--app-data-file-dir',
413*6777b538SAndroid Build Coastguard Worker      help='Host directory to which app data files will be'
414*6777b538SAndroid Build Coastguard Worker           ' saved. Used with --app-data-file.')
415*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
416*6777b538SAndroid Build Coastguard Worker      '--enable-xml-result-parsing',
417*6777b538SAndroid Build Coastguard Worker      action='store_true', help=argparse.SUPPRESS)
418*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
419*6777b538SAndroid Build Coastguard Worker      '--executable-dist-dir',
420*6777b538SAndroid Build Coastguard Worker      type=os.path.realpath,
421*6777b538SAndroid Build Coastguard Worker      help="Path to executable's dist directory for native"
422*6777b538SAndroid Build Coastguard Worker           " (non-apk) tests.")
423*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
424*6777b538SAndroid Build Coastguard Worker      '--extract-test-list-from-filter',
425*6777b538SAndroid Build Coastguard Worker      action='store_true',
426*6777b538SAndroid Build Coastguard Worker      help='When a test filter is specified, and the list of '
427*6777b538SAndroid Build Coastguard Worker           'tests can be determined from it, skip querying the '
428*6777b538SAndroid Build Coastguard Worker           'device for the list of all tests. Speeds up local '
429*6777b538SAndroid Build Coastguard Worker           'development, but is not safe to use on bots ('
430*6777b538SAndroid Build Coastguard Worker           'http://crbug.com/549214')
431*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
432*6777b538SAndroid Build Coastguard Worker      '--gs-test-artifacts-bucket',
433*6777b538SAndroid Build Coastguard Worker      help=('If present, test artifacts will be uploaded to this Google '
434*6777b538SAndroid Build Coastguard Worker            'Storage bucket.'))
435*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
436*6777b538SAndroid Build Coastguard Worker      '--render-test-output-dir',
437*6777b538SAndroid Build Coastguard Worker      help='If present, store rendering artifacts in this path.')
438*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
439*6777b538SAndroid Build Coastguard Worker      '--runtime-deps-path',
440*6777b538SAndroid Build Coastguard Worker      dest='runtime_deps_path', type=os.path.realpath,
441*6777b538SAndroid Build Coastguard Worker      help='Runtime data dependency file from GN.')
442*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
443*6777b538SAndroid Build Coastguard Worker      '-t', '--shard-timeout',
444*6777b538SAndroid Build Coastguard Worker      dest='shard_timeout', type=int, default=120,
445*6777b538SAndroid Build Coastguard Worker      help='Timeout to wait for each test (default: %(default)s).')
446*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
447*6777b538SAndroid Build Coastguard Worker      '--store-tombstones',
448*6777b538SAndroid Build Coastguard Worker      dest='store_tombstones', action='store_true',
449*6777b538SAndroid Build Coastguard Worker      help='Add tombstones in results if crash.')
450*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
451*6777b538SAndroid Build Coastguard Worker      '-s', '--suite',
452*6777b538SAndroid Build Coastguard Worker      dest='suite_name', nargs='+', metavar='SUITE_NAME', required=True,
453*6777b538SAndroid Build Coastguard Worker      help='Executable name of the test suite to run.')
454*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
455*6777b538SAndroid Build Coastguard Worker      '--test-apk-incremental-install-json',
456*6777b538SAndroid Build Coastguard Worker      type=os.path.realpath,
457*6777b538SAndroid Build Coastguard Worker      help='Path to install json for the test apk.')
458*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--test-launcher-batch-limit',
459*6777b538SAndroid Build Coastguard Worker                      dest='test_launcher_batch_limit',
460*6777b538SAndroid Build Coastguard Worker                      type=int,
461*6777b538SAndroid Build Coastguard Worker                      help='The max number of tests to run in a shard. '
462*6777b538SAndroid Build Coastguard Worker                      'Ignores non-positive ints and those greater than '
463*6777b538SAndroid Build Coastguard Worker                      'MAX_SHARDS')
464*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
465*6777b538SAndroid Build Coastguard Worker      '-w', '--wait-for-java-debugger', action='store_true',
466*6777b538SAndroid Build Coastguard Worker      help='Wait for java debugger to attach before running any application '
467*6777b538SAndroid Build Coastguard Worker           'code. Also disables test timeouts and sets retries=0.')
468*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
469*6777b538SAndroid Build Coastguard Worker      '--coverage-dir',
470*6777b538SAndroid Build Coastguard Worker      type=os.path.realpath,
471*6777b538SAndroid Build Coastguard Worker      help='Directory in which to place all generated coverage files.')
472*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
473*6777b538SAndroid Build Coastguard Worker      '--use-existing-test-data',
474*6777b538SAndroid Build Coastguard Worker      action='store_true',
475*6777b538SAndroid Build Coastguard Worker      help='Do not push new files to the device, instead using existing APK '
476*6777b538SAndroid Build Coastguard Worker      'and test data. Only use when running the same test for multiple '
477*6777b538SAndroid Build Coastguard Worker      'iterations.')
478*6777b538SAndroid Build Coastguard Worker  # This is currently only implemented for gtests tests.
479*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--gtest_also_run_pre_tests',
480*6777b538SAndroid Build Coastguard Worker                      '--gtest-also-run-pre-tests',
481*6777b538SAndroid Build Coastguard Worker                      dest='run_pre_tests',
482*6777b538SAndroid Build Coastguard Worker                      action='store_true',
483*6777b538SAndroid Build Coastguard Worker                      help='Also run PRE_ tests if applicable.')
484*6777b538SAndroid Build Coastguard Worker
485*6777b538SAndroid Build Coastguard Worker
486*6777b538SAndroid Build Coastguard Workerdef AddInstrumentationTestOptions(parser):
487*6777b538SAndroid Build Coastguard Worker  """Adds Instrumentation test options to |parser|."""
488*6777b538SAndroid Build Coastguard Worker
489*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group('instrumentation arguments')
490*6777b538SAndroid Build Coastguard Worker
491*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--additional-apex',
492*6777b538SAndroid Build Coastguard Worker                      action='append',
493*6777b538SAndroid Build Coastguard Worker                      dest='additional_apexs',
494*6777b538SAndroid Build Coastguard Worker                      default=[],
495*6777b538SAndroid Build Coastguard Worker                      type=_RealPath,
496*6777b538SAndroid Build Coastguard Worker                      help='Additional apex that must be installed on '
497*6777b538SAndroid Build Coastguard Worker                      'the device when the tests are run')
498*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
499*6777b538SAndroid Build Coastguard Worker      '--additional-apk',
500*6777b538SAndroid Build Coastguard Worker      action='append', dest='additional_apks', default=[],
501*6777b538SAndroid Build Coastguard Worker      type=_RealPath,
502*6777b538SAndroid Build Coastguard Worker      help='Additional apk that must be installed on '
503*6777b538SAndroid Build Coastguard Worker           'the device when the tests are run')
504*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--forced-queryable-additional-apk',
505*6777b538SAndroid Build Coastguard Worker                      action='append',
506*6777b538SAndroid Build Coastguard Worker                      dest='forced_queryable_additional_apks',
507*6777b538SAndroid Build Coastguard Worker                      default=[],
508*6777b538SAndroid Build Coastguard Worker                      type=_RealPath,
509*6777b538SAndroid Build Coastguard Worker                      help='Configures an additional-apk to be forced '
510*6777b538SAndroid Build Coastguard Worker                      'to be queryable by other APKs.')
511*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--instant-additional-apk',
512*6777b538SAndroid Build Coastguard Worker                      action='append',
513*6777b538SAndroid Build Coastguard Worker                      dest='instant_additional_apks',
514*6777b538SAndroid Build Coastguard Worker                      default=[],
515*6777b538SAndroid Build Coastguard Worker                      type=_RealPath,
516*6777b538SAndroid Build Coastguard Worker                      help='Configures an additional-apk to be an instant APK')
517*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
518*6777b538SAndroid Build Coastguard Worker      '-A', '--annotation',
519*6777b538SAndroid Build Coastguard Worker      dest='annotation_str',
520*6777b538SAndroid Build Coastguard Worker      help='Comma-separated list of annotations. Run only tests with any of '
521*6777b538SAndroid Build Coastguard Worker           'the given annotations. An annotation can be either a key or a '
522*6777b538SAndroid Build Coastguard Worker           'key-values pair. A test that has no annotation is considered '
523*6777b538SAndroid Build Coastguard Worker           '"SmallTest".')
524*6777b538SAndroid Build Coastguard Worker  # TODO(jbudorick): Remove support for name-style APK specification once
525*6777b538SAndroid Build Coastguard Worker  # bots are no longer doing it.
526*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
527*6777b538SAndroid Build Coastguard Worker      '--apk-under-test',
528*6777b538SAndroid Build Coastguard Worker      help='Path or name of the apk under test.')
529*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
530*6777b538SAndroid Build Coastguard Worker      '--store-data-dependencies-in-temp',
531*6777b538SAndroid Build Coastguard Worker      action='store_true',
532*6777b538SAndroid Build Coastguard Worker      help='Store data dependencies in /data/local/tmp/chromium_tests_root')
533*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
534*6777b538SAndroid Build Coastguard Worker      '--module',
535*6777b538SAndroid Build Coastguard Worker      action='append',
536*6777b538SAndroid Build Coastguard Worker      dest='modules',
537*6777b538SAndroid Build Coastguard Worker      help='Specify Android App Bundle modules to install in addition to the '
538*6777b538SAndroid Build Coastguard Worker      'base module.')
539*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
540*6777b538SAndroid Build Coastguard Worker      '--fake-module',
541*6777b538SAndroid Build Coastguard Worker      action='append',
542*6777b538SAndroid Build Coastguard Worker      dest='fake_modules',
543*6777b538SAndroid Build Coastguard Worker      help='Specify Android App Bundle modules to fake install in addition to '
544*6777b538SAndroid Build Coastguard Worker      'the real modules.')
545*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
546*6777b538SAndroid Build Coastguard Worker      '--additional-locale',
547*6777b538SAndroid Build Coastguard Worker      action='append',
548*6777b538SAndroid Build Coastguard Worker      dest='additional_locales',
549*6777b538SAndroid Build Coastguard Worker      help='Specify locales in addition to the device locale to install splits '
550*6777b538SAndroid Build Coastguard Worker      'for when --apk-under-test is an Android App Bundle.')
551*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
552*6777b538SAndroid Build Coastguard Worker      '--coverage-dir',
553*6777b538SAndroid Build Coastguard Worker      type=os.path.realpath,
554*6777b538SAndroid Build Coastguard Worker      help='Directory in which to place all generated '
555*6777b538SAndroid Build Coastguard Worker      'Jacoco coverage files.')
556*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
557*6777b538SAndroid Build Coastguard Worker      '--disable-dalvik-asserts',
558*6777b538SAndroid Build Coastguard Worker      dest='set_asserts', action='store_false', default=True,
559*6777b538SAndroid Build Coastguard Worker      help='Removes the dalvik.vm.enableassertions property')
560*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
561*6777b538SAndroid Build Coastguard Worker      '--proguard-mapping-path',
562*6777b538SAndroid Build Coastguard Worker      help='.mapping file to use to Deobfuscate java stack traces in test '
563*6777b538SAndroid Build Coastguard Worker      'output and logcat.')
564*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
565*6777b538SAndroid Build Coastguard Worker      '-E', '--exclude-annotation',
566*6777b538SAndroid Build Coastguard Worker      dest='exclude_annotation_str',
567*6777b538SAndroid Build Coastguard Worker      help='Comma-separated list of annotations. Exclude tests with these '
568*6777b538SAndroid Build Coastguard Worker           'annotations.')
569*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
570*6777b538SAndroid Build Coastguard Worker      '--enable-breakpad-dump',
571*6777b538SAndroid Build Coastguard Worker      action='store_true',
572*6777b538SAndroid Build Coastguard Worker      help='Stores any breakpad dumps till the end of the test.')
573*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
574*6777b538SAndroid Build Coastguard Worker      '--replace-system-package',
575*6777b538SAndroid Build Coastguard Worker      type=_RealPath,
576*6777b538SAndroid Build Coastguard Worker      default=None,
577*6777b538SAndroid Build Coastguard Worker      help='Use this apk to temporarily replace a system package with the same '
578*6777b538SAndroid Build Coastguard Worker      'package name.')
579*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
580*6777b538SAndroid Build Coastguard Worker      '--remove-system-package',
581*6777b538SAndroid Build Coastguard Worker      default=[],
582*6777b538SAndroid Build Coastguard Worker      action='append',
583*6777b538SAndroid Build Coastguard Worker      dest='system_packages_to_remove',
584*6777b538SAndroid Build Coastguard Worker      help='Specifies a system package to remove before testing if it exists '
585*6777b538SAndroid Build Coastguard Worker      'on the system. WARNING: THIS WILL PERMANENTLY REMOVE THE SYSTEM APP. '
586*6777b538SAndroid Build Coastguard Worker      'Unlike --replace-system-package, the app will not be restored after '
587*6777b538SAndroid Build Coastguard Worker      'tests are finished.')
588*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
589*6777b538SAndroid Build Coastguard Worker      '--use-voice-interaction-service',
590*6777b538SAndroid Build Coastguard Worker      help='This can be used to update the voice interaction service to be a '
591*6777b538SAndroid Build Coastguard Worker      'custom one. This is useful for mocking assistants. eg: '
592*6777b538SAndroid Build Coastguard Worker      'android.assist.service/.MainInteractionService')
593*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
594*6777b538SAndroid Build Coastguard Worker      '--use-webview-provider',
595*6777b538SAndroid Build Coastguard Worker      type=_RealPath, default=None,
596*6777b538SAndroid Build Coastguard Worker      help='Use this apk as the webview provider during test. '
597*6777b538SAndroid Build Coastguard Worker           'The original provider will be restored if possible, '
598*6777b538SAndroid Build Coastguard Worker           "on Nougat the provider can't be determined and so "
599*6777b538SAndroid Build Coastguard Worker           'the system will choose the default provider.')
600*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
601*6777b538SAndroid Build Coastguard Worker      '--webview-command-line-arg',
602*6777b538SAndroid Build Coastguard Worker      default=[],
603*6777b538SAndroid Build Coastguard Worker      action='append',
604*6777b538SAndroid Build Coastguard Worker      help="Specifies command line arguments to add to WebView's flag file")
605*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
606*6777b538SAndroid Build Coastguard Worker      '--run-setup-command',
607*6777b538SAndroid Build Coastguard Worker      default=[],
608*6777b538SAndroid Build Coastguard Worker      action='append',
609*6777b538SAndroid Build Coastguard Worker      dest='run_setup_commands',
610*6777b538SAndroid Build Coastguard Worker      help='This can be used to run a custom shell command on the device as a '
611*6777b538SAndroid Build Coastguard Worker      'setup step')
612*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
613*6777b538SAndroid Build Coastguard Worker      '--run-teardown-command',
614*6777b538SAndroid Build Coastguard Worker      default=[],
615*6777b538SAndroid Build Coastguard Worker      action='append',
616*6777b538SAndroid Build Coastguard Worker      dest='run_teardown_commands',
617*6777b538SAndroid Build Coastguard Worker      help='This can be used to run a custom shell command on the device as a '
618*6777b538SAndroid Build Coastguard Worker      'teardown step')
619*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
620*6777b538SAndroid Build Coastguard Worker      '--runtime-deps-path',
621*6777b538SAndroid Build Coastguard Worker      dest='runtime_deps_path', type=os.path.realpath,
622*6777b538SAndroid Build Coastguard Worker      help='Runtime data dependency file from GN.')
623*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
624*6777b538SAndroid Build Coastguard Worker      '--screenshot-directory',
625*6777b538SAndroid Build Coastguard Worker      dest='screenshot_dir', type=os.path.realpath,
626*6777b538SAndroid Build Coastguard Worker      help='Capture screenshots of test failures')
627*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
628*6777b538SAndroid Build Coastguard Worker      '--store-tombstones',
629*6777b538SAndroid Build Coastguard Worker      action='store_true', dest='store_tombstones',
630*6777b538SAndroid Build Coastguard Worker      help='Add tombstones in results if crash.')
631*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
632*6777b538SAndroid Build Coastguard Worker      '--strict-mode',
633*6777b538SAndroid Build Coastguard Worker      dest='strict_mode', default='testing',
634*6777b538SAndroid Build Coastguard Worker      help='StrictMode command-line flag set on the device, '
635*6777b538SAndroid Build Coastguard Worker           'death/testing to kill the process, off to stop '
636*6777b538SAndroid Build Coastguard Worker           'checking, flash to flash only. (default: %(default)s)')
637*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
638*6777b538SAndroid Build Coastguard Worker      '--test-apk',
639*6777b538SAndroid Build Coastguard Worker      required=True,
640*6777b538SAndroid Build Coastguard Worker      help='Path or name of the apk containing the tests.')
641*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
642*6777b538SAndroid Build Coastguard Worker      '--test-apk-as-instant',
643*6777b538SAndroid Build Coastguard Worker      action='store_true',
644*6777b538SAndroid Build Coastguard Worker      help='Install the test apk as an instant app. '
645*6777b538SAndroid Build Coastguard Worker      'Instant apps run in a more restrictive execution environment.')
646*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
647*6777b538SAndroid Build Coastguard Worker      '--test-launcher-batch-limit',
648*6777b538SAndroid Build Coastguard Worker      dest='test_launcher_batch_limit',
649*6777b538SAndroid Build Coastguard Worker      type=int,
650*6777b538SAndroid Build Coastguard Worker      help=('Not actually used for instrumentation tests, but can be used as '
651*6777b538SAndroid Build Coastguard Worker            'a proxy for determining if the current run is a retry without '
652*6777b538SAndroid Build Coastguard Worker            'patch.'))
653*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
654*6777b538SAndroid Build Coastguard Worker      '--timeout-scale',
655*6777b538SAndroid Build Coastguard Worker      type=float,
656*6777b538SAndroid Build Coastguard Worker      help='Factor by which timeouts should be scaled.')
657*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
658*6777b538SAndroid Build Coastguard Worker      '--is-unit-test',
659*6777b538SAndroid Build Coastguard Worker      action='store_true',
660*6777b538SAndroid Build Coastguard Worker      help=('Specify the test suite as composed of unit tests, blocking '
661*6777b538SAndroid Build Coastguard Worker            'certain operations.'))
662*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
663*6777b538SAndroid Build Coastguard Worker      '-w', '--wait-for-java-debugger', action='store_true',
664*6777b538SAndroid Build Coastguard Worker      help='Wait for java debugger to attach before running any application '
665*6777b538SAndroid Build Coastguard Worker           'code. Also disables test timeouts and sets retries=0.')
666*6777b538SAndroid Build Coastguard Worker
667*6777b538SAndroid Build Coastguard Worker  # WPR record mode.
668*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--wpr-enable-record',
669*6777b538SAndroid Build Coastguard Worker                      action='store_true',
670*6777b538SAndroid Build Coastguard Worker                      default=False,
671*6777b538SAndroid Build Coastguard Worker                      help='If true, WPR server runs in record mode.'
672*6777b538SAndroid Build Coastguard Worker                      'otherwise, runs in replay mode.')
673*6777b538SAndroid Build Coastguard Worker
674*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
675*6777b538SAndroid Build Coastguard Worker      '--approve-app-links',
676*6777b538SAndroid Build Coastguard Worker      help='Force enables Digital Asset Link verification for the provided '
677*6777b538SAndroid Build Coastguard Worker      'package and domain, example usage: --approve-app-links '
678*6777b538SAndroid Build Coastguard Worker      'com.android.package:www.example.com')
679*6777b538SAndroid Build Coastguard Worker
680*6777b538SAndroid Build Coastguard Worker  # These arguments are suppressed from the help text because they should
681*6777b538SAndroid Build Coastguard Worker  # only ever be specified by an intermediate script.
682*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
683*6777b538SAndroid Build Coastguard Worker      '--apk-under-test-incremental-install-json',
684*6777b538SAndroid Build Coastguard Worker      help=argparse.SUPPRESS)
685*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
686*6777b538SAndroid Build Coastguard Worker      '--test-apk-incremental-install-json',
687*6777b538SAndroid Build Coastguard Worker      type=os.path.realpath,
688*6777b538SAndroid Build Coastguard Worker      help=argparse.SUPPRESS)
689*6777b538SAndroid Build Coastguard Worker
690*6777b538SAndroid Build Coastguard Worker
691*6777b538SAndroid Build Coastguard Workerdef AddSkiaGoldTestOptions(parser):
692*6777b538SAndroid Build Coastguard Worker  """Adds Skia Gold test options to |parser|."""
693*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group("Skia Gold arguments")
694*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
695*6777b538SAndroid Build Coastguard Worker      '--code-review-system',
696*6777b538SAndroid Build Coastguard Worker      help='A non-default code review system to pass to pass to Gold, if '
697*6777b538SAndroid Build Coastguard Worker      'applicable')
698*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
699*6777b538SAndroid Build Coastguard Worker      '--continuous-integration-system',
700*6777b538SAndroid Build Coastguard Worker      help='A non-default continuous integration system to pass to Gold, if '
701*6777b538SAndroid Build Coastguard Worker      'applicable')
702*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
703*6777b538SAndroid Build Coastguard Worker      '--git-revision', help='The git commit currently being tested.')
704*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
705*6777b538SAndroid Build Coastguard Worker      '--gerrit-issue',
706*6777b538SAndroid Build Coastguard Worker      help='The Gerrit issue this test is being run on, if applicable.')
707*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
708*6777b538SAndroid Build Coastguard Worker      '--gerrit-patchset',
709*6777b538SAndroid Build Coastguard Worker      help='The Gerrit patchset this test is being run on, if applicable.')
710*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
711*6777b538SAndroid Build Coastguard Worker      '--buildbucket-id',
712*6777b538SAndroid Build Coastguard Worker      help='The Buildbucket build ID that this test was triggered from, if '
713*6777b538SAndroid Build Coastguard Worker      'applicable.')
714*6777b538SAndroid Build Coastguard Worker  local_group = parser.add_mutually_exclusive_group()
715*6777b538SAndroid Build Coastguard Worker  local_group.add_argument(
716*6777b538SAndroid Build Coastguard Worker      '--local-pixel-tests',
717*6777b538SAndroid Build Coastguard Worker      action='store_true',
718*6777b538SAndroid Build Coastguard Worker      default=None,
719*6777b538SAndroid Build Coastguard Worker      help='Specifies to run the Skia Gold pixel tests in local mode. When run '
720*6777b538SAndroid Build Coastguard Worker      'in local mode, uploading to Gold is disabled and traditional '
721*6777b538SAndroid Build Coastguard Worker      'generated/golden/diff images are output instead of triage links. '
722*6777b538SAndroid Build Coastguard Worker      'Running in local mode also implies --no-luci-auth. If both this '
723*6777b538SAndroid Build Coastguard Worker      'and --no-local-pixel-tests are left unset, the test harness will '
724*6777b538SAndroid Build Coastguard Worker      'attempt to detect whether it is running on a workstation or not '
725*6777b538SAndroid Build Coastguard Worker      'and set the options accordingly.')
726*6777b538SAndroid Build Coastguard Worker  local_group.add_argument(
727*6777b538SAndroid Build Coastguard Worker      '--no-local-pixel-tests',
728*6777b538SAndroid Build Coastguard Worker      action='store_false',
729*6777b538SAndroid Build Coastguard Worker      dest='local_pixel_tests',
730*6777b538SAndroid Build Coastguard Worker      help='Specifies to run the Skia Gold pixel tests in non-local (bot) '
731*6777b538SAndroid Build Coastguard Worker      'mode. When run in this mode, data is actually uploaded to Gold and '
732*6777b538SAndroid Build Coastguard Worker      'triage links are generated. If both this and --local-pixel-tests '
733*6777b538SAndroid Build Coastguard Worker      'are left unset, the test harness will attempt to detect whether '
734*6777b538SAndroid Build Coastguard Worker      'it is running on a workstation or not and set the options '
735*6777b538SAndroid Build Coastguard Worker      'accordingly.')
736*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
737*6777b538SAndroid Build Coastguard Worker      '--no-luci-auth',
738*6777b538SAndroid Build Coastguard Worker      action='store_true',
739*6777b538SAndroid Build Coastguard Worker      default=False,
740*6777b538SAndroid Build Coastguard Worker      help="Don't use the serve account provided by LUCI for authentication "
741*6777b538SAndroid Build Coastguard Worker      'with Skia Gold, instead relying on gsutil to be pre-authenticated. '
742*6777b538SAndroid Build Coastguard Worker      'Meant for testing locally instead of on the bots.')
743*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
744*6777b538SAndroid Build Coastguard Worker      '--bypass-skia-gold-functionality',
745*6777b538SAndroid Build Coastguard Worker      action='store_true',
746*6777b538SAndroid Build Coastguard Worker      default=False,
747*6777b538SAndroid Build Coastguard Worker      help='Bypass all interaction with Skia Gold, effectively disabling the '
748*6777b538SAndroid Build Coastguard Worker      'image comparison portion of any tests that use Gold. Only meant to be '
749*6777b538SAndroid Build Coastguard Worker      'used in case a Gold outage occurs and cannot be fixed quickly.')
750*6777b538SAndroid Build Coastguard Worker
751*6777b538SAndroid Build Coastguard Worker
752*6777b538SAndroid Build Coastguard Workerdef AddHostsideTestOptions(parser):
753*6777b538SAndroid Build Coastguard Worker  """Adds hostside test options to |parser|."""
754*6777b538SAndroid Build Coastguard Worker
755*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group('hostside arguments')
756*6777b538SAndroid Build Coastguard Worker
757*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
758*6777b538SAndroid Build Coastguard Worker      '-s', '--test-suite', required=True,
759*6777b538SAndroid Build Coastguard Worker      help='Hostside test suite to run.')
760*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
761*6777b538SAndroid Build Coastguard Worker      '--test-apk-as-instant',
762*6777b538SAndroid Build Coastguard Worker      action='store_true',
763*6777b538SAndroid Build Coastguard Worker      help='Install the test apk as an instant app. '
764*6777b538SAndroid Build Coastguard Worker      'Instant apps run in a more restrictive execution environment.')
765*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
766*6777b538SAndroid Build Coastguard Worker      '--additional-apk',
767*6777b538SAndroid Build Coastguard Worker      action='append',
768*6777b538SAndroid Build Coastguard Worker      dest='additional_apks',
769*6777b538SAndroid Build Coastguard Worker      default=[],
770*6777b538SAndroid Build Coastguard Worker      type=_RealPath,
771*6777b538SAndroid Build Coastguard Worker      help='Additional apk that must be installed on '
772*6777b538SAndroid Build Coastguard Worker           'the device when the tests are run')
773*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
774*6777b538SAndroid Build Coastguard Worker      '--use-webview-provider',
775*6777b538SAndroid Build Coastguard Worker      type=_RealPath, default=None,
776*6777b538SAndroid Build Coastguard Worker      help='Use this apk as the webview provider during test. '
777*6777b538SAndroid Build Coastguard Worker           'The original provider will be restored if possible, '
778*6777b538SAndroid Build Coastguard Worker           "on Nougat the provider can't be determined and so "
779*6777b538SAndroid Build Coastguard Worker           'the system will choose the default provider.')
780*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
781*6777b538SAndroid Build Coastguard Worker      '--tradefed-executable',
782*6777b538SAndroid Build Coastguard Worker      type=_RealPath, default=None,
783*6777b538SAndroid Build Coastguard Worker      help='Location of the cts-tradefed script')
784*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
785*6777b538SAndroid Build Coastguard Worker      '--tradefed-aapt-path',
786*6777b538SAndroid Build Coastguard Worker      type=_RealPath, default=None,
787*6777b538SAndroid Build Coastguard Worker      help='Location of the directory containing aapt binary')
788*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
789*6777b538SAndroid Build Coastguard Worker      '--tradefed-adb-path',
790*6777b538SAndroid Build Coastguard Worker      type=_RealPath, default=None,
791*6777b538SAndroid Build Coastguard Worker      help='Location of the directory containing adb binary')
792*6777b538SAndroid Build Coastguard Worker  # The below arguments are not used, but allow us to pass the same arguments
793*6777b538SAndroid Build Coastguard Worker  # from run_cts.py regardless of type of run (instrumentation/hostside)
794*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
795*6777b538SAndroid Build Coastguard Worker      '--apk-under-test',
796*6777b538SAndroid Build Coastguard Worker      help=argparse.SUPPRESS)
797*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
798*6777b538SAndroid Build Coastguard Worker      '--use-apk-under-test-flags-file',
799*6777b538SAndroid Build Coastguard Worker      action='store_true',
800*6777b538SAndroid Build Coastguard Worker      help=argparse.SUPPRESS)
801*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
802*6777b538SAndroid Build Coastguard Worker      '-E', '--exclude-annotation',
803*6777b538SAndroid Build Coastguard Worker      dest='exclude_annotation_str',
804*6777b538SAndroid Build Coastguard Worker      help=argparse.SUPPRESS)
805*6777b538SAndroid Build Coastguard Worker
806*6777b538SAndroid Build Coastguard Worker
807*6777b538SAndroid Build Coastguard Workerdef AddJUnitTestOptions(parser):
808*6777b538SAndroid Build Coastguard Worker  """Adds junit test options to |parser|."""
809*6777b538SAndroid Build Coastguard Worker
810*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group('junit arguments')
811*6777b538SAndroid Build Coastguard Worker
812*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
813*6777b538SAndroid Build Coastguard Worker      '--coverage-on-the-fly',
814*6777b538SAndroid Build Coastguard Worker      action='store_true',
815*6777b538SAndroid Build Coastguard Worker      help='Generate coverage data by Jacoco on-the-fly instrumentation.')
816*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
817*6777b538SAndroid Build Coastguard Worker      '--coverage-dir', type=os.path.realpath,
818*6777b538SAndroid Build Coastguard Worker      help='Directory to store coverage info.')
819*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
820*6777b538SAndroid Build Coastguard Worker      '--package-filter',
821*6777b538SAndroid Build Coastguard Worker      help='Filters tests by package.')
822*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
823*6777b538SAndroid Build Coastguard Worker      '--runner-filter',
824*6777b538SAndroid Build Coastguard Worker      help='Filters tests by runner class. Must be fully qualified.')
825*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--json-config',
826*6777b538SAndroid Build Coastguard Worker                      help='Runs only tests listed in this config.')
827*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
828*6777b538SAndroid Build Coastguard Worker      '--shards',
829*6777b538SAndroid Build Coastguard Worker      type=int,
830*6777b538SAndroid Build Coastguard Worker      help='Number of shards to run junit tests in parallel on. Only 1 shard '
831*6777b538SAndroid Build Coastguard Worker      'is supported when test-filter is specified. Values less than 1 will '
832*6777b538SAndroid Build Coastguard Worker      'use auto select.')
833*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--shard-filter',
834*6777b538SAndroid Build Coastguard Worker                      help='Comma separated list of shard indices to run.')
835*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
836*6777b538SAndroid Build Coastguard Worker      '-s', '--test-suite', required=True,
837*6777b538SAndroid Build Coastguard Worker      help='JUnit test suite to run.')
838*6777b538SAndroid Build Coastguard Worker  debug_group = parser.add_mutually_exclusive_group()
839*6777b538SAndroid Build Coastguard Worker  debug_group.add_argument(
840*6777b538SAndroid Build Coastguard Worker      '-w', '--wait-for-java-debugger', action='store_const', const='8701',
841*6777b538SAndroid Build Coastguard Worker      dest='debug_socket', help='Alias for --debug-socket=8701')
842*6777b538SAndroid Build Coastguard Worker  debug_group.add_argument(
843*6777b538SAndroid Build Coastguard Worker      '--debug-socket',
844*6777b538SAndroid Build Coastguard Worker      help='Wait for java debugger to attach at specified socket address '
845*6777b538SAndroid Build Coastguard Worker           'before running any application code. Also disables test timeouts '
846*6777b538SAndroid Build Coastguard Worker           'and sets retries=0.')
847*6777b538SAndroid Build Coastguard Worker
848*6777b538SAndroid Build Coastguard Worker  # These arguments are for Android Robolectric tests.
849*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
850*6777b538SAndroid Build Coastguard Worker      '--robolectric-runtime-deps-dir',
851*6777b538SAndroid Build Coastguard Worker      help='Path to runtime deps for Robolectric.')
852*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--native-libs-dir',
853*6777b538SAndroid Build Coastguard Worker                      help='Path to search for native libraries.')
854*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
855*6777b538SAndroid Build Coastguard Worker      '--resource-apk',
856*6777b538SAndroid Build Coastguard Worker      required=True,
857*6777b538SAndroid Build Coastguard Worker      help='Path to .ap_ containing binary resources for Robolectric.')
858*6777b538SAndroid Build Coastguard Worker
859*6777b538SAndroid Build Coastguard Worker
860*6777b538SAndroid Build Coastguard Workerdef AddLinkerTestOptions(parser):
861*6777b538SAndroid Build Coastguard Worker
862*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group('linker arguments')
863*6777b538SAndroid Build Coastguard Worker
864*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
865*6777b538SAndroid Build Coastguard Worker      '--test-apk',
866*6777b538SAndroid Build Coastguard Worker      type=os.path.realpath,
867*6777b538SAndroid Build Coastguard Worker      help='Path to the linker test APK.')
868*6777b538SAndroid Build Coastguard Worker
869*6777b538SAndroid Build Coastguard Worker
870*6777b538SAndroid Build Coastguard Workerdef AddMonkeyTestOptions(parser):
871*6777b538SAndroid Build Coastguard Worker  """Adds monkey test options to |parser|."""
872*6777b538SAndroid Build Coastguard Worker
873*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group('monkey arguments')
874*6777b538SAndroid Build Coastguard Worker
875*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--browser',
876*6777b538SAndroid Build Coastguard Worker                      required=True,
877*6777b538SAndroid Build Coastguard Worker                      choices=list(constants.PACKAGE_INFO.keys()),
878*6777b538SAndroid Build Coastguard Worker                      metavar='BROWSER',
879*6777b538SAndroid Build Coastguard Worker                      help='Browser under test.')
880*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
881*6777b538SAndroid Build Coastguard Worker      '--category',
882*6777b538SAndroid Build Coastguard Worker      nargs='*', dest='categories', default=[],
883*6777b538SAndroid Build Coastguard Worker      help='A list of allowed categories. Monkey will only visit activities '
884*6777b538SAndroid Build Coastguard Worker           'that are listed with one of the specified categories.')
885*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
886*6777b538SAndroid Build Coastguard Worker      '--event-count',
887*6777b538SAndroid Build Coastguard Worker      default=10000, type=int,
888*6777b538SAndroid Build Coastguard Worker      help='Number of events to generate (default: %(default)s).')
889*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
890*6777b538SAndroid Build Coastguard Worker      '--seed',
891*6777b538SAndroid Build Coastguard Worker      type=int,
892*6777b538SAndroid Build Coastguard Worker      help='Seed value for pseudo-random generator. Same seed value generates '
893*6777b538SAndroid Build Coastguard Worker           'the same sequence of events. Seed is randomized by default.')
894*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
895*6777b538SAndroid Build Coastguard Worker      '--throttle',
896*6777b538SAndroid Build Coastguard Worker      default=100, type=int,
897*6777b538SAndroid Build Coastguard Worker      help='Delay between events (ms) (default: %(default)s). ')
898*6777b538SAndroid Build Coastguard Worker
899*6777b538SAndroid Build Coastguard Worker
900*6777b538SAndroid Build Coastguard Workerdef AddPythonTestOptions(parser):
901*6777b538SAndroid Build Coastguard Worker
902*6777b538SAndroid Build Coastguard Worker  parser = parser.add_argument_group('python arguments')
903*6777b538SAndroid Build Coastguard Worker
904*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-s',
905*6777b538SAndroid Build Coastguard Worker                      '--suite',
906*6777b538SAndroid Build Coastguard Worker                      dest='suite_name',
907*6777b538SAndroid Build Coastguard Worker                      metavar='SUITE_NAME',
908*6777b538SAndroid Build Coastguard Worker                      choices=list(constants.PYTHON_UNIT_TEST_SUITES.keys()),
909*6777b538SAndroid Build Coastguard Worker                      help='Name of the test suite to run.')
910*6777b538SAndroid Build Coastguard Worker
911*6777b538SAndroid Build Coastguard Worker
912*6777b538SAndroid Build Coastguard Workerdef _CreateClassToFileNameDict(test_apk):
913*6777b538SAndroid Build Coastguard Worker  """Creates a dict mapping classes to file names from size-info apk."""
914*6777b538SAndroid Build Coastguard Worker  constants.CheckOutputDirectory()
915*6777b538SAndroid Build Coastguard Worker  test_apk_size_info = os.path.join(constants.GetOutDirectory(), 'size-info',
916*6777b538SAndroid Build Coastguard Worker                                    os.path.basename(test_apk) + '.jar.info')
917*6777b538SAndroid Build Coastguard Worker
918*6777b538SAndroid Build Coastguard Worker  class_to_file_dict = {}
919*6777b538SAndroid Build Coastguard Worker  # Some tests such as webview_cts_tests use a separately downloaded apk to run
920*6777b538SAndroid Build Coastguard Worker  # tests. This means the apk may not have been built by the system and hence
921*6777b538SAndroid Build Coastguard Worker  # no size info file exists.
922*6777b538SAndroid Build Coastguard Worker  if not os.path.exists(test_apk_size_info):
923*6777b538SAndroid Build Coastguard Worker    logging.debug('Apk size file not found. %s', test_apk_size_info)
924*6777b538SAndroid Build Coastguard Worker    return class_to_file_dict
925*6777b538SAndroid Build Coastguard Worker
926*6777b538SAndroid Build Coastguard Worker  with open(test_apk_size_info, 'r') as f:
927*6777b538SAndroid Build Coastguard Worker    for line in f:
928*6777b538SAndroid Build Coastguard Worker      file_class, file_name = line.rstrip().split(',', 1)
929*6777b538SAndroid Build Coastguard Worker      # Only want files that are not prebuilt.
930*6777b538SAndroid Build Coastguard Worker      if file_name.startswith('../../'):
931*6777b538SAndroid Build Coastguard Worker        class_to_file_dict[file_class] = str(
932*6777b538SAndroid Build Coastguard Worker            file_name.replace('../../', '//', 1))
933*6777b538SAndroid Build Coastguard Worker
934*6777b538SAndroid Build Coastguard Worker  return class_to_file_dict
935*6777b538SAndroid Build Coastguard Worker
936*6777b538SAndroid Build Coastguard Worker
937*6777b538SAndroid Build Coastguard Workerdef _RunPythonTests(args):
938*6777b538SAndroid Build Coastguard Worker  """Subcommand of RunTestsCommand which runs python unit tests."""
939*6777b538SAndroid Build Coastguard Worker  suite_vars = constants.PYTHON_UNIT_TEST_SUITES[args.suite_name]
940*6777b538SAndroid Build Coastguard Worker  suite_path = suite_vars['path']
941*6777b538SAndroid Build Coastguard Worker  suite_test_modules = suite_vars['test_modules']
942*6777b538SAndroid Build Coastguard Worker
943*6777b538SAndroid Build Coastguard Worker  sys.path = [suite_path] + sys.path
944*6777b538SAndroid Build Coastguard Worker  try:
945*6777b538SAndroid Build Coastguard Worker    suite = unittest.TestSuite()
946*6777b538SAndroid Build Coastguard Worker    suite.addTests(unittest.defaultTestLoader.loadTestsFromName(m)
947*6777b538SAndroid Build Coastguard Worker                   for m in suite_test_modules)
948*6777b538SAndroid Build Coastguard Worker    runner = unittest.TextTestRunner(verbosity=1+args.verbose_count)
949*6777b538SAndroid Build Coastguard Worker    return 0 if runner.run(suite).wasSuccessful() else 1
950*6777b538SAndroid Build Coastguard Worker  finally:
951*6777b538SAndroid Build Coastguard Worker    sys.path = sys.path[1:]
952*6777b538SAndroid Build Coastguard Worker
953*6777b538SAndroid Build Coastguard Worker
954*6777b538SAndroid Build Coastguard Worker_DEFAULT_PLATFORM_MODE_TESTS = [
955*6777b538SAndroid Build Coastguard Worker    'gtest', 'hostside', 'instrumentation', 'junit', 'linker', 'monkey'
956*6777b538SAndroid Build Coastguard Worker]
957*6777b538SAndroid Build Coastguard Worker
958*6777b538SAndroid Build Coastguard Worker
959*6777b538SAndroid Build Coastguard Workerdef RunTestsCommand(args, result_sink_client=None):
960*6777b538SAndroid Build Coastguard Worker  """Checks test type and dispatches to the appropriate function.
961*6777b538SAndroid Build Coastguard Worker
962*6777b538SAndroid Build Coastguard Worker  Args:
963*6777b538SAndroid Build Coastguard Worker    args: argparse.Namespace object.
964*6777b538SAndroid Build Coastguard Worker    result_sink_client: A ResultSinkClient object.
965*6777b538SAndroid Build Coastguard Worker
966*6777b538SAndroid Build Coastguard Worker  Returns:
967*6777b538SAndroid Build Coastguard Worker    Integer indicated exit code.
968*6777b538SAndroid Build Coastguard Worker
969*6777b538SAndroid Build Coastguard Worker  Raises:
970*6777b538SAndroid Build Coastguard Worker    Exception: Unknown command name passed in, or an exception from an
971*6777b538SAndroid Build Coastguard Worker        individual test runner.
972*6777b538SAndroid Build Coastguard Worker  """
973*6777b538SAndroid Build Coastguard Worker  command = args.command
974*6777b538SAndroid Build Coastguard Worker
975*6777b538SAndroid Build Coastguard Worker  ProcessCommonOptions(args)
976*6777b538SAndroid Build Coastguard Worker  logging.info('command: %s', ' '.join(sys.argv))
977*6777b538SAndroid Build Coastguard Worker  if args.enable_platform_mode or command in _DEFAULT_PLATFORM_MODE_TESTS:
978*6777b538SAndroid Build Coastguard Worker    return RunTestsInPlatformMode(args, result_sink_client)
979*6777b538SAndroid Build Coastguard Worker
980*6777b538SAndroid Build Coastguard Worker  if command == 'python':
981*6777b538SAndroid Build Coastguard Worker    return _RunPythonTests(args)
982*6777b538SAndroid Build Coastguard Worker  raise Exception('Unknown test type.')
983*6777b538SAndroid Build Coastguard Worker
984*6777b538SAndroid Build Coastguard Worker
985*6777b538SAndroid Build Coastguard Workerdef _SinkTestResult(test_result, test_file_name, result_sink_client):
986*6777b538SAndroid Build Coastguard Worker  """Upload test result to result_sink.
987*6777b538SAndroid Build Coastguard Worker
988*6777b538SAndroid Build Coastguard Worker  Args:
989*6777b538SAndroid Build Coastguard Worker    test_result: A BaseTestResult object
990*6777b538SAndroid Build Coastguard Worker    test_file_name: A string representing the file location of the test
991*6777b538SAndroid Build Coastguard Worker    result_sink_client: A ResultSinkClient object
992*6777b538SAndroid Build Coastguard Worker
993*6777b538SAndroid Build Coastguard Worker  Returns:
994*6777b538SAndroid Build Coastguard Worker    N/A
995*6777b538SAndroid Build Coastguard Worker  """
996*6777b538SAndroid Build Coastguard Worker  # Some tests put in non utf-8 char as part of the test
997*6777b538SAndroid Build Coastguard Worker  # which breaks uploads, so need to decode and re-encode.
998*6777b538SAndroid Build Coastguard Worker  log_decoded = test_result.GetLog()
999*6777b538SAndroid Build Coastguard Worker  if isinstance(log_decoded, bytes):
1000*6777b538SAndroid Build Coastguard Worker    log_decoded = log_decoded.decode('utf-8', 'replace')
1001*6777b538SAndroid Build Coastguard Worker  html_artifact = ''
1002*6777b538SAndroid Build Coastguard Worker  https_artifacts = []
1003*6777b538SAndroid Build Coastguard Worker  for link_name, link_url in sorted(test_result.GetLinks().items()):
1004*6777b538SAndroid Build Coastguard Worker    if link_url.startswith('https:'):
1005*6777b538SAndroid Build Coastguard Worker      https_artifacts.append('<li><a target="_blank" href=%s>%s</a></li>' %
1006*6777b538SAndroid Build Coastguard Worker                             (link_url, link_name))
1007*6777b538SAndroid Build Coastguard Worker    else:
1008*6777b538SAndroid Build Coastguard Worker      logging.info('Skipping non-https link %r (%s) for test %s.', link_name,
1009*6777b538SAndroid Build Coastguard Worker                   link_url, test_result.GetName())
1010*6777b538SAndroid Build Coastguard Worker  if https_artifacts:
1011*6777b538SAndroid Build Coastguard Worker    html_artifact += '<ul>%s</ul>' % '\n'.join(https_artifacts)
1012*6777b538SAndroid Build Coastguard Worker  result_sink_client.Post(test_result.GetNameForResultSink(),
1013*6777b538SAndroid Build Coastguard Worker                          test_result.GetType(),
1014*6777b538SAndroid Build Coastguard Worker                          test_result.GetDuration(),
1015*6777b538SAndroid Build Coastguard Worker                          log_decoded,
1016*6777b538SAndroid Build Coastguard Worker                          test_file_name,
1017*6777b538SAndroid Build Coastguard Worker                          variant=test_result.GetVariantForResultSink(),
1018*6777b538SAndroid Build Coastguard Worker                          failure_reason=test_result.GetFailureReason(),
1019*6777b538SAndroid Build Coastguard Worker                          html_artifact=html_artifact)
1020*6777b538SAndroid Build Coastguard Worker
1021*6777b538SAndroid Build Coastguard Worker
1022*6777b538SAndroid Build Coastguard Worker_SUPPORTED_IN_PLATFORM_MODE = [
1023*6777b538SAndroid Build Coastguard Worker  # TODO(jbudorick): Add support for more test types.
1024*6777b538SAndroid Build Coastguard Worker  'gtest',
1025*6777b538SAndroid Build Coastguard Worker  'hostside',
1026*6777b538SAndroid Build Coastguard Worker  'instrumentation',
1027*6777b538SAndroid Build Coastguard Worker  'junit',
1028*6777b538SAndroid Build Coastguard Worker  'linker',
1029*6777b538SAndroid Build Coastguard Worker  'monkey',
1030*6777b538SAndroid Build Coastguard Worker]
1031*6777b538SAndroid Build Coastguard Worker
1032*6777b538SAndroid Build Coastguard Worker
1033*6777b538SAndroid Build Coastguard Workerdef RunTestsInPlatformMode(args, result_sink_client=None):
1034*6777b538SAndroid Build Coastguard Worker
1035*6777b538SAndroid Build Coastguard Worker  def infra_error(message):
1036*6777b538SAndroid Build Coastguard Worker    logging.fatal(message)
1037*6777b538SAndroid Build Coastguard Worker    sys.exit(constants.INFRA_EXIT_CODE)
1038*6777b538SAndroid Build Coastguard Worker
1039*6777b538SAndroid Build Coastguard Worker  if args.command not in _SUPPORTED_IN_PLATFORM_MODE:
1040*6777b538SAndroid Build Coastguard Worker    infra_error('%s is not yet supported in platform mode' % args.command)
1041*6777b538SAndroid Build Coastguard Worker
1042*6777b538SAndroid Build Coastguard Worker  ### Set up sigterm handler.
1043*6777b538SAndroid Build Coastguard Worker
1044*6777b538SAndroid Build Coastguard Worker  contexts_to_notify_on_sigterm = []
1045*6777b538SAndroid Build Coastguard Worker  def unexpected_sigterm(_signum, _frame):
1046*6777b538SAndroid Build Coastguard Worker    msg = [
1047*6777b538SAndroid Build Coastguard Worker      'Received SIGTERM. Shutting down.',
1048*6777b538SAndroid Build Coastguard Worker    ]
1049*6777b538SAndroid Build Coastguard Worker    for live_thread in threading.enumerate():
1050*6777b538SAndroid Build Coastguard Worker      # pylint: disable=protected-access
1051*6777b538SAndroid Build Coastguard Worker      thread_stack = ''.join(traceback.format_stack(
1052*6777b538SAndroid Build Coastguard Worker          sys._current_frames()[live_thread.ident]))
1053*6777b538SAndroid Build Coastguard Worker      msg.extend([
1054*6777b538SAndroid Build Coastguard Worker        'Thread "%s" (ident: %s) is currently running:' % (
1055*6777b538SAndroid Build Coastguard Worker            live_thread.name, live_thread.ident),
1056*6777b538SAndroid Build Coastguard Worker        thread_stack])
1057*6777b538SAndroid Build Coastguard Worker
1058*6777b538SAndroid Build Coastguard Worker    for context in contexts_to_notify_on_sigterm:
1059*6777b538SAndroid Build Coastguard Worker      context.ReceivedSigterm()
1060*6777b538SAndroid Build Coastguard Worker
1061*6777b538SAndroid Build Coastguard Worker    infra_error('\n'.join(msg))
1062*6777b538SAndroid Build Coastguard Worker
1063*6777b538SAndroid Build Coastguard Worker  signal.signal(signal.SIGTERM, unexpected_sigterm)
1064*6777b538SAndroid Build Coastguard Worker
1065*6777b538SAndroid Build Coastguard Worker  ### Set up results handling.
1066*6777b538SAndroid Build Coastguard Worker  # TODO(jbudorick): Rewrite results handling.
1067*6777b538SAndroid Build Coastguard Worker
1068*6777b538SAndroid Build Coastguard Worker  # all_raw_results is a list of lists of
1069*6777b538SAndroid Build Coastguard Worker  # base_test_result.TestRunResults objects. Each instance of
1070*6777b538SAndroid Build Coastguard Worker  # TestRunResults contains all test results produced by a single try,
1071*6777b538SAndroid Build Coastguard Worker  # while each list of TestRunResults contains all tries in a single
1072*6777b538SAndroid Build Coastguard Worker  # iteration.
1073*6777b538SAndroid Build Coastguard Worker  all_raw_results = []
1074*6777b538SAndroid Build Coastguard Worker
1075*6777b538SAndroid Build Coastguard Worker  # all_iteration_results is a list of base_test_result.TestRunResults
1076*6777b538SAndroid Build Coastguard Worker  # objects. Each instance of TestRunResults contains the last test
1077*6777b538SAndroid Build Coastguard Worker  # result for each test run in that iteration.
1078*6777b538SAndroid Build Coastguard Worker  all_iteration_results = []
1079*6777b538SAndroid Build Coastguard Worker
1080*6777b538SAndroid Build Coastguard Worker  global_results_tags = set()
1081*6777b538SAndroid Build Coastguard Worker
1082*6777b538SAndroid Build Coastguard Worker  json_file = tempfile.NamedTemporaryFile(delete=False)
1083*6777b538SAndroid Build Coastguard Worker  json_file.close()
1084*6777b538SAndroid Build Coastguard Worker
1085*6777b538SAndroid Build Coastguard Worker  @contextlib.contextmanager
1086*6777b538SAndroid Build Coastguard Worker  def json_finalizer():
1087*6777b538SAndroid Build Coastguard Worker    try:
1088*6777b538SAndroid Build Coastguard Worker      yield
1089*6777b538SAndroid Build Coastguard Worker    finally:
1090*6777b538SAndroid Build Coastguard Worker      if args.json_results_file and os.path.exists(json_file.name):
1091*6777b538SAndroid Build Coastguard Worker        shutil.move(json_file.name, args.json_results_file)
1092*6777b538SAndroid Build Coastguard Worker      elif args.isolated_script_test_output and os.path.exists(json_file.name):
1093*6777b538SAndroid Build Coastguard Worker        shutil.move(json_file.name, args.isolated_script_test_output)
1094*6777b538SAndroid Build Coastguard Worker      else:
1095*6777b538SAndroid Build Coastguard Worker        os.remove(json_file.name)
1096*6777b538SAndroid Build Coastguard Worker
1097*6777b538SAndroid Build Coastguard Worker  @contextlib.contextmanager
1098*6777b538SAndroid Build Coastguard Worker  def json_writer():
1099*6777b538SAndroid Build Coastguard Worker    try:
1100*6777b538SAndroid Build Coastguard Worker      yield
1101*6777b538SAndroid Build Coastguard Worker    except Exception:
1102*6777b538SAndroid Build Coastguard Worker      global_results_tags.add('UNRELIABLE_RESULTS')
1103*6777b538SAndroid Build Coastguard Worker      raise
1104*6777b538SAndroid Build Coastguard Worker    finally:
1105*6777b538SAndroid Build Coastguard Worker      if args.isolated_script_test_output:
1106*6777b538SAndroid Build Coastguard Worker        interrupted = 'UNRELIABLE_RESULTS' in global_results_tags
1107*6777b538SAndroid Build Coastguard Worker        json_results.GenerateJsonTestResultFormatFile(all_raw_results,
1108*6777b538SAndroid Build Coastguard Worker                                                      interrupted,
1109*6777b538SAndroid Build Coastguard Worker                                                      json_file.name,
1110*6777b538SAndroid Build Coastguard Worker                                                      indent=2)
1111*6777b538SAndroid Build Coastguard Worker      else:
1112*6777b538SAndroid Build Coastguard Worker        json_results.GenerateJsonResultsFile(
1113*6777b538SAndroid Build Coastguard Worker            all_raw_results,
1114*6777b538SAndroid Build Coastguard Worker            json_file.name,
1115*6777b538SAndroid Build Coastguard Worker            global_tags=list(global_results_tags),
1116*6777b538SAndroid Build Coastguard Worker            indent=2)
1117*6777b538SAndroid Build Coastguard Worker
1118*6777b538SAndroid Build Coastguard Worker      test_class_to_file_name_dict = {}
1119*6777b538SAndroid Build Coastguard Worker      # Test Location is only supported for instrumentation tests as it
1120*6777b538SAndroid Build Coastguard Worker      # requires the size-info file.
1121*6777b538SAndroid Build Coastguard Worker      if test_instance.TestType() == 'instrumentation':
1122*6777b538SAndroid Build Coastguard Worker        test_class_to_file_name_dict = _CreateClassToFileNameDict(args.test_apk)
1123*6777b538SAndroid Build Coastguard Worker
1124*6777b538SAndroid Build Coastguard Worker      if result_sink_client:
1125*6777b538SAndroid Build Coastguard Worker        for run in all_raw_results:
1126*6777b538SAndroid Build Coastguard Worker          for results in run:
1127*6777b538SAndroid Build Coastguard Worker            for r in results.GetAll():
1128*6777b538SAndroid Build Coastguard Worker              # Matches chrome.page_info.PageInfoViewTest#testChromePage
1129*6777b538SAndroid Build Coastguard Worker              match = re.search(r'^(.+\..+)#', r.GetName())
1130*6777b538SAndroid Build Coastguard Worker              test_file_name = test_class_to_file_name_dict.get(
1131*6777b538SAndroid Build Coastguard Worker                  match.group(1)) if match else None
1132*6777b538SAndroid Build Coastguard Worker              _SinkTestResult(r, test_file_name, result_sink_client)
1133*6777b538SAndroid Build Coastguard Worker
1134*6777b538SAndroid Build Coastguard Worker  @contextlib.contextmanager
1135*6777b538SAndroid Build Coastguard Worker  def upload_logcats_file():
1136*6777b538SAndroid Build Coastguard Worker    try:
1137*6777b538SAndroid Build Coastguard Worker      yield
1138*6777b538SAndroid Build Coastguard Worker    finally:
1139*6777b538SAndroid Build Coastguard Worker      if not args.logcat_output_file:
1140*6777b538SAndroid Build Coastguard Worker        logging.critical('Cannot upload logcat file: no file specified.')
1141*6777b538SAndroid Build Coastguard Worker      elif not os.path.exists(args.logcat_output_file):
1142*6777b538SAndroid Build Coastguard Worker        logging.critical("Cannot upload logcat file: file doesn't exist.")
1143*6777b538SAndroid Build Coastguard Worker      else:
1144*6777b538SAndroid Build Coastguard Worker        with open(args.logcat_output_file) as src:
1145*6777b538SAndroid Build Coastguard Worker          dst = logdog_helper.open_text('unified_logcats')
1146*6777b538SAndroid Build Coastguard Worker          if dst:
1147*6777b538SAndroid Build Coastguard Worker            shutil.copyfileobj(src, dst)
1148*6777b538SAndroid Build Coastguard Worker            dst.close()
1149*6777b538SAndroid Build Coastguard Worker            logging.critical(
1150*6777b538SAndroid Build Coastguard Worker                'Logcat: %s', logdog_helper.get_viewer_url('unified_logcats'))
1151*6777b538SAndroid Build Coastguard Worker
1152*6777b538SAndroid Build Coastguard Worker
1153*6777b538SAndroid Build Coastguard Worker  logcats_uploader = contextlib_ext.Optional(
1154*6777b538SAndroid Build Coastguard Worker      upload_logcats_file(),
1155*6777b538SAndroid Build Coastguard Worker      'upload_logcats_file' in args and args.upload_logcats_file)
1156*6777b538SAndroid Build Coastguard Worker
1157*6777b538SAndroid Build Coastguard Worker  save_detailed_results = (args.local_output or not local_utils.IsOnSwarming()
1158*6777b538SAndroid Build Coastguard Worker                           ) and not args.isolated_script_test_output
1159*6777b538SAndroid Build Coastguard Worker
1160*6777b538SAndroid Build Coastguard Worker  ### Set up test objects.
1161*6777b538SAndroid Build Coastguard Worker
1162*6777b538SAndroid Build Coastguard Worker  out_manager = output_manager_factory.CreateOutputManager(args)
1163*6777b538SAndroid Build Coastguard Worker  env = environment_factory.CreateEnvironment(
1164*6777b538SAndroid Build Coastguard Worker      args, out_manager, infra_error)
1165*6777b538SAndroid Build Coastguard Worker  test_instance = test_instance_factory.CreateTestInstance(args, infra_error)
1166*6777b538SAndroid Build Coastguard Worker  test_run = test_run_factory.CreateTestRun(env, test_instance, infra_error)
1167*6777b538SAndroid Build Coastguard Worker
1168*6777b538SAndroid Build Coastguard Worker  contexts_to_notify_on_sigterm.append(env)
1169*6777b538SAndroid Build Coastguard Worker  contexts_to_notify_on_sigterm.append(test_run)
1170*6777b538SAndroid Build Coastguard Worker
1171*6777b538SAndroid Build Coastguard Worker  if args.list_tests:
1172*6777b538SAndroid Build Coastguard Worker    try:
1173*6777b538SAndroid Build Coastguard Worker      with out_manager, env, test_instance, test_run:
1174*6777b538SAndroid Build Coastguard Worker        test_names = test_run.GetTestsForListing()
1175*6777b538SAndroid Build Coastguard Worker      print('There are {} tests:'.format(len(test_names)))
1176*6777b538SAndroid Build Coastguard Worker      for n in test_names:
1177*6777b538SAndroid Build Coastguard Worker        print(n)
1178*6777b538SAndroid Build Coastguard Worker      return 0
1179*6777b538SAndroid Build Coastguard Worker    except NotImplementedError:
1180*6777b538SAndroid Build Coastguard Worker      sys.stderr.write('Test does not support --list-tests (type={}).\n'.format(
1181*6777b538SAndroid Build Coastguard Worker          args.command))
1182*6777b538SAndroid Build Coastguard Worker      return 1
1183*6777b538SAndroid Build Coastguard Worker
1184*6777b538SAndroid Build Coastguard Worker  ### Run.
1185*6777b538SAndroid Build Coastguard Worker  with out_manager, json_finalizer():
1186*6777b538SAndroid Build Coastguard Worker    # |raw_logs_fh| is only used by Robolectric tests.
1187*6777b538SAndroid Build Coastguard Worker    raw_logs_fh = io.StringIO() if save_detailed_results else None
1188*6777b538SAndroid Build Coastguard Worker
1189*6777b538SAndroid Build Coastguard Worker    with json_writer(), logcats_uploader, env, test_instance, test_run:
1190*6777b538SAndroid Build Coastguard Worker
1191*6777b538SAndroid Build Coastguard Worker      repetitions = (range(args.repeat +
1192*6777b538SAndroid Build Coastguard Worker                           1) if args.repeat >= 0 else itertools.count())
1193*6777b538SAndroid Build Coastguard Worker      result_counts = collections.defaultdict(
1194*6777b538SAndroid Build Coastguard Worker          lambda: collections.defaultdict(int))
1195*6777b538SAndroid Build Coastguard Worker      iteration_count = 0
1196*6777b538SAndroid Build Coastguard Worker      for _ in repetitions:
1197*6777b538SAndroid Build Coastguard Worker        # raw_results will be populated with base_test_result.TestRunResults by
1198*6777b538SAndroid Build Coastguard Worker        # test_run.RunTests(). It is immediately added to all_raw_results so
1199*6777b538SAndroid Build Coastguard Worker        # that in the event of an exception, all_raw_results will already have
1200*6777b538SAndroid Build Coastguard Worker        # the up-to-date results and those can be written to disk.
1201*6777b538SAndroid Build Coastguard Worker        raw_results = []
1202*6777b538SAndroid Build Coastguard Worker        all_raw_results.append(raw_results)
1203*6777b538SAndroid Build Coastguard Worker
1204*6777b538SAndroid Build Coastguard Worker        test_run.RunTests(raw_results, raw_logs_fh=raw_logs_fh)
1205*6777b538SAndroid Build Coastguard Worker        if not raw_results:
1206*6777b538SAndroid Build Coastguard Worker          all_raw_results.pop()
1207*6777b538SAndroid Build Coastguard Worker          continue
1208*6777b538SAndroid Build Coastguard Worker
1209*6777b538SAndroid Build Coastguard Worker        iteration_results = base_test_result.TestRunResults()
1210*6777b538SAndroid Build Coastguard Worker        for r in reversed(raw_results):
1211*6777b538SAndroid Build Coastguard Worker          iteration_results.AddTestRunResults(r)
1212*6777b538SAndroid Build Coastguard Worker        all_iteration_results.append(iteration_results)
1213*6777b538SAndroid Build Coastguard Worker        iteration_count += 1
1214*6777b538SAndroid Build Coastguard Worker
1215*6777b538SAndroid Build Coastguard Worker        for r in iteration_results.GetAll():
1216*6777b538SAndroid Build Coastguard Worker          result_counts[r.GetName()][r.GetType()] += 1
1217*6777b538SAndroid Build Coastguard Worker
1218*6777b538SAndroid Build Coastguard Worker        report_results.LogFull(
1219*6777b538SAndroid Build Coastguard Worker            results=iteration_results,
1220*6777b538SAndroid Build Coastguard Worker            test_type=test_instance.TestType(),
1221*6777b538SAndroid Build Coastguard Worker            test_package=test_run.TestPackage(),
1222*6777b538SAndroid Build Coastguard Worker            annotation=getattr(args, 'annotations', None),
1223*6777b538SAndroid Build Coastguard Worker            flakiness_server=getattr(args, 'flakiness_dashboard_server',
1224*6777b538SAndroid Build Coastguard Worker                                     None))
1225*6777b538SAndroid Build Coastguard Worker
1226*6777b538SAndroid Build Coastguard Worker        failed_tests = (iteration_results.GetNotPass() -
1227*6777b538SAndroid Build Coastguard Worker                        iteration_results.GetSkip())
1228*6777b538SAndroid Build Coastguard Worker        if failed_tests:
1229*6777b538SAndroid Build Coastguard Worker          _LogRerunStatement(failed_tests, args.wrapper_script_args)
1230*6777b538SAndroid Build Coastguard Worker
1231*6777b538SAndroid Build Coastguard Worker        if args.break_on_failure and not iteration_results.DidRunPass():
1232*6777b538SAndroid Build Coastguard Worker          break
1233*6777b538SAndroid Build Coastguard Worker
1234*6777b538SAndroid Build Coastguard Worker      if iteration_count > 1:
1235*6777b538SAndroid Build Coastguard Worker        # display summary results
1236*6777b538SAndroid Build Coastguard Worker        # only display results for a test if at least one test did not pass
1237*6777b538SAndroid Build Coastguard Worker        all_pass = 0
1238*6777b538SAndroid Build Coastguard Worker        tot_tests = 0
1239*6777b538SAndroid Build Coastguard Worker        for test_name in result_counts:
1240*6777b538SAndroid Build Coastguard Worker          tot_tests += 1
1241*6777b538SAndroid Build Coastguard Worker          if any(result_counts[test_name][x] for x in (
1242*6777b538SAndroid Build Coastguard Worker              base_test_result.ResultType.FAIL,
1243*6777b538SAndroid Build Coastguard Worker              base_test_result.ResultType.CRASH,
1244*6777b538SAndroid Build Coastguard Worker              base_test_result.ResultType.TIMEOUT,
1245*6777b538SAndroid Build Coastguard Worker              base_test_result.ResultType.UNKNOWN)):
1246*6777b538SAndroid Build Coastguard Worker            logging.critical(
1247*6777b538SAndroid Build Coastguard Worker                '%s: %s',
1248*6777b538SAndroid Build Coastguard Worker                test_name,
1249*6777b538SAndroid Build Coastguard Worker                ', '.join('%s %s' % (str(result_counts[test_name][i]), i)
1250*6777b538SAndroid Build Coastguard Worker                          for i in base_test_result.ResultType.GetTypes()))
1251*6777b538SAndroid Build Coastguard Worker          else:
1252*6777b538SAndroid Build Coastguard Worker            all_pass += 1
1253*6777b538SAndroid Build Coastguard Worker
1254*6777b538SAndroid Build Coastguard Worker        logging.critical('%s of %s tests passed in all %s runs',
1255*6777b538SAndroid Build Coastguard Worker                         str(all_pass),
1256*6777b538SAndroid Build Coastguard Worker                         str(tot_tests),
1257*6777b538SAndroid Build Coastguard Worker                         str(iteration_count))
1258*6777b538SAndroid Build Coastguard Worker
1259*6777b538SAndroid Build Coastguard Worker    if save_detailed_results:
1260*6777b538SAndroid Build Coastguard Worker      assert raw_logs_fh
1261*6777b538SAndroid Build Coastguard Worker      raw_logs_fh.seek(0)
1262*6777b538SAndroid Build Coastguard Worker      raw_logs = raw_logs_fh.read()
1263*6777b538SAndroid Build Coastguard Worker      if raw_logs:
1264*6777b538SAndroid Build Coastguard Worker        with out_manager.ArchivedTempfile(
1265*6777b538SAndroid Build Coastguard Worker            'raw_logs.txt', 'raw_logs',
1266*6777b538SAndroid Build Coastguard Worker            output_manager.Datatype.TEXT) as raw_logs_file:
1267*6777b538SAndroid Build Coastguard Worker          raw_logs_file.write(raw_logs)
1268*6777b538SAndroid Build Coastguard Worker        logging.critical('RAW LOGS: %s', raw_logs_file.Link())
1269*6777b538SAndroid Build Coastguard Worker
1270*6777b538SAndroid Build Coastguard Worker      with out_manager.ArchivedTempfile(
1271*6777b538SAndroid Build Coastguard Worker          'test_results_presentation.html',
1272*6777b538SAndroid Build Coastguard Worker          'test_results_presentation',
1273*6777b538SAndroid Build Coastguard Worker          output_manager.Datatype.HTML) as results_detail_file:
1274*6777b538SAndroid Build Coastguard Worker        result_html_string, _, _ = test_results_presentation.result_details(
1275*6777b538SAndroid Build Coastguard Worker            json_path=json_file.name,
1276*6777b538SAndroid Build Coastguard Worker            test_name=args.command,
1277*6777b538SAndroid Build Coastguard Worker            cs_base_url='http://cs.chromium.org',
1278*6777b538SAndroid Build Coastguard Worker            local_output=True)
1279*6777b538SAndroid Build Coastguard Worker        results_detail_file.write(result_html_string)
1280*6777b538SAndroid Build Coastguard Worker        results_detail_file.flush()
1281*6777b538SAndroid Build Coastguard Worker      logging.critical('TEST RESULTS: %s', results_detail_file.Link())
1282*6777b538SAndroid Build Coastguard Worker
1283*6777b538SAndroid Build Coastguard Worker      ui_screenshots = test_results_presentation.ui_screenshot_set(
1284*6777b538SAndroid Build Coastguard Worker          json_file.name)
1285*6777b538SAndroid Build Coastguard Worker      if ui_screenshots:
1286*6777b538SAndroid Build Coastguard Worker        with out_manager.ArchivedTempfile(
1287*6777b538SAndroid Build Coastguard Worker            'ui_screenshots.json',
1288*6777b538SAndroid Build Coastguard Worker            'ui_capture',
1289*6777b538SAndroid Build Coastguard Worker            output_manager.Datatype.JSON) as ui_screenshot_file:
1290*6777b538SAndroid Build Coastguard Worker          ui_screenshot_file.write(ui_screenshots)
1291*6777b538SAndroid Build Coastguard Worker        logging.critical('UI Screenshots: %s', ui_screenshot_file.Link())
1292*6777b538SAndroid Build Coastguard Worker
1293*6777b538SAndroid Build Coastguard Worker  return (0 if all(r.DidRunPass() for r in all_iteration_results)
1294*6777b538SAndroid Build Coastguard Worker          else constants.ERROR_EXIT_CODE)
1295*6777b538SAndroid Build Coastguard Worker
1296*6777b538SAndroid Build Coastguard Worker
1297*6777b538SAndroid Build Coastguard Workerdef _LogRerunStatement(failed_tests, wrapper_arg_str):
1298*6777b538SAndroid Build Coastguard Worker  """Logs a message that can rerun the failed tests.
1299*6777b538SAndroid Build Coastguard Worker
1300*6777b538SAndroid Build Coastguard Worker  Logs a copy/pasteable message that filters tests so just the failing tests
1301*6777b538SAndroid Build Coastguard Worker  are run.
1302*6777b538SAndroid Build Coastguard Worker
1303*6777b538SAndroid Build Coastguard Worker  Args:
1304*6777b538SAndroid Build Coastguard Worker    failed_tests: A set of test results that did not pass.
1305*6777b538SAndroid Build Coastguard Worker    wrapper_arg_str: A string of args that were passed to the called wrapper
1306*6777b538SAndroid Build Coastguard Worker        script.
1307*6777b538SAndroid Build Coastguard Worker  """
1308*6777b538SAndroid Build Coastguard Worker  rerun_arg_list = []
1309*6777b538SAndroid Build Coastguard Worker  try:
1310*6777b538SAndroid Build Coastguard Worker    constants.CheckOutputDirectory()
1311*6777b538SAndroid Build Coastguard Worker  # constants.CheckOutputDirectory throws bare exceptions.
1312*6777b538SAndroid Build Coastguard Worker  except:  # pylint: disable=bare-except
1313*6777b538SAndroid Build Coastguard Worker    logging.exception('Output directory not found. Unable to generate failing '
1314*6777b538SAndroid Build Coastguard Worker                      'test filter file.')
1315*6777b538SAndroid Build Coastguard Worker    return
1316*6777b538SAndroid Build Coastguard Worker
1317*6777b538SAndroid Build Coastguard Worker  output_directory = constants.GetOutDirectory()
1318*6777b538SAndroid Build Coastguard Worker  if not os.path.exists(output_directory):
1319*6777b538SAndroid Build Coastguard Worker    logging.error('Output directory not found. Unable to generate failing '
1320*6777b538SAndroid Build Coastguard Worker                  'test filter file.')
1321*6777b538SAndroid Build Coastguard Worker    return
1322*6777b538SAndroid Build Coastguard Worker
1323*6777b538SAndroid Build Coastguard Worker  test_filter_file = os.path.join(os.path.relpath(output_directory),
1324*6777b538SAndroid Build Coastguard Worker                                  _RERUN_FAILED_TESTS_FILE)
1325*6777b538SAndroid Build Coastguard Worker  arg_list = shlex.split(wrapper_arg_str) if wrapper_arg_str else sys.argv
1326*6777b538SAndroid Build Coastguard Worker  index = 0
1327*6777b538SAndroid Build Coastguard Worker  while index < len(arg_list):
1328*6777b538SAndroid Build Coastguard Worker    arg = arg_list[index]
1329*6777b538SAndroid Build Coastguard Worker    # Skip adding the filter=<file> and/or the filter arg as we're replacing
1330*6777b538SAndroid Build Coastguard Worker    # it with the new filter arg.
1331*6777b538SAndroid Build Coastguard Worker    # This covers --test-filter=, --test-launcher-filter-file=, --gtest-filter=,
1332*6777b538SAndroid Build Coastguard Worker    # --test-filter *Foobar.baz, -f *foobar, --package-filter <package>,
1333*6777b538SAndroid Build Coastguard Worker    # --runner-filter <runner>.
1334*6777b538SAndroid Build Coastguard Worker    if 'filter' in arg or arg == '-f':
1335*6777b538SAndroid Build Coastguard Worker      index += 1 if '=' in arg else 2
1336*6777b538SAndroid Build Coastguard Worker      continue
1337*6777b538SAndroid Build Coastguard Worker
1338*6777b538SAndroid Build Coastguard Worker    rerun_arg_list.append(arg)
1339*6777b538SAndroid Build Coastguard Worker    index += 1
1340*6777b538SAndroid Build Coastguard Worker
1341*6777b538SAndroid Build Coastguard Worker  failed_test_list = [str(t) for t in failed_tests]
1342*6777b538SAndroid Build Coastguard Worker  with open(test_filter_file, 'w') as fp:
1343*6777b538SAndroid Build Coastguard Worker    for t in failed_test_list:
1344*6777b538SAndroid Build Coastguard Worker      # Test result names can have # in them that don't match when applied as
1345*6777b538SAndroid Build Coastguard Worker      # a test name filter.
1346*6777b538SAndroid Build Coastguard Worker      fp.write('%s\n' % t.replace('#', '.'))
1347*6777b538SAndroid Build Coastguard Worker
1348*6777b538SAndroid Build Coastguard Worker  rerun_arg_list.append('--test-launcher-filter-file=%s' % test_filter_file)
1349*6777b538SAndroid Build Coastguard Worker  msg = """
1350*6777b538SAndroid Build Coastguard Worker    %d Test(s) failed.
1351*6777b538SAndroid Build Coastguard Worker    Rerun failed tests with copy and pastable command:
1352*6777b538SAndroid Build Coastguard Worker        %s
1353*6777b538SAndroid Build Coastguard Worker    """
1354*6777b538SAndroid Build Coastguard Worker  logging.critical(msg, len(failed_tests), shlex.join(rerun_arg_list))
1355*6777b538SAndroid Build Coastguard Worker
1356*6777b538SAndroid Build Coastguard Worker
1357*6777b538SAndroid Build Coastguard Workerdef DumpThreadStacks(_signal, _frame):
1358*6777b538SAndroid Build Coastguard Worker  for thread in threading.enumerate():
1359*6777b538SAndroid Build Coastguard Worker    reraiser_thread.LogThreadStack(thread)
1360*6777b538SAndroid Build Coastguard Worker
1361*6777b538SAndroid Build Coastguard Worker
1362*6777b538SAndroid Build Coastguard Workerdef main():
1363*6777b538SAndroid Build Coastguard Worker  signal.signal(signal.SIGUSR1, DumpThreadStacks)
1364*6777b538SAndroid Build Coastguard Worker
1365*6777b538SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
1366*6777b538SAndroid Build Coastguard Worker  command_parsers = parser.add_subparsers(
1367*6777b538SAndroid Build Coastguard Worker      title='test types', dest='command')
1368*6777b538SAndroid Build Coastguard Worker
1369*6777b538SAndroid Build Coastguard Worker  subp = command_parsers.add_parser(
1370*6777b538SAndroid Build Coastguard Worker      'gtest',
1371*6777b538SAndroid Build Coastguard Worker      help='googletest-based C++ tests')
1372*6777b538SAndroid Build Coastguard Worker  AddCommonOptions(subp)
1373*6777b538SAndroid Build Coastguard Worker  AddDeviceOptions(subp)
1374*6777b538SAndroid Build Coastguard Worker  AddEmulatorOptions(subp)
1375*6777b538SAndroid Build Coastguard Worker  AddGTestOptions(subp)
1376*6777b538SAndroid Build Coastguard Worker  AddTracingOptions(subp)
1377*6777b538SAndroid Build Coastguard Worker  AddCommandLineOptions(subp)
1378*6777b538SAndroid Build Coastguard Worker
1379*6777b538SAndroid Build Coastguard Worker  subp = command_parsers.add_parser(
1380*6777b538SAndroid Build Coastguard Worker      'hostside',
1381*6777b538SAndroid Build Coastguard Worker      help='Webview CTS host-side tests')
1382*6777b538SAndroid Build Coastguard Worker  AddCommonOptions(subp)
1383*6777b538SAndroid Build Coastguard Worker  AddDeviceOptions(subp)
1384*6777b538SAndroid Build Coastguard Worker  AddEmulatorOptions(subp)
1385*6777b538SAndroid Build Coastguard Worker  AddHostsideTestOptions(subp)
1386*6777b538SAndroid Build Coastguard Worker
1387*6777b538SAndroid Build Coastguard Worker  subp = command_parsers.add_parser(
1388*6777b538SAndroid Build Coastguard Worker      'instrumentation',
1389*6777b538SAndroid Build Coastguard Worker      help='InstrumentationTestCase-based Java tests')
1390*6777b538SAndroid Build Coastguard Worker  AddCommonOptions(subp)
1391*6777b538SAndroid Build Coastguard Worker  AddDeviceOptions(subp)
1392*6777b538SAndroid Build Coastguard Worker  AddEmulatorOptions(subp)
1393*6777b538SAndroid Build Coastguard Worker  AddInstrumentationTestOptions(subp)
1394*6777b538SAndroid Build Coastguard Worker  AddSkiaGoldTestOptions(subp)
1395*6777b538SAndroid Build Coastguard Worker  AddTracingOptions(subp)
1396*6777b538SAndroid Build Coastguard Worker  AddCommandLineOptions(subp)
1397*6777b538SAndroid Build Coastguard Worker
1398*6777b538SAndroid Build Coastguard Worker  subp = command_parsers.add_parser(
1399*6777b538SAndroid Build Coastguard Worker      'junit',
1400*6777b538SAndroid Build Coastguard Worker      help='JUnit4-based Java tests')
1401*6777b538SAndroid Build Coastguard Worker  AddCommonOptions(subp)
1402*6777b538SAndroid Build Coastguard Worker  AddJUnitTestOptions(subp)
1403*6777b538SAndroid Build Coastguard Worker
1404*6777b538SAndroid Build Coastguard Worker  subp = command_parsers.add_parser(
1405*6777b538SAndroid Build Coastguard Worker      'linker',
1406*6777b538SAndroid Build Coastguard Worker      help='linker tests')
1407*6777b538SAndroid Build Coastguard Worker  AddCommonOptions(subp)
1408*6777b538SAndroid Build Coastguard Worker  AddDeviceOptions(subp)
1409*6777b538SAndroid Build Coastguard Worker  AddEmulatorOptions(subp)
1410*6777b538SAndroid Build Coastguard Worker  AddLinkerTestOptions(subp)
1411*6777b538SAndroid Build Coastguard Worker
1412*6777b538SAndroid Build Coastguard Worker  subp = command_parsers.add_parser(
1413*6777b538SAndroid Build Coastguard Worker      'monkey',
1414*6777b538SAndroid Build Coastguard Worker      help="tests based on Android's monkey command")
1415*6777b538SAndroid Build Coastguard Worker  AddCommonOptions(subp)
1416*6777b538SAndroid Build Coastguard Worker  AddDeviceOptions(subp)
1417*6777b538SAndroid Build Coastguard Worker  AddEmulatorOptions(subp)
1418*6777b538SAndroid Build Coastguard Worker  AddMonkeyTestOptions(subp)
1419*6777b538SAndroid Build Coastguard Worker
1420*6777b538SAndroid Build Coastguard Worker  subp = command_parsers.add_parser(
1421*6777b538SAndroid Build Coastguard Worker      'python',
1422*6777b538SAndroid Build Coastguard Worker      help='python tests based on unittest.TestCase')
1423*6777b538SAndroid Build Coastguard Worker  AddCommonOptions(subp)
1424*6777b538SAndroid Build Coastguard Worker  AddPythonTestOptions(subp)
1425*6777b538SAndroid Build Coastguard Worker
1426*6777b538SAndroid Build Coastguard Worker  args, unknown_args = parser.parse_known_args()
1427*6777b538SAndroid Build Coastguard Worker  if unknown_args:
1428*6777b538SAndroid Build Coastguard Worker    if hasattr(args, 'allow_unknown') and args.allow_unknown:
1429*6777b538SAndroid Build Coastguard Worker      args.command_line_flags = unknown_args
1430*6777b538SAndroid Build Coastguard Worker    else:
1431*6777b538SAndroid Build Coastguard Worker      parser.error('unrecognized arguments: %s' % ' '.join(unknown_args))
1432*6777b538SAndroid Build Coastguard Worker
1433*6777b538SAndroid Build Coastguard Worker  # --replace-system-package/--remove-system-package has the potential to cause
1434*6777b538SAndroid Build Coastguard Worker  # issues if --enable-concurrent-adb is set, so disallow that combination.
1435*6777b538SAndroid Build Coastguard Worker  concurrent_adb_enabled = (hasattr(args, 'enable_concurrent_adb')
1436*6777b538SAndroid Build Coastguard Worker                            and args.enable_concurrent_adb)
1437*6777b538SAndroid Build Coastguard Worker  replacing_system_packages = (hasattr(args, 'replace_system_package')
1438*6777b538SAndroid Build Coastguard Worker                               and args.replace_system_package)
1439*6777b538SAndroid Build Coastguard Worker  removing_system_packages = (hasattr(args, 'system_packages_to_remove')
1440*6777b538SAndroid Build Coastguard Worker                              and args.system_packages_to_remove)
1441*6777b538SAndroid Build Coastguard Worker  if (concurrent_adb_enabled
1442*6777b538SAndroid Build Coastguard Worker      and (replacing_system_packages or removing_system_packages)):
1443*6777b538SAndroid Build Coastguard Worker    parser.error('--enable-concurrent-adb cannot be used with either '
1444*6777b538SAndroid Build Coastguard Worker                 '--replace-system-package or --remove-system-package')
1445*6777b538SAndroid Build Coastguard Worker
1446*6777b538SAndroid Build Coastguard Worker  # --use-webview-provider has the potential to cause issues if
1447*6777b538SAndroid Build Coastguard Worker  # --enable-concurrent-adb is set, so disallow that combination
1448*6777b538SAndroid Build Coastguard Worker  if (hasattr(args, 'use_webview_provider') and
1449*6777b538SAndroid Build Coastguard Worker      hasattr(args, 'enable_concurrent_adb') and args.use_webview_provider and
1450*6777b538SAndroid Build Coastguard Worker      args.enable_concurrent_adb):
1451*6777b538SAndroid Build Coastguard Worker    parser.error('--use-webview-provider and --enable-concurrent-adb cannot '
1452*6777b538SAndroid Build Coastguard Worker                 'be used together')
1453*6777b538SAndroid Build Coastguard Worker
1454*6777b538SAndroid Build Coastguard Worker  if (getattr(args, 'coverage_on_the_fly', False)
1455*6777b538SAndroid Build Coastguard Worker      and not getattr(args, 'coverage_dir', '')):
1456*6777b538SAndroid Build Coastguard Worker    parser.error('--coverage-on-the-fly requires --coverage-dir')
1457*6777b538SAndroid Build Coastguard Worker
1458*6777b538SAndroid Build Coastguard Worker  if (hasattr(args, 'debug_socket') or
1459*6777b538SAndroid Build Coastguard Worker      (hasattr(args, 'wait_for_java_debugger') and
1460*6777b538SAndroid Build Coastguard Worker      args.wait_for_java_debugger)):
1461*6777b538SAndroid Build Coastguard Worker    args.num_retries = 0
1462*6777b538SAndroid Build Coastguard Worker
1463*6777b538SAndroid Build Coastguard Worker  # Result-sink may not exist in the environment if rdb stream is not enabled.
1464*6777b538SAndroid Build Coastguard Worker  result_sink_client = result_sink.TryInitClient()
1465*6777b538SAndroid Build Coastguard Worker
1466*6777b538SAndroid Build Coastguard Worker  try:
1467*6777b538SAndroid Build Coastguard Worker    return RunTestsCommand(args, result_sink_client)
1468*6777b538SAndroid Build Coastguard Worker  except base_error.BaseError as e:
1469*6777b538SAndroid Build Coastguard Worker    logging.exception('Error occurred.')
1470*6777b538SAndroid Build Coastguard Worker    if e.is_infra_error:
1471*6777b538SAndroid Build Coastguard Worker      return constants.INFRA_EXIT_CODE
1472*6777b538SAndroid Build Coastguard Worker    return constants.ERROR_EXIT_CODE
1473*6777b538SAndroid Build Coastguard Worker  except Exception:  # pylint: disable=W0703
1474*6777b538SAndroid Build Coastguard Worker    logging.exception('Unrecognized error occurred.')
1475*6777b538SAndroid Build Coastguard Worker    return constants.ERROR_EXIT_CODE
1476*6777b538SAndroid Build Coastguard Worker
1477*6777b538SAndroid Build Coastguard Worker
1478*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__':
1479*6777b538SAndroid Build Coastguard Worker  exit_code = main()
1480*6777b538SAndroid Build Coastguard Worker  if exit_code == constants.INFRA_EXIT_CODE:
1481*6777b538SAndroid Build Coastguard Worker    # This exit code is returned in case of missing, unreachable,
1482*6777b538SAndroid Build Coastguard Worker    # or otherwise not fit for purpose test devices.
1483*6777b538SAndroid Build Coastguard Worker    # When this happens, the graceful cleanup triggered by sys.exit()
1484*6777b538SAndroid Build Coastguard Worker    # hangs indefinitely (on swarming - until it hits 20min timeout).
1485*6777b538SAndroid Build Coastguard Worker    # Skip cleanup (other than flushing output streams) and exit forcefully
1486*6777b538SAndroid Build Coastguard Worker    # to avoid the hang.
1487*6777b538SAndroid Build Coastguard Worker    sys.stdout.flush()
1488*6777b538SAndroid Build Coastguard Worker    sys.stderr.flush()
1489*6777b538SAndroid Build Coastguard Worker    os._exit(exit_code)  # pylint: disable=protected-access
1490*6777b538SAndroid Build Coastguard Worker  else:
1491*6777b538SAndroid Build Coastguard Worker    sys.exit(exit_code)
1492