xref: /aosp_15_r20/external/cronet/testing/scripts/run_isolated_script_test.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1#!/usr/bin/env vpython3
2# Copyright 2015 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Runs a script that can run as an isolate (or not).
7
8If optional argument --isolated-script-test-output=[FILENAME] is passed
9to the script, json is written to that file in the format detailed in
10//docs/testing/json-test-results-format.md.
11
12If optional argument --isolated-script-test-filter=[TEST_NAMES] is passed to
13the script, it should be a  double-colon-separated ("::") list of test names,
14to run just that subset of tests.
15
16This script is intended to be the base command invoked by the isolate,
17followed by a subsequent Python script. It could be generalized to
18invoke an arbitrary executable.
19"""
20
21import argparse
22import json
23import os
24import pprint
25import sys
26import tempfile
27
28
29# Add src/testing/ into sys.path for importing common.
30sys.path.append(
31    os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
32from scripts import common
33
34
35# Some harnesses understand the --isolated-script-test arguments
36# directly and prefer that they be passed through.
37KNOWN_ISOLATED_SCRIPT_TEST_RUNNERS = {'run_web_tests.py', 'run_webgpu_cts.py'}
38
39
40# Known typ test runners this script wraps. They need a different argument name
41# when selecting which tests to run.
42# TODO(dpranke): Detect if the wrapped test suite uses typ better.
43KNOWN_TYP_TEST_RUNNERS = {
44    'metrics_python_tests.py',
45    'monochrome_python_tests.py',
46    'run_blinkpy_tests.py',
47    'run_mac_signing_tests.py',
48    'run_mini_installer_tests.py',
49    'test_suite_all.py',  # //tools/grit:grit_python_unittests
50}
51
52KNOWN_TYP_VPYTHON3_TEST_RUNNERS = {
53    'monochrome_python_tests.py',
54    'run_polymer_tools_tests.py',
55    'test_suite_all.py',  # //tools/grit:grit_python_unittests
56}
57
58# pylint: disable=super-with-arguments
59
60class BareScriptTestAdapter(common.BaseIsolatedScriptArgsAdapter):
61  def __init__(self):
62    super().__init__()
63    # Arguments that are ignored, but added here because it's easier to ignore
64    # them than to update bot configs to not pass them.
65    common.add_emulator_args(self._parser)
66    self._parser.add_argument(
67        '--coverage-dir', type=str, help='Unused')
68    self._parser.add_argument(
69        '--use-persistent-shell', action='store_true', help='Unused')
70
71
72class IsolatedScriptTestAdapter(common.BaseIsolatedScriptArgsAdapter):
73  def generate_sharding_args(self, total_shards, shard_index):
74    # This script only uses environment variable for sharding.
75    del total_shards, shard_index  # unused
76    return []
77
78  def generate_test_also_run_disabled_tests_args(self):
79    return ['--isolated-script-test-also-run-disabled-tests']
80
81  def generate_test_filter_args(self, test_filter_str):
82    return ['--isolated-script-test-filter=%s' % test_filter_str]
83
84  def generate_test_output_args(self, output):
85    return ['--isolated-script-test-output=%s' % output]
86
87  def generate_test_launcher_retry_limit_args(self, retry_limit):
88    return ['--isolated-script-test-launcher-retry-limit=%d' % retry_limit]
89
90  def generate_test_repeat_args(self, repeat_count):
91    return ['--isolated-script-test-repeat=%d' % repeat_count]
92
93
94class TypUnittestAdapter(common.BaseIsolatedScriptArgsAdapter):
95
96  def __init__(self):
97    super(TypUnittestAdapter, self).__init__()
98    self._temp_filter_file = None
99
100  def generate_sharding_args(self, total_shards, shard_index):
101    # This script only uses environment variable for sharding.
102    del total_shards, shard_index  # unused
103    return []
104
105  def generate_test_filter_args(self, test_filter_str):
106    filter_list = common.extract_filter_list(test_filter_str)
107    self._temp_filter_file = tempfile.NamedTemporaryFile(
108        mode='w', delete=False)
109    self._temp_filter_file.write('\n'.join(filter_list))
110    self._temp_filter_file.close()
111    arg_name = 'test-list'
112    if any(r in self.rest_args[0] for r in KNOWN_TYP_TEST_RUNNERS):
113      arg_name = 'file-list'
114
115    return ['--%s=' % arg_name + self._temp_filter_file.name]
116
117  def generate_test_output_args(self, output):
118    return ['--write-full-results-to', output]
119
120  def generate_test_launcher_retry_limit_args(self, retry_limit):
121    return ['--isolated-script-test-launcher-retry-limit=%d' % retry_limit]
122
123  def generate_test_repeat_args(self, repeat_count):
124    return ['--isolated-script-test-repeat=%d' % repeat_count]
125
126  def clean_up_after_test_run(self):
127    if self._temp_filter_file:
128      os.unlink(self._temp_filter_file.name)
129
130  def select_python_executable(self):
131    if any(r in self.rest_args[0] for r in KNOWN_TYP_VPYTHON3_TEST_RUNNERS):
132      return 'vpython3.bat' if sys.platform == 'win32' else 'vpython3'
133    return super(TypUnittestAdapter, self).select_python_executable()
134
135
136def main():
137  parser = argparse.ArgumentParser()
138  parser.add_argument('--script-type', choices=['isolated', 'typ', 'bare'])
139  args, _ = parser.parse_known_args()
140
141  kind = args.script_type
142  if not kind:
143    if any(r in sys.argv[1] for r in KNOWN_ISOLATED_SCRIPT_TEST_RUNNERS):
144      kind = 'isolated'
145    else:
146      kind = 'typ'
147
148  if kind == 'isolated':
149    adapter = IsolatedScriptTestAdapter()
150  elif kind == 'typ':
151    adapter = TypUnittestAdapter()
152  else:
153    adapter = BareScriptTestAdapter()
154  return adapter.run_test()
155
156# This is not really a "script test" so does not need to manually add
157# any additional compile targets.
158def main_compile_targets(args):
159  json.dump([], args.output)
160
161
162if __name__ == '__main__':
163  # Conform minimally to the protocol defined by ScriptTest.
164  if 'compile_targets' in sys.argv:
165    funcs = {
166      'run': None,
167      'compile_targets': main_compile_targets,
168    }
169    sys.exit(common.run_script(sys.argv[1:], funcs))
170  sys.exit(main())
171