gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/packetimpact/runner/defs.bzl (about)

     1  """Defines rules for packetimpact test targets."""
     2  
     3  load("//tools:defs.bzl", "go_test")
     4  
     5  def _packetimpact_test_impl(ctx):
     6      test_runner = ctx.executable.test_runner
     7      bench = ctx.actions.declare_file("%s-bench" % ctx.label.name)
     8      dut_binary_flag = [] if ctx.attr.dut_binary == None else [
     9          "--dut_binary",
    10          ctx.file.dut_binary.short_path,
    11      ]
    12      bench_content = "\n".join([
    13          "#!/bin/bash",
    14          # This test will run part in a distinct user namespace. This can cause
    15          # permission problems, because all runfiles may not be owned by the
    16          # current user, and no other users will be mapped in that namespace.
    17          # Make sure that everything is readable here.
    18          "find . -type f -or -type d -exec chmod a+rx {} \\;",
    19          "%s %s --testbench_binary %s --num_duts %d $@\n" % (
    20              test_runner.short_path,
    21              " ".join(ctx.attr.flags + dut_binary_flag),
    22              ctx.files.testbench_binary[0].short_path,
    23              ctx.attr.num_duts,
    24          ),
    25      ])
    26      ctx.actions.write(bench, bench_content, is_executable = True)
    27  
    28      transitive_files = []
    29      if hasattr(ctx.attr.test_runner, "data_runfiles"):
    30          transitive_files.append(ctx.attr.test_runner.data_runfiles.files)
    31      if hasattr(ctx.attr.dut_binary, "data_runfiles"):
    32          transitive_files.append(ctx.attr.dut_binary.data_runfiles.files)
    33      files = [test_runner] + ctx.files.testbench_binary + ctx.files._posix_server + ctx.files.dut_binary
    34      runfiles = ctx.runfiles(
    35          files = files,
    36          transitive_files = depset(transitive = transitive_files),
    37          collect_default = True,
    38          collect_data = True,
    39      )
    40      return [DefaultInfo(executable = bench, runfiles = runfiles)]
    41  
    42  _packetimpact_test = rule(
    43      attrs = {
    44          "test_runner": attr.label(
    45              executable = True,
    46              cfg = "target",
    47              default = ":packetimpact_test",
    48          ),
    49          "_posix_server": attr.label(
    50              cfg = "target",
    51              default = "//test/packetimpact/dut:posix_server",
    52          ),
    53          "testbench_binary": attr.label(
    54              cfg = "target",
    55              mandatory = True,
    56          ),
    57          "flags": attr.string_list(
    58              mandatory = False,
    59              default = [],
    60          ),
    61          "num_duts": attr.int(
    62              mandatory = False,
    63              default = 1,
    64          ),
    65          "dut_binary": attr.label(
    66              executable = True,
    67              cfg = "target",
    68              allow_single_file = True,
    69          ),
    70      },
    71      test = True,
    72      implementation = _packetimpact_test_impl,
    73  )
    74  
    75  PACKETIMPACT_TAGS = [
    76      "manual",
    77      "notap",
    78      "packetimpact",
    79  ]
    80  
    81  def packetimpact_native_test(
    82          name,
    83          testbench_binary,
    84          expect_failure = False,
    85          **kwargs):
    86      """Add a native packetimpact test.
    87  
    88      Args:
    89          name: name of the test
    90          testbench_binary: the testbench binary
    91          expect_failure: the test must fail
    92          **kwargs: all the other args, forwarded to _packetimpact_test
    93      """
    94      expect_failure_flag = ["--expect_failure"] if expect_failure else []
    95      _packetimpact_test(
    96          test_runner = "//test/packetimpact/runner:main",
    97          name = name + "_native_test",
    98          testbench_binary = testbench_binary,
    99          flags = expect_failure_flag + ["--variant", "native"],
   100          dut_binary = "//test/packetimpact/dut/native",
   101          tags = PACKETIMPACT_TAGS,
   102          **kwargs
   103      )
   104  
   105  def packetimpact_netstack_test(
   106          name,
   107          testbench_binary,
   108          expect_failure = False,
   109          **kwargs):
   110      """Add a packetimpact test on netstack.
   111  
   112      Args:
   113          name: name of the test
   114          testbench_binary: the testbench binary
   115          expect_failure: the test must fail
   116          **kwargs: all the other args, forwarded to _packetimpact_test
   117      """
   118      expect_failure_flag = []
   119      if expect_failure:
   120          expect_failure_flag = ["--expect_failure"]
   121      _packetimpact_test(
   122          test_runner = "//test/packetimpact/runner:main",
   123          name = name + "_netstack_test",
   124          testbench_binary = testbench_binary,
   125          flags = expect_failure_flag + ["--variant", "gvisor"],
   126          dut_binary = "//test/packetimpact/dut/runsc",
   127          tags = PACKETIMPACT_TAGS,
   128          **kwargs
   129      )
   130  
   131  def packetimpact_go_test(name, expect_native_failure = False, expect_netstack_failure = False, num_duts = 1, **kwargs):
   132      """Add packetimpact tests written in go.
   133  
   134      Args:
   135          name: name of the test
   136          expect_native_failure: the test must fail natively
   137          expect_netstack_failure: the test must fail for Netstack
   138          num_duts: how many DUTs are needed for the test
   139          **kwargs: all the other args, forwarded to packetimpact_native_test and packetimpact_netstack_test
   140      """
   141      testbench_binary = name + "_test"
   142      packetimpact_native_test(
   143          name = name,
   144          expect_failure = expect_native_failure,
   145          num_duts = num_duts,
   146          testbench_binary = testbench_binary,
   147          **kwargs
   148      )
   149      packetimpact_netstack_test(
   150          name = name,
   151          expect_failure = expect_netstack_failure,
   152          num_duts = num_duts,
   153          testbench_binary = testbench_binary,
   154          **kwargs
   155      )
   156  
   157  def packetimpact_testbench(name, size = "small", pure = True, **kwargs):
   158      """Build packetimpact testbench written in go.
   159  
   160      Args:
   161          name: name of the test
   162          size: size of the test
   163          pure: make a static go binary
   164          **kwargs: all the other args, forwarded to go_test
   165      """
   166      go_test(
   167          name = name + "_test",
   168          size = size,
   169          pure = pure,
   170          nogo = False,  # FIXME(gvisor.dev/issue/3374): Not working with all build systems.
   171          tags = [
   172              "manual",
   173              "notap",
   174          ],
   175          **kwargs
   176      )
   177  
   178  PacketimpactTestInfo = provider(
   179      doc = "Provide information for packetimpact tests",
   180      fields = [
   181          "name",
   182          "timeout",
   183          "expect_netstack_failure",
   184          "num_duts",
   185      ],
   186  )
   187  
   188  ALL_TESTS = [
   189      PacketimpactTestInfo(
   190          name = "fin_wait2_timeout",
   191      ),
   192      PacketimpactTestInfo(
   193          name = "ipv4_id_uniqueness",
   194      ),
   195      PacketimpactTestInfo(
   196          name = "udp_discard_mcast_source_addr",
   197      ),
   198      PacketimpactTestInfo(
   199          name = "udp_any_addr_recv_unicast",
   200      ),
   201      PacketimpactTestInfo(
   202          name = "udp_icmp_error_propagation",
   203      ),
   204      PacketimpactTestInfo(
   205          name = "tcp_window_shrink",
   206      ),
   207      PacketimpactTestInfo(
   208          name = "tcp_zero_window_probe",
   209      ),
   210      PacketimpactTestInfo(
   211          name = "tcp_zero_window_probe_retransmit",
   212      ),
   213      PacketimpactTestInfo(
   214          name = "tcp_zero_window_probe_usertimeout",
   215      ),
   216      PacketimpactTestInfo(
   217          name = "tcp_retransmits",
   218      ),
   219      PacketimpactTestInfo(
   220          name = "tcp_outside_the_window",
   221      ),
   222      PacketimpactTestInfo(
   223          name = "tcp_noaccept_close_rst",
   224      ),
   225      PacketimpactTestInfo(
   226          name = "tcp_send_window_sizes_piggyback",
   227      ),
   228      PacketimpactTestInfo(
   229          name = "tcp_unacc_seq_ack",
   230      ),
   231      PacketimpactTestInfo(
   232          name = "tcp_paws_mechanism",
   233          # TODO(b/156682000): Fix netstack then remove the line below.
   234          expect_netstack_failure = True,
   235      ),
   236      PacketimpactTestInfo(
   237          name = "tcp_user_timeout",
   238      ),
   239      PacketimpactTestInfo(
   240          name = "tcp_zero_receive_window",
   241      ),
   242      PacketimpactTestInfo(
   243          name = "tcp_queue_send_recv_in_syn_sent",
   244      ),
   245      PacketimpactTestInfo(
   246          name = "tcp_synsent_reset",
   247      ),
   248      PacketimpactTestInfo(
   249          name = "tcp_synrcvd_reset",
   250      ),
   251      PacketimpactTestInfo(
   252          name = "tcp_network_unreachable",
   253      ),
   254      PacketimpactTestInfo(
   255          name = "tcp_cork_mss",
   256      ),
   257      PacketimpactTestInfo(
   258          name = "tcp_handshake_window_size",
   259      ),
   260      PacketimpactTestInfo(
   261          name = "tcp_timewait_reset",
   262          # TODO(b/168523247): Fix netstack then remove the line below.
   263          expect_netstack_failure = True,
   264      ),
   265      PacketimpactTestInfo(
   266          name = "tcp_listen_backlog",
   267      ),
   268      PacketimpactTestInfo(
   269          name = "tcp_syncookie",
   270      ),
   271      PacketimpactTestInfo(
   272          name = "tcp_connect_icmp_error",
   273      ),
   274      PacketimpactTestInfo(
   275          name = "icmpv6_param_problem",
   276      ),
   277      PacketimpactTestInfo(
   278          name = "ipv6_unknown_options_action",
   279      ),
   280      PacketimpactTestInfo(
   281          name = "ipv4_fragment_reassembly",
   282      ),
   283      PacketimpactTestInfo(
   284          name = "ipv6_fragment_reassembly",
   285      ),
   286      PacketimpactTestInfo(
   287          name = "ipv6_fragment_icmp_error",
   288          num_duts = 3,
   289      ),
   290      PacketimpactTestInfo(
   291          name = "tcp_linger",
   292      ),
   293      PacketimpactTestInfo(
   294          name = "tcp_rcv_buf_space",
   295      ),
   296      PacketimpactTestInfo(
   297          name = "tcp_rack",
   298          expect_netstack_failure = True,
   299      ),
   300      PacketimpactTestInfo(
   301          name = "tcp_info",
   302      ),
   303      PacketimpactTestInfo(
   304          name = "tcp_fin_retransmission",
   305      ),
   306      PacketimpactTestInfo(
   307          name = "generic_dgram_socket_send_recv",
   308          timeout = "long",
   309      ),
   310      PacketimpactTestInfo(
   311          name = "tcp_acceptable_ack_syn_rcvd",
   312      ),
   313  ]
   314  
   315  def validate_all_tests():
   316      """
   317      Make sure that ALL_TESTS list is in sync with the rules in BUILD.
   318  
   319      This function is order-dependent, it is intended to be used after
   320      all packetimpact_testbench rules and before using ALL_TESTS list
   321      at the end of BUILD.
   322      """
   323      all_tests_dict = {}  # there is no set, using dict to approximate.
   324      for test in ALL_TESTS:
   325          rule_name = test.name + "_test"
   326          all_tests_dict[rule_name] = True
   327          if not native.existing_rule(rule_name):
   328              fail("%s does not have a packetimpact_testbench rule in BUILD" % test.name)
   329      for name in native.existing_rules():
   330          if name.endswith("_test") and name not in all_tests_dict:
   331              fail("%s is not declared in ALL_TESTS list in defs.bzl" % name[:-5])