xref: /aosp_15_r20/external/grpc-grpc/tools/run_tests/artifacts/distribtest_targets.py (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1#!/usr/bin/env python3
2# Copyright 2016 gRPC authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""Definition of targets run distribution package tests."""
16
17import os.path
18import sys
19
20sys.path.insert(0, os.path.abspath(".."))
21import python_utils.jobset as jobset
22
23
24def create_docker_jobspec(
25    name,
26    dockerfile_dir,
27    shell_command,
28    environ={},
29    flake_retries=0,
30    timeout_retries=0,
31    copy_rel_path=None,
32    timeout_seconds=30 * 60,
33):
34    """Creates jobspec for a task running under docker."""
35    environ = environ.copy()
36    # the entire repo will be cloned if copy_rel_path is not set.
37    if copy_rel_path:
38        environ["RELATIVE_COPY_PATH"] = copy_rel_path
39
40    docker_args = []
41    for k, v in list(environ.items()):
42        docker_args += ["-e", "%s=%s" % (k, v)]
43    docker_env = {
44        "DOCKERFILE_DIR": dockerfile_dir,
45        "DOCKER_RUN_SCRIPT": "tools/run_tests/dockerize/docker_run.sh",
46        "DOCKER_RUN_SCRIPT_COMMAND": shell_command,
47    }
48    jobspec = jobset.JobSpec(
49        cmdline=["tools/run_tests/dockerize/build_and_run_docker.sh"]
50        + docker_args,
51        environ=docker_env,
52        shortname="distribtest.%s" % (name),
53        timeout_seconds=timeout_seconds,
54        flake_retries=flake_retries,
55        timeout_retries=timeout_retries,
56    )
57    return jobspec
58
59
60def create_jobspec(
61    name,
62    cmdline,
63    environ=None,
64    shell=False,
65    flake_retries=0,
66    timeout_retries=0,
67    use_workspace=False,
68    timeout_seconds=10 * 60,
69):
70    """Creates jobspec."""
71    environ = environ.copy()
72    if use_workspace:
73        environ["WORKSPACE_NAME"] = "workspace_%s" % name
74        cmdline = [
75            "bash",
76            "tools/run_tests/artifacts/run_in_workspace.sh",
77        ] + cmdline
78    jobspec = jobset.JobSpec(
79        cmdline=cmdline,
80        environ=environ,
81        shortname="distribtest.%s" % (name),
82        timeout_seconds=timeout_seconds,
83        flake_retries=flake_retries,
84        timeout_retries=timeout_retries,
85        shell=shell,
86    )
87    return jobspec
88
89
90class CSharpDistribTest(object):
91    """Tests C# NuGet package"""
92
93    def __init__(
94        self,
95        platform,
96        arch,
97        docker_suffix=None,
98        use_dotnet_cli=False,
99        presubmit=False,
100    ):
101        self.name = "csharp_%s_%s" % (platform, arch)
102        self.platform = platform
103        self.arch = arch
104        self.docker_suffix = docker_suffix
105        self.labels = ["distribtest", "csharp", platform, arch]
106        if presubmit:
107            self.labels.append("presubmit")
108        self.script_suffix = ""
109        if docker_suffix:
110            self.name += "_%s" % docker_suffix
111            self.labels.append(docker_suffix)
112        if use_dotnet_cli:
113            self.name += "_dotnetcli"
114            self.script_suffix = "_dotnetcli"
115            self.labels.append("dotnetcli")
116        else:
117            self.labels.append("olddotnet")
118
119    def pre_build_jobspecs(self):
120        return []
121
122    def build_jobspec(self, inner_jobs=None):
123        del inner_jobs  # arg unused as there is little opportunity for parallelizing whats inside the distribtests
124        if self.platform == "linux":
125            return create_docker_jobspec(
126                self.name,
127                "tools/dockerfile/distribtest/csharp_%s_%s"
128                % (self.docker_suffix, self.arch),
129                "test/distrib/csharp/run_distrib_test%s.sh"
130                % self.script_suffix,
131                copy_rel_path="test/distrib",
132            )
133        elif self.platform == "macos":
134            return create_jobspec(
135                self.name,
136                [
137                    "test/distrib/csharp/run_distrib_test%s.sh"
138                    % self.script_suffix
139                ],
140                environ={
141                    "EXTERNAL_GIT_ROOT": "../../../..",
142                    "SKIP_NETCOREAPP21_DISTRIBTEST": "1",
143                    "SKIP_NET50_DISTRIBTEST": "1",
144                },
145                use_workspace=True,
146            )
147        elif self.platform == "windows":
148            # TODO(jtattermusch): re-enable windows distribtest
149            return create_jobspec(
150                self.name,
151                ["bash", "tools/run_tests/artifacts/run_distribtest_csharp.sh"],
152                environ={},
153                use_workspace=True,
154            )
155        else:
156            raise Exception("Not supported yet.")
157
158    def __str__(self):
159        return self.name
160
161
162class PythonDistribTest(object):
163    """Tests Python package"""
164
165    def __init__(
166        self, platform, arch, docker_suffix, source=False, presubmit=False
167    ):
168        self.source = source
169        if source:
170            self.name = "python_dev_%s_%s_%s" % (platform, arch, docker_suffix)
171        else:
172            self.name = "python_%s_%s_%s" % (platform, arch, docker_suffix)
173        self.platform = platform
174        self.arch = arch
175        self.docker_suffix = docker_suffix
176        self.labels = ["distribtest", "python", platform, arch, docker_suffix]
177        if presubmit:
178            self.labels.append("presubmit")
179
180    def pre_build_jobspecs(self):
181        return []
182
183    def build_jobspec(self, inner_jobs=None):
184        # TODO(jtattermusch): honor inner_jobs arg for this task.
185        del inner_jobs
186        if not self.platform == "linux":
187            raise Exception("Not supported yet.")
188
189        if self.source:
190            return create_docker_jobspec(
191                self.name,
192                "tools/dockerfile/distribtest/python_dev_%s_%s"
193                % (self.docker_suffix, self.arch),
194                "test/distrib/python/run_source_distrib_test.sh",
195                copy_rel_path="test/distrib",
196                timeout_seconds=45 * 60,
197            )
198        else:
199            return create_docker_jobspec(
200                self.name,
201                "tools/dockerfile/distribtest/python_%s_%s"
202                % (self.docker_suffix, self.arch),
203                "test/distrib/python/run_binary_distrib_test.sh",
204                copy_rel_path="test/distrib",
205                timeout_seconds=45 * 60,
206            )
207
208    def __str__(self):
209        return self.name
210
211
212class RubyDistribTest(object):
213    """Tests Ruby package"""
214
215    def __init__(
216        self,
217        platform,
218        arch,
219        docker_suffix,
220        ruby_version=None,
221        source=False,
222        presubmit=False,
223    ):
224        self.package_type = "binary"
225        if source:
226            self.package_type = "source"
227        self.name = "ruby_%s_%s_%s_version_%s_package_type_%s" % (
228            platform,
229            arch,
230            docker_suffix,
231            ruby_version or "unspecified",
232            self.package_type,
233        )
234        self.platform = platform
235        self.arch = arch
236        self.docker_suffix = docker_suffix
237        self.ruby_version = ruby_version
238        self.labels = ["distribtest", "ruby", platform, arch, docker_suffix]
239        if presubmit:
240            self.labels.append("presubmit")
241
242    def pre_build_jobspecs(self):
243        return []
244
245    def build_jobspec(self, inner_jobs=None):
246        # TODO(jtattermusch): honor inner_jobs arg for this task.
247        del inner_jobs
248        arch_to_gem_arch = {
249            "x64": "x86_64",
250            "x86": "x86",
251        }
252        if not self.platform == "linux":
253            raise Exception("Not supported yet.")
254
255        dockerfile_name = "tools/dockerfile/distribtest/ruby_%s_%s" % (
256            self.docker_suffix,
257            self.arch,
258        )
259        if self.ruby_version is not None:
260            dockerfile_name += "_%s" % self.ruby_version
261        return create_docker_jobspec(
262            self.name,
263            dockerfile_name,
264            "test/distrib/ruby/run_distrib_test.sh %s %s %s"
265            % (arch_to_gem_arch[self.arch], self.platform, self.package_type),
266            copy_rel_path="test/distrib",
267        )
268
269    def __str__(self):
270        return self.name
271
272
273class PHP7DistribTest(object):
274    """Tests PHP7 package"""
275
276    def __init__(self, platform, arch, docker_suffix=None, presubmit=False):
277        self.name = "php7_%s_%s_%s" % (platform, arch, docker_suffix)
278        self.platform = platform
279        self.arch = arch
280        self.docker_suffix = docker_suffix
281        self.labels = ["distribtest", "php", "php7", platform, arch]
282        if presubmit:
283            self.labels.append("presubmit")
284        if docker_suffix:
285            self.labels.append(docker_suffix)
286
287    def pre_build_jobspecs(self):
288        return []
289
290    def build_jobspec(self, inner_jobs=None):
291        # TODO(jtattermusch): honor inner_jobs arg for this task.
292        del inner_jobs
293        if self.platform == "linux":
294            return create_docker_jobspec(
295                self.name,
296                "tools/dockerfile/distribtest/php7_%s_%s"
297                % (self.docker_suffix, self.arch),
298                "test/distrib/php/run_distrib_test.sh",
299                copy_rel_path="test/distrib",
300            )
301        elif self.platform == "macos":
302            return create_jobspec(
303                self.name,
304                ["test/distrib/php/run_distrib_test_macos.sh"],
305                environ={"EXTERNAL_GIT_ROOT": "../../../.."},
306                timeout_seconds=30 * 60,
307                use_workspace=True,
308            )
309        else:
310            raise Exception("Not supported yet.")
311
312    def __str__(self):
313        return self.name
314
315
316class CppDistribTest(object):
317    """Tests Cpp make install by building examples."""
318
319    def __init__(
320        self, platform, arch, docker_suffix=None, testcase=None, presubmit=False
321    ):
322        if platform == "linux":
323            self.name = "cpp_%s_%s_%s_%s" % (
324                platform,
325                arch,
326                docker_suffix,
327                testcase,
328            )
329        else:
330            self.name = "cpp_%s_%s_%s" % (platform, arch, testcase)
331        self.platform = platform
332        self.arch = arch
333        self.docker_suffix = docker_suffix
334        self.testcase = testcase
335        self.labels = [
336            "distribtest",
337            "cpp",
338            platform,
339            arch,
340            testcase,
341        ]
342        if presubmit:
343            self.labels.append("presubmit")
344        if docker_suffix:
345            self.labels.append(docker_suffix)
346
347    def pre_build_jobspecs(self):
348        return []
349
350    def build_jobspec(self, inner_jobs=None):
351        environ = {}
352        if inner_jobs is not None:
353            # set number of parallel jobs for the C++ build
354            environ["GRPC_CPP_DISTRIBTEST_BUILD_COMPILER_JOBS"] = str(
355                inner_jobs
356            )
357
358        if self.platform == "linux":
359            return create_docker_jobspec(
360                self.name,
361                "tools/dockerfile/distribtest/cpp_%s_%s"
362                % (self.docker_suffix, self.arch),
363                "test/distrib/cpp/run_distrib_test_%s.sh" % self.testcase,
364                timeout_seconds=60 * 60,
365            )
366        elif self.platform == "windows":
367            return create_jobspec(
368                self.name,
369                ["test\\distrib\\cpp\\run_distrib_test_%s.bat" % self.testcase],
370                environ={},
371                timeout_seconds=60 * 60,
372                use_workspace=True,
373            )
374        else:
375            raise Exception("Not supported yet.")
376
377    def __str__(self):
378        return self.name
379
380
381def targets():
382    """Gets list of supported targets"""
383    return [
384        # C++
385        # The "dummy" C++ distribtest so that the set of tasks to run isn't empty
386        # when grpc_distribtest_standalone runs on PRs.
387        CppDistribTest("linux", "x64", "debian10", "dummy", presubmit=True),
388        CppDistribTest("linux", "x64", "debian10", "cmake", presubmit=False),
389        CppDistribTest(
390            "linux", "x64", "debian10", "cmake_as_submodule", presubmit=False
391        ),
392        CppDistribTest(
393            "linux",
394            "x64",
395            "debian10",
396            "cmake_as_externalproject",
397            presubmit=False,
398        ),
399        CppDistribTest(
400            "linux", "x64", "debian10", "cmake_fetchcontent", presubmit=False
401        ),
402        CppDistribTest(
403            "linux", "x64", "debian10", "cmake_module_install", presubmit=False
404        ),
405        CppDistribTest(
406            "linux", "x64", "debian10", "cmake_pkgconfig", presubmit=False
407        ),
408        CppDistribTest(
409            "linux",
410            "x64",
411            "debian10_aarch64_cross",
412            "cmake_aarch64_cross",
413            presubmit=False,
414        ),
415        CppDistribTest("windows", "x86", testcase="cmake", presubmit=True),
416        CppDistribTest(
417            "windows",
418            "x86",
419            testcase="cmake_as_externalproject",
420            presubmit=True,
421        ),
422        CppDistribTest(
423            "windows",
424            "x86",
425            testcase="cmake_for_dll",
426            presubmit=True,
427        ),
428        # C#
429        CSharpDistribTest(
430            "linux", "x64", "debian10", use_dotnet_cli=True, presubmit=True
431        ),
432        CSharpDistribTest("linux", "x64", "ubuntu2204", use_dotnet_cli=True),
433        CSharpDistribTest(
434            "linux", "x64", "alpine", use_dotnet_cli=True, presubmit=True
435        ),
436        CSharpDistribTest(
437            "linux", "x64", "dotnet31", use_dotnet_cli=True, presubmit=True
438        ),
439        CSharpDistribTest(
440            "linux", "x64", "dotnet5", use_dotnet_cli=True, presubmit=True
441        ),
442        CSharpDistribTest("macos", "x64", use_dotnet_cli=True, presubmit=True),
443        CSharpDistribTest("windows", "x86", presubmit=True),
444        CSharpDistribTest("windows", "x64", presubmit=True),
445        # Python
446        PythonDistribTest("linux", "x64", "bullseye", presubmit=True),
447        PythonDistribTest("linux", "x86", "bullseye", presubmit=True),
448        PythonDistribTest("linux", "x64", "fedora36"),
449        PythonDistribTest("linux", "x64", "arch"),
450        PythonDistribTest("linux", "x64", "alpine"),
451        PythonDistribTest("linux", "x64", "ubuntu2204"),
452        PythonDistribTest(
453            "linux", "aarch64", "python38_buster", presubmit=True
454        ),
455        PythonDistribTest(
456            "linux", "x64", "alpine3.7", source=True, presubmit=True
457        ),
458        PythonDistribTest(
459            "linux", "x64", "bullseye", source=True, presubmit=True
460        ),
461        PythonDistribTest(
462            "linux", "x86", "bullseye", source=True, presubmit=True
463        ),
464        PythonDistribTest("linux", "x64", "fedora36", source=True),
465        PythonDistribTest("linux", "x64", "arch", source=True),
466        PythonDistribTest("linux", "x64", "ubuntu2204", source=True),
467        # Ruby
468        RubyDistribTest(
469            "linux",
470            "x64",
471            "debian11",
472            ruby_version="ruby_3_2",
473            source=True,
474            presubmit=True,
475        ),
476        RubyDistribTest(
477            "linux", "x64", "debian11", ruby_version="ruby_3_0", presubmit=True
478        ),
479        RubyDistribTest(
480            "linux", "x64", "debian11", ruby_version="ruby_3_1", presubmit=True
481        ),
482        RubyDistribTest(
483            "linux", "x64", "debian11", ruby_version="ruby_3_2", presubmit=True
484        ),
485        RubyDistribTest(
486            "linux", "x64", "debian11", ruby_version="ruby_3_3", presubmit=True
487        ),
488        RubyDistribTest("linux", "x64", "centos7"),
489        RubyDistribTest("linux", "x64", "ubuntu2004"),
490        RubyDistribTest("linux", "x64", "ubuntu2204", presubmit=True),
491        # PHP7
492        PHP7DistribTest("linux", "x64", "debian10", presubmit=True),
493        PHP7DistribTest("macos", "x64", presubmit=True),
494    ]
495