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