xref: /aosp_15_r20/external/grpc-grpc/tools/run_tests/run_tests.py (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1*cc02d7e2SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*cc02d7e2SAndroid Build Coastguard Worker# Copyright 2015 gRPC authors.
3*cc02d7e2SAndroid Build Coastguard Worker#
4*cc02d7e2SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*cc02d7e2SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*cc02d7e2SAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*cc02d7e2SAndroid Build Coastguard Worker#
8*cc02d7e2SAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
9*cc02d7e2SAndroid Build Coastguard Worker#
10*cc02d7e2SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*cc02d7e2SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*cc02d7e2SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*cc02d7e2SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*cc02d7e2SAndroid Build Coastguard Worker# limitations under the License.
15*cc02d7e2SAndroid Build Coastguard Worker"""Run tests in parallel."""
16*cc02d7e2SAndroid Build Coastguard Worker
17*cc02d7e2SAndroid Build Coastguard Workerfrom __future__ import print_function
18*cc02d7e2SAndroid Build Coastguard Worker
19*cc02d7e2SAndroid Build Coastguard Workerimport argparse
20*cc02d7e2SAndroid Build Coastguard Workerimport ast
21*cc02d7e2SAndroid Build Coastguard Workerimport collections
22*cc02d7e2SAndroid Build Coastguard Workerimport glob
23*cc02d7e2SAndroid Build Coastguard Workerimport itertools
24*cc02d7e2SAndroid Build Coastguard Workerimport json
25*cc02d7e2SAndroid Build Coastguard Workerimport logging
26*cc02d7e2SAndroid Build Coastguard Workerimport multiprocessing
27*cc02d7e2SAndroid Build Coastguard Workerimport os
28*cc02d7e2SAndroid Build Coastguard Workerimport os.path
29*cc02d7e2SAndroid Build Coastguard Workerimport platform
30*cc02d7e2SAndroid Build Coastguard Workerimport random
31*cc02d7e2SAndroid Build Coastguard Workerimport re
32*cc02d7e2SAndroid Build Coastguard Workerimport shlex
33*cc02d7e2SAndroid Build Coastguard Workerimport socket
34*cc02d7e2SAndroid Build Coastguard Workerimport subprocess
35*cc02d7e2SAndroid Build Coastguard Workerimport sys
36*cc02d7e2SAndroid Build Coastguard Workerimport tempfile
37*cc02d7e2SAndroid Build Coastguard Workerimport time
38*cc02d7e2SAndroid Build Coastguard Workerimport traceback
39*cc02d7e2SAndroid Build Coastguard Workerimport uuid
40*cc02d7e2SAndroid Build Coastguard Worker
41*cc02d7e2SAndroid Build Coastguard Workerimport six
42*cc02d7e2SAndroid Build Coastguard Workerfrom six.moves import urllib
43*cc02d7e2SAndroid Build Coastguard Worker
44*cc02d7e2SAndroid Build Coastguard Workerimport python_utils.jobset as jobset
45*cc02d7e2SAndroid Build Coastguard Workerimport python_utils.report_utils as report_utils
46*cc02d7e2SAndroid Build Coastguard Workerimport python_utils.start_port_server as start_port_server
47*cc02d7e2SAndroid Build Coastguard Workerimport python_utils.watch_dirs as watch_dirs
48*cc02d7e2SAndroid Build Coastguard Worker
49*cc02d7e2SAndroid Build Coastguard Workertry:
50*cc02d7e2SAndroid Build Coastguard Worker    from python_utils.upload_test_results import upload_results_to_bq
51*cc02d7e2SAndroid Build Coastguard Workerexcept ImportError:
52*cc02d7e2SAndroid Build Coastguard Worker    pass  # It's ok to not import because this is only necessary to upload results to BQ.
53*cc02d7e2SAndroid Build Coastguard Worker
54*cc02d7e2SAndroid Build Coastguard Workergcp_utils_dir = os.path.abspath(
55*cc02d7e2SAndroid Build Coastguard Worker    os.path.join(os.path.dirname(__file__), "../gcp/utils")
56*cc02d7e2SAndroid Build Coastguard Worker)
57*cc02d7e2SAndroid Build Coastguard Workersys.path.append(gcp_utils_dir)
58*cc02d7e2SAndroid Build Coastguard Worker
59*cc02d7e2SAndroid Build Coastguard Worker_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../.."))
60*cc02d7e2SAndroid Build Coastguard Workeros.chdir(_ROOT)
61*cc02d7e2SAndroid Build Coastguard Worker
62*cc02d7e2SAndroid Build Coastguard Worker_FORCE_ENVIRON_FOR_WRAPPERS = {
63*cc02d7e2SAndroid Build Coastguard Worker    "GRPC_VERBOSITY": "DEBUG",
64*cc02d7e2SAndroid Build Coastguard Worker}
65*cc02d7e2SAndroid Build Coastguard Worker
66*cc02d7e2SAndroid Build Coastguard Worker_POLLING_STRATEGIES = {
67*cc02d7e2SAndroid Build Coastguard Worker    "linux": ["epoll1", "poll"],
68*cc02d7e2SAndroid Build Coastguard Worker    "mac": ["poll"],
69*cc02d7e2SAndroid Build Coastguard Worker}
70*cc02d7e2SAndroid Build Coastguard Worker
71*cc02d7e2SAndroid Build Coastguard Worker
72*cc02d7e2SAndroid Build Coastguard Workerdef platform_string():
73*cc02d7e2SAndroid Build Coastguard Worker    return jobset.platform_string()
74*cc02d7e2SAndroid Build Coastguard Worker
75*cc02d7e2SAndroid Build Coastguard Worker
76*cc02d7e2SAndroid Build Coastguard Worker_DEFAULT_TIMEOUT_SECONDS = 5 * 60
77*cc02d7e2SAndroid Build Coastguard Worker_PRE_BUILD_STEP_TIMEOUT_SECONDS = 10 * 60
78*cc02d7e2SAndroid Build Coastguard Worker
79*cc02d7e2SAndroid Build Coastguard Worker
80*cc02d7e2SAndroid Build Coastguard Workerdef run_shell_command(cmd, env=None, cwd=None):
81*cc02d7e2SAndroid Build Coastguard Worker    try:
82*cc02d7e2SAndroid Build Coastguard Worker        subprocess.check_output(cmd, shell=True, env=env, cwd=cwd)
83*cc02d7e2SAndroid Build Coastguard Worker    except subprocess.CalledProcessError as e:
84*cc02d7e2SAndroid Build Coastguard Worker        logging.exception(
85*cc02d7e2SAndroid Build Coastguard Worker            "Error while running command '%s'. Exit status %d. Output:\n%s",
86*cc02d7e2SAndroid Build Coastguard Worker            e.cmd,
87*cc02d7e2SAndroid Build Coastguard Worker            e.returncode,
88*cc02d7e2SAndroid Build Coastguard Worker            e.output,
89*cc02d7e2SAndroid Build Coastguard Worker        )
90*cc02d7e2SAndroid Build Coastguard Worker        raise
91*cc02d7e2SAndroid Build Coastguard Worker
92*cc02d7e2SAndroid Build Coastguard Worker
93*cc02d7e2SAndroid Build Coastguard Workerdef max_parallel_tests_for_current_platform():
94*cc02d7e2SAndroid Build Coastguard Worker    # Too much test parallelization has only been seen to be a problem
95*cc02d7e2SAndroid Build Coastguard Worker    # so far on windows.
96*cc02d7e2SAndroid Build Coastguard Worker    if jobset.platform_string() == "windows":
97*cc02d7e2SAndroid Build Coastguard Worker        return 64
98*cc02d7e2SAndroid Build Coastguard Worker    return 1024
99*cc02d7e2SAndroid Build Coastguard Worker
100*cc02d7e2SAndroid Build Coastguard Worker
101*cc02d7e2SAndroid Build Coastguard Workerdef _print_debug_info_epilogue(dockerfile_dir=None):
102*cc02d7e2SAndroid Build Coastguard Worker    """Use to print useful info for debug/repro just before exiting."""
103*cc02d7e2SAndroid Build Coastguard Worker    print("")
104*cc02d7e2SAndroid Build Coastguard Worker    print("=== run_tests.py DEBUG INFO ===")
105*cc02d7e2SAndroid Build Coastguard Worker    print('command: "%s"' % " ".join(sys.argv))
106*cc02d7e2SAndroid Build Coastguard Worker    if dockerfile_dir:
107*cc02d7e2SAndroid Build Coastguard Worker        print("dockerfile: %s" % dockerfile_dir)
108*cc02d7e2SAndroid Build Coastguard Worker    kokoro_job_name = os.getenv("KOKORO_JOB_NAME")
109*cc02d7e2SAndroid Build Coastguard Worker    if kokoro_job_name:
110*cc02d7e2SAndroid Build Coastguard Worker        print("kokoro job name: %s" % kokoro_job_name)
111*cc02d7e2SAndroid Build Coastguard Worker    print("===============================")
112*cc02d7e2SAndroid Build Coastguard Worker
113*cc02d7e2SAndroid Build Coastguard Worker
114*cc02d7e2SAndroid Build Coastguard Worker# SimpleConfig: just compile with CONFIG=config, and run the binary to test
115*cc02d7e2SAndroid Build Coastguard Workerclass Config(object):
116*cc02d7e2SAndroid Build Coastguard Worker    def __init__(
117*cc02d7e2SAndroid Build Coastguard Worker        self,
118*cc02d7e2SAndroid Build Coastguard Worker        config,
119*cc02d7e2SAndroid Build Coastguard Worker        environ=None,
120*cc02d7e2SAndroid Build Coastguard Worker        timeout_multiplier=1,
121*cc02d7e2SAndroid Build Coastguard Worker        tool_prefix=[],
122*cc02d7e2SAndroid Build Coastguard Worker        iomgr_platform="native",
123*cc02d7e2SAndroid Build Coastguard Worker    ):
124*cc02d7e2SAndroid Build Coastguard Worker        if environ is None:
125*cc02d7e2SAndroid Build Coastguard Worker            environ = {}
126*cc02d7e2SAndroid Build Coastguard Worker        self.build_config = config
127*cc02d7e2SAndroid Build Coastguard Worker        self.environ = environ
128*cc02d7e2SAndroid Build Coastguard Worker        self.environ["CONFIG"] = config
129*cc02d7e2SAndroid Build Coastguard Worker        self.tool_prefix = tool_prefix
130*cc02d7e2SAndroid Build Coastguard Worker        self.timeout_multiplier = timeout_multiplier
131*cc02d7e2SAndroid Build Coastguard Worker        self.iomgr_platform = iomgr_platform
132*cc02d7e2SAndroid Build Coastguard Worker
133*cc02d7e2SAndroid Build Coastguard Worker    def job_spec(
134*cc02d7e2SAndroid Build Coastguard Worker        self,
135*cc02d7e2SAndroid Build Coastguard Worker        cmdline,
136*cc02d7e2SAndroid Build Coastguard Worker        timeout_seconds=_DEFAULT_TIMEOUT_SECONDS,
137*cc02d7e2SAndroid Build Coastguard Worker        shortname=None,
138*cc02d7e2SAndroid Build Coastguard Worker        environ={},
139*cc02d7e2SAndroid Build Coastguard Worker        cpu_cost=1.0,
140*cc02d7e2SAndroid Build Coastguard Worker        flaky=False,
141*cc02d7e2SAndroid Build Coastguard Worker    ):
142*cc02d7e2SAndroid Build Coastguard Worker        """Construct a jobset.JobSpec for a test under this config
143*cc02d7e2SAndroid Build Coastguard Worker
144*cc02d7e2SAndroid Build Coastguard Worker        Args:
145*cc02d7e2SAndroid Build Coastguard Worker          cmdline:      a list of strings specifying the command line the test
146*cc02d7e2SAndroid Build Coastguard Worker                        would like to run
147*cc02d7e2SAndroid Build Coastguard Worker        """
148*cc02d7e2SAndroid Build Coastguard Worker        actual_environ = self.environ.copy()
149*cc02d7e2SAndroid Build Coastguard Worker        for k, v in environ.items():
150*cc02d7e2SAndroid Build Coastguard Worker            actual_environ[k] = v
151*cc02d7e2SAndroid Build Coastguard Worker        if not flaky and shortname and shortname in flaky_tests:
152*cc02d7e2SAndroid Build Coastguard Worker            flaky = True
153*cc02d7e2SAndroid Build Coastguard Worker        if shortname in shortname_to_cpu:
154*cc02d7e2SAndroid Build Coastguard Worker            cpu_cost = shortname_to_cpu[shortname]
155*cc02d7e2SAndroid Build Coastguard Worker        return jobset.JobSpec(
156*cc02d7e2SAndroid Build Coastguard Worker            cmdline=self.tool_prefix + cmdline,
157*cc02d7e2SAndroid Build Coastguard Worker            shortname=shortname,
158*cc02d7e2SAndroid Build Coastguard Worker            environ=actual_environ,
159*cc02d7e2SAndroid Build Coastguard Worker            cpu_cost=cpu_cost,
160*cc02d7e2SAndroid Build Coastguard Worker            timeout_seconds=(
161*cc02d7e2SAndroid Build Coastguard Worker                self.timeout_multiplier * timeout_seconds
162*cc02d7e2SAndroid Build Coastguard Worker                if timeout_seconds
163*cc02d7e2SAndroid Build Coastguard Worker                else None
164*cc02d7e2SAndroid Build Coastguard Worker            ),
165*cc02d7e2SAndroid Build Coastguard Worker            flake_retries=4 if flaky or args.allow_flakes else 0,
166*cc02d7e2SAndroid Build Coastguard Worker            timeout_retries=1 if flaky or args.allow_flakes else 0,
167*cc02d7e2SAndroid Build Coastguard Worker        )
168*cc02d7e2SAndroid Build Coastguard Worker
169*cc02d7e2SAndroid Build Coastguard Worker
170*cc02d7e2SAndroid Build Coastguard Workerdef get_c_tests(travis, test_lang):
171*cc02d7e2SAndroid Build Coastguard Worker    out = []
172*cc02d7e2SAndroid Build Coastguard Worker    platforms_str = "ci_platforms" if travis else "platforms"
173*cc02d7e2SAndroid Build Coastguard Worker    with open("tools/run_tests/generated/tests.json") as f:
174*cc02d7e2SAndroid Build Coastguard Worker        js = json.load(f)
175*cc02d7e2SAndroid Build Coastguard Worker        return [
176*cc02d7e2SAndroid Build Coastguard Worker            tgt
177*cc02d7e2SAndroid Build Coastguard Worker            for tgt in js
178*cc02d7e2SAndroid Build Coastguard Worker            if tgt["language"] == test_lang
179*cc02d7e2SAndroid Build Coastguard Worker            and platform_string() in tgt[platforms_str]
180*cc02d7e2SAndroid Build Coastguard Worker            and not (travis and tgt["flaky"])
181*cc02d7e2SAndroid Build Coastguard Worker        ]
182*cc02d7e2SAndroid Build Coastguard Worker
183*cc02d7e2SAndroid Build Coastguard Worker
184*cc02d7e2SAndroid Build Coastguard Workerdef _check_compiler(compiler, supported_compilers):
185*cc02d7e2SAndroid Build Coastguard Worker    if compiler not in supported_compilers:
186*cc02d7e2SAndroid Build Coastguard Worker        raise Exception(
187*cc02d7e2SAndroid Build Coastguard Worker            "Compiler %s not supported (on this platform)." % compiler
188*cc02d7e2SAndroid Build Coastguard Worker        )
189*cc02d7e2SAndroid Build Coastguard Worker
190*cc02d7e2SAndroid Build Coastguard Worker
191*cc02d7e2SAndroid Build Coastguard Workerdef _check_arch(arch, supported_archs):
192*cc02d7e2SAndroid Build Coastguard Worker    if arch not in supported_archs:
193*cc02d7e2SAndroid Build Coastguard Worker        raise Exception("Architecture %s not supported." % arch)
194*cc02d7e2SAndroid Build Coastguard Worker
195*cc02d7e2SAndroid Build Coastguard Worker
196*cc02d7e2SAndroid Build Coastguard Workerdef _is_use_docker_child():
197*cc02d7e2SAndroid Build Coastguard Worker    """Returns True if running running as a --use_docker child."""
198*cc02d7e2SAndroid Build Coastguard Worker    return True if os.getenv("DOCKER_RUN_SCRIPT_COMMAND") else False
199*cc02d7e2SAndroid Build Coastguard Worker
200*cc02d7e2SAndroid Build Coastguard Worker
201*cc02d7e2SAndroid Build Coastguard Worker_PythonConfigVars = collections.namedtuple(
202*cc02d7e2SAndroid Build Coastguard Worker    "_ConfigVars",
203*cc02d7e2SAndroid Build Coastguard Worker    [
204*cc02d7e2SAndroid Build Coastguard Worker        "shell",
205*cc02d7e2SAndroid Build Coastguard Worker        "builder",
206*cc02d7e2SAndroid Build Coastguard Worker        "builder_prefix_arguments",
207*cc02d7e2SAndroid Build Coastguard Worker        "venv_relative_python",
208*cc02d7e2SAndroid Build Coastguard Worker        "toolchain",
209*cc02d7e2SAndroid Build Coastguard Worker        "runner",
210*cc02d7e2SAndroid Build Coastguard Worker    ],
211*cc02d7e2SAndroid Build Coastguard Worker)
212*cc02d7e2SAndroid Build Coastguard Worker
213*cc02d7e2SAndroid Build Coastguard Worker
214*cc02d7e2SAndroid Build Coastguard Workerdef _python_config_generator(name, major, minor, bits, config_vars):
215*cc02d7e2SAndroid Build Coastguard Worker    build = (
216*cc02d7e2SAndroid Build Coastguard Worker        config_vars.shell
217*cc02d7e2SAndroid Build Coastguard Worker        + config_vars.builder
218*cc02d7e2SAndroid Build Coastguard Worker        + config_vars.builder_prefix_arguments
219*cc02d7e2SAndroid Build Coastguard Worker        + [_python_pattern_function(major=major, minor=minor, bits=bits)]
220*cc02d7e2SAndroid Build Coastguard Worker        + [name]
221*cc02d7e2SAndroid Build Coastguard Worker        + config_vars.venv_relative_python
222*cc02d7e2SAndroid Build Coastguard Worker        + config_vars.toolchain
223*cc02d7e2SAndroid Build Coastguard Worker    )
224*cc02d7e2SAndroid Build Coastguard Worker    # run: [tools/run_tests/helper_scripts/run_python.sh py37/bin/python]
225*cc02d7e2SAndroid Build Coastguard Worker    python_path = os.path.join(name, config_vars.venv_relative_python[0])
226*cc02d7e2SAndroid Build Coastguard Worker    run = config_vars.shell + config_vars.runner + [python_path]
227*cc02d7e2SAndroid Build Coastguard Worker    return PythonConfig(name, build, run, python_path)
228*cc02d7e2SAndroid Build Coastguard Worker
229*cc02d7e2SAndroid Build Coastguard Worker
230*cc02d7e2SAndroid Build Coastguard Workerdef _pypy_config_generator(name, major, config_vars):
231*cc02d7e2SAndroid Build Coastguard Worker    # Something like "py37/bin/python"
232*cc02d7e2SAndroid Build Coastguard Worker    python_path = os.path.join(name, config_vars.venv_relative_python[0])
233*cc02d7e2SAndroid Build Coastguard Worker    return PythonConfig(
234*cc02d7e2SAndroid Build Coastguard Worker        name,
235*cc02d7e2SAndroid Build Coastguard Worker        config_vars.shell
236*cc02d7e2SAndroid Build Coastguard Worker        + config_vars.builder
237*cc02d7e2SAndroid Build Coastguard Worker        + config_vars.builder_prefix_arguments
238*cc02d7e2SAndroid Build Coastguard Worker        + [_pypy_pattern_function(major=major)]
239*cc02d7e2SAndroid Build Coastguard Worker        + [name]
240*cc02d7e2SAndroid Build Coastguard Worker        + config_vars.venv_relative_python
241*cc02d7e2SAndroid Build Coastguard Worker        + config_vars.toolchain,
242*cc02d7e2SAndroid Build Coastguard Worker        config_vars.shell + config_vars.runner + [python_path],
243*cc02d7e2SAndroid Build Coastguard Worker        python_path,
244*cc02d7e2SAndroid Build Coastguard Worker    )
245*cc02d7e2SAndroid Build Coastguard Worker
246*cc02d7e2SAndroid Build Coastguard Worker
247*cc02d7e2SAndroid Build Coastguard Workerdef _python_pattern_function(major, minor, bits):
248*cc02d7e2SAndroid Build Coastguard Worker    # Bit-ness is handled by the test machine's environment
249*cc02d7e2SAndroid Build Coastguard Worker    if os.name == "nt":
250*cc02d7e2SAndroid Build Coastguard Worker        if bits == "64":
251*cc02d7e2SAndroid Build Coastguard Worker            return "/c/Python{major}{minor}/python.exe".format(
252*cc02d7e2SAndroid Build Coastguard Worker                major=major, minor=minor, bits=bits
253*cc02d7e2SAndroid Build Coastguard Worker            )
254*cc02d7e2SAndroid Build Coastguard Worker        else:
255*cc02d7e2SAndroid Build Coastguard Worker            return "/c/Python{major}{minor}_{bits}bits/python.exe".format(
256*cc02d7e2SAndroid Build Coastguard Worker                major=major, minor=minor, bits=bits
257*cc02d7e2SAndroid Build Coastguard Worker            )
258*cc02d7e2SAndroid Build Coastguard Worker    else:
259*cc02d7e2SAndroid Build Coastguard Worker        return "python{major}.{minor}".format(major=major, minor=minor)
260*cc02d7e2SAndroid Build Coastguard Worker
261*cc02d7e2SAndroid Build Coastguard Worker
262*cc02d7e2SAndroid Build Coastguard Workerdef _pypy_pattern_function(major):
263*cc02d7e2SAndroid Build Coastguard Worker    if major == "2":
264*cc02d7e2SAndroid Build Coastguard Worker        return "pypy"
265*cc02d7e2SAndroid Build Coastguard Worker    elif major == "3":
266*cc02d7e2SAndroid Build Coastguard Worker        return "pypy3"
267*cc02d7e2SAndroid Build Coastguard Worker    else:
268*cc02d7e2SAndroid Build Coastguard Worker        raise ValueError("Unknown PyPy major version")
269*cc02d7e2SAndroid Build Coastguard Worker
270*cc02d7e2SAndroid Build Coastguard Worker
271*cc02d7e2SAndroid Build Coastguard Workerclass CLanguage(object):
272*cc02d7e2SAndroid Build Coastguard Worker    def __init__(self, lang_suffix, test_lang):
273*cc02d7e2SAndroid Build Coastguard Worker        self.lang_suffix = lang_suffix
274*cc02d7e2SAndroid Build Coastguard Worker        self.platform = platform_string()
275*cc02d7e2SAndroid Build Coastguard Worker        self.test_lang = test_lang
276*cc02d7e2SAndroid Build Coastguard Worker
277*cc02d7e2SAndroid Build Coastguard Worker    def configure(self, config, args):
278*cc02d7e2SAndroid Build Coastguard Worker        self.config = config
279*cc02d7e2SAndroid Build Coastguard Worker        self.args = args
280*cc02d7e2SAndroid Build Coastguard Worker        if self.platform == "windows":
281*cc02d7e2SAndroid Build Coastguard Worker            _check_compiler(
282*cc02d7e2SAndroid Build Coastguard Worker                self.args.compiler,
283*cc02d7e2SAndroid Build Coastguard Worker                [
284*cc02d7e2SAndroid Build Coastguard Worker                    "default",
285*cc02d7e2SAndroid Build Coastguard Worker                    "cmake",
286*cc02d7e2SAndroid Build Coastguard Worker                    "cmake_ninja_vs2019",
287*cc02d7e2SAndroid Build Coastguard Worker                    "cmake_ninja_vs2022",
288*cc02d7e2SAndroid Build Coastguard Worker                    "cmake_vs2019",
289*cc02d7e2SAndroid Build Coastguard Worker                    "cmake_vs2022",
290*cc02d7e2SAndroid Build Coastguard Worker                ],
291*cc02d7e2SAndroid Build Coastguard Worker            )
292*cc02d7e2SAndroid Build Coastguard Worker            _check_arch(self.args.arch, ["default", "x64", "x86"])
293*cc02d7e2SAndroid Build Coastguard Worker
294*cc02d7e2SAndroid Build Coastguard Worker            activate_vs_tools = ""
295*cc02d7e2SAndroid Build Coastguard Worker            if (
296*cc02d7e2SAndroid Build Coastguard Worker                self.args.compiler == "cmake_ninja_vs2019"
297*cc02d7e2SAndroid Build Coastguard Worker                or self.args.compiler == "cmake"
298*cc02d7e2SAndroid Build Coastguard Worker                or self.args.compiler == "default"
299*cc02d7e2SAndroid Build Coastguard Worker            ):
300*cc02d7e2SAndroid Build Coastguard Worker                # cmake + ninja build is the default because it is faster and supports boringssl assembly optimizations
301*cc02d7e2SAndroid Build Coastguard Worker                # the compiler used is exactly the same as for cmake_vs2017
302*cc02d7e2SAndroid Build Coastguard Worker                cmake_generator = "Ninja"
303*cc02d7e2SAndroid Build Coastguard Worker                activate_vs_tools = "2019"
304*cc02d7e2SAndroid Build Coastguard Worker            elif self.args.compiler == "cmake_ninja_vs2022":
305*cc02d7e2SAndroid Build Coastguard Worker                cmake_generator = "Ninja"
306*cc02d7e2SAndroid Build Coastguard Worker                activate_vs_tools = "2022"
307*cc02d7e2SAndroid Build Coastguard Worker            elif self.args.compiler == "cmake_vs2019":
308*cc02d7e2SAndroid Build Coastguard Worker                cmake_generator = "Visual Studio 16 2019"
309*cc02d7e2SAndroid Build Coastguard Worker            elif self.args.compiler == "cmake_vs2022":
310*cc02d7e2SAndroid Build Coastguard Worker                cmake_generator = "Visual Studio 17 2022"
311*cc02d7e2SAndroid Build Coastguard Worker            else:
312*cc02d7e2SAndroid Build Coastguard Worker                print("should never reach here.")
313*cc02d7e2SAndroid Build Coastguard Worker                sys.exit(1)
314*cc02d7e2SAndroid Build Coastguard Worker
315*cc02d7e2SAndroid Build Coastguard Worker            self._cmake_configure_extra_args = list(
316*cc02d7e2SAndroid Build Coastguard Worker                self.args.cmake_configure_extra_args
317*cc02d7e2SAndroid Build Coastguard Worker            )
318*cc02d7e2SAndroid Build Coastguard Worker            self._cmake_generator_windows = cmake_generator
319*cc02d7e2SAndroid Build Coastguard Worker            # required to pass as cmake "-A" configuration for VS builds (but not for Ninja)
320*cc02d7e2SAndroid Build Coastguard Worker            self._cmake_architecture_windows = (
321*cc02d7e2SAndroid Build Coastguard Worker                "x64" if self.args.arch == "x64" else "Win32"
322*cc02d7e2SAndroid Build Coastguard Worker            )
323*cc02d7e2SAndroid Build Coastguard Worker            # when builing with Ninja, the VS common tools need to be activated first
324*cc02d7e2SAndroid Build Coastguard Worker            self._activate_vs_tools_windows = activate_vs_tools
325*cc02d7e2SAndroid Build Coastguard Worker            # "x64_x86" means create 32bit binaries, but use 64bit toolkit to secure more memory for the build
326*cc02d7e2SAndroid Build Coastguard Worker            self._vs_tools_architecture_windows = (
327*cc02d7e2SAndroid Build Coastguard Worker                "x64" if self.args.arch == "x64" else "x64_x86"
328*cc02d7e2SAndroid Build Coastguard Worker            )
329*cc02d7e2SAndroid Build Coastguard Worker
330*cc02d7e2SAndroid Build Coastguard Worker        else:
331*cc02d7e2SAndroid Build Coastguard Worker            if self.platform == "linux":
332*cc02d7e2SAndroid Build Coastguard Worker                # Allow all the known architectures. _check_arch_option has already checked that we're not doing
333*cc02d7e2SAndroid Build Coastguard Worker                # something illegal when not running under docker.
334*cc02d7e2SAndroid Build Coastguard Worker                _check_arch(self.args.arch, ["default", "x64", "x86", "arm64"])
335*cc02d7e2SAndroid Build Coastguard Worker            else:
336*cc02d7e2SAndroid Build Coastguard Worker                _check_arch(self.args.arch, ["default"])
337*cc02d7e2SAndroid Build Coastguard Worker
338*cc02d7e2SAndroid Build Coastguard Worker            (
339*cc02d7e2SAndroid Build Coastguard Worker                self._docker_distro,
340*cc02d7e2SAndroid Build Coastguard Worker                self._cmake_configure_extra_args,
341*cc02d7e2SAndroid Build Coastguard Worker            ) = self._compiler_options(
342*cc02d7e2SAndroid Build Coastguard Worker                self.args.use_docker,
343*cc02d7e2SAndroid Build Coastguard Worker                self.args.compiler,
344*cc02d7e2SAndroid Build Coastguard Worker                self.args.cmake_configure_extra_args,
345*cc02d7e2SAndroid Build Coastguard Worker            )
346*cc02d7e2SAndroid Build Coastguard Worker
347*cc02d7e2SAndroid Build Coastguard Worker    def test_specs(self):
348*cc02d7e2SAndroid Build Coastguard Worker        out = []
349*cc02d7e2SAndroid Build Coastguard Worker        binaries = get_c_tests(self.args.travis, self.test_lang)
350*cc02d7e2SAndroid Build Coastguard Worker        for target in binaries:
351*cc02d7e2SAndroid Build Coastguard Worker            if target.get("boringssl", False):
352*cc02d7e2SAndroid Build Coastguard Worker                # cmake doesn't build boringssl tests
353*cc02d7e2SAndroid Build Coastguard Worker                continue
354*cc02d7e2SAndroid Build Coastguard Worker            auto_timeout_scaling = target.get("auto_timeout_scaling", True)
355*cc02d7e2SAndroid Build Coastguard Worker            polling_strategies = (
356*cc02d7e2SAndroid Build Coastguard Worker                _POLLING_STRATEGIES.get(self.platform, ["all"])
357*cc02d7e2SAndroid Build Coastguard Worker                if target.get("uses_polling", True)
358*cc02d7e2SAndroid Build Coastguard Worker                else ["none"]
359*cc02d7e2SAndroid Build Coastguard Worker            )
360*cc02d7e2SAndroid Build Coastguard Worker            for polling_strategy in polling_strategies:
361*cc02d7e2SAndroid Build Coastguard Worker                env = {
362*cc02d7e2SAndroid Build Coastguard Worker                    "GRPC_DEFAULT_SSL_ROOTS_FILE_PATH": _ROOT
363*cc02d7e2SAndroid Build Coastguard Worker                    + "/src/core/tsi/test_creds/ca.pem",
364*cc02d7e2SAndroid Build Coastguard Worker                    "GRPC_POLL_STRATEGY": polling_strategy,
365*cc02d7e2SAndroid Build Coastguard Worker                    "GRPC_VERBOSITY": "DEBUG",
366*cc02d7e2SAndroid Build Coastguard Worker                }
367*cc02d7e2SAndroid Build Coastguard Worker                resolver = os.environ.get("GRPC_DNS_RESOLVER", None)
368*cc02d7e2SAndroid Build Coastguard Worker                if resolver:
369*cc02d7e2SAndroid Build Coastguard Worker                    env["GRPC_DNS_RESOLVER"] = resolver
370*cc02d7e2SAndroid Build Coastguard Worker                shortname_ext = (
371*cc02d7e2SAndroid Build Coastguard Worker                    ""
372*cc02d7e2SAndroid Build Coastguard Worker                    if polling_strategy == "all"
373*cc02d7e2SAndroid Build Coastguard Worker                    else " GRPC_POLL_STRATEGY=%s" % polling_strategy
374*cc02d7e2SAndroid Build Coastguard Worker                )
375*cc02d7e2SAndroid Build Coastguard Worker                if polling_strategy in target.get("excluded_poll_engines", []):
376*cc02d7e2SAndroid Build Coastguard Worker                    continue
377*cc02d7e2SAndroid Build Coastguard Worker
378*cc02d7e2SAndroid Build Coastguard Worker                timeout_scaling = 1
379*cc02d7e2SAndroid Build Coastguard Worker                if auto_timeout_scaling:
380*cc02d7e2SAndroid Build Coastguard Worker                    config = self.args.config
381*cc02d7e2SAndroid Build Coastguard Worker                    if (
382*cc02d7e2SAndroid Build Coastguard Worker                        "asan" in config
383*cc02d7e2SAndroid Build Coastguard Worker                        or config == "msan"
384*cc02d7e2SAndroid Build Coastguard Worker                        or config == "tsan"
385*cc02d7e2SAndroid Build Coastguard Worker                        or config == "ubsan"
386*cc02d7e2SAndroid Build Coastguard Worker                        or config == "helgrind"
387*cc02d7e2SAndroid Build Coastguard Worker                        or config == "memcheck"
388*cc02d7e2SAndroid Build Coastguard Worker                    ):
389*cc02d7e2SAndroid Build Coastguard Worker                        # Scale overall test timeout if running under various sanitizers.
390*cc02d7e2SAndroid Build Coastguard Worker                        # scaling value is based on historical data analysis
391*cc02d7e2SAndroid Build Coastguard Worker                        timeout_scaling *= 3
392*cc02d7e2SAndroid Build Coastguard Worker
393*cc02d7e2SAndroid Build Coastguard Worker                if self.config.build_config in target["exclude_configs"]:
394*cc02d7e2SAndroid Build Coastguard Worker                    continue
395*cc02d7e2SAndroid Build Coastguard Worker                if self.args.iomgr_platform in target.get("exclude_iomgrs", []):
396*cc02d7e2SAndroid Build Coastguard Worker                    continue
397*cc02d7e2SAndroid Build Coastguard Worker
398*cc02d7e2SAndroid Build Coastguard Worker                if self.platform == "windows":
399*cc02d7e2SAndroid Build Coastguard Worker                    if self._cmake_generator_windows == "Ninja":
400*cc02d7e2SAndroid Build Coastguard Worker                        binary = "cmake/build/%s.exe" % target["name"]
401*cc02d7e2SAndroid Build Coastguard Worker                    else:
402*cc02d7e2SAndroid Build Coastguard Worker                        binary = "cmake/build/%s/%s.exe" % (
403*cc02d7e2SAndroid Build Coastguard Worker                            _MSBUILD_CONFIG[self.config.build_config],
404*cc02d7e2SAndroid Build Coastguard Worker                            target["name"],
405*cc02d7e2SAndroid Build Coastguard Worker                        )
406*cc02d7e2SAndroid Build Coastguard Worker                else:
407*cc02d7e2SAndroid Build Coastguard Worker                    binary = "cmake/build/%s" % target["name"]
408*cc02d7e2SAndroid Build Coastguard Worker
409*cc02d7e2SAndroid Build Coastguard Worker                cpu_cost = target["cpu_cost"]
410*cc02d7e2SAndroid Build Coastguard Worker                if cpu_cost == "capacity":
411*cc02d7e2SAndroid Build Coastguard Worker                    cpu_cost = multiprocessing.cpu_count()
412*cc02d7e2SAndroid Build Coastguard Worker                if os.path.isfile(binary):
413*cc02d7e2SAndroid Build Coastguard Worker                    list_test_command = None
414*cc02d7e2SAndroid Build Coastguard Worker                    filter_test_command = None
415*cc02d7e2SAndroid Build Coastguard Worker
416*cc02d7e2SAndroid Build Coastguard Worker                    # these are the flag defined by gtest and benchmark framework to list
417*cc02d7e2SAndroid Build Coastguard Worker                    # and filter test runs. We use them to split each individual test
418*cc02d7e2SAndroid Build Coastguard Worker                    # into its own JobSpec, and thus into its own process.
419*cc02d7e2SAndroid Build Coastguard Worker                    if "benchmark" in target and target["benchmark"]:
420*cc02d7e2SAndroid Build Coastguard Worker                        with open(os.devnull, "w") as fnull:
421*cc02d7e2SAndroid Build Coastguard Worker                            tests = subprocess.check_output(
422*cc02d7e2SAndroid Build Coastguard Worker                                [binary, "--benchmark_list_tests"], stderr=fnull
423*cc02d7e2SAndroid Build Coastguard Worker                            )
424*cc02d7e2SAndroid Build Coastguard Worker                        for line in tests.decode().split("\n"):
425*cc02d7e2SAndroid Build Coastguard Worker                            test = line.strip()
426*cc02d7e2SAndroid Build Coastguard Worker                            if not test:
427*cc02d7e2SAndroid Build Coastguard Worker                                continue
428*cc02d7e2SAndroid Build Coastguard Worker                            cmdline = [
429*cc02d7e2SAndroid Build Coastguard Worker                                binary,
430*cc02d7e2SAndroid Build Coastguard Worker                                "--benchmark_filter=%s$" % test,
431*cc02d7e2SAndroid Build Coastguard Worker                            ] + target["args"]
432*cc02d7e2SAndroid Build Coastguard Worker                            out.append(
433*cc02d7e2SAndroid Build Coastguard Worker                                self.config.job_spec(
434*cc02d7e2SAndroid Build Coastguard Worker                                    cmdline,
435*cc02d7e2SAndroid Build Coastguard Worker                                    shortname="%s %s"
436*cc02d7e2SAndroid Build Coastguard Worker                                    % (" ".join(cmdline), shortname_ext),
437*cc02d7e2SAndroid Build Coastguard Worker                                    cpu_cost=cpu_cost,
438*cc02d7e2SAndroid Build Coastguard Worker                                    timeout_seconds=target.get(
439*cc02d7e2SAndroid Build Coastguard Worker                                        "timeout_seconds",
440*cc02d7e2SAndroid Build Coastguard Worker                                        _DEFAULT_TIMEOUT_SECONDS,
441*cc02d7e2SAndroid Build Coastguard Worker                                    )
442*cc02d7e2SAndroid Build Coastguard Worker                                    * timeout_scaling,
443*cc02d7e2SAndroid Build Coastguard Worker                                    environ=env,
444*cc02d7e2SAndroid Build Coastguard Worker                                )
445*cc02d7e2SAndroid Build Coastguard Worker                            )
446*cc02d7e2SAndroid Build Coastguard Worker                    elif "gtest" in target and target["gtest"]:
447*cc02d7e2SAndroid Build Coastguard Worker                        # here we parse the output of --gtest_list_tests to build up a complete
448*cc02d7e2SAndroid Build Coastguard Worker                        # list of the tests contained in a binary for each test, we then
449*cc02d7e2SAndroid Build Coastguard Worker                        # add a job to run, filtering for just that test.
450*cc02d7e2SAndroid Build Coastguard Worker                        with open(os.devnull, "w") as fnull:
451*cc02d7e2SAndroid Build Coastguard Worker                            tests = subprocess.check_output(
452*cc02d7e2SAndroid Build Coastguard Worker                                [binary, "--gtest_list_tests"], stderr=fnull
453*cc02d7e2SAndroid Build Coastguard Worker                            )
454*cc02d7e2SAndroid Build Coastguard Worker                        base = None
455*cc02d7e2SAndroid Build Coastguard Worker                        for line in tests.decode().split("\n"):
456*cc02d7e2SAndroid Build Coastguard Worker                            i = line.find("#")
457*cc02d7e2SAndroid Build Coastguard Worker                            if i >= 0:
458*cc02d7e2SAndroid Build Coastguard Worker                                line = line[:i]
459*cc02d7e2SAndroid Build Coastguard Worker                            if not line:
460*cc02d7e2SAndroid Build Coastguard Worker                                continue
461*cc02d7e2SAndroid Build Coastguard Worker                            if line[0] != " ":
462*cc02d7e2SAndroid Build Coastguard Worker                                base = line.strip()
463*cc02d7e2SAndroid Build Coastguard Worker                            else:
464*cc02d7e2SAndroid Build Coastguard Worker                                assert base is not None
465*cc02d7e2SAndroid Build Coastguard Worker                                assert line[1] == " "
466*cc02d7e2SAndroid Build Coastguard Worker                                test = base + line.strip()
467*cc02d7e2SAndroid Build Coastguard Worker                                cmdline = [
468*cc02d7e2SAndroid Build Coastguard Worker                                    binary,
469*cc02d7e2SAndroid Build Coastguard Worker                                    "--gtest_filter=%s" % test,
470*cc02d7e2SAndroid Build Coastguard Worker                                ] + target["args"]
471*cc02d7e2SAndroid Build Coastguard Worker                                out.append(
472*cc02d7e2SAndroid Build Coastguard Worker                                    self.config.job_spec(
473*cc02d7e2SAndroid Build Coastguard Worker                                        cmdline,
474*cc02d7e2SAndroid Build Coastguard Worker                                        shortname="%s %s"
475*cc02d7e2SAndroid Build Coastguard Worker                                        % (" ".join(cmdline), shortname_ext),
476*cc02d7e2SAndroid Build Coastguard Worker                                        cpu_cost=cpu_cost,
477*cc02d7e2SAndroid Build Coastguard Worker                                        timeout_seconds=target.get(
478*cc02d7e2SAndroid Build Coastguard Worker                                            "timeout_seconds",
479*cc02d7e2SAndroid Build Coastguard Worker                                            _DEFAULT_TIMEOUT_SECONDS,
480*cc02d7e2SAndroid Build Coastguard Worker                                        )
481*cc02d7e2SAndroid Build Coastguard Worker                                        * timeout_scaling,
482*cc02d7e2SAndroid Build Coastguard Worker                                        environ=env,
483*cc02d7e2SAndroid Build Coastguard Worker                                    )
484*cc02d7e2SAndroid Build Coastguard Worker                                )
485*cc02d7e2SAndroid Build Coastguard Worker                    else:
486*cc02d7e2SAndroid Build Coastguard Worker                        cmdline = [binary] + target["args"]
487*cc02d7e2SAndroid Build Coastguard Worker                        shortname = target.get(
488*cc02d7e2SAndroid Build Coastguard Worker                            "shortname",
489*cc02d7e2SAndroid Build Coastguard Worker                            " ".join(shlex.quote(arg) for arg in cmdline),
490*cc02d7e2SAndroid Build Coastguard Worker                        )
491*cc02d7e2SAndroid Build Coastguard Worker                        shortname += shortname_ext
492*cc02d7e2SAndroid Build Coastguard Worker                        out.append(
493*cc02d7e2SAndroid Build Coastguard Worker                            self.config.job_spec(
494*cc02d7e2SAndroid Build Coastguard Worker                                cmdline,
495*cc02d7e2SAndroid Build Coastguard Worker                                shortname=shortname,
496*cc02d7e2SAndroid Build Coastguard Worker                                cpu_cost=cpu_cost,
497*cc02d7e2SAndroid Build Coastguard Worker                                flaky=target.get("flaky", False),
498*cc02d7e2SAndroid Build Coastguard Worker                                timeout_seconds=target.get(
499*cc02d7e2SAndroid Build Coastguard Worker                                    "timeout_seconds", _DEFAULT_TIMEOUT_SECONDS
500*cc02d7e2SAndroid Build Coastguard Worker                                )
501*cc02d7e2SAndroid Build Coastguard Worker                                * timeout_scaling,
502*cc02d7e2SAndroid Build Coastguard Worker                                environ=env,
503*cc02d7e2SAndroid Build Coastguard Worker                            )
504*cc02d7e2SAndroid Build Coastguard Worker                        )
505*cc02d7e2SAndroid Build Coastguard Worker                elif self.args.regex == ".*" or self.platform == "windows":
506*cc02d7e2SAndroid Build Coastguard Worker                    print("\nWARNING: binary not found, skipping", binary)
507*cc02d7e2SAndroid Build Coastguard Worker        return sorted(out)
508*cc02d7e2SAndroid Build Coastguard Worker
509*cc02d7e2SAndroid Build Coastguard Worker    def pre_build_steps(self):
510*cc02d7e2SAndroid Build Coastguard Worker        return []
511*cc02d7e2SAndroid Build Coastguard Worker
512*cc02d7e2SAndroid Build Coastguard Worker    def build_steps(self):
513*cc02d7e2SAndroid Build Coastguard Worker        if self.platform == "windows":
514*cc02d7e2SAndroid Build Coastguard Worker            return [
515*cc02d7e2SAndroid Build Coastguard Worker                [
516*cc02d7e2SAndroid Build Coastguard Worker                    "tools\\run_tests\\helper_scripts\\build_cxx.bat",
517*cc02d7e2SAndroid Build Coastguard Worker                    "-DgRPC_BUILD_MSVC_MP_COUNT=%d" % self.args.jobs,
518*cc02d7e2SAndroid Build Coastguard Worker                ]
519*cc02d7e2SAndroid Build Coastguard Worker                + self._cmake_configure_extra_args
520*cc02d7e2SAndroid Build Coastguard Worker            ]
521*cc02d7e2SAndroid Build Coastguard Worker        else:
522*cc02d7e2SAndroid Build Coastguard Worker            return [
523*cc02d7e2SAndroid Build Coastguard Worker                ["tools/run_tests/helper_scripts/build_cxx.sh"]
524*cc02d7e2SAndroid Build Coastguard Worker                + self._cmake_configure_extra_args
525*cc02d7e2SAndroid Build Coastguard Worker            ]
526*cc02d7e2SAndroid Build Coastguard Worker
527*cc02d7e2SAndroid Build Coastguard Worker    def build_steps_environ(self):
528*cc02d7e2SAndroid Build Coastguard Worker        """Extra environment variables set for pre_build_steps and build_steps jobs."""
529*cc02d7e2SAndroid Build Coastguard Worker        environ = {"GRPC_RUN_TESTS_CXX_LANGUAGE_SUFFIX": self.lang_suffix}
530*cc02d7e2SAndroid Build Coastguard Worker        if self.platform == "windows":
531*cc02d7e2SAndroid Build Coastguard Worker            environ["GRPC_CMAKE_GENERATOR"] = self._cmake_generator_windows
532*cc02d7e2SAndroid Build Coastguard Worker            environ[
533*cc02d7e2SAndroid Build Coastguard Worker                "GRPC_CMAKE_ARCHITECTURE"
534*cc02d7e2SAndroid Build Coastguard Worker            ] = self._cmake_architecture_windows
535*cc02d7e2SAndroid Build Coastguard Worker            environ[
536*cc02d7e2SAndroid Build Coastguard Worker                "GRPC_BUILD_ACTIVATE_VS_TOOLS"
537*cc02d7e2SAndroid Build Coastguard Worker            ] = self._activate_vs_tools_windows
538*cc02d7e2SAndroid Build Coastguard Worker            environ[
539*cc02d7e2SAndroid Build Coastguard Worker                "GRPC_BUILD_VS_TOOLS_ARCHITECTURE"
540*cc02d7e2SAndroid Build Coastguard Worker            ] = self._vs_tools_architecture_windows
541*cc02d7e2SAndroid Build Coastguard Worker        elif self.platform == "linux":
542*cc02d7e2SAndroid Build Coastguard Worker            environ["GRPC_RUNTESTS_ARCHITECTURE"] = self.args.arch
543*cc02d7e2SAndroid Build Coastguard Worker        return environ
544*cc02d7e2SAndroid Build Coastguard Worker
545*cc02d7e2SAndroid Build Coastguard Worker    def post_tests_steps(self):
546*cc02d7e2SAndroid Build Coastguard Worker        if self.platform == "windows":
547*cc02d7e2SAndroid Build Coastguard Worker            return []
548*cc02d7e2SAndroid Build Coastguard Worker        else:
549*cc02d7e2SAndroid Build Coastguard Worker            return [["tools/run_tests/helper_scripts/post_tests_c.sh"]]
550*cc02d7e2SAndroid Build Coastguard Worker
551*cc02d7e2SAndroid Build Coastguard Worker    def _clang_cmake_configure_extra_args(self, version_suffix=""):
552*cc02d7e2SAndroid Build Coastguard Worker        return [
553*cc02d7e2SAndroid Build Coastguard Worker            "-DCMAKE_C_COMPILER=clang%s" % version_suffix,
554*cc02d7e2SAndroid Build Coastguard Worker            "-DCMAKE_CXX_COMPILER=clang++%s" % version_suffix,
555*cc02d7e2SAndroid Build Coastguard Worker        ]
556*cc02d7e2SAndroid Build Coastguard Worker
557*cc02d7e2SAndroid Build Coastguard Worker    def _compiler_options(
558*cc02d7e2SAndroid Build Coastguard Worker        self, use_docker, compiler, cmake_configure_extra_args
559*cc02d7e2SAndroid Build Coastguard Worker    ):
560*cc02d7e2SAndroid Build Coastguard Worker        """Returns docker distro and cmake configure args to use for given compiler."""
561*cc02d7e2SAndroid Build Coastguard Worker        if cmake_configure_extra_args:
562*cc02d7e2SAndroid Build Coastguard Worker            # only allow specifying extra cmake args for "vanilla" compiler
563*cc02d7e2SAndroid Build Coastguard Worker            _check_compiler(compiler, ["default", "cmake"])
564*cc02d7e2SAndroid Build Coastguard Worker            return ("nonexistent_docker_distro", cmake_configure_extra_args)
565*cc02d7e2SAndroid Build Coastguard Worker        if not use_docker and not _is_use_docker_child():
566*cc02d7e2SAndroid Build Coastguard Worker            # if not running under docker, we cannot ensure the right compiler version will be used,
567*cc02d7e2SAndroid Build Coastguard Worker            # so we only allow the non-specific choices.
568*cc02d7e2SAndroid Build Coastguard Worker            _check_compiler(compiler, ["default", "cmake"])
569*cc02d7e2SAndroid Build Coastguard Worker
570*cc02d7e2SAndroid Build Coastguard Worker        if compiler == "default" or compiler == "cmake":
571*cc02d7e2SAndroid Build Coastguard Worker            return ("debian11", [])
572*cc02d7e2SAndroid Build Coastguard Worker        elif compiler == "gcc8":
573*cc02d7e2SAndroid Build Coastguard Worker            return ("gcc_8", [])
574*cc02d7e2SAndroid Build Coastguard Worker        elif compiler == "gcc10.2":
575*cc02d7e2SAndroid Build Coastguard Worker            return ("debian11", [])
576*cc02d7e2SAndroid Build Coastguard Worker        elif compiler == "gcc10.2_openssl102":
577*cc02d7e2SAndroid Build Coastguard Worker            return (
578*cc02d7e2SAndroid Build Coastguard Worker                "debian11_openssl102",
579*cc02d7e2SAndroid Build Coastguard Worker                [
580*cc02d7e2SAndroid Build Coastguard Worker                    "-DgRPC_SSL_PROVIDER=package",
581*cc02d7e2SAndroid Build Coastguard Worker                ],
582*cc02d7e2SAndroid Build Coastguard Worker            )
583*cc02d7e2SAndroid Build Coastguard Worker        elif compiler == "gcc10.2_openssl111":
584*cc02d7e2SAndroid Build Coastguard Worker            return (
585*cc02d7e2SAndroid Build Coastguard Worker                "debian11_openssl111",
586*cc02d7e2SAndroid Build Coastguard Worker                [
587*cc02d7e2SAndroid Build Coastguard Worker                    "-DgRPC_SSL_PROVIDER=package",
588*cc02d7e2SAndroid Build Coastguard Worker                ],
589*cc02d7e2SAndroid Build Coastguard Worker            )
590*cc02d7e2SAndroid Build Coastguard Worker        elif compiler == "gcc12":
591*cc02d7e2SAndroid Build Coastguard Worker            return ("gcc_12", ["-DCMAKE_CXX_STANDARD=20"])
592*cc02d7e2SAndroid Build Coastguard Worker        elif compiler == "gcc12_openssl309":
593*cc02d7e2SAndroid Build Coastguard Worker            return (
594*cc02d7e2SAndroid Build Coastguard Worker                "debian12_openssl309",
595*cc02d7e2SAndroid Build Coastguard Worker                [
596*cc02d7e2SAndroid Build Coastguard Worker                    "-DgRPC_SSL_PROVIDER=package",
597*cc02d7e2SAndroid Build Coastguard Worker                ],
598*cc02d7e2SAndroid Build Coastguard Worker            )
599*cc02d7e2SAndroid Build Coastguard Worker        elif compiler == "gcc_musl":
600*cc02d7e2SAndroid Build Coastguard Worker            return ("alpine", [])
601*cc02d7e2SAndroid Build Coastguard Worker        elif compiler == "clang6":
602*cc02d7e2SAndroid Build Coastguard Worker            return ("clang_6", self._clang_cmake_configure_extra_args())
603*cc02d7e2SAndroid Build Coastguard Worker        elif compiler == "clang17":
604*cc02d7e2SAndroid Build Coastguard Worker            return ("clang_17", self._clang_cmake_configure_extra_args())
605*cc02d7e2SAndroid Build Coastguard Worker        else:
606*cc02d7e2SAndroid Build Coastguard Worker            raise Exception("Compiler %s not supported." % compiler)
607*cc02d7e2SAndroid Build Coastguard Worker
608*cc02d7e2SAndroid Build Coastguard Worker    def dockerfile_dir(self):
609*cc02d7e2SAndroid Build Coastguard Worker        return "tools/dockerfile/test/cxx_%s_%s" % (
610*cc02d7e2SAndroid Build Coastguard Worker            self._docker_distro,
611*cc02d7e2SAndroid Build Coastguard Worker            _docker_arch_suffix(self.args.arch),
612*cc02d7e2SAndroid Build Coastguard Worker        )
613*cc02d7e2SAndroid Build Coastguard Worker
614*cc02d7e2SAndroid Build Coastguard Worker    def __str__(self):
615*cc02d7e2SAndroid Build Coastguard Worker        return self.lang_suffix
616*cc02d7e2SAndroid Build Coastguard Worker
617*cc02d7e2SAndroid Build Coastguard Worker
618*cc02d7e2SAndroid Build Coastguard Workerclass Php7Language(object):
619*cc02d7e2SAndroid Build Coastguard Worker    def configure(self, config, args):
620*cc02d7e2SAndroid Build Coastguard Worker        self.config = config
621*cc02d7e2SAndroid Build Coastguard Worker        self.args = args
622*cc02d7e2SAndroid Build Coastguard Worker        _check_compiler(self.args.compiler, ["default"])
623*cc02d7e2SAndroid Build Coastguard Worker
624*cc02d7e2SAndroid Build Coastguard Worker    def test_specs(self):
625*cc02d7e2SAndroid Build Coastguard Worker        return [
626*cc02d7e2SAndroid Build Coastguard Worker            self.config.job_spec(
627*cc02d7e2SAndroid Build Coastguard Worker                ["src/php/bin/run_tests.sh"],
628*cc02d7e2SAndroid Build Coastguard Worker                environ=_FORCE_ENVIRON_FOR_WRAPPERS,
629*cc02d7e2SAndroid Build Coastguard Worker            )
630*cc02d7e2SAndroid Build Coastguard Worker        ]
631*cc02d7e2SAndroid Build Coastguard Worker
632*cc02d7e2SAndroid Build Coastguard Worker    def pre_build_steps(self):
633*cc02d7e2SAndroid Build Coastguard Worker        return []
634*cc02d7e2SAndroid Build Coastguard Worker
635*cc02d7e2SAndroid Build Coastguard Worker    def build_steps(self):
636*cc02d7e2SAndroid Build Coastguard Worker        return [["tools/run_tests/helper_scripts/build_php.sh"]]
637*cc02d7e2SAndroid Build Coastguard Worker
638*cc02d7e2SAndroid Build Coastguard Worker    def build_steps_environ(self):
639*cc02d7e2SAndroid Build Coastguard Worker        """Extra environment variables set for pre_build_steps and build_steps jobs."""
640*cc02d7e2SAndroid Build Coastguard Worker        return {}
641*cc02d7e2SAndroid Build Coastguard Worker
642*cc02d7e2SAndroid Build Coastguard Worker    def post_tests_steps(self):
643*cc02d7e2SAndroid Build Coastguard Worker        return [["tools/run_tests/helper_scripts/post_tests_php.sh"]]
644*cc02d7e2SAndroid Build Coastguard Worker
645*cc02d7e2SAndroid Build Coastguard Worker    def dockerfile_dir(self):
646*cc02d7e2SAndroid Build Coastguard Worker        return "tools/dockerfile/test/php7_debian11_%s" % _docker_arch_suffix(
647*cc02d7e2SAndroid Build Coastguard Worker            self.args.arch
648*cc02d7e2SAndroid Build Coastguard Worker        )
649*cc02d7e2SAndroid Build Coastguard Worker
650*cc02d7e2SAndroid Build Coastguard Worker    def __str__(self):
651*cc02d7e2SAndroid Build Coastguard Worker        return "php7"
652*cc02d7e2SAndroid Build Coastguard Worker
653*cc02d7e2SAndroid Build Coastguard Worker
654*cc02d7e2SAndroid Build Coastguard Workerclass PythonConfig(
655*cc02d7e2SAndroid Build Coastguard Worker    collections.namedtuple(
656*cc02d7e2SAndroid Build Coastguard Worker        "PythonConfig", ["name", "build", "run", "python_path"]
657*cc02d7e2SAndroid Build Coastguard Worker    )
658*cc02d7e2SAndroid Build Coastguard Worker):
659*cc02d7e2SAndroid Build Coastguard Worker    """Tuple of commands (named s.t. 'what it says on the tin' applies)"""
660*cc02d7e2SAndroid Build Coastguard Worker
661*cc02d7e2SAndroid Build Coastguard Worker
662*cc02d7e2SAndroid Build Coastguard Workerclass PythonLanguage(object):
663*cc02d7e2SAndroid Build Coastguard Worker    _TEST_SPECS_FILE = {
664*cc02d7e2SAndroid Build Coastguard Worker        "native": ["src/python/grpcio_tests/tests/tests.json"],
665*cc02d7e2SAndroid Build Coastguard Worker        "asyncio": ["src/python/grpcio_tests/tests_aio/tests.json"],
666*cc02d7e2SAndroid Build Coastguard Worker    }
667*cc02d7e2SAndroid Build Coastguard Worker
668*cc02d7e2SAndroid Build Coastguard Worker    _TEST_COMMAND = {
669*cc02d7e2SAndroid Build Coastguard Worker        "native": "test_lite",
670*cc02d7e2SAndroid Build Coastguard Worker        "asyncio": "test_aio",
671*cc02d7e2SAndroid Build Coastguard Worker    }
672*cc02d7e2SAndroid Build Coastguard Worker
673*cc02d7e2SAndroid Build Coastguard Worker    def configure(self, config, args):
674*cc02d7e2SAndroid Build Coastguard Worker        self.config = config
675*cc02d7e2SAndroid Build Coastguard Worker        self.args = args
676*cc02d7e2SAndroid Build Coastguard Worker        self.pythons = self._get_pythons(self.args)
677*cc02d7e2SAndroid Build Coastguard Worker
678*cc02d7e2SAndroid Build Coastguard Worker    def test_specs(self):
679*cc02d7e2SAndroid Build Coastguard Worker        # load list of known test suites
680*cc02d7e2SAndroid Build Coastguard Worker        jobs = []
681*cc02d7e2SAndroid Build Coastguard Worker
682*cc02d7e2SAndroid Build Coastguard Worker        # Run tests across all supported interpreters.
683*cc02d7e2SAndroid Build Coastguard Worker        for python_config in self.pythons:
684*cc02d7e2SAndroid Build Coastguard Worker            # Run non-io-manager-specific tests.
685*cc02d7e2SAndroid Build Coastguard Worker            if os.name != "nt":
686*cc02d7e2SAndroid Build Coastguard Worker                jobs.append(
687*cc02d7e2SAndroid Build Coastguard Worker                    self.config.job_spec(
688*cc02d7e2SAndroid Build Coastguard Worker                        [
689*cc02d7e2SAndroid Build Coastguard Worker                            python_config.python_path,
690*cc02d7e2SAndroid Build Coastguard Worker                            "tools/distrib/python/xds_protos/generated_file_import_test.py",
691*cc02d7e2SAndroid Build Coastguard Worker                        ],
692*cc02d7e2SAndroid Build Coastguard Worker                        timeout_seconds=60,
693*cc02d7e2SAndroid Build Coastguard Worker                        environ=_FORCE_ENVIRON_FOR_WRAPPERS,
694*cc02d7e2SAndroid Build Coastguard Worker                        shortname=f"{python_config.name}.xds_protos",
695*cc02d7e2SAndroid Build Coastguard Worker                    )
696*cc02d7e2SAndroid Build Coastguard Worker                )
697*cc02d7e2SAndroid Build Coastguard Worker
698*cc02d7e2SAndroid Build Coastguard Worker            # Run main test suite across all support IO managers.
699*cc02d7e2SAndroid Build Coastguard Worker            for io_platform in self._TEST_SPECS_FILE:
700*cc02d7e2SAndroid Build Coastguard Worker                test_cases = []
701*cc02d7e2SAndroid Build Coastguard Worker                for tests_json_file_name in self._TEST_SPECS_FILE[io_platform]:
702*cc02d7e2SAndroid Build Coastguard Worker                    with open(tests_json_file_name) as tests_json_file:
703*cc02d7e2SAndroid Build Coastguard Worker                        test_cases.extend(json.load(tests_json_file))
704*cc02d7e2SAndroid Build Coastguard Worker
705*cc02d7e2SAndroid Build Coastguard Worker                environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
706*cc02d7e2SAndroid Build Coastguard Worker                # TODO(https://github.com/grpc/grpc/issues/21401) Fork handlers is not
707*cc02d7e2SAndroid Build Coastguard Worker                # designed for non-native IO manager. It has a side-effect that
708*cc02d7e2SAndroid Build Coastguard Worker                # overrides threading settings in C-Core.
709*cc02d7e2SAndroid Build Coastguard Worker                if io_platform != "native":
710*cc02d7e2SAndroid Build Coastguard Worker                    environment["GRPC_ENABLE_FORK_SUPPORT"] = "0"
711*cc02d7e2SAndroid Build Coastguard Worker                jobs.extend(
712*cc02d7e2SAndroid Build Coastguard Worker                    [
713*cc02d7e2SAndroid Build Coastguard Worker                        self.config.job_spec(
714*cc02d7e2SAndroid Build Coastguard Worker                            python_config.run
715*cc02d7e2SAndroid Build Coastguard Worker                            + [self._TEST_COMMAND[io_platform]],
716*cc02d7e2SAndroid Build Coastguard Worker                            timeout_seconds=8 * 60,
717*cc02d7e2SAndroid Build Coastguard Worker                            environ=dict(
718*cc02d7e2SAndroid Build Coastguard Worker                                GRPC_PYTHON_TESTRUNNER_FILTER=str(test_case),
719*cc02d7e2SAndroid Build Coastguard Worker                                **environment,
720*cc02d7e2SAndroid Build Coastguard Worker                            ),
721*cc02d7e2SAndroid Build Coastguard Worker                            shortname=f"{python_config.name}.{io_platform}.{test_case}",
722*cc02d7e2SAndroid Build Coastguard Worker                        )
723*cc02d7e2SAndroid Build Coastguard Worker                        for test_case in test_cases
724*cc02d7e2SAndroid Build Coastguard Worker                    ]
725*cc02d7e2SAndroid Build Coastguard Worker                )
726*cc02d7e2SAndroid Build Coastguard Worker        return jobs
727*cc02d7e2SAndroid Build Coastguard Worker
728*cc02d7e2SAndroid Build Coastguard Worker    def pre_build_steps(self):
729*cc02d7e2SAndroid Build Coastguard Worker        return []
730*cc02d7e2SAndroid Build Coastguard Worker
731*cc02d7e2SAndroid Build Coastguard Worker    def build_steps(self):
732*cc02d7e2SAndroid Build Coastguard Worker        return [config.build for config in self.pythons]
733*cc02d7e2SAndroid Build Coastguard Worker
734*cc02d7e2SAndroid Build Coastguard Worker    def build_steps_environ(self):
735*cc02d7e2SAndroid Build Coastguard Worker        """Extra environment variables set for pre_build_steps and build_steps jobs."""
736*cc02d7e2SAndroid Build Coastguard Worker        return {}
737*cc02d7e2SAndroid Build Coastguard Worker
738*cc02d7e2SAndroid Build Coastguard Worker    def post_tests_steps(self):
739*cc02d7e2SAndroid Build Coastguard Worker        if self.config.build_config != "gcov":
740*cc02d7e2SAndroid Build Coastguard Worker            return []
741*cc02d7e2SAndroid Build Coastguard Worker        else:
742*cc02d7e2SAndroid Build Coastguard Worker            return [["tools/run_tests/helper_scripts/post_tests_python.sh"]]
743*cc02d7e2SAndroid Build Coastguard Worker
744*cc02d7e2SAndroid Build Coastguard Worker    def dockerfile_dir(self):
745*cc02d7e2SAndroid Build Coastguard Worker        return "tools/dockerfile/test/python_%s_%s" % (
746*cc02d7e2SAndroid Build Coastguard Worker            self._python_docker_distro_name(),
747*cc02d7e2SAndroid Build Coastguard Worker            _docker_arch_suffix(self.args.arch),
748*cc02d7e2SAndroid Build Coastguard Worker        )
749*cc02d7e2SAndroid Build Coastguard Worker
750*cc02d7e2SAndroid Build Coastguard Worker    def _python_docker_distro_name(self):
751*cc02d7e2SAndroid Build Coastguard Worker        """Choose the docker image to use based on python version."""
752*cc02d7e2SAndroid Build Coastguard Worker        if self.args.compiler == "python_alpine":
753*cc02d7e2SAndroid Build Coastguard Worker            return "alpine"
754*cc02d7e2SAndroid Build Coastguard Worker        else:
755*cc02d7e2SAndroid Build Coastguard Worker            return "debian11_default"
756*cc02d7e2SAndroid Build Coastguard Worker
757*cc02d7e2SAndroid Build Coastguard Worker    def _get_pythons(self, args):
758*cc02d7e2SAndroid Build Coastguard Worker        """Get python runtimes to test with, based on current platform, architecture, compiler etc."""
759*cc02d7e2SAndroid Build Coastguard Worker        if args.iomgr_platform != "native":
760*cc02d7e2SAndroid Build Coastguard Worker            raise ValueError(
761*cc02d7e2SAndroid Build Coastguard Worker                "Python builds no longer differentiate IO Manager platforms,"
762*cc02d7e2SAndroid Build Coastguard Worker                ' please use "native"'
763*cc02d7e2SAndroid Build Coastguard Worker            )
764*cc02d7e2SAndroid Build Coastguard Worker
765*cc02d7e2SAndroid Build Coastguard Worker        if args.arch == "x86":
766*cc02d7e2SAndroid Build Coastguard Worker            bits = "32"
767*cc02d7e2SAndroid Build Coastguard Worker        else:
768*cc02d7e2SAndroid Build Coastguard Worker            bits = "64"
769*cc02d7e2SAndroid Build Coastguard Worker
770*cc02d7e2SAndroid Build Coastguard Worker        if os.name == "nt":
771*cc02d7e2SAndroid Build Coastguard Worker            shell = ["bash"]
772*cc02d7e2SAndroid Build Coastguard Worker            builder = [
773*cc02d7e2SAndroid Build Coastguard Worker                os.path.abspath(
774*cc02d7e2SAndroid Build Coastguard Worker                    "tools/run_tests/helper_scripts/build_python_msys2.sh"
775*cc02d7e2SAndroid Build Coastguard Worker                )
776*cc02d7e2SAndroid Build Coastguard Worker            ]
777*cc02d7e2SAndroid Build Coastguard Worker            builder_prefix_arguments = ["MINGW{}".format(bits)]
778*cc02d7e2SAndroid Build Coastguard Worker            venv_relative_python = ["Scripts/python.exe"]
779*cc02d7e2SAndroid Build Coastguard Worker            toolchain = ["mingw32"]
780*cc02d7e2SAndroid Build Coastguard Worker        else:
781*cc02d7e2SAndroid Build Coastguard Worker            shell = []
782*cc02d7e2SAndroid Build Coastguard Worker            builder = [
783*cc02d7e2SAndroid Build Coastguard Worker                os.path.abspath(
784*cc02d7e2SAndroid Build Coastguard Worker                    "tools/run_tests/helper_scripts/build_python.sh"
785*cc02d7e2SAndroid Build Coastguard Worker                )
786*cc02d7e2SAndroid Build Coastguard Worker            ]
787*cc02d7e2SAndroid Build Coastguard Worker            builder_prefix_arguments = []
788*cc02d7e2SAndroid Build Coastguard Worker            venv_relative_python = ["bin/python"]
789*cc02d7e2SAndroid Build Coastguard Worker            toolchain = ["unix"]
790*cc02d7e2SAndroid Build Coastguard Worker
791*cc02d7e2SAndroid Build Coastguard Worker        runner = [
792*cc02d7e2SAndroid Build Coastguard Worker            os.path.abspath("tools/run_tests/helper_scripts/run_python.sh")
793*cc02d7e2SAndroid Build Coastguard Worker        ]
794*cc02d7e2SAndroid Build Coastguard Worker
795*cc02d7e2SAndroid Build Coastguard Worker        config_vars = _PythonConfigVars(
796*cc02d7e2SAndroid Build Coastguard Worker            shell,
797*cc02d7e2SAndroid Build Coastguard Worker            builder,
798*cc02d7e2SAndroid Build Coastguard Worker            builder_prefix_arguments,
799*cc02d7e2SAndroid Build Coastguard Worker            venv_relative_python,
800*cc02d7e2SAndroid Build Coastguard Worker            toolchain,
801*cc02d7e2SAndroid Build Coastguard Worker            runner,
802*cc02d7e2SAndroid Build Coastguard Worker        )
803*cc02d7e2SAndroid Build Coastguard Worker
804*cc02d7e2SAndroid Build Coastguard Worker        # TODO: Supported version range should be defined by a single
805*cc02d7e2SAndroid Build Coastguard Worker        # source of truth.
806*cc02d7e2SAndroid Build Coastguard Worker        python38_config = _python_config_generator(
807*cc02d7e2SAndroid Build Coastguard Worker            name="py38",
808*cc02d7e2SAndroid Build Coastguard Worker            major="3",
809*cc02d7e2SAndroid Build Coastguard Worker            minor="8",
810*cc02d7e2SAndroid Build Coastguard Worker            bits=bits,
811*cc02d7e2SAndroid Build Coastguard Worker            config_vars=config_vars,
812*cc02d7e2SAndroid Build Coastguard Worker        )
813*cc02d7e2SAndroid Build Coastguard Worker        python39_config = _python_config_generator(
814*cc02d7e2SAndroid Build Coastguard Worker            name="py39",
815*cc02d7e2SAndroid Build Coastguard Worker            major="3",
816*cc02d7e2SAndroid Build Coastguard Worker            minor="9",
817*cc02d7e2SAndroid Build Coastguard Worker            bits=bits,
818*cc02d7e2SAndroid Build Coastguard Worker            config_vars=config_vars,
819*cc02d7e2SAndroid Build Coastguard Worker        )
820*cc02d7e2SAndroid Build Coastguard Worker        python310_config = _python_config_generator(
821*cc02d7e2SAndroid Build Coastguard Worker            name="py310",
822*cc02d7e2SAndroid Build Coastguard Worker            major="3",
823*cc02d7e2SAndroid Build Coastguard Worker            minor="10",
824*cc02d7e2SAndroid Build Coastguard Worker            bits=bits,
825*cc02d7e2SAndroid Build Coastguard Worker            config_vars=config_vars,
826*cc02d7e2SAndroid Build Coastguard Worker        )
827*cc02d7e2SAndroid Build Coastguard Worker        python311_config = _python_config_generator(
828*cc02d7e2SAndroid Build Coastguard Worker            name="py311",
829*cc02d7e2SAndroid Build Coastguard Worker            major="3",
830*cc02d7e2SAndroid Build Coastguard Worker            minor="11",
831*cc02d7e2SAndroid Build Coastguard Worker            bits=bits,
832*cc02d7e2SAndroid Build Coastguard Worker            config_vars=config_vars,
833*cc02d7e2SAndroid Build Coastguard Worker        )
834*cc02d7e2SAndroid Build Coastguard Worker        python312_config = _python_config_generator(
835*cc02d7e2SAndroid Build Coastguard Worker            name="py312",
836*cc02d7e2SAndroid Build Coastguard Worker            major="3",
837*cc02d7e2SAndroid Build Coastguard Worker            minor="12",
838*cc02d7e2SAndroid Build Coastguard Worker            bits=bits,
839*cc02d7e2SAndroid Build Coastguard Worker            config_vars=config_vars,
840*cc02d7e2SAndroid Build Coastguard Worker        )
841*cc02d7e2SAndroid Build Coastguard Worker        pypy27_config = _pypy_config_generator(
842*cc02d7e2SAndroid Build Coastguard Worker            name="pypy", major="2", config_vars=config_vars
843*cc02d7e2SAndroid Build Coastguard Worker        )
844*cc02d7e2SAndroid Build Coastguard Worker        pypy32_config = _pypy_config_generator(
845*cc02d7e2SAndroid Build Coastguard Worker            name="pypy3", major="3", config_vars=config_vars
846*cc02d7e2SAndroid Build Coastguard Worker        )
847*cc02d7e2SAndroid Build Coastguard Worker
848*cc02d7e2SAndroid Build Coastguard Worker        if args.compiler == "default":
849*cc02d7e2SAndroid Build Coastguard Worker            if os.name == "nt":
850*cc02d7e2SAndroid Build Coastguard Worker                return (python38_config,)
851*cc02d7e2SAndroid Build Coastguard Worker            elif os.uname()[0] == "Darwin":
852*cc02d7e2SAndroid Build Coastguard Worker                # NOTE(rbellevi): Testing takes significantly longer on
853*cc02d7e2SAndroid Build Coastguard Worker                # MacOS, so we restrict the number of interpreter versions
854*cc02d7e2SAndroid Build Coastguard Worker                # tested.
855*cc02d7e2SAndroid Build Coastguard Worker                return (python38_config,)
856*cc02d7e2SAndroid Build Coastguard Worker            elif platform.machine() == "aarch64":
857*cc02d7e2SAndroid Build Coastguard Worker                # Currently the python_debian11_default_arm64 docker image
858*cc02d7e2SAndroid Build Coastguard Worker                # only has python3.9 installed (and that seems sufficient
859*cc02d7e2SAndroid Build Coastguard Worker                # for arm64 testing)
860*cc02d7e2SAndroid Build Coastguard Worker                return (python39_config,)
861*cc02d7e2SAndroid Build Coastguard Worker            else:
862*cc02d7e2SAndroid Build Coastguard Worker                # Default set tested on master. Test oldest and newest.
863*cc02d7e2SAndroid Build Coastguard Worker                return (
864*cc02d7e2SAndroid Build Coastguard Worker                    python38_config,
865*cc02d7e2SAndroid Build Coastguard Worker                    python312_config,
866*cc02d7e2SAndroid Build Coastguard Worker                )
867*cc02d7e2SAndroid Build Coastguard Worker        elif args.compiler == "python3.8":
868*cc02d7e2SAndroid Build Coastguard Worker            return (python38_config,)
869*cc02d7e2SAndroid Build Coastguard Worker        elif args.compiler == "python3.9":
870*cc02d7e2SAndroid Build Coastguard Worker            return (python39_config,)
871*cc02d7e2SAndroid Build Coastguard Worker        elif args.compiler == "python3.10":
872*cc02d7e2SAndroid Build Coastguard Worker            return (python310_config,)
873*cc02d7e2SAndroid Build Coastguard Worker        elif args.compiler == "python3.11":
874*cc02d7e2SAndroid Build Coastguard Worker            return (python311_config,)
875*cc02d7e2SAndroid Build Coastguard Worker        elif args.compiler == "python3.12":
876*cc02d7e2SAndroid Build Coastguard Worker            return (python312_config,)
877*cc02d7e2SAndroid Build Coastguard Worker        elif args.compiler == "pypy":
878*cc02d7e2SAndroid Build Coastguard Worker            return (pypy27_config,)
879*cc02d7e2SAndroid Build Coastguard Worker        elif args.compiler == "pypy3":
880*cc02d7e2SAndroid Build Coastguard Worker            return (pypy32_config,)
881*cc02d7e2SAndroid Build Coastguard Worker        elif args.compiler == "python_alpine":
882*cc02d7e2SAndroid Build Coastguard Worker            return (python39_config,)
883*cc02d7e2SAndroid Build Coastguard Worker        elif args.compiler == "all_the_cpythons":
884*cc02d7e2SAndroid Build Coastguard Worker            return (
885*cc02d7e2SAndroid Build Coastguard Worker                python38_config,
886*cc02d7e2SAndroid Build Coastguard Worker                python39_config,
887*cc02d7e2SAndroid Build Coastguard Worker                python310_config,
888*cc02d7e2SAndroid Build Coastguard Worker                python311_config,
889*cc02d7e2SAndroid Build Coastguard Worker                python312_config,
890*cc02d7e2SAndroid Build Coastguard Worker            )
891*cc02d7e2SAndroid Build Coastguard Worker        else:
892*cc02d7e2SAndroid Build Coastguard Worker            raise Exception("Compiler %s not supported." % args.compiler)
893*cc02d7e2SAndroid Build Coastguard Worker
894*cc02d7e2SAndroid Build Coastguard Worker    def __str__(self):
895*cc02d7e2SAndroid Build Coastguard Worker        return "python"
896*cc02d7e2SAndroid Build Coastguard Worker
897*cc02d7e2SAndroid Build Coastguard Worker
898*cc02d7e2SAndroid Build Coastguard Workerclass RubyLanguage(object):
899*cc02d7e2SAndroid Build Coastguard Worker    def configure(self, config, args):
900*cc02d7e2SAndroid Build Coastguard Worker        self.config = config
901*cc02d7e2SAndroid Build Coastguard Worker        self.args = args
902*cc02d7e2SAndroid Build Coastguard Worker        _check_compiler(self.args.compiler, ["default"])
903*cc02d7e2SAndroid Build Coastguard Worker
904*cc02d7e2SAndroid Build Coastguard Worker    def test_specs(self):
905*cc02d7e2SAndroid Build Coastguard Worker        tests = [
906*cc02d7e2SAndroid Build Coastguard Worker            self.config.job_spec(
907*cc02d7e2SAndroid Build Coastguard Worker                ["tools/run_tests/helper_scripts/run_ruby.sh"],
908*cc02d7e2SAndroid Build Coastguard Worker                timeout_seconds=10 * 60,
909*cc02d7e2SAndroid Build Coastguard Worker                environ=_FORCE_ENVIRON_FOR_WRAPPERS,
910*cc02d7e2SAndroid Build Coastguard Worker            )
911*cc02d7e2SAndroid Build Coastguard Worker        ]
912*cc02d7e2SAndroid Build Coastguard Worker        # TODO(apolcyn): re-enable the following tests after
913*cc02d7e2SAndroid Build Coastguard Worker        # https://bugs.ruby-lang.org/issues/15499 is fixed:
914*cc02d7e2SAndroid Build Coastguard Worker        # They previously worked on ruby 2.5 but needed to be disabled
915*cc02d7e2SAndroid Build Coastguard Worker        # after dropping support for ruby 2.5:
916*cc02d7e2SAndroid Build Coastguard Worker        #   - src/ruby/end2end/channel_state_test.rb
917*cc02d7e2SAndroid Build Coastguard Worker        #   - src/ruby/end2end/sig_int_during_channel_watch_test.rb
918*cc02d7e2SAndroid Build Coastguard Worker        # TODO(apolcyn): the following test is skipped because it sometimes
919*cc02d7e2SAndroid Build Coastguard Worker        # hits "Bus Error" crashes while requiring the grpc/ruby C-extension.
920*cc02d7e2SAndroid Build Coastguard Worker        # This crashes have been unreproducible outside of CI. Also see
921*cc02d7e2SAndroid Build Coastguard Worker        # b/266212253.
922*cc02d7e2SAndroid Build Coastguard Worker        #   - src/ruby/end2end/grpc_class_init_test.rb
923*cc02d7e2SAndroid Build Coastguard Worker        for test in [
924*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/fork_test.rb",
925*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/simple_fork_test.rb",
926*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/prefork_without_using_grpc_test.rb",
927*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/prefork_postfork_loop_test.rb",
928*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/secure_fork_test.rb",
929*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/bad_usage_fork_test.rb",
930*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/sig_handling_test.rb",
931*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/channel_closing_test.rb",
932*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/killed_client_thread_test.rb",
933*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/forking_client_test.rb",
934*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/multiple_killed_watching_threads_test.rb",
935*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/load_grpc_with_gc_stress_test.rb",
936*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/client_memory_usage_test.rb",
937*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/package_with_underscore_test.rb",
938*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/graceful_sig_handling_test.rb",
939*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/graceful_sig_stop_test.rb",
940*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/errors_load_before_grpc_lib_test.rb",
941*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/logger_load_before_grpc_lib_test.rb",
942*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/status_codes_load_before_grpc_lib_test.rb",
943*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/call_credentials_timeout_test.rb",
944*cc02d7e2SAndroid Build Coastguard Worker            "src/ruby/end2end/call_credentials_returning_bad_metadata_doesnt_kill_background_thread_test.rb",
945*cc02d7e2SAndroid Build Coastguard Worker        ]:
946*cc02d7e2SAndroid Build Coastguard Worker            if test in [
947*cc02d7e2SAndroid Build Coastguard Worker                "src/ruby/end2end/fork_test.rb",
948*cc02d7e2SAndroid Build Coastguard Worker                "src/ruby/end2end/simple_fork_test.rb",
949*cc02d7e2SAndroid Build Coastguard Worker                "src/ruby/end2end/secure_fork_test.rb",
950*cc02d7e2SAndroid Build Coastguard Worker                "src/ruby/end2end/bad_usage_fork_test.rb",
951*cc02d7e2SAndroid Build Coastguard Worker                "src/ruby/end2end/prefork_without_using_grpc_test.rb",
952*cc02d7e2SAndroid Build Coastguard Worker                "src/ruby/end2end/prefork_postfork_loop_test.rb",
953*cc02d7e2SAndroid Build Coastguard Worker                "src/ruby/end2end/fork_test_repro_35489.rb",
954*cc02d7e2SAndroid Build Coastguard Worker            ]:
955*cc02d7e2SAndroid Build Coastguard Worker                # Skip fork tests in general until https://github.com/grpc/grpc/issues/34442
956*cc02d7e2SAndroid Build Coastguard Worker                # is fixed. Otherwise we see too many flakes.
957*cc02d7e2SAndroid Build Coastguard Worker                # After that's fixed, we should continue to skip on mac
958*cc02d7e2SAndroid Build Coastguard Worker                # indefinitely, and on "dbg" builds until the Event Engine
959*cc02d7e2SAndroid Build Coastguard Worker                # migration completes.
960*cc02d7e2SAndroid Build Coastguard Worker                continue
961*cc02d7e2SAndroid Build Coastguard Worker            tests.append(
962*cc02d7e2SAndroid Build Coastguard Worker                self.config.job_spec(
963*cc02d7e2SAndroid Build Coastguard Worker                    ["ruby", test],
964*cc02d7e2SAndroid Build Coastguard Worker                    shortname=test,
965*cc02d7e2SAndroid Build Coastguard Worker                    timeout_seconds=20 * 60,
966*cc02d7e2SAndroid Build Coastguard Worker                    environ=_FORCE_ENVIRON_FOR_WRAPPERS,
967*cc02d7e2SAndroid Build Coastguard Worker                )
968*cc02d7e2SAndroid Build Coastguard Worker            )
969*cc02d7e2SAndroid Build Coastguard Worker        return tests
970*cc02d7e2SAndroid Build Coastguard Worker
971*cc02d7e2SAndroid Build Coastguard Worker    def pre_build_steps(self):
972*cc02d7e2SAndroid Build Coastguard Worker        return [["tools/run_tests/helper_scripts/pre_build_ruby.sh"]]
973*cc02d7e2SAndroid Build Coastguard Worker
974*cc02d7e2SAndroid Build Coastguard Worker    def build_steps(self):
975*cc02d7e2SAndroid Build Coastguard Worker        return [["tools/run_tests/helper_scripts/build_ruby.sh"]]
976*cc02d7e2SAndroid Build Coastguard Worker
977*cc02d7e2SAndroid Build Coastguard Worker    def build_steps_environ(self):
978*cc02d7e2SAndroid Build Coastguard Worker        """Extra environment variables set for pre_build_steps and build_steps jobs."""
979*cc02d7e2SAndroid Build Coastguard Worker        return {}
980*cc02d7e2SAndroid Build Coastguard Worker
981*cc02d7e2SAndroid Build Coastguard Worker    def post_tests_steps(self):
982*cc02d7e2SAndroid Build Coastguard Worker        return [["tools/run_tests/helper_scripts/post_tests_ruby.sh"]]
983*cc02d7e2SAndroid Build Coastguard Worker
984*cc02d7e2SAndroid Build Coastguard Worker    def dockerfile_dir(self):
985*cc02d7e2SAndroid Build Coastguard Worker        return "tools/dockerfile/test/ruby_debian11_%s" % _docker_arch_suffix(
986*cc02d7e2SAndroid Build Coastguard Worker            self.args.arch
987*cc02d7e2SAndroid Build Coastguard Worker        )
988*cc02d7e2SAndroid Build Coastguard Worker
989*cc02d7e2SAndroid Build Coastguard Worker    def __str__(self):
990*cc02d7e2SAndroid Build Coastguard Worker        return "ruby"
991*cc02d7e2SAndroid Build Coastguard Worker
992*cc02d7e2SAndroid Build Coastguard Worker
993*cc02d7e2SAndroid Build Coastguard Workerclass CSharpLanguage(object):
994*cc02d7e2SAndroid Build Coastguard Worker    def __init__(self):
995*cc02d7e2SAndroid Build Coastguard Worker        self.platform = platform_string()
996*cc02d7e2SAndroid Build Coastguard Worker
997*cc02d7e2SAndroid Build Coastguard Worker    def configure(self, config, args):
998*cc02d7e2SAndroid Build Coastguard Worker        self.config = config
999*cc02d7e2SAndroid Build Coastguard Worker        self.args = args
1000*cc02d7e2SAndroid Build Coastguard Worker        _check_compiler(self.args.compiler, ["default", "coreclr", "mono"])
1001*cc02d7e2SAndroid Build Coastguard Worker        if self.args.compiler == "default":
1002*cc02d7e2SAndroid Build Coastguard Worker            # test both runtimes by default
1003*cc02d7e2SAndroid Build Coastguard Worker            self.test_runtimes = ["coreclr", "mono"]
1004*cc02d7e2SAndroid Build Coastguard Worker        else:
1005*cc02d7e2SAndroid Build Coastguard Worker            # only test the specified runtime
1006*cc02d7e2SAndroid Build Coastguard Worker            self.test_runtimes = [self.args.compiler]
1007*cc02d7e2SAndroid Build Coastguard Worker
1008*cc02d7e2SAndroid Build Coastguard Worker        if self.platform == "windows":
1009*cc02d7e2SAndroid Build Coastguard Worker            _check_arch(self.args.arch, ["default"])
1010*cc02d7e2SAndroid Build Coastguard Worker            self._cmake_arch_option = "x64"
1011*cc02d7e2SAndroid Build Coastguard Worker        else:
1012*cc02d7e2SAndroid Build Coastguard Worker            self._docker_distro = "debian11"
1013*cc02d7e2SAndroid Build Coastguard Worker
1014*cc02d7e2SAndroid Build Coastguard Worker    def test_specs(self):
1015*cc02d7e2SAndroid Build Coastguard Worker        with open("src/csharp/tests.json") as f:
1016*cc02d7e2SAndroid Build Coastguard Worker            tests_by_assembly = json.load(f)
1017*cc02d7e2SAndroid Build Coastguard Worker
1018*cc02d7e2SAndroid Build Coastguard Worker        msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
1019*cc02d7e2SAndroid Build Coastguard Worker        nunit_args = ["--labels=All", "--noresult", "--workers=1"]
1020*cc02d7e2SAndroid Build Coastguard Worker
1021*cc02d7e2SAndroid Build Coastguard Worker        specs = []
1022*cc02d7e2SAndroid Build Coastguard Worker        for test_runtime in self.test_runtimes:
1023*cc02d7e2SAndroid Build Coastguard Worker            if test_runtime == "coreclr":
1024*cc02d7e2SAndroid Build Coastguard Worker                assembly_extension = ".dll"
1025*cc02d7e2SAndroid Build Coastguard Worker                assembly_subdir = "bin/%s/netcoreapp3.1" % msbuild_config
1026*cc02d7e2SAndroid Build Coastguard Worker                runtime_cmd = ["dotnet", "exec"]
1027*cc02d7e2SAndroid Build Coastguard Worker            elif test_runtime == "mono":
1028*cc02d7e2SAndroid Build Coastguard Worker                assembly_extension = ".exe"
1029*cc02d7e2SAndroid Build Coastguard Worker                assembly_subdir = "bin/%s/net45" % msbuild_config
1030*cc02d7e2SAndroid Build Coastguard Worker                if self.platform == "windows":
1031*cc02d7e2SAndroid Build Coastguard Worker                    runtime_cmd = []
1032*cc02d7e2SAndroid Build Coastguard Worker                elif self.platform == "mac":
1033*cc02d7e2SAndroid Build Coastguard Worker                    # mono before version 5.2 on MacOS defaults to 32bit runtime
1034*cc02d7e2SAndroid Build Coastguard Worker                    runtime_cmd = ["mono", "--arch=64"]
1035*cc02d7e2SAndroid Build Coastguard Worker                else:
1036*cc02d7e2SAndroid Build Coastguard Worker                    runtime_cmd = ["mono"]
1037*cc02d7e2SAndroid Build Coastguard Worker            else:
1038*cc02d7e2SAndroid Build Coastguard Worker                raise Exception('Illegal runtime "%s" was specified.')
1039*cc02d7e2SAndroid Build Coastguard Worker
1040*cc02d7e2SAndroid Build Coastguard Worker            for assembly in six.iterkeys(tests_by_assembly):
1041*cc02d7e2SAndroid Build Coastguard Worker                assembly_file = "src/csharp/%s/%s/%s%s" % (
1042*cc02d7e2SAndroid Build Coastguard Worker                    assembly,
1043*cc02d7e2SAndroid Build Coastguard Worker                    assembly_subdir,
1044*cc02d7e2SAndroid Build Coastguard Worker                    assembly,
1045*cc02d7e2SAndroid Build Coastguard Worker                    assembly_extension,
1046*cc02d7e2SAndroid Build Coastguard Worker                )
1047*cc02d7e2SAndroid Build Coastguard Worker
1048*cc02d7e2SAndroid Build Coastguard Worker                # normally, run each test as a separate process
1049*cc02d7e2SAndroid Build Coastguard Worker                for test in tests_by_assembly[assembly]:
1050*cc02d7e2SAndroid Build Coastguard Worker                    cmdline = (
1051*cc02d7e2SAndroid Build Coastguard Worker                        runtime_cmd
1052*cc02d7e2SAndroid Build Coastguard Worker                        + [assembly_file, "--test=%s" % test]
1053*cc02d7e2SAndroid Build Coastguard Worker                        + nunit_args
1054*cc02d7e2SAndroid Build Coastguard Worker                    )
1055*cc02d7e2SAndroid Build Coastguard Worker                    specs.append(
1056*cc02d7e2SAndroid Build Coastguard Worker                        self.config.job_spec(
1057*cc02d7e2SAndroid Build Coastguard Worker                            cmdline,
1058*cc02d7e2SAndroid Build Coastguard Worker                            shortname="csharp.%s.%s" % (test_runtime, test),
1059*cc02d7e2SAndroid Build Coastguard Worker                            environ=_FORCE_ENVIRON_FOR_WRAPPERS,
1060*cc02d7e2SAndroid Build Coastguard Worker                        )
1061*cc02d7e2SAndroid Build Coastguard Worker                    )
1062*cc02d7e2SAndroid Build Coastguard Worker        return specs
1063*cc02d7e2SAndroid Build Coastguard Worker
1064*cc02d7e2SAndroid Build Coastguard Worker    def pre_build_steps(self):
1065*cc02d7e2SAndroid Build Coastguard Worker        if self.platform == "windows":
1066*cc02d7e2SAndroid Build Coastguard Worker            return [["tools\\run_tests\\helper_scripts\\pre_build_csharp.bat"]]
1067*cc02d7e2SAndroid Build Coastguard Worker        else:
1068*cc02d7e2SAndroid Build Coastguard Worker            return [["tools/run_tests/helper_scripts/pre_build_csharp.sh"]]
1069*cc02d7e2SAndroid Build Coastguard Worker
1070*cc02d7e2SAndroid Build Coastguard Worker    def build_steps(self):
1071*cc02d7e2SAndroid Build Coastguard Worker        if self.platform == "windows":
1072*cc02d7e2SAndroid Build Coastguard Worker            return [["tools\\run_tests\\helper_scripts\\build_csharp.bat"]]
1073*cc02d7e2SAndroid Build Coastguard Worker        else:
1074*cc02d7e2SAndroid Build Coastguard Worker            return [["tools/run_tests/helper_scripts/build_csharp.sh"]]
1075*cc02d7e2SAndroid Build Coastguard Worker
1076*cc02d7e2SAndroid Build Coastguard Worker    def build_steps_environ(self):
1077*cc02d7e2SAndroid Build Coastguard Worker        """Extra environment variables set for pre_build_steps and build_steps jobs."""
1078*cc02d7e2SAndroid Build Coastguard Worker        if self.platform == "windows":
1079*cc02d7e2SAndroid Build Coastguard Worker            return {"ARCHITECTURE": self._cmake_arch_option}
1080*cc02d7e2SAndroid Build Coastguard Worker        else:
1081*cc02d7e2SAndroid Build Coastguard Worker            return {}
1082*cc02d7e2SAndroid Build Coastguard Worker
1083*cc02d7e2SAndroid Build Coastguard Worker    def post_tests_steps(self):
1084*cc02d7e2SAndroid Build Coastguard Worker        if self.platform == "windows":
1085*cc02d7e2SAndroid Build Coastguard Worker            return [["tools\\run_tests\\helper_scripts\\post_tests_csharp.bat"]]
1086*cc02d7e2SAndroid Build Coastguard Worker        else:
1087*cc02d7e2SAndroid Build Coastguard Worker            return [["tools/run_tests/helper_scripts/post_tests_csharp.sh"]]
1088*cc02d7e2SAndroid Build Coastguard Worker
1089*cc02d7e2SAndroid Build Coastguard Worker    def dockerfile_dir(self):
1090*cc02d7e2SAndroid Build Coastguard Worker        return "tools/dockerfile/test/csharp_%s_%s" % (
1091*cc02d7e2SAndroid Build Coastguard Worker            self._docker_distro,
1092*cc02d7e2SAndroid Build Coastguard Worker            _docker_arch_suffix(self.args.arch),
1093*cc02d7e2SAndroid Build Coastguard Worker        )
1094*cc02d7e2SAndroid Build Coastguard Worker
1095*cc02d7e2SAndroid Build Coastguard Worker    def __str__(self):
1096*cc02d7e2SAndroid Build Coastguard Worker        return "csharp"
1097*cc02d7e2SAndroid Build Coastguard Worker
1098*cc02d7e2SAndroid Build Coastguard Worker
1099*cc02d7e2SAndroid Build Coastguard Workerclass ObjCLanguage(object):
1100*cc02d7e2SAndroid Build Coastguard Worker    def configure(self, config, args):
1101*cc02d7e2SAndroid Build Coastguard Worker        self.config = config
1102*cc02d7e2SAndroid Build Coastguard Worker        self.args = args
1103*cc02d7e2SAndroid Build Coastguard Worker        _check_compiler(self.args.compiler, ["default"])
1104*cc02d7e2SAndroid Build Coastguard Worker
1105*cc02d7e2SAndroid Build Coastguard Worker    def test_specs(self):
1106*cc02d7e2SAndroid Build Coastguard Worker        out = []
1107*cc02d7e2SAndroid Build Coastguard Worker        out.append(
1108*cc02d7e2SAndroid Build Coastguard Worker            self.config.job_spec(
1109*cc02d7e2SAndroid Build Coastguard Worker                ["src/objective-c/tests/build_one_example.sh"],
1110*cc02d7e2SAndroid Build Coastguard Worker                timeout_seconds=20 * 60,
1111*cc02d7e2SAndroid Build Coastguard Worker                shortname="ios-buildtest-example-sample",
1112*cc02d7e2SAndroid Build Coastguard Worker                cpu_cost=1e6,
1113*cc02d7e2SAndroid Build Coastguard Worker                environ={
1114*cc02d7e2SAndroid Build Coastguard Worker                    "SCHEME": "Sample",
1115*cc02d7e2SAndroid Build Coastguard Worker                    "EXAMPLE_PATH": "src/objective-c/examples/Sample",
1116*cc02d7e2SAndroid Build Coastguard Worker                },
1117*cc02d7e2SAndroid Build Coastguard Worker            )
1118*cc02d7e2SAndroid Build Coastguard Worker        )
1119*cc02d7e2SAndroid Build Coastguard Worker        # TODO(jtattermusch): Create bazel target for the sample and remove the test task from here.
1120*cc02d7e2SAndroid Build Coastguard Worker        out.append(
1121*cc02d7e2SAndroid Build Coastguard Worker            self.config.job_spec(
1122*cc02d7e2SAndroid Build Coastguard Worker                ["src/objective-c/tests/build_one_example.sh"],
1123*cc02d7e2SAndroid Build Coastguard Worker                timeout_seconds=20 * 60,
1124*cc02d7e2SAndroid Build Coastguard Worker                shortname="ios-buildtest-example-switftsample",
1125*cc02d7e2SAndroid Build Coastguard Worker                cpu_cost=1e6,
1126*cc02d7e2SAndroid Build Coastguard Worker                environ={
1127*cc02d7e2SAndroid Build Coastguard Worker                    "SCHEME": "SwiftSample",
1128*cc02d7e2SAndroid Build Coastguard Worker                    "EXAMPLE_PATH": "src/objective-c/examples/SwiftSample",
1129*cc02d7e2SAndroid Build Coastguard Worker                },
1130*cc02d7e2SAndroid Build Coastguard Worker            )
1131*cc02d7e2SAndroid Build Coastguard Worker        )
1132*cc02d7e2SAndroid Build Coastguard Worker        out.append(
1133*cc02d7e2SAndroid Build Coastguard Worker            self.config.job_spec(
1134*cc02d7e2SAndroid Build Coastguard Worker                ["src/objective-c/tests/build_one_example.sh"],
1135*cc02d7e2SAndroid Build Coastguard Worker                timeout_seconds=20 * 60,
1136*cc02d7e2SAndroid Build Coastguard Worker                shortname="ios-buildtest-example-switft-use-frameworks",
1137*cc02d7e2SAndroid Build Coastguard Worker                cpu_cost=1e6,
1138*cc02d7e2SAndroid Build Coastguard Worker                environ={
1139*cc02d7e2SAndroid Build Coastguard Worker                    "SCHEME": "SwiftUseFrameworks",
1140*cc02d7e2SAndroid Build Coastguard Worker                    "EXAMPLE_PATH": "src/objective-c/examples/SwiftUseFrameworks",
1141*cc02d7e2SAndroid Build Coastguard Worker                },
1142*cc02d7e2SAndroid Build Coastguard Worker            )
1143*cc02d7e2SAndroid Build Coastguard Worker        )
1144*cc02d7e2SAndroid Build Coastguard Worker
1145*cc02d7e2SAndroid Build Coastguard Worker        # Disabled due to #20258
1146*cc02d7e2SAndroid Build Coastguard Worker        # TODO (mxyan): Reenable this test when #20258 is resolved.
1147*cc02d7e2SAndroid Build Coastguard Worker        # out.append(
1148*cc02d7e2SAndroid Build Coastguard Worker        #     self.config.job_spec(
1149*cc02d7e2SAndroid Build Coastguard Worker        #         ['src/objective-c/tests/build_one_example_bazel.sh'],
1150*cc02d7e2SAndroid Build Coastguard Worker        #         timeout_seconds=20 * 60,
1151*cc02d7e2SAndroid Build Coastguard Worker        #         shortname='ios-buildtest-example-watchOS-sample',
1152*cc02d7e2SAndroid Build Coastguard Worker        #         cpu_cost=1e6,
1153*cc02d7e2SAndroid Build Coastguard Worker        #         environ={
1154*cc02d7e2SAndroid Build Coastguard Worker        #             'SCHEME': 'watchOS-sample-WatchKit-App',
1155*cc02d7e2SAndroid Build Coastguard Worker        #             'EXAMPLE_PATH': 'src/objective-c/examples/watchOS-sample',
1156*cc02d7e2SAndroid Build Coastguard Worker        #             'FRAMEWORKS': 'NO'
1157*cc02d7e2SAndroid Build Coastguard Worker        #         }))
1158*cc02d7e2SAndroid Build Coastguard Worker
1159*cc02d7e2SAndroid Build Coastguard Worker        # TODO(jtattermusch): move the test out of the test/core/iomgr/CFStreamTests directory?
1160*cc02d7e2SAndroid Build Coastguard Worker        # How does one add the cfstream dependency in bazel?
1161*cc02d7e2SAndroid Build Coastguard Worker        out.append(
1162*cc02d7e2SAndroid Build Coastguard Worker            self.config.job_spec(
1163*cc02d7e2SAndroid Build Coastguard Worker                ["test/core/iomgr/ios/CFStreamTests/build_and_run_tests.sh"],
1164*cc02d7e2SAndroid Build Coastguard Worker                timeout_seconds=60 * 60,
1165*cc02d7e2SAndroid Build Coastguard Worker                shortname="ios-test-cfstream-tests",
1166*cc02d7e2SAndroid Build Coastguard Worker                cpu_cost=1e6,
1167*cc02d7e2SAndroid Build Coastguard Worker                environ=_FORCE_ENVIRON_FOR_WRAPPERS,
1168*cc02d7e2SAndroid Build Coastguard Worker            )
1169*cc02d7e2SAndroid Build Coastguard Worker        )
1170*cc02d7e2SAndroid Build Coastguard Worker        return sorted(out)
1171*cc02d7e2SAndroid Build Coastguard Worker
1172*cc02d7e2SAndroid Build Coastguard Worker    def pre_build_steps(self):
1173*cc02d7e2SAndroid Build Coastguard Worker        return []
1174*cc02d7e2SAndroid Build Coastguard Worker
1175*cc02d7e2SAndroid Build Coastguard Worker    def build_steps(self):
1176*cc02d7e2SAndroid Build Coastguard Worker        return []
1177*cc02d7e2SAndroid Build Coastguard Worker
1178*cc02d7e2SAndroid Build Coastguard Worker    def build_steps_environ(self):
1179*cc02d7e2SAndroid Build Coastguard Worker        """Extra environment variables set for pre_build_steps and build_steps jobs."""
1180*cc02d7e2SAndroid Build Coastguard Worker        return {}
1181*cc02d7e2SAndroid Build Coastguard Worker
1182*cc02d7e2SAndroid Build Coastguard Worker    def post_tests_steps(self):
1183*cc02d7e2SAndroid Build Coastguard Worker        return []
1184*cc02d7e2SAndroid Build Coastguard Worker
1185*cc02d7e2SAndroid Build Coastguard Worker    def dockerfile_dir(self):
1186*cc02d7e2SAndroid Build Coastguard Worker        return None
1187*cc02d7e2SAndroid Build Coastguard Worker
1188*cc02d7e2SAndroid Build Coastguard Worker    def __str__(self):
1189*cc02d7e2SAndroid Build Coastguard Worker        return "objc"
1190*cc02d7e2SAndroid Build Coastguard Worker
1191*cc02d7e2SAndroid Build Coastguard Worker
1192*cc02d7e2SAndroid Build Coastguard Workerclass Sanity(object):
1193*cc02d7e2SAndroid Build Coastguard Worker    def __init__(self, config_file):
1194*cc02d7e2SAndroid Build Coastguard Worker        self.config_file = config_file
1195*cc02d7e2SAndroid Build Coastguard Worker
1196*cc02d7e2SAndroid Build Coastguard Worker    def configure(self, config, args):
1197*cc02d7e2SAndroid Build Coastguard Worker        self.config = config
1198*cc02d7e2SAndroid Build Coastguard Worker        self.args = args
1199*cc02d7e2SAndroid Build Coastguard Worker        _check_compiler(self.args.compiler, ["default"])
1200*cc02d7e2SAndroid Build Coastguard Worker
1201*cc02d7e2SAndroid Build Coastguard Worker    def test_specs(self):
1202*cc02d7e2SAndroid Build Coastguard Worker        import yaml
1203*cc02d7e2SAndroid Build Coastguard Worker
1204*cc02d7e2SAndroid Build Coastguard Worker        with open("tools/run_tests/sanity/%s" % self.config_file, "r") as f:
1205*cc02d7e2SAndroid Build Coastguard Worker            environ = {"TEST": "true"}
1206*cc02d7e2SAndroid Build Coastguard Worker            if _is_use_docker_child():
1207*cc02d7e2SAndroid Build Coastguard Worker                environ["CLANG_FORMAT_SKIP_DOCKER"] = "true"
1208*cc02d7e2SAndroid Build Coastguard Worker                environ["CLANG_TIDY_SKIP_DOCKER"] = "true"
1209*cc02d7e2SAndroid Build Coastguard Worker                environ["IWYU_SKIP_DOCKER"] = "true"
1210*cc02d7e2SAndroid Build Coastguard Worker                # sanity tests run tools/bazel wrapper concurrently
1211*cc02d7e2SAndroid Build Coastguard Worker                # and that can result in a download/run race in the wrapper.
1212*cc02d7e2SAndroid Build Coastguard Worker                # under docker we already have the right version of bazel
1213*cc02d7e2SAndroid Build Coastguard Worker                # so we can just disable the wrapper.
1214*cc02d7e2SAndroid Build Coastguard Worker                environ["DISABLE_BAZEL_WRAPPER"] = "true"
1215*cc02d7e2SAndroid Build Coastguard Worker            return [
1216*cc02d7e2SAndroid Build Coastguard Worker                self.config.job_spec(
1217*cc02d7e2SAndroid Build Coastguard Worker                    cmd["script"].split(),
1218*cc02d7e2SAndroid Build Coastguard Worker                    timeout_seconds=45 * 60,
1219*cc02d7e2SAndroid Build Coastguard Worker                    environ=environ,
1220*cc02d7e2SAndroid Build Coastguard Worker                    cpu_cost=cmd.get("cpu_cost", 1),
1221*cc02d7e2SAndroid Build Coastguard Worker                )
1222*cc02d7e2SAndroid Build Coastguard Worker                for cmd in yaml.safe_load(f)
1223*cc02d7e2SAndroid Build Coastguard Worker            ]
1224*cc02d7e2SAndroid Build Coastguard Worker
1225*cc02d7e2SAndroid Build Coastguard Worker    def pre_build_steps(self):
1226*cc02d7e2SAndroid Build Coastguard Worker        return []
1227*cc02d7e2SAndroid Build Coastguard Worker
1228*cc02d7e2SAndroid Build Coastguard Worker    def build_steps(self):
1229*cc02d7e2SAndroid Build Coastguard Worker        return []
1230*cc02d7e2SAndroid Build Coastguard Worker
1231*cc02d7e2SAndroid Build Coastguard Worker    def build_steps_environ(self):
1232*cc02d7e2SAndroid Build Coastguard Worker        """Extra environment variables set for pre_build_steps and build_steps jobs."""
1233*cc02d7e2SAndroid Build Coastguard Worker        return {}
1234*cc02d7e2SAndroid Build Coastguard Worker
1235*cc02d7e2SAndroid Build Coastguard Worker    def post_tests_steps(self):
1236*cc02d7e2SAndroid Build Coastguard Worker        return []
1237*cc02d7e2SAndroid Build Coastguard Worker
1238*cc02d7e2SAndroid Build Coastguard Worker    def dockerfile_dir(self):
1239*cc02d7e2SAndroid Build Coastguard Worker        return "tools/dockerfile/test/sanity"
1240*cc02d7e2SAndroid Build Coastguard Worker
1241*cc02d7e2SAndroid Build Coastguard Worker    def __str__(self):
1242*cc02d7e2SAndroid Build Coastguard Worker        return "sanity"
1243*cc02d7e2SAndroid Build Coastguard Worker
1244*cc02d7e2SAndroid Build Coastguard Worker
1245*cc02d7e2SAndroid Build Coastguard Worker# different configurations we can run under
1246*cc02d7e2SAndroid Build Coastguard Workerwith open("tools/run_tests/generated/configs.json") as f:
1247*cc02d7e2SAndroid Build Coastguard Worker    _CONFIGS = dict(
1248*cc02d7e2SAndroid Build Coastguard Worker        (cfg["config"], Config(**cfg)) for cfg in ast.literal_eval(f.read())
1249*cc02d7e2SAndroid Build Coastguard Worker    )
1250*cc02d7e2SAndroid Build Coastguard Worker
1251*cc02d7e2SAndroid Build Coastguard Worker_LANGUAGES = {
1252*cc02d7e2SAndroid Build Coastguard Worker    "c++": CLanguage("cxx", "c++"),
1253*cc02d7e2SAndroid Build Coastguard Worker    "c": CLanguage("c", "c"),
1254*cc02d7e2SAndroid Build Coastguard Worker    "php7": Php7Language(),
1255*cc02d7e2SAndroid Build Coastguard Worker    "python": PythonLanguage(),
1256*cc02d7e2SAndroid Build Coastguard Worker    "ruby": RubyLanguage(),
1257*cc02d7e2SAndroid Build Coastguard Worker    "csharp": CSharpLanguage(),
1258*cc02d7e2SAndroid Build Coastguard Worker    "objc": ObjCLanguage(),
1259*cc02d7e2SAndroid Build Coastguard Worker    "sanity": Sanity("sanity_tests.yaml"),
1260*cc02d7e2SAndroid Build Coastguard Worker    "clang-tidy": Sanity("clang_tidy_tests.yaml"),
1261*cc02d7e2SAndroid Build Coastguard Worker}
1262*cc02d7e2SAndroid Build Coastguard Worker
1263*cc02d7e2SAndroid Build Coastguard Worker_MSBUILD_CONFIG = {
1264*cc02d7e2SAndroid Build Coastguard Worker    "dbg": "Debug",
1265*cc02d7e2SAndroid Build Coastguard Worker    "opt": "Release",
1266*cc02d7e2SAndroid Build Coastguard Worker    "gcov": "Debug",
1267*cc02d7e2SAndroid Build Coastguard Worker}
1268*cc02d7e2SAndroid Build Coastguard Worker
1269*cc02d7e2SAndroid Build Coastguard Worker
1270*cc02d7e2SAndroid Build Coastguard Workerdef _build_step_environ(cfg, extra_env={}):
1271*cc02d7e2SAndroid Build Coastguard Worker    """Environment variables set for each build step."""
1272*cc02d7e2SAndroid Build Coastguard Worker    environ = {"CONFIG": cfg, "GRPC_RUN_TESTS_JOBS": str(args.jobs)}
1273*cc02d7e2SAndroid Build Coastguard Worker    msbuild_cfg = _MSBUILD_CONFIG.get(cfg)
1274*cc02d7e2SAndroid Build Coastguard Worker    if msbuild_cfg:
1275*cc02d7e2SAndroid Build Coastguard Worker        environ["MSBUILD_CONFIG"] = msbuild_cfg
1276*cc02d7e2SAndroid Build Coastguard Worker    environ.update(extra_env)
1277*cc02d7e2SAndroid Build Coastguard Worker    return environ
1278*cc02d7e2SAndroid Build Coastguard Worker
1279*cc02d7e2SAndroid Build Coastguard Worker
1280*cc02d7e2SAndroid Build Coastguard Workerdef _windows_arch_option(arch):
1281*cc02d7e2SAndroid Build Coastguard Worker    """Returns msbuild cmdline option for selected architecture."""
1282*cc02d7e2SAndroid Build Coastguard Worker    if arch == "default" or arch == "x86":
1283*cc02d7e2SAndroid Build Coastguard Worker        return "/p:Platform=Win32"
1284*cc02d7e2SAndroid Build Coastguard Worker    elif arch == "x64":
1285*cc02d7e2SAndroid Build Coastguard Worker        return "/p:Platform=x64"
1286*cc02d7e2SAndroid Build Coastguard Worker    else:
1287*cc02d7e2SAndroid Build Coastguard Worker        print("Architecture %s not supported." % arch)
1288*cc02d7e2SAndroid Build Coastguard Worker        sys.exit(1)
1289*cc02d7e2SAndroid Build Coastguard Worker
1290*cc02d7e2SAndroid Build Coastguard Worker
1291*cc02d7e2SAndroid Build Coastguard Workerdef _check_arch_option(arch):
1292*cc02d7e2SAndroid Build Coastguard Worker    """Checks that architecture option is valid."""
1293*cc02d7e2SAndroid Build Coastguard Worker    if platform_string() == "windows":
1294*cc02d7e2SAndroid Build Coastguard Worker        _windows_arch_option(arch)
1295*cc02d7e2SAndroid Build Coastguard Worker    elif platform_string() == "linux":
1296*cc02d7e2SAndroid Build Coastguard Worker        # On linux, we need to be running under docker with the right architecture.
1297*cc02d7e2SAndroid Build Coastguard Worker        runtime_machine = platform.machine()
1298*cc02d7e2SAndroid Build Coastguard Worker        runtime_arch = platform.architecture()[0]
1299*cc02d7e2SAndroid Build Coastguard Worker        if arch == "default":
1300*cc02d7e2SAndroid Build Coastguard Worker            return
1301*cc02d7e2SAndroid Build Coastguard Worker        elif (
1302*cc02d7e2SAndroid Build Coastguard Worker            runtime_machine == "x86_64"
1303*cc02d7e2SAndroid Build Coastguard Worker            and runtime_arch == "64bit"
1304*cc02d7e2SAndroid Build Coastguard Worker            and arch == "x64"
1305*cc02d7e2SAndroid Build Coastguard Worker        ):
1306*cc02d7e2SAndroid Build Coastguard Worker            return
1307*cc02d7e2SAndroid Build Coastguard Worker        elif (
1308*cc02d7e2SAndroid Build Coastguard Worker            runtime_machine == "x86_64"
1309*cc02d7e2SAndroid Build Coastguard Worker            and runtime_arch == "32bit"
1310*cc02d7e2SAndroid Build Coastguard Worker            and arch == "x86"
1311*cc02d7e2SAndroid Build Coastguard Worker        ):
1312*cc02d7e2SAndroid Build Coastguard Worker            return
1313*cc02d7e2SAndroid Build Coastguard Worker        elif (
1314*cc02d7e2SAndroid Build Coastguard Worker            runtime_machine == "aarch64"
1315*cc02d7e2SAndroid Build Coastguard Worker            and runtime_arch == "64bit"
1316*cc02d7e2SAndroid Build Coastguard Worker            and arch == "arm64"
1317*cc02d7e2SAndroid Build Coastguard Worker        ):
1318*cc02d7e2SAndroid Build Coastguard Worker            return
1319*cc02d7e2SAndroid Build Coastguard Worker        else:
1320*cc02d7e2SAndroid Build Coastguard Worker            print(
1321*cc02d7e2SAndroid Build Coastguard Worker                "Architecture %s does not match current runtime architecture."
1322*cc02d7e2SAndroid Build Coastguard Worker                % arch
1323*cc02d7e2SAndroid Build Coastguard Worker            )
1324*cc02d7e2SAndroid Build Coastguard Worker            sys.exit(1)
1325*cc02d7e2SAndroid Build Coastguard Worker    else:
1326*cc02d7e2SAndroid Build Coastguard Worker        if args.arch != "default":
1327*cc02d7e2SAndroid Build Coastguard Worker            print(
1328*cc02d7e2SAndroid Build Coastguard Worker                "Architecture %s not supported on current platform." % args.arch
1329*cc02d7e2SAndroid Build Coastguard Worker            )
1330*cc02d7e2SAndroid Build Coastguard Worker            sys.exit(1)
1331*cc02d7e2SAndroid Build Coastguard Worker
1332*cc02d7e2SAndroid Build Coastguard Worker
1333*cc02d7e2SAndroid Build Coastguard Workerdef _docker_arch_suffix(arch):
1334*cc02d7e2SAndroid Build Coastguard Worker    """Returns suffix to dockerfile dir to use."""
1335*cc02d7e2SAndroid Build Coastguard Worker    if arch == "default" or arch == "x64":
1336*cc02d7e2SAndroid Build Coastguard Worker        return "x64"
1337*cc02d7e2SAndroid Build Coastguard Worker    elif arch == "x86":
1338*cc02d7e2SAndroid Build Coastguard Worker        return "x86"
1339*cc02d7e2SAndroid Build Coastguard Worker    elif arch == "arm64":
1340*cc02d7e2SAndroid Build Coastguard Worker        return "arm64"
1341*cc02d7e2SAndroid Build Coastguard Worker    else:
1342*cc02d7e2SAndroid Build Coastguard Worker        print("Architecture %s not supported with current settings." % arch)
1343*cc02d7e2SAndroid Build Coastguard Worker        sys.exit(1)
1344*cc02d7e2SAndroid Build Coastguard Worker
1345*cc02d7e2SAndroid Build Coastguard Worker
1346*cc02d7e2SAndroid Build Coastguard Workerdef runs_per_test_type(arg_str):
1347*cc02d7e2SAndroid Build Coastguard Worker    """Auxiliary function to parse the "runs_per_test" flag.
1348*cc02d7e2SAndroid Build Coastguard Worker
1349*cc02d7e2SAndroid Build Coastguard Worker    Returns:
1350*cc02d7e2SAndroid Build Coastguard Worker        A positive integer or 0, the latter indicating an infinite number of
1351*cc02d7e2SAndroid Build Coastguard Worker        runs.
1352*cc02d7e2SAndroid Build Coastguard Worker
1353*cc02d7e2SAndroid Build Coastguard Worker    Raises:
1354*cc02d7e2SAndroid Build Coastguard Worker        argparse.ArgumentTypeError: Upon invalid input.
1355*cc02d7e2SAndroid Build Coastguard Worker    """
1356*cc02d7e2SAndroid Build Coastguard Worker    if arg_str == "inf":
1357*cc02d7e2SAndroid Build Coastguard Worker        return 0
1358*cc02d7e2SAndroid Build Coastguard Worker    try:
1359*cc02d7e2SAndroid Build Coastguard Worker        n = int(arg_str)
1360*cc02d7e2SAndroid Build Coastguard Worker        if n <= 0:
1361*cc02d7e2SAndroid Build Coastguard Worker            raise ValueError
1362*cc02d7e2SAndroid Build Coastguard Worker        return n
1363*cc02d7e2SAndroid Build Coastguard Worker    except:
1364*cc02d7e2SAndroid Build Coastguard Worker        msg = "'{}' is not a positive integer or 'inf'".format(arg_str)
1365*cc02d7e2SAndroid Build Coastguard Worker        raise argparse.ArgumentTypeError(msg)
1366*cc02d7e2SAndroid Build Coastguard Worker
1367*cc02d7e2SAndroid Build Coastguard Worker
1368*cc02d7e2SAndroid Build Coastguard Workerdef percent_type(arg_str):
1369*cc02d7e2SAndroid Build Coastguard Worker    pct = float(arg_str)
1370*cc02d7e2SAndroid Build Coastguard Worker    if pct > 100 or pct < 0:
1371*cc02d7e2SAndroid Build Coastguard Worker        raise argparse.ArgumentTypeError(
1372*cc02d7e2SAndroid Build Coastguard Worker            "'%f' is not a valid percentage in the [0, 100] range" % pct
1373*cc02d7e2SAndroid Build Coastguard Worker        )
1374*cc02d7e2SAndroid Build Coastguard Worker    return pct
1375*cc02d7e2SAndroid Build Coastguard Worker
1376*cc02d7e2SAndroid Build Coastguard Worker
1377*cc02d7e2SAndroid Build Coastguard Worker# This is math.isclose in python >= 3.5
1378*cc02d7e2SAndroid Build Coastguard Workerdef isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
1379*cc02d7e2SAndroid Build Coastguard Worker    return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
1380*cc02d7e2SAndroid Build Coastguard Worker
1381*cc02d7e2SAndroid Build Coastguard Worker
1382*cc02d7e2SAndroid Build Coastguard Workerdef _shut_down_legacy_server(legacy_server_port):
1383*cc02d7e2SAndroid Build Coastguard Worker    """Shut down legacy version of port server."""
1384*cc02d7e2SAndroid Build Coastguard Worker    try:
1385*cc02d7e2SAndroid Build Coastguard Worker        version = int(
1386*cc02d7e2SAndroid Build Coastguard Worker            urllib.request.urlopen(
1387*cc02d7e2SAndroid Build Coastguard Worker                "http://localhost:%d/version_number" % legacy_server_port,
1388*cc02d7e2SAndroid Build Coastguard Worker                timeout=10,
1389*cc02d7e2SAndroid Build Coastguard Worker            ).read()
1390*cc02d7e2SAndroid Build Coastguard Worker        )
1391*cc02d7e2SAndroid Build Coastguard Worker    except:
1392*cc02d7e2SAndroid Build Coastguard Worker        pass
1393*cc02d7e2SAndroid Build Coastguard Worker    else:
1394*cc02d7e2SAndroid Build Coastguard Worker        urllib.request.urlopen(
1395*cc02d7e2SAndroid Build Coastguard Worker            "http://localhost:%d/quitquitquit" % legacy_server_port
1396*cc02d7e2SAndroid Build Coastguard Worker        ).read()
1397*cc02d7e2SAndroid Build Coastguard Worker
1398*cc02d7e2SAndroid Build Coastguard Worker
1399*cc02d7e2SAndroid Build Coastguard Workerdef _calculate_num_runs_failures(list_of_results):
1400*cc02d7e2SAndroid Build Coastguard Worker    """Calculate number of runs and failures for a particular test.
1401*cc02d7e2SAndroid Build Coastguard Worker
1402*cc02d7e2SAndroid Build Coastguard Worker    Args:
1403*cc02d7e2SAndroid Build Coastguard Worker      list_of_results: (List) of JobResult object.
1404*cc02d7e2SAndroid Build Coastguard Worker    Returns:
1405*cc02d7e2SAndroid Build Coastguard Worker      A tuple of total number of runs and failures.
1406*cc02d7e2SAndroid Build Coastguard Worker    """
1407*cc02d7e2SAndroid Build Coastguard Worker    num_runs = len(list_of_results)  # By default, there is 1 run per JobResult.
1408*cc02d7e2SAndroid Build Coastguard Worker    num_failures = 0
1409*cc02d7e2SAndroid Build Coastguard Worker    for jobresult in list_of_results:
1410*cc02d7e2SAndroid Build Coastguard Worker        if jobresult.retries > 0:
1411*cc02d7e2SAndroid Build Coastguard Worker            num_runs += jobresult.retries
1412*cc02d7e2SAndroid Build Coastguard Worker        if jobresult.num_failures > 0:
1413*cc02d7e2SAndroid Build Coastguard Worker            num_failures += jobresult.num_failures
1414*cc02d7e2SAndroid Build Coastguard Worker    return num_runs, num_failures
1415*cc02d7e2SAndroid Build Coastguard Worker
1416*cc02d7e2SAndroid Build Coastguard Worker
1417*cc02d7e2SAndroid Build Coastguard Workerclass BuildAndRunError(object):
1418*cc02d7e2SAndroid Build Coastguard Worker    """Represents error type in _build_and_run."""
1419*cc02d7e2SAndroid Build Coastguard Worker
1420*cc02d7e2SAndroid Build Coastguard Worker    BUILD = object()
1421*cc02d7e2SAndroid Build Coastguard Worker    TEST = object()
1422*cc02d7e2SAndroid Build Coastguard Worker    POST_TEST = object()
1423*cc02d7e2SAndroid Build Coastguard Worker
1424*cc02d7e2SAndroid Build Coastguard Worker
1425*cc02d7e2SAndroid Build Coastguard Worker# returns a list of things that failed (or an empty list on success)
1426*cc02d7e2SAndroid Build Coastguard Workerdef _build_and_run(
1427*cc02d7e2SAndroid Build Coastguard Worker    check_cancelled, newline_on_success, xml_report=None, build_only=False
1428*cc02d7e2SAndroid Build Coastguard Worker):
1429*cc02d7e2SAndroid Build Coastguard Worker    """Do one pass of building & running tests."""
1430*cc02d7e2SAndroid Build Coastguard Worker    # build latest sequentially
1431*cc02d7e2SAndroid Build Coastguard Worker    num_failures, resultset = jobset.run(
1432*cc02d7e2SAndroid Build Coastguard Worker        build_steps,
1433*cc02d7e2SAndroid Build Coastguard Worker        maxjobs=1,
1434*cc02d7e2SAndroid Build Coastguard Worker        stop_on_failure=True,
1435*cc02d7e2SAndroid Build Coastguard Worker        newline_on_success=newline_on_success,
1436*cc02d7e2SAndroid Build Coastguard Worker        travis=args.travis,
1437*cc02d7e2SAndroid Build Coastguard Worker    )
1438*cc02d7e2SAndroid Build Coastguard Worker    if num_failures:
1439*cc02d7e2SAndroid Build Coastguard Worker        return [BuildAndRunError.BUILD]
1440*cc02d7e2SAndroid Build Coastguard Worker
1441*cc02d7e2SAndroid Build Coastguard Worker    if build_only:
1442*cc02d7e2SAndroid Build Coastguard Worker        if xml_report:
1443*cc02d7e2SAndroid Build Coastguard Worker            report_utils.render_junit_xml_report(
1444*cc02d7e2SAndroid Build Coastguard Worker                resultset, xml_report, suite_name=args.report_suite_name
1445*cc02d7e2SAndroid Build Coastguard Worker            )
1446*cc02d7e2SAndroid Build Coastguard Worker        return []
1447*cc02d7e2SAndroid Build Coastguard Worker
1448*cc02d7e2SAndroid Build Coastguard Worker    # start antagonists
1449*cc02d7e2SAndroid Build Coastguard Worker    antagonists = [
1450*cc02d7e2SAndroid Build Coastguard Worker        subprocess.Popen(["tools/run_tests/python_utils/antagonist.py"])
1451*cc02d7e2SAndroid Build Coastguard Worker        for _ in range(0, args.antagonists)
1452*cc02d7e2SAndroid Build Coastguard Worker    ]
1453*cc02d7e2SAndroid Build Coastguard Worker    start_port_server.start_port_server()
1454*cc02d7e2SAndroid Build Coastguard Worker    resultset = None
1455*cc02d7e2SAndroid Build Coastguard Worker    num_test_failures = 0
1456*cc02d7e2SAndroid Build Coastguard Worker    try:
1457*cc02d7e2SAndroid Build Coastguard Worker        infinite_runs = runs_per_test == 0
1458*cc02d7e2SAndroid Build Coastguard Worker        one_run = set(
1459*cc02d7e2SAndroid Build Coastguard Worker            spec
1460*cc02d7e2SAndroid Build Coastguard Worker            for language in languages
1461*cc02d7e2SAndroid Build Coastguard Worker            for spec in language.test_specs()
1462*cc02d7e2SAndroid Build Coastguard Worker            if (
1463*cc02d7e2SAndroid Build Coastguard Worker                re.search(args.regex, spec.shortname)
1464*cc02d7e2SAndroid Build Coastguard Worker                and (
1465*cc02d7e2SAndroid Build Coastguard Worker                    args.regex_exclude == ""
1466*cc02d7e2SAndroid Build Coastguard Worker                    or not re.search(args.regex_exclude, spec.shortname)
1467*cc02d7e2SAndroid Build Coastguard Worker                )
1468*cc02d7e2SAndroid Build Coastguard Worker            )
1469*cc02d7e2SAndroid Build Coastguard Worker        )
1470*cc02d7e2SAndroid Build Coastguard Worker        # When running on travis, we want out test runs to be as similar as possible
1471*cc02d7e2SAndroid Build Coastguard Worker        # for reproducibility purposes.
1472*cc02d7e2SAndroid Build Coastguard Worker        if args.travis and args.max_time <= 0:
1473*cc02d7e2SAndroid Build Coastguard Worker            massaged_one_run = sorted(one_run, key=lambda x: x.cpu_cost)
1474*cc02d7e2SAndroid Build Coastguard Worker        else:
1475*cc02d7e2SAndroid Build Coastguard Worker            # whereas otherwise, we want to shuffle things up to give all tests a
1476*cc02d7e2SAndroid Build Coastguard Worker            # chance to run.
1477*cc02d7e2SAndroid Build Coastguard Worker            massaged_one_run = list(
1478*cc02d7e2SAndroid Build Coastguard Worker                one_run
1479*cc02d7e2SAndroid Build Coastguard Worker            )  # random.sample needs an indexable seq.
1480*cc02d7e2SAndroid Build Coastguard Worker            num_jobs = len(massaged_one_run)
1481*cc02d7e2SAndroid Build Coastguard Worker            # for a random sample, get as many as indicated by the 'sample_percent'
1482*cc02d7e2SAndroid Build Coastguard Worker            # argument. By default this arg is 100, resulting in a shuffle of all
1483*cc02d7e2SAndroid Build Coastguard Worker            # jobs.
1484*cc02d7e2SAndroid Build Coastguard Worker            sample_size = int(num_jobs * args.sample_percent / 100.0)
1485*cc02d7e2SAndroid Build Coastguard Worker            massaged_one_run = random.sample(massaged_one_run, sample_size)
1486*cc02d7e2SAndroid Build Coastguard Worker            if not isclose(args.sample_percent, 100.0):
1487*cc02d7e2SAndroid Build Coastguard Worker                assert (
1488*cc02d7e2SAndroid Build Coastguard Worker                    args.runs_per_test == 1
1489*cc02d7e2SAndroid Build Coastguard Worker                ), "Can't do sampling (-p) over multiple runs (-n)."
1490*cc02d7e2SAndroid Build Coastguard Worker                print(
1491*cc02d7e2SAndroid Build Coastguard Worker                    "Running %d tests out of %d (~%d%%)"
1492*cc02d7e2SAndroid Build Coastguard Worker                    % (sample_size, num_jobs, args.sample_percent)
1493*cc02d7e2SAndroid Build Coastguard Worker                )
1494*cc02d7e2SAndroid Build Coastguard Worker        if infinite_runs:
1495*cc02d7e2SAndroid Build Coastguard Worker            assert (
1496*cc02d7e2SAndroid Build Coastguard Worker                len(massaged_one_run) > 0
1497*cc02d7e2SAndroid Build Coastguard Worker            ), "Must have at least one test for a -n inf run"
1498*cc02d7e2SAndroid Build Coastguard Worker        runs_sequence = (
1499*cc02d7e2SAndroid Build Coastguard Worker            itertools.repeat(massaged_one_run)
1500*cc02d7e2SAndroid Build Coastguard Worker            if infinite_runs
1501*cc02d7e2SAndroid Build Coastguard Worker            else itertools.repeat(massaged_one_run, runs_per_test)
1502*cc02d7e2SAndroid Build Coastguard Worker        )
1503*cc02d7e2SAndroid Build Coastguard Worker        all_runs = itertools.chain.from_iterable(runs_sequence)
1504*cc02d7e2SAndroid Build Coastguard Worker
1505*cc02d7e2SAndroid Build Coastguard Worker        if args.quiet_success:
1506*cc02d7e2SAndroid Build Coastguard Worker            jobset.message(
1507*cc02d7e2SAndroid Build Coastguard Worker                "START",
1508*cc02d7e2SAndroid Build Coastguard Worker                "Running tests quietly, only failing tests will be reported",
1509*cc02d7e2SAndroid Build Coastguard Worker                do_newline=True,
1510*cc02d7e2SAndroid Build Coastguard Worker            )
1511*cc02d7e2SAndroid Build Coastguard Worker        num_test_failures, resultset = jobset.run(
1512*cc02d7e2SAndroid Build Coastguard Worker            all_runs,
1513*cc02d7e2SAndroid Build Coastguard Worker            check_cancelled,
1514*cc02d7e2SAndroid Build Coastguard Worker            newline_on_success=newline_on_success,
1515*cc02d7e2SAndroid Build Coastguard Worker            travis=args.travis,
1516*cc02d7e2SAndroid Build Coastguard Worker            maxjobs=args.jobs,
1517*cc02d7e2SAndroid Build Coastguard Worker            maxjobs_cpu_agnostic=max_parallel_tests_for_current_platform(),
1518*cc02d7e2SAndroid Build Coastguard Worker            stop_on_failure=args.stop_on_failure,
1519*cc02d7e2SAndroid Build Coastguard Worker            quiet_success=args.quiet_success,
1520*cc02d7e2SAndroid Build Coastguard Worker            max_time=args.max_time,
1521*cc02d7e2SAndroid Build Coastguard Worker        )
1522*cc02d7e2SAndroid Build Coastguard Worker        if resultset:
1523*cc02d7e2SAndroid Build Coastguard Worker            for k, v in sorted(resultset.items()):
1524*cc02d7e2SAndroid Build Coastguard Worker                num_runs, num_failures = _calculate_num_runs_failures(v)
1525*cc02d7e2SAndroid Build Coastguard Worker                if num_failures > 0:
1526*cc02d7e2SAndroid Build Coastguard Worker                    if num_failures == num_runs:  # what about infinite_runs???
1527*cc02d7e2SAndroid Build Coastguard Worker                        jobset.message("FAILED", k, do_newline=True)
1528*cc02d7e2SAndroid Build Coastguard Worker                    else:
1529*cc02d7e2SAndroid Build Coastguard Worker                        jobset.message(
1530*cc02d7e2SAndroid Build Coastguard Worker                            "FLAKE",
1531*cc02d7e2SAndroid Build Coastguard Worker                            "%s [%d/%d runs flaked]"
1532*cc02d7e2SAndroid Build Coastguard Worker                            % (k, num_failures, num_runs),
1533*cc02d7e2SAndroid Build Coastguard Worker                            do_newline=True,
1534*cc02d7e2SAndroid Build Coastguard Worker                        )
1535*cc02d7e2SAndroid Build Coastguard Worker    finally:
1536*cc02d7e2SAndroid Build Coastguard Worker        for antagonist in antagonists:
1537*cc02d7e2SAndroid Build Coastguard Worker            antagonist.kill()
1538*cc02d7e2SAndroid Build Coastguard Worker        if args.bq_result_table and resultset:
1539*cc02d7e2SAndroid Build Coastguard Worker            upload_extra_fields = {
1540*cc02d7e2SAndroid Build Coastguard Worker                "compiler": args.compiler,
1541*cc02d7e2SAndroid Build Coastguard Worker                "config": args.config,
1542*cc02d7e2SAndroid Build Coastguard Worker                "iomgr_platform": args.iomgr_platform,
1543*cc02d7e2SAndroid Build Coastguard Worker                "language": args.language[
1544*cc02d7e2SAndroid Build Coastguard Worker                    0
1545*cc02d7e2SAndroid Build Coastguard Worker                ],  # args.language is a list but will always have one element when uploading to BQ is enabled.
1546*cc02d7e2SAndroid Build Coastguard Worker                "platform": platform_string(),
1547*cc02d7e2SAndroid Build Coastguard Worker            }
1548*cc02d7e2SAndroid Build Coastguard Worker            try:
1549*cc02d7e2SAndroid Build Coastguard Worker                upload_results_to_bq(
1550*cc02d7e2SAndroid Build Coastguard Worker                    resultset, args.bq_result_table, upload_extra_fields
1551*cc02d7e2SAndroid Build Coastguard Worker                )
1552*cc02d7e2SAndroid Build Coastguard Worker            except NameError as e:
1553*cc02d7e2SAndroid Build Coastguard Worker                logging.warning(
1554*cc02d7e2SAndroid Build Coastguard Worker                    e
1555*cc02d7e2SAndroid Build Coastguard Worker                )  # It's fine to ignore since this is not critical
1556*cc02d7e2SAndroid Build Coastguard Worker        if xml_report and resultset:
1557*cc02d7e2SAndroid Build Coastguard Worker            report_utils.render_junit_xml_report(
1558*cc02d7e2SAndroid Build Coastguard Worker                resultset,
1559*cc02d7e2SAndroid Build Coastguard Worker                xml_report,
1560*cc02d7e2SAndroid Build Coastguard Worker                suite_name=args.report_suite_name,
1561*cc02d7e2SAndroid Build Coastguard Worker                multi_target=args.report_multi_target,
1562*cc02d7e2SAndroid Build Coastguard Worker            )
1563*cc02d7e2SAndroid Build Coastguard Worker
1564*cc02d7e2SAndroid Build Coastguard Worker    number_failures, _ = jobset.run(
1565*cc02d7e2SAndroid Build Coastguard Worker        post_tests_steps,
1566*cc02d7e2SAndroid Build Coastguard Worker        maxjobs=1,
1567*cc02d7e2SAndroid Build Coastguard Worker        stop_on_failure=False,
1568*cc02d7e2SAndroid Build Coastguard Worker        newline_on_success=newline_on_success,
1569*cc02d7e2SAndroid Build Coastguard Worker        travis=args.travis,
1570*cc02d7e2SAndroid Build Coastguard Worker    )
1571*cc02d7e2SAndroid Build Coastguard Worker
1572*cc02d7e2SAndroid Build Coastguard Worker    out = []
1573*cc02d7e2SAndroid Build Coastguard Worker    if number_failures:
1574*cc02d7e2SAndroid Build Coastguard Worker        out.append(BuildAndRunError.POST_TEST)
1575*cc02d7e2SAndroid Build Coastguard Worker    if num_test_failures:
1576*cc02d7e2SAndroid Build Coastguard Worker        out.append(BuildAndRunError.TEST)
1577*cc02d7e2SAndroid Build Coastguard Worker
1578*cc02d7e2SAndroid Build Coastguard Worker    return out
1579*cc02d7e2SAndroid Build Coastguard Worker
1580*cc02d7e2SAndroid Build Coastguard Worker
1581*cc02d7e2SAndroid Build Coastguard Worker# parse command line
1582*cc02d7e2SAndroid Build Coastguard Workerargp = argparse.ArgumentParser(description="Run grpc tests.")
1583*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1584*cc02d7e2SAndroid Build Coastguard Worker    "-c", "--config", choices=sorted(_CONFIGS.keys()), default="opt"
1585*cc02d7e2SAndroid Build Coastguard Worker)
1586*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1587*cc02d7e2SAndroid Build Coastguard Worker    "-n",
1588*cc02d7e2SAndroid Build Coastguard Worker    "--runs_per_test",
1589*cc02d7e2SAndroid Build Coastguard Worker    default=1,
1590*cc02d7e2SAndroid Build Coastguard Worker    type=runs_per_test_type,
1591*cc02d7e2SAndroid Build Coastguard Worker    help=(
1592*cc02d7e2SAndroid Build Coastguard Worker        'A positive integer or "inf". If "inf", all tests will run in an '
1593*cc02d7e2SAndroid Build Coastguard Worker        'infinite loop. Especially useful in combination with "-f"'
1594*cc02d7e2SAndroid Build Coastguard Worker    ),
1595*cc02d7e2SAndroid Build Coastguard Worker)
1596*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("-r", "--regex", default=".*", type=str)
1597*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("--regex_exclude", default="", type=str)
1598*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("-j", "--jobs", default=multiprocessing.cpu_count(), type=int)
1599*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("-s", "--slowdown", default=1.0, type=float)
1600*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1601*cc02d7e2SAndroid Build Coastguard Worker    "-p",
1602*cc02d7e2SAndroid Build Coastguard Worker    "--sample_percent",
1603*cc02d7e2SAndroid Build Coastguard Worker    default=100.0,
1604*cc02d7e2SAndroid Build Coastguard Worker    type=percent_type,
1605*cc02d7e2SAndroid Build Coastguard Worker    help="Run a random sample with that percentage of tests",
1606*cc02d7e2SAndroid Build Coastguard Worker)
1607*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1608*cc02d7e2SAndroid Build Coastguard Worker    "-t",
1609*cc02d7e2SAndroid Build Coastguard Worker    "--travis",
1610*cc02d7e2SAndroid Build Coastguard Worker    default=False,
1611*cc02d7e2SAndroid Build Coastguard Worker    action="store_const",
1612*cc02d7e2SAndroid Build Coastguard Worker    const=True,
1613*cc02d7e2SAndroid Build Coastguard Worker    help=(
1614*cc02d7e2SAndroid Build Coastguard Worker        "When set, indicates that the script is running on CI (= not locally)."
1615*cc02d7e2SAndroid Build Coastguard Worker    ),
1616*cc02d7e2SAndroid Build Coastguard Worker)
1617*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1618*cc02d7e2SAndroid Build Coastguard Worker    "--newline_on_success", default=False, action="store_const", const=True
1619*cc02d7e2SAndroid Build Coastguard Worker)
1620*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1621*cc02d7e2SAndroid Build Coastguard Worker    "-l",
1622*cc02d7e2SAndroid Build Coastguard Worker    "--language",
1623*cc02d7e2SAndroid Build Coastguard Worker    choices=sorted(_LANGUAGES.keys()),
1624*cc02d7e2SAndroid Build Coastguard Worker    nargs="+",
1625*cc02d7e2SAndroid Build Coastguard Worker    required=True,
1626*cc02d7e2SAndroid Build Coastguard Worker)
1627*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1628*cc02d7e2SAndroid Build Coastguard Worker    "-S", "--stop_on_failure", default=False, action="store_const", const=True
1629*cc02d7e2SAndroid Build Coastguard Worker)
1630*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1631*cc02d7e2SAndroid Build Coastguard Worker    "--use_docker",
1632*cc02d7e2SAndroid Build Coastguard Worker    default=False,
1633*cc02d7e2SAndroid Build Coastguard Worker    action="store_const",
1634*cc02d7e2SAndroid Build Coastguard Worker    const=True,
1635*cc02d7e2SAndroid Build Coastguard Worker    help="Run all the tests under docker. That provides "
1636*cc02d7e2SAndroid Build Coastguard Worker    + "additional isolation and prevents the need to install "
1637*cc02d7e2SAndroid Build Coastguard Worker    + "language specific prerequisites. Only available on Linux.",
1638*cc02d7e2SAndroid Build Coastguard Worker)
1639*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1640*cc02d7e2SAndroid Build Coastguard Worker    "--allow_flakes",
1641*cc02d7e2SAndroid Build Coastguard Worker    default=False,
1642*cc02d7e2SAndroid Build Coastguard Worker    action="store_const",
1643*cc02d7e2SAndroid Build Coastguard Worker    const=True,
1644*cc02d7e2SAndroid Build Coastguard Worker    help=(
1645*cc02d7e2SAndroid Build Coastguard Worker        "Allow flaky tests to show as passing (re-runs failed tests up to five"
1646*cc02d7e2SAndroid Build Coastguard Worker        " times)"
1647*cc02d7e2SAndroid Build Coastguard Worker    ),
1648*cc02d7e2SAndroid Build Coastguard Worker)
1649*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1650*cc02d7e2SAndroid Build Coastguard Worker    "--arch",
1651*cc02d7e2SAndroid Build Coastguard Worker    choices=["default", "x86", "x64", "arm64"],
1652*cc02d7e2SAndroid Build Coastguard Worker    default="default",
1653*cc02d7e2SAndroid Build Coastguard Worker    help=(
1654*cc02d7e2SAndroid Build Coastguard Worker        'Selects architecture to target. For some platforms "default" is the'
1655*cc02d7e2SAndroid Build Coastguard Worker        " only supported choice."
1656*cc02d7e2SAndroid Build Coastguard Worker    ),
1657*cc02d7e2SAndroid Build Coastguard Worker)
1658*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1659*cc02d7e2SAndroid Build Coastguard Worker    "--compiler",
1660*cc02d7e2SAndroid Build Coastguard Worker    choices=[
1661*cc02d7e2SAndroid Build Coastguard Worker        "default",
1662*cc02d7e2SAndroid Build Coastguard Worker        "gcc8",
1663*cc02d7e2SAndroid Build Coastguard Worker        "gcc10.2",
1664*cc02d7e2SAndroid Build Coastguard Worker        "gcc10.2_openssl102",
1665*cc02d7e2SAndroid Build Coastguard Worker        "gcc10.2_openssl111",
1666*cc02d7e2SAndroid Build Coastguard Worker        "gcc12",
1667*cc02d7e2SAndroid Build Coastguard Worker        "gcc12_openssl309",
1668*cc02d7e2SAndroid Build Coastguard Worker        "gcc_musl",
1669*cc02d7e2SAndroid Build Coastguard Worker        "clang6",
1670*cc02d7e2SAndroid Build Coastguard Worker        "clang17",
1671*cc02d7e2SAndroid Build Coastguard Worker        # TODO: Automatically populate from supported version
1672*cc02d7e2SAndroid Build Coastguard Worker        "python3.7",
1673*cc02d7e2SAndroid Build Coastguard Worker        "python3.8",
1674*cc02d7e2SAndroid Build Coastguard Worker        "python3.9",
1675*cc02d7e2SAndroid Build Coastguard Worker        "python3.10",
1676*cc02d7e2SAndroid Build Coastguard Worker        "python3.11",
1677*cc02d7e2SAndroid Build Coastguard Worker        "python3.12",
1678*cc02d7e2SAndroid Build Coastguard Worker        "pypy",
1679*cc02d7e2SAndroid Build Coastguard Worker        "pypy3",
1680*cc02d7e2SAndroid Build Coastguard Worker        "python_alpine",
1681*cc02d7e2SAndroid Build Coastguard Worker        "all_the_cpythons",
1682*cc02d7e2SAndroid Build Coastguard Worker        "coreclr",
1683*cc02d7e2SAndroid Build Coastguard Worker        "cmake",
1684*cc02d7e2SAndroid Build Coastguard Worker        "cmake_ninja_vs2019",
1685*cc02d7e2SAndroid Build Coastguard Worker        "cmake_ninja_vs2022",
1686*cc02d7e2SAndroid Build Coastguard Worker        "cmake_vs2019",
1687*cc02d7e2SAndroid Build Coastguard Worker        "cmake_vs2022",
1688*cc02d7e2SAndroid Build Coastguard Worker        "mono",
1689*cc02d7e2SAndroid Build Coastguard Worker    ],
1690*cc02d7e2SAndroid Build Coastguard Worker    default="default",
1691*cc02d7e2SAndroid Build Coastguard Worker    help=(
1692*cc02d7e2SAndroid Build Coastguard Worker        "Selects compiler to use. Allowed values depend on the platform and"
1693*cc02d7e2SAndroid Build Coastguard Worker        " language."
1694*cc02d7e2SAndroid Build Coastguard Worker    ),
1695*cc02d7e2SAndroid Build Coastguard Worker)
1696*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1697*cc02d7e2SAndroid Build Coastguard Worker    "--iomgr_platform",
1698*cc02d7e2SAndroid Build Coastguard Worker    choices=["native", "gevent", "asyncio"],
1699*cc02d7e2SAndroid Build Coastguard Worker    default="native",
1700*cc02d7e2SAndroid Build Coastguard Worker    help="Selects iomgr platform to build on",
1701*cc02d7e2SAndroid Build Coastguard Worker)
1702*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1703*cc02d7e2SAndroid Build Coastguard Worker    "--build_only",
1704*cc02d7e2SAndroid Build Coastguard Worker    default=False,
1705*cc02d7e2SAndroid Build Coastguard Worker    action="store_const",
1706*cc02d7e2SAndroid Build Coastguard Worker    const=True,
1707*cc02d7e2SAndroid Build Coastguard Worker    help="Perform all the build steps but don't run any tests.",
1708*cc02d7e2SAndroid Build Coastguard Worker)
1709*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1710*cc02d7e2SAndroid Build Coastguard Worker    "--measure_cpu_costs",
1711*cc02d7e2SAndroid Build Coastguard Worker    default=False,
1712*cc02d7e2SAndroid Build Coastguard Worker    action="store_const",
1713*cc02d7e2SAndroid Build Coastguard Worker    const=True,
1714*cc02d7e2SAndroid Build Coastguard Worker    help="Measure the cpu costs of tests",
1715*cc02d7e2SAndroid Build Coastguard Worker)
1716*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("-a", "--antagonists", default=0, type=int)
1717*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1718*cc02d7e2SAndroid Build Coastguard Worker    "-x",
1719*cc02d7e2SAndroid Build Coastguard Worker    "--xml_report",
1720*cc02d7e2SAndroid Build Coastguard Worker    default=None,
1721*cc02d7e2SAndroid Build Coastguard Worker    type=str,
1722*cc02d7e2SAndroid Build Coastguard Worker    help="Generates a JUnit-compatible XML report",
1723*cc02d7e2SAndroid Build Coastguard Worker)
1724*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1725*cc02d7e2SAndroid Build Coastguard Worker    "--report_suite_name",
1726*cc02d7e2SAndroid Build Coastguard Worker    default="tests",
1727*cc02d7e2SAndroid Build Coastguard Worker    type=str,
1728*cc02d7e2SAndroid Build Coastguard Worker    help="Test suite name to use in generated JUnit XML report",
1729*cc02d7e2SAndroid Build Coastguard Worker)
1730*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1731*cc02d7e2SAndroid Build Coastguard Worker    "--report_multi_target",
1732*cc02d7e2SAndroid Build Coastguard Worker    default=False,
1733*cc02d7e2SAndroid Build Coastguard Worker    const=True,
1734*cc02d7e2SAndroid Build Coastguard Worker    action="store_const",
1735*cc02d7e2SAndroid Build Coastguard Worker    help=(
1736*cc02d7e2SAndroid Build Coastguard Worker        "Generate separate XML report for each test job (Looks better in UIs)."
1737*cc02d7e2SAndroid Build Coastguard Worker    ),
1738*cc02d7e2SAndroid Build Coastguard Worker)
1739*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1740*cc02d7e2SAndroid Build Coastguard Worker    "--quiet_success",
1741*cc02d7e2SAndroid Build Coastguard Worker    default=False,
1742*cc02d7e2SAndroid Build Coastguard Worker    action="store_const",
1743*cc02d7e2SAndroid Build Coastguard Worker    const=True,
1744*cc02d7e2SAndroid Build Coastguard Worker    help=(
1745*cc02d7e2SAndroid Build Coastguard Worker        "Don't print anything when a test passes. Passing tests also will not"
1746*cc02d7e2SAndroid Build Coastguard Worker        " be reported in XML report. "
1747*cc02d7e2SAndroid Build Coastguard Worker    )
1748*cc02d7e2SAndroid Build Coastguard Worker    + "Useful when running many iterations of each test (argument -n).",
1749*cc02d7e2SAndroid Build Coastguard Worker)
1750*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1751*cc02d7e2SAndroid Build Coastguard Worker    "--force_default_poller",
1752*cc02d7e2SAndroid Build Coastguard Worker    default=False,
1753*cc02d7e2SAndroid Build Coastguard Worker    action="store_const",
1754*cc02d7e2SAndroid Build Coastguard Worker    const=True,
1755*cc02d7e2SAndroid Build Coastguard Worker    help="Don't try to iterate over many polling strategies when they exist",
1756*cc02d7e2SAndroid Build Coastguard Worker)
1757*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1758*cc02d7e2SAndroid Build Coastguard Worker    "--force_use_pollers",
1759*cc02d7e2SAndroid Build Coastguard Worker    default=None,
1760*cc02d7e2SAndroid Build Coastguard Worker    type=str,
1761*cc02d7e2SAndroid Build Coastguard Worker    help=(
1762*cc02d7e2SAndroid Build Coastguard Worker        "Only use the specified comma-delimited list of polling engines. "
1763*cc02d7e2SAndroid Build Coastguard Worker        "Example: --force_use_pollers epoll1,poll "
1764*cc02d7e2SAndroid Build Coastguard Worker        " (This flag has no effect if --force_default_poller flag is also used)"
1765*cc02d7e2SAndroid Build Coastguard Worker    ),
1766*cc02d7e2SAndroid Build Coastguard Worker)
1767*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1768*cc02d7e2SAndroid Build Coastguard Worker    "--max_time", default=-1, type=int, help="Maximum test runtime in seconds"
1769*cc02d7e2SAndroid Build Coastguard Worker)
1770*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1771*cc02d7e2SAndroid Build Coastguard Worker    "--bq_result_table",
1772*cc02d7e2SAndroid Build Coastguard Worker    default="",
1773*cc02d7e2SAndroid Build Coastguard Worker    type=str,
1774*cc02d7e2SAndroid Build Coastguard Worker    nargs="?",
1775*cc02d7e2SAndroid Build Coastguard Worker    help="Upload test results to a specified BQ table.",
1776*cc02d7e2SAndroid Build Coastguard Worker)
1777*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument(
1778*cc02d7e2SAndroid Build Coastguard Worker    "--cmake_configure_extra_args",
1779*cc02d7e2SAndroid Build Coastguard Worker    default=[],
1780*cc02d7e2SAndroid Build Coastguard Worker    nargs="+",
1781*cc02d7e2SAndroid Build Coastguard Worker    help="Extra arguments that will be passed to the cmake configure command. Only works for C/C++.",
1782*cc02d7e2SAndroid Build Coastguard Worker)
1783*cc02d7e2SAndroid Build Coastguard Workerargs = argp.parse_args()
1784*cc02d7e2SAndroid Build Coastguard Worker
1785*cc02d7e2SAndroid Build Coastguard Workerflaky_tests = set()
1786*cc02d7e2SAndroid Build Coastguard Workershortname_to_cpu = {}
1787*cc02d7e2SAndroid Build Coastguard Worker
1788*cc02d7e2SAndroid Build Coastguard Workerif args.force_default_poller:
1789*cc02d7e2SAndroid Build Coastguard Worker    _POLLING_STRATEGIES = {}
1790*cc02d7e2SAndroid Build Coastguard Workerelif args.force_use_pollers:
1791*cc02d7e2SAndroid Build Coastguard Worker    _POLLING_STRATEGIES[platform_string()] = args.force_use_pollers.split(",")
1792*cc02d7e2SAndroid Build Coastguard Worker
1793*cc02d7e2SAndroid Build Coastguard Workerjobset.measure_cpu_costs = args.measure_cpu_costs
1794*cc02d7e2SAndroid Build Coastguard Worker
1795*cc02d7e2SAndroid Build Coastguard Worker# grab config
1796*cc02d7e2SAndroid Build Coastguard Workerrun_config = _CONFIGS[args.config]
1797*cc02d7e2SAndroid Build Coastguard Workerbuild_config = run_config.build_config
1798*cc02d7e2SAndroid Build Coastguard Worker
1799*cc02d7e2SAndroid Build Coastguard Workerlanguages = set(_LANGUAGES[l] for l in args.language)
1800*cc02d7e2SAndroid Build Coastguard Workerfor l in languages:
1801*cc02d7e2SAndroid Build Coastguard Worker    l.configure(run_config, args)
1802*cc02d7e2SAndroid Build Coastguard Worker
1803*cc02d7e2SAndroid Build Coastguard Workerif len(languages) != 1:
1804*cc02d7e2SAndroid Build Coastguard Worker    print("Building multiple languages simultaneously is not supported!")
1805*cc02d7e2SAndroid Build Coastguard Worker    sys.exit(1)
1806*cc02d7e2SAndroid Build Coastguard Worker
1807*cc02d7e2SAndroid Build Coastguard Worker# If --use_docker was used, respawn the run_tests.py script under a docker container
1808*cc02d7e2SAndroid Build Coastguard Worker# instead of continuing.
1809*cc02d7e2SAndroid Build Coastguard Workerif args.use_docker:
1810*cc02d7e2SAndroid Build Coastguard Worker    if not args.travis:
1811*cc02d7e2SAndroid Build Coastguard Worker        print("Seen --use_docker flag, will run tests under docker.")
1812*cc02d7e2SAndroid Build Coastguard Worker        print("")
1813*cc02d7e2SAndroid Build Coastguard Worker        print(
1814*cc02d7e2SAndroid Build Coastguard Worker            "IMPORTANT: The changes you are testing need to be locally"
1815*cc02d7e2SAndroid Build Coastguard Worker            " committed"
1816*cc02d7e2SAndroid Build Coastguard Worker        )
1817*cc02d7e2SAndroid Build Coastguard Worker        print(
1818*cc02d7e2SAndroid Build Coastguard Worker            "because only the committed changes in the current branch will be"
1819*cc02d7e2SAndroid Build Coastguard Worker        )
1820*cc02d7e2SAndroid Build Coastguard Worker        print("copied to the docker environment.")
1821*cc02d7e2SAndroid Build Coastguard Worker        time.sleep(5)
1822*cc02d7e2SAndroid Build Coastguard Worker
1823*cc02d7e2SAndroid Build Coastguard Worker    dockerfile_dirs = set([l.dockerfile_dir() for l in languages])
1824*cc02d7e2SAndroid Build Coastguard Worker    if len(dockerfile_dirs) > 1:
1825*cc02d7e2SAndroid Build Coastguard Worker        print(
1826*cc02d7e2SAndroid Build Coastguard Worker            "Languages to be tested require running under different docker "
1827*cc02d7e2SAndroid Build Coastguard Worker            "images."
1828*cc02d7e2SAndroid Build Coastguard Worker        )
1829*cc02d7e2SAndroid Build Coastguard Worker        sys.exit(1)
1830*cc02d7e2SAndroid Build Coastguard Worker    else:
1831*cc02d7e2SAndroid Build Coastguard Worker        dockerfile_dir = next(iter(dockerfile_dirs))
1832*cc02d7e2SAndroid Build Coastguard Worker
1833*cc02d7e2SAndroid Build Coastguard Worker    child_argv = [arg for arg in sys.argv if not arg == "--use_docker"]
1834*cc02d7e2SAndroid Build Coastguard Worker    run_tests_cmd = "python3 tools/run_tests/run_tests.py %s" % " ".join(
1835*cc02d7e2SAndroid Build Coastguard Worker        child_argv[1:]
1836*cc02d7e2SAndroid Build Coastguard Worker    )
1837*cc02d7e2SAndroid Build Coastguard Worker
1838*cc02d7e2SAndroid Build Coastguard Worker    env = os.environ.copy()
1839*cc02d7e2SAndroid Build Coastguard Worker    env["DOCKERFILE_DIR"] = dockerfile_dir
1840*cc02d7e2SAndroid Build Coastguard Worker    env["DOCKER_RUN_SCRIPT"] = "tools/run_tests/dockerize/docker_run.sh"
1841*cc02d7e2SAndroid Build Coastguard Worker    env["DOCKER_RUN_SCRIPT_COMMAND"] = run_tests_cmd
1842*cc02d7e2SAndroid Build Coastguard Worker
1843*cc02d7e2SAndroid Build Coastguard Worker    retcode = subprocess.call(
1844*cc02d7e2SAndroid Build Coastguard Worker        "tools/run_tests/dockerize/build_and_run_docker.sh", shell=True, env=env
1845*cc02d7e2SAndroid Build Coastguard Worker    )
1846*cc02d7e2SAndroid Build Coastguard Worker    _print_debug_info_epilogue(dockerfile_dir=dockerfile_dir)
1847*cc02d7e2SAndroid Build Coastguard Worker    sys.exit(retcode)
1848*cc02d7e2SAndroid Build Coastguard Worker
1849*cc02d7e2SAndroid Build Coastguard Worker_check_arch_option(args.arch)
1850*cc02d7e2SAndroid Build Coastguard Worker
1851*cc02d7e2SAndroid Build Coastguard Worker# collect pre-build steps (which get retried if they fail, e.g. to avoid
1852*cc02d7e2SAndroid Build Coastguard Worker# flakes on downloading dependencies etc.)
1853*cc02d7e2SAndroid Build Coastguard Workerbuild_steps = list(
1854*cc02d7e2SAndroid Build Coastguard Worker    set(
1855*cc02d7e2SAndroid Build Coastguard Worker        jobset.JobSpec(
1856*cc02d7e2SAndroid Build Coastguard Worker            cmdline,
1857*cc02d7e2SAndroid Build Coastguard Worker            environ=_build_step_environ(
1858*cc02d7e2SAndroid Build Coastguard Worker                build_config, extra_env=l.build_steps_environ()
1859*cc02d7e2SAndroid Build Coastguard Worker            ),
1860*cc02d7e2SAndroid Build Coastguard Worker            timeout_seconds=_PRE_BUILD_STEP_TIMEOUT_SECONDS,
1861*cc02d7e2SAndroid Build Coastguard Worker            flake_retries=2,
1862*cc02d7e2SAndroid Build Coastguard Worker        )
1863*cc02d7e2SAndroid Build Coastguard Worker        for l in languages
1864*cc02d7e2SAndroid Build Coastguard Worker        for cmdline in l.pre_build_steps()
1865*cc02d7e2SAndroid Build Coastguard Worker    )
1866*cc02d7e2SAndroid Build Coastguard Worker)
1867*cc02d7e2SAndroid Build Coastguard Worker
1868*cc02d7e2SAndroid Build Coastguard Worker# collect build steps
1869*cc02d7e2SAndroid Build Coastguard Workerbuild_steps.extend(
1870*cc02d7e2SAndroid Build Coastguard Worker    set(
1871*cc02d7e2SAndroid Build Coastguard Worker        jobset.JobSpec(
1872*cc02d7e2SAndroid Build Coastguard Worker            cmdline,
1873*cc02d7e2SAndroid Build Coastguard Worker            environ=_build_step_environ(
1874*cc02d7e2SAndroid Build Coastguard Worker                build_config, extra_env=l.build_steps_environ()
1875*cc02d7e2SAndroid Build Coastguard Worker            ),
1876*cc02d7e2SAndroid Build Coastguard Worker            timeout_seconds=None,
1877*cc02d7e2SAndroid Build Coastguard Worker        )
1878*cc02d7e2SAndroid Build Coastguard Worker        for l in languages
1879*cc02d7e2SAndroid Build Coastguard Worker        for cmdline in l.build_steps()
1880*cc02d7e2SAndroid Build Coastguard Worker    )
1881*cc02d7e2SAndroid Build Coastguard Worker)
1882*cc02d7e2SAndroid Build Coastguard Worker
1883*cc02d7e2SAndroid Build Coastguard Worker# collect post test steps
1884*cc02d7e2SAndroid Build Coastguard Workerpost_tests_steps = list(
1885*cc02d7e2SAndroid Build Coastguard Worker    set(
1886*cc02d7e2SAndroid Build Coastguard Worker        jobset.JobSpec(
1887*cc02d7e2SAndroid Build Coastguard Worker            cmdline,
1888*cc02d7e2SAndroid Build Coastguard Worker            environ=_build_step_environ(
1889*cc02d7e2SAndroid Build Coastguard Worker                build_config, extra_env=l.build_steps_environ()
1890*cc02d7e2SAndroid Build Coastguard Worker            ),
1891*cc02d7e2SAndroid Build Coastguard Worker        )
1892*cc02d7e2SAndroid Build Coastguard Worker        for l in languages
1893*cc02d7e2SAndroid Build Coastguard Worker        for cmdline in l.post_tests_steps()
1894*cc02d7e2SAndroid Build Coastguard Worker    )
1895*cc02d7e2SAndroid Build Coastguard Worker)
1896*cc02d7e2SAndroid Build Coastguard Workerruns_per_test = args.runs_per_test
1897*cc02d7e2SAndroid Build Coastguard Worker
1898*cc02d7e2SAndroid Build Coastguard Workererrors = _build_and_run(
1899*cc02d7e2SAndroid Build Coastguard Worker    check_cancelled=lambda: False,
1900*cc02d7e2SAndroid Build Coastguard Worker    newline_on_success=args.newline_on_success,
1901*cc02d7e2SAndroid Build Coastguard Worker    xml_report=args.xml_report,
1902*cc02d7e2SAndroid Build Coastguard Worker    build_only=args.build_only,
1903*cc02d7e2SAndroid Build Coastguard Worker)
1904*cc02d7e2SAndroid Build Coastguard Workerif not errors:
1905*cc02d7e2SAndroid Build Coastguard Worker    jobset.message("SUCCESS", "All tests passed", do_newline=True)
1906*cc02d7e2SAndroid Build Coastguard Workerelse:
1907*cc02d7e2SAndroid Build Coastguard Worker    jobset.message("FAILED", "Some tests failed", do_newline=True)
1908*cc02d7e2SAndroid Build Coastguard Worker
1909*cc02d7e2SAndroid Build Coastguard Workerif not _is_use_docker_child():
1910*cc02d7e2SAndroid Build Coastguard Worker    # if --use_docker was used, the outer invocation of run_tests.py will
1911*cc02d7e2SAndroid Build Coastguard Worker    # print the debug info instead.
1912*cc02d7e2SAndroid Build Coastguard Worker    _print_debug_info_epilogue()
1913*cc02d7e2SAndroid Build Coastguard Worker
1914*cc02d7e2SAndroid Build Coastguard Workerexit_code = 0
1915*cc02d7e2SAndroid Build Coastguard Workerif BuildAndRunError.BUILD in errors:
1916*cc02d7e2SAndroid Build Coastguard Worker    exit_code |= 1
1917*cc02d7e2SAndroid Build Coastguard Workerif BuildAndRunError.TEST in errors:
1918*cc02d7e2SAndroid Build Coastguard Worker    exit_code |= 2
1919*cc02d7e2SAndroid Build Coastguard Workerif BuildAndRunError.POST_TEST in errors:
1920*cc02d7e2SAndroid Build Coastguard Worker    exit_code |= 4
1921*cc02d7e2SAndroid Build Coastguard Workersys.exit(exit_code)
1922