gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/runner/defs.bzl (about) 1 """Defines a rule for syscall test targets.""" 2 3 load("//tools:defs.bzl", "default_platform", "platform_capabilities", "platforms", "save_restore_platforms") 4 5 # Maps platform names to a GVISOR_PLATFORM_SUPPORT environment variable consumed by platform_util.cc 6 _platform_support_env_vars = { 7 platform: ",".join(sorted([ 8 ("%s:%s" % (capability, "TRUE" if supported else "FALSE")) 9 for capability, supported in support.items() 10 ])) 11 for platform, support in platform_capabilities.items() 12 } 13 14 def _runner_test_impl(ctx): 15 # Generate a runner binary. 16 runner = ctx.actions.declare_file(ctx.label.name) 17 runner_content = "\n".join([ 18 "#!/bin/bash", 19 "set -euf -x -o pipefail", 20 "if [[ -n \"${TEST_UNDECLARED_OUTPUTS_DIR}\" ]]; then", 21 " mkdir -p \"${TEST_UNDECLARED_OUTPUTS_DIR}\"", 22 " chmod a+rwx \"${TEST_UNDECLARED_OUTPUTS_DIR}\"", 23 "fi", 24 "exec %s %s \"$@\" %s\n" % ( 25 ctx.files.runner[0].short_path, 26 " ".join(ctx.attr.runner_args), 27 ctx.files.test[0].short_path, 28 ), 29 ]) 30 ctx.actions.write(runner, runner_content, is_executable = True) 31 32 # Return with all transitive files. 33 runfiles = ctx.runfiles( 34 transitive_files = depset(transitive = [ 35 target.data_runfiles.files 36 for target in (ctx.attr.runner, ctx.attr.test) 37 if hasattr(target, "data_runfiles") 38 ]), 39 files = ctx.files.runner + ctx.files.test, 40 collect_default = True, 41 collect_data = True, 42 ) 43 return [DefaultInfo(executable = runner, runfiles = runfiles)] 44 45 _runner_test = rule( 46 attrs = { 47 "runner": attr.label( 48 default = "//test/runner:runner", 49 ), 50 "test": attr.label( 51 mandatory = True, 52 ), 53 "runner_args": attr.string_list(), 54 "data": attr.label_list( 55 allow_files = True, 56 ), 57 }, 58 test = True, 59 implementation = _runner_test_impl, 60 ) 61 62 def _syscall_test( 63 test, 64 platform, 65 use_tmpfs, 66 tags, 67 debug, 68 network = "none", 69 file_access = "exclusive", 70 overlay = False, 71 add_host_uds = False, 72 add_host_connector = False, 73 add_host_fifo = False, 74 iouring = False, 75 container = None, 76 one_sandbox = True, 77 fusefs = False, 78 directfs = False, 79 leak_check = False, 80 save = False, 81 save_resume = False, 82 **kwargs): 83 # Prepend "runsc" to non-native platform names. 84 full_platform = platform if platform == "native" else "runsc_" + platform 85 86 # Name the test appropriately. 87 name = test.split(":")[1] + "_" + full_platform 88 if file_access == "shared": 89 name += "_shared" 90 if overlay: 91 name += "_overlay" 92 if network != "none": 93 name += "_" + network + "net" 94 if fusefs: 95 name += "_fuse" 96 if directfs: 97 name += "_directfs" 98 if save: 99 name += "_save" 100 if save_resume: 101 name += "_save_resume" 102 103 # Apply all tags. 104 if tags == None: 105 tags = [] 106 107 # Add the full_platform and file access in a tag to make it easier to run 108 # all the tests on a specific flavor. Use --test_tag_filters=runsc_systrap,file_shared. 109 tags = list(tags) 110 tags += [full_platform, "file_" + file_access] 111 112 if save or save_resume: 113 tags.append("allsave") 114 if platform in save_restore_platforms: 115 if save: 116 tags.append("save_restore") 117 if save_resume: 118 tags.append("save_resume") 119 120 # Hash this target into one of 15 buckets. This can be used to 121 # randomly split targets between different workflows. 122 hash15 = hash(native.package_name() + name) % 15 123 tags.append("hash15:" + str(hash15)) 124 tags.append("hash15") 125 126 # Disable off-host networking. 127 tags.append("requires-net:loopback") 128 tags.append("requires-net:ipv4") 129 tags.append("block-network") 130 131 # gotsan makes sense only if tests are running in gVisor. 132 if platform == "native": 133 tags.append("nogotsan") 134 135 if container == None: 136 # Containerize in the following cases: 137 # - "container" is explicitly specified as a tag 138 # - Running tests natively 139 # - Running tests with host networking 140 container = "container" in tags or network == "host" 141 142 if platform == "native": 143 # The "native" platform supports everything. 144 platform_support = ",".join(sorted([ 145 ("%s:TRUE" % key) 146 for key in platform_capabilities[default_platform].keys() 147 ])) 148 else: 149 platform_support = _platform_support_env_vars.get(platform, "") 150 151 runner_args = [ 152 # Arguments are passed directly to runner binary. 153 "--platform=" + platform, 154 "--platform-support=" + platform_support, 155 "--network=" + network, 156 "--use-tmpfs=" + str(use_tmpfs), 157 "--fusefs=" + str(fusefs), 158 "--file-access=" + file_access, 159 "--overlay=" + str(overlay), 160 "--add-host-uds=" + str(add_host_uds), 161 "--add-host-connector=" + str(add_host_connector), 162 "--add-host-fifo=" + str(add_host_fifo), 163 "--strace=" + str(debug), 164 "--debug=" + str(debug), 165 "--container=" + str(container), 166 "--one-sandbox=" + str(one_sandbox), 167 "--iouring=" + str(iouring), 168 "--directfs=" + str(directfs), 169 "--leak-check=" + str(leak_check), 170 "--save=" + str(save), 171 "--save-resume=" + str(save_resume), 172 ] 173 174 # Trace points are platform agnostic, so enable them for ptrace only. 175 if platform == "ptrace": 176 runner_args.append("--trace") 177 178 # Call the rule above. 179 _runner_test( 180 name = name, 181 test = test, 182 runner_args = runner_args, 183 tags = tags, 184 **kwargs 185 ) 186 187 def all_platforms(): 188 """All platforms returns a list of all platforms.""" 189 available = dict(platforms.items()) 190 available[default_platform] = platforms.get(default_platform, []) 191 return available.items() 192 193 def syscall_test_variants( 194 test, 195 use_tmpfs = False, 196 add_fusefs = False, 197 add_overlay = False, 198 add_host_uds = False, 199 add_host_connector = False, 200 add_host_fifo = False, 201 add_hostinet = False, 202 add_directfs = True, 203 one_sandbox = True, 204 iouring = False, 205 allow_native = True, 206 leak_check = True, 207 debug = True, 208 container = None, 209 tags = None, 210 save = False, 211 save_resume = False, 212 size = "medium", 213 timeout = None, 214 **kwargs): 215 """Generates syscall tests for all variants. 216 217 Args: 218 test: the test target. 219 use_tmpfs: use tmpfs in the defined tests. 220 add_fusefs: add a fusefs test. 221 add_overlay: add an overlay test. 222 add_host_uds: setup bound UDS on the host. 223 add_host_connector: setup host threads to connect to bound UDS created by sandbox. 224 add_host_fifo: setup FIFO files on the host. 225 add_hostinet: add a hostinet test. 226 add_directfs: add a directfs test. 227 one_sandbox: runs each unit test in a new sandbox instance. 228 iouring: enable IO_URING support. 229 allow_native: generate a native test variant. 230 debug: enable debug output. 231 container: Run the test in a container. If None, determined from other information. 232 tags: starting test tags. 233 leak_check: enables leak check. 234 save: save restore test. 235 size: test size. 236 timeout: timeout for the test. 237 save_resume: save resume test. 238 **kwargs: additional test arguments. 239 """ 240 for platform, platform_tags in all_platforms(): 241 # Add directfs to the default platform variant. 242 directfs = add_directfs and platform == default_platform 243 _syscall_test( 244 test = test, 245 platform = platform, 246 use_tmpfs = use_tmpfs, 247 add_host_uds = add_host_uds, 248 add_host_connector = add_host_connector, 249 add_host_fifo = add_host_fifo, 250 tags = platform_tags + tags, 251 iouring = iouring, 252 directfs = directfs, 253 debug = debug, 254 container = container, 255 one_sandbox = one_sandbox, 256 leak_check = leak_check, 257 save = save, 258 save_resume = save_resume, 259 size = size, 260 timeout = timeout, 261 **kwargs 262 ) 263 264 if add_overlay: 265 _syscall_test( 266 test = test, 267 platform = default_platform, 268 use_tmpfs = use_tmpfs, 269 add_host_uds = add_host_uds, 270 add_host_connector = add_host_connector, 271 add_host_fifo = add_host_fifo, 272 tags = platforms.get(default_platform, []) + tags, 273 debug = debug, 274 iouring = iouring, 275 container = container, 276 one_sandbox = one_sandbox, 277 overlay = True, 278 leak_check = leak_check, 279 save = save, 280 save_resume = save_resume, 281 size = size, 282 timeout = timeout, 283 **kwargs 284 ) 285 286 # TODO(b/192114729): hostinet is not supported with S/R. 287 if add_hostinet and not (save or save_resume): 288 _syscall_test( 289 test = test, 290 platform = default_platform, 291 use_tmpfs = use_tmpfs, 292 network = "host", 293 add_host_uds = add_host_uds, 294 add_host_connector = add_host_connector, 295 add_host_fifo = add_host_fifo, 296 tags = platforms.get(default_platform, []) + tags, 297 debug = debug, 298 iouring = iouring, 299 container = container, 300 one_sandbox = one_sandbox, 301 leak_check = leak_check, 302 save = save, 303 save_resume = save_resume, 304 size = size, 305 timeout = timeout, 306 **kwargs 307 ) 308 if not use_tmpfs: 309 # Also test shared gofer access. 310 _syscall_test( 311 test = test, 312 platform = default_platform, 313 use_tmpfs = use_tmpfs, 314 add_host_uds = add_host_uds, 315 add_host_connector = add_host_connector, 316 add_host_fifo = add_host_fifo, 317 tags = platforms.get(default_platform, []) + tags, 318 iouring = iouring, 319 debug = debug, 320 container = container, 321 one_sandbox = one_sandbox, 322 file_access = "shared", 323 leak_check = leak_check, 324 save = save, 325 save_resume = save_resume, 326 size = size, 327 timeout = timeout, 328 **kwargs 329 ) 330 if add_fusefs: 331 _syscall_test( 332 test = test, 333 platform = default_platform, 334 use_tmpfs = True, 335 fusefs = True, 336 add_host_uds = add_host_uds, 337 add_host_connector = add_host_connector, 338 add_host_fifo = add_host_fifo, 339 tags = platforms.get(default_platform, []) + tags, 340 debug = debug, 341 container = container, 342 one_sandbox = one_sandbox, 343 leak_check = leak_check, 344 save = save, 345 save_resume = save_resume, 346 size = size, 347 timeout = timeout, 348 **kwargs 349 ) 350 351 def syscall_test( 352 test, 353 use_tmpfs = False, 354 add_fusefs = False, 355 add_overlay = False, 356 add_host_uds = False, 357 add_host_connector = False, 358 add_host_fifo = False, 359 add_hostinet = False, 360 add_directfs = True, 361 one_sandbox = True, 362 iouring = False, 363 allow_native = True, 364 leak_check = True, 365 debug = True, 366 container = None, 367 tags = None, 368 save = True, 369 size = "medium", 370 **kwargs): 371 """syscall_test is a macro that will create targets for all platforms. 372 373 Args: 374 test: the test target. 375 use_tmpfs: use tmpfs in the defined tests. 376 add_fusefs: add a fusefs test. 377 add_overlay: add an overlay test. 378 add_host_uds: setup bound UDS on the host. 379 add_host_connector: setup host threads to connect to bound UDS created by sandbox. 380 add_host_fifo: setup FIFO files on the host. 381 add_hostinet: add a hostinet test. 382 add_directfs: add a directfs test. 383 one_sandbox: runs each unit test in a new sandbox instance. 384 iouring: enable IO_URING support. 385 allow_native: generate a native test variant. 386 debug: enable debug output. 387 container: Run the test in a container. If None, determined from other information. 388 tags: starting test tags. 389 leak_check: enables leak check. 390 save: enables save/restore and save/resume test variants. 391 size: test size. 392 **kwargs: additional test arguments. 393 """ 394 if not tags: 395 tags = [] 396 397 if allow_native: 398 _syscall_test( 399 test = test, 400 platform = "native", 401 use_tmpfs = False, 402 add_host_uds = add_host_uds, 403 add_host_connector = add_host_connector, 404 add_host_fifo = add_host_fifo, 405 tags = tags, 406 iouring = iouring, 407 debug = debug, 408 container = container, 409 one_sandbox = one_sandbox, 410 **kwargs 411 ) 412 413 syscall_test_variants( 414 test, 415 use_tmpfs, 416 add_fusefs, 417 add_overlay, 418 add_host_uds, 419 add_host_connector, 420 add_host_fifo, 421 add_hostinet, 422 add_directfs, 423 one_sandbox, 424 iouring, 425 allow_native, 426 leak_check, 427 debug, 428 container, 429 tags, 430 False, # save, generate all tests without save variant. 431 False, # save_resume, generate all tests without save_resume variant. 432 size, 433 **kwargs 434 ) 435 436 # Add save and save_resume variants to all other variants generated above. 437 if save: 438 # Disable go sanitizers for save tests. 439 tags.append("nogotsan") 440 syscall_test_variants( 441 test, 442 use_tmpfs, 443 add_fusefs, 444 add_overlay, 445 add_host_uds, 446 add_host_connector, 447 add_host_fifo, 448 add_hostinet, 449 add_directfs, 450 one_sandbox, 451 iouring, 452 allow_native, 453 leak_check, 454 debug, 455 container, 456 tags, 457 True, # save, generate all tests with save variant. 458 False, # save_resume, generate all tests without save_resume variant. 459 "large", # size, use size as large by default for all S/R tests. 460 "long", # timeout, use long timeout for S/R tests. 461 **kwargs 462 ) 463 464 # Add save resume variant to all other variants generated above. 465 syscall_test_variants( 466 test, 467 use_tmpfs, 468 add_fusefs, 469 add_overlay, 470 add_host_uds, 471 add_host_connector, 472 add_host_fifo, 473 add_hostinet, 474 add_directfs, 475 one_sandbox, 476 iouring, 477 allow_native, 478 leak_check, 479 debug, 480 container, 481 tags, 482 False, # save, generate all tests without save variant. 483 True, # save_resume, generate all tests with save_resume variant. 484 "large", # size, use size as large by default for all S/R tests. 485 "long", # timeout, use long timeout for S/R tests. 486 **kwargs 487 )