diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2024-04-20 05:52:36 +0300 | 
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2024-04-23 20:13:56 +0300 | 
| commit | 31611cea8f0f45f0b803b010be47a37792ba58a8 (patch) | |
| tree | 7788f24597ab1bc6d4c2b58ec2aab71efdd19ff2 /tools/testing/selftests/net/lib/py/utils.py | |
| parent | 01b431641c33d488ecc6cd6d9e01f7f073bfa54f (diff) | |
| download | linux-31611cea8f0f45f0b803b010be47a37792ba58a8.tar.xz | |
selftests: drv-net: add a TCP ping test case (and useful helpers)
More complex tests often have to spawn a background process,
like a server which will respond to requests or tcpdump.
Add support for creating such processes using the with keyword:
  with bkg("my-daemon", ..):
     # my-daemon is alive in this block
My initial thought was to add this support to cmd() directly
but it runs the command in the constructor, so by the time
we __enter__ it's too late to make sure we used "background=True".
Second useful helper transplanted from net_helper.sh is
wait_port_listen().
The test itself uses socat, which insists on v6 addresses
being wrapped in [], it's not the only command which requires
this format, so add the wrapped address to env. The hope
is to save test code from checking if address is v6.
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://lore.kernel.org/r/20240420025237.3309296-7-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'tools/testing/selftests/net/lib/py/utils.py')
| -rw-r--r-- | tools/testing/selftests/net/lib/py/utils.py | 43 | 
1 files changed, 43 insertions, 0 deletions
| diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py index 7347d0c0ff05..d3715e6c21f2 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -1,7 +1,11 @@  # SPDX-License-Identifier: GPL-2.0  import json as _json +import random +import re  import subprocess +import time +  class cmd:      def __init__(self, comm, shell=True, fail=True, ns=None, background=False, host=None): @@ -38,6 +42,20 @@ class cmd:                              (self.proc.args, stdout, stderr)) +class bkg(cmd): +    def __init__(self, comm, shell=True, fail=True, ns=None, host=None, +                 exit_wait=False): +        super().__init__(comm, background=True, +                         shell=shell, fail=fail, ns=ns, host=host) +        self.terminate = not exit_wait + +    def __enter__(self): +        return self + +    def __exit__(self, ex_type, ex_value, ex_tb): +        return self.process(terminate=self.terminate) + +  def ip(args, json=None, ns=None, host=None):      cmd_str = "ip "      if json: @@ -47,3 +65,28 @@ def ip(args, json=None, ns=None, host=None):      if json:          return _json.loads(cmd_obj.stdout)      return cmd_obj + + +def rand_port(): +    """ +    Get unprivileged port, for now just random, one day we may decide to check if used. +    """ +    return random.randint(1024, 65535) + + +def wait_port_listen(port, proto="tcp", ns=None, host=None, sleep=0.005, deadline=5): +    end = time.monotonic() + deadline + +    pattern = f":{port:04X} .* " +    if proto == "tcp": # for tcp protocol additionally check the socket state +        pattern += "0A" +    pattern = re.compile(pattern) + +    while True: +        data = cmd(f'cat /proc/net/{proto}*', ns=ns, host=host, shell=True).stdout +        for row in data.split("\n"): +            if pattern.search(row): +                return +        if time.monotonic() > end: +            raise Exception("Waiting for port listen timed out") +        time.sleep(sleep) | 
