github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/runner/defs.bzl (about)

     1  """Defines a rule for syscall test targets."""
     2  
     3  load("//tools:defs.bzl", "default_platform", "platforms")
     4  
     5  def _runner_test_impl(ctx):
     6      # Generate a runner binary.
     7      runner = ctx.actions.declare_file(ctx.label.name)
     8      runner_content = "\n".join([
     9          "#!/bin/bash",
    10          "set -euf -x -o pipefail",
    11          "if [[ -n \"${TEST_UNDECLARED_OUTPUTS_DIR}\" ]]; then",
    12          "  mkdir -p \"${TEST_UNDECLARED_OUTPUTS_DIR}\"",
    13          "  chmod a+rwx \"${TEST_UNDECLARED_OUTPUTS_DIR}\"",
    14          "fi",
    15          "exec %s %s \"$@\" %s\n" % (
    16              ctx.files.runner[0].short_path,
    17              " ".join(ctx.attr.runner_args),
    18              ctx.files.test[0].short_path,
    19          ),
    20      ])
    21      ctx.actions.write(runner, runner_content, is_executable = True)
    22  
    23      # Return with all transitive files.
    24      runfiles = ctx.runfiles(
    25          transitive_files = depset(transitive = [
    26              target.data_runfiles.files
    27              for target in (ctx.attr.runner, ctx.attr.test)
    28              if hasattr(target, "data_runfiles")
    29          ]),
    30          files = ctx.files.runner + ctx.files.test,
    31          collect_default = True,
    32          collect_data = True,
    33      )
    34      return [DefaultInfo(executable = runner, runfiles = runfiles)]
    35  
    36  _runner_test = rule(
    37      attrs = {
    38          "runner": attr.label(
    39              default = "//test/runner:runner",
    40          ),
    41          "test": attr.label(
    42              mandatory = True,
    43          ),
    44          "runner_args": attr.string_list(),
    45          "data": attr.label_list(
    46              allow_files = True,
    47          ),
    48      },
    49      test = True,
    50      implementation = _runner_test_impl,
    51  )
    52  
    53  def _syscall_test(
    54          test,
    55          platform,
    56          use_tmpfs,
    57          tags,
    58          debug,
    59          network = "none",
    60          file_access = "exclusive",
    61          overlay = False,
    62          add_uds_tree = False,
    63          vfs2 = False,
    64          fuse = False,
    65          **kwargs):
    66      # Prepend "runsc" to non-native platform names.
    67      full_platform = platform if platform == "native" else "runsc_" + platform
    68  
    69      # Name the test appropriately.
    70      name = test.split(":")[1] + "_" + full_platform
    71      if file_access == "shared":
    72          name += "_shared"
    73      if overlay:
    74          name += "_overlay"
    75      if vfs2:
    76          name += "_vfs2"
    77          if fuse:
    78              name += "_fuse"
    79      if network != "none":
    80          name += "_" + network + "net"
    81  
    82      # Apply all tags.
    83      if tags == None:
    84          tags = []
    85  
    86      # Add the full_platform and file access in a tag to make it easier to run
    87      # all the tests on a specific flavor. Use --test_tag_filters=ptrace,file_shared.
    88      tags = list(tags)
    89      tags += [full_platform, "file_" + file_access]
    90  
    91      # Hash this target into one of 15 buckets. This can be used to
    92      # randomly split targets between different workflows.
    93      hash15 = hash(native.package_name() + name) % 15
    94      tags.append("hash15:" + str(hash15))
    95      tags.append("hash15")
    96  
    97      # Disable off-host networking.
    98      tags.append("requires-net:loopback")
    99      tags.append("requires-net:ipv4")
   100      tags.append("block-network")
   101  
   102      # gotsan makes sense only if tests are running in gVisor.
   103      if platform == "native":
   104          tags.append("nogotsan")
   105  
   106      container = "container" in tags
   107  
   108      runner_args = [
   109          # Arguments are passed directly to runner binary.
   110          "--platform=" + platform,
   111          "--network=" + network,
   112          "--use-tmpfs=" + str(use_tmpfs),
   113          "--file-access=" + file_access,
   114          "--overlay=" + str(overlay),
   115          "--add-uds-tree=" + str(add_uds_tree),
   116          "--vfs2=" + str(vfs2),
   117          "--fuse=" + str(fuse),
   118          "--strace=" + str(debug),
   119          "--debug=" + str(debug),
   120          "--container=" + str(container),
   121      ]
   122  
   123      # Call the rule above.
   124      _runner_test(
   125          name = name,
   126          test = test,
   127          runner_args = runner_args,
   128          tags = tags,
   129          **kwargs
   130      )
   131  
   132  def syscall_test(
   133          test,
   134          use_tmpfs = False,
   135          add_overlay = False,
   136          add_uds_tree = False,
   137          add_hostinet = False,
   138          vfs2 = True,
   139          fuse = False,
   140          debug = True,
   141          tags = None,
   142          **kwargs):
   143      """syscall_test is a macro that will create targets for all platforms.
   144  
   145      Args:
   146        test: the test target.
   147        use_tmpfs: use tmpfs in the defined tests.
   148        add_overlay: add an overlay test.
   149        add_uds_tree: add a UDS test.
   150        add_hostinet: add a hostinet test.
   151        vfs2: enable VFS2 support.
   152        fuse: enable FUSE support.
   153        debug: enable debug output.
   154        tags: starting test tags.
   155        **kwargs: additional test arguments.
   156      """
   157      if not tags:
   158          tags = []
   159  
   160      if vfs2 and not fuse:
   161          # Generate a vfs1 plain test. Most testing will now be
   162          # biased towards vfs2, with only a single vfs1 case.
   163          _syscall_test(
   164              test = test,
   165              platform = default_platform,
   166              use_tmpfs = use_tmpfs,
   167              add_uds_tree = add_uds_tree,
   168              tags = tags + platforms[default_platform],
   169              debug = debug,
   170              vfs2 = False,
   171              **kwargs
   172          )
   173  
   174      if not fuse:
   175          # Generate a native test if fuse is not required.
   176          _syscall_test(
   177              test = test,
   178              platform = "native",
   179              use_tmpfs = False,
   180              add_uds_tree = add_uds_tree,
   181              tags = tags,
   182              debug = debug,
   183              **kwargs
   184          )
   185  
   186      for (platform, platform_tags) in platforms.items():
   187          _syscall_test(
   188              test = test,
   189              platform = platform,
   190              use_tmpfs = use_tmpfs,
   191              add_uds_tree = add_uds_tree,
   192              tags = platform_tags + tags,
   193              fuse = fuse,
   194              vfs2 = vfs2,
   195              debug = debug,
   196              **kwargs
   197          )
   198  
   199      if add_overlay:
   200          _syscall_test(
   201              test = test,
   202              platform = default_platform,
   203              use_tmpfs = use_tmpfs,
   204              add_uds_tree = add_uds_tree,
   205              tags = platforms[default_platform] + tags,
   206              debug = debug,
   207              fuse = fuse,
   208              vfs2 = vfs2,
   209              overlay = True,
   210              **kwargs
   211          )
   212      if add_hostinet:
   213          _syscall_test(
   214              test = test,
   215              platform = default_platform,
   216              use_tmpfs = use_tmpfs,
   217              network = "host",
   218              add_uds_tree = add_uds_tree,
   219              tags = platforms[default_platform] + tags,
   220              debug = debug,
   221              fuse = fuse,
   222              vfs2 = vfs2,
   223              **kwargs
   224          )
   225      if not use_tmpfs:
   226          # Also test shared gofer access.
   227          _syscall_test(
   228              test = test,
   229              platform = default_platform,
   230              use_tmpfs = use_tmpfs,
   231              add_uds_tree = add_uds_tree,
   232              tags = platforms[default_platform] + tags,
   233              debug = debug,
   234              file_access = "shared",
   235              fuse = fuse,
   236              vfs2 = vfs2,
   237              **kwargs
   238          )