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