diff options
Diffstat (limited to 'tools/testing/selftests/net/lib/py/utils.py')
| -rw-r--r-- | tools/testing/selftests/net/lib/py/utils.py | 45 | 
1 files changed, 34 insertions, 11 deletions
| diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py index f395c90fb0f1..cb40ecef9456 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -1,9 +1,7 @@  # SPDX-License-Identifier: GPL-2.0 -import errno  import json as _json  import os -import random  import re  import select  import socket @@ -21,17 +19,19 @@ def fd_read_timeout(fd, timeout):      rlist, _, _ = select.select([fd], [], [], timeout)      if rlist:          return os.read(fd, 1024) -    else: -        raise TimeoutError("Timeout waiting for fd read") +    raise TimeoutError("Timeout waiting for fd read")  class cmd:      """      Execute a command on local or remote host. +    @shell defaults to false, and class will try to split @comm into a list +    if it's a string with spaces. +      Use bkg() instead to run a command in the background.      """ -    def __init__(self, comm, shell=True, fail=True, ns=None, background=False, +    def __init__(self, comm, shell=None, fail=True, ns=None, background=False,                   host=None, timeout=5, ksft_wait=None):          if ns:              comm = f'ip netns exec {ns} ' + comm @@ -45,6 +45,10 @@ class cmd:          if host:              self.proc = host.cmd(comm)          else: +            # If user doesn't explicitly request shell try to avoid it. +            if shell is None and isinstance(comm, str) and ' ' in comm: +                comm = comm.split() +              # ksft_wait lets us wait for the background process to fully start,              # we pass an FD to the child process, and wait for it to write back.              # Similarly term_fd tells child it's time to exit. @@ -111,12 +115,13 @@ class bkg(cmd):          with bkg("my_binary", ksft_wait=5):      """ -    def __init__(self, comm, shell=True, fail=None, ns=None, host=None, +    def __init__(self, comm, shell=None, fail=None, ns=None, host=None,                   exit_wait=False, ksft_wait=None):          super().__init__(comm, background=True,                           shell=shell, fail=fail, ns=ns, host=host,                           ksft_wait=ksft_wait)          self.terminate = not exit_wait and not ksft_wait +        self._exit_wait = exit_wait          self.check_fail = fail          if shell and self.terminate: @@ -127,7 +132,9 @@ class bkg(cmd):          return self      def __exit__(self, ex_type, ex_value, ex_tb): -        return self.process(terminate=self.terminate, fail=self.check_fail) +        # Force termination on exception +        terminate = self.terminate or (self._exit_wait and ex_type) +        return self.process(terminate=terminate, fail=self.check_fail)  global_defer_queue = [] @@ -135,8 +142,6 @@ global_defer_queue = []  class defer:      def __init__(self, func, *args, **kwargs): -        global global_defer_queue -          if not callable(func):              raise Exception("defer created with un-callable object, did you call the function instead of passing its name?") @@ -224,11 +229,11 @@ def bpftrace(expr, json=None, ns=None, host=None, timeout=None):      return cmd_obj -def rand_port(type=socket.SOCK_STREAM): +def rand_port(stype=socket.SOCK_STREAM):      """      Get a random unprivileged port.      """ -    with socket.socket(socket.AF_INET6, type) as s: +    with socket.socket(socket.AF_INET6, stype) as s:          s.bind(("", 0))          return s.getsockname()[1] @@ -249,3 +254,21 @@ def wait_port_listen(port, proto="tcp", ns=None, host=None, sleep=0.005, deadlin          if time.monotonic() > end:              raise Exception("Waiting for port listen timed out")          time.sleep(sleep) + + +def wait_file(fname, test_fn, sleep=0.005, deadline=5, encoding='utf-8'): +    """ +    Wait for file contents on the local system to satisfy a condition. +    test_fn() should take one argument (file contents) and return whether +    condition is met. +    """ +    end = time.monotonic() + deadline + +    with open(fname, "r", encoding=encoding) as fp: +        while True: +            if test_fn(fp.read()): +                break +            fp.seek(0) +            if time.monotonic() > end: +                raise TimeoutError("Wait for file contents failed", fname) +            time.sleep(sleep) | 
