]> git.puffer.fish Git - matthieu/frr.git/commitdiff
tests: import munet version 0.13.1
authorChristian Hopps <chopps@labn.net>
Sun, 23 Apr 2023 05:29:49 +0000 (01:29 -0400)
committerChristian Hopps <chopps@labn.net>
Sun, 23 Apr 2023 13:51:46 +0000 (09:51 -0400)
- adds more generic config option handling than pytestconfig
- Change to search order for kinds.yaml

Signed-off-by: Christian Hopps <chopps@labn.net>
tests/topotests/munet/base.py
tests/topotests/munet/compat.py
tests/topotests/munet/config.py
tests/topotests/munet/native.py
tests/topotests/munet/parser.py

index 38da7faa0169882ea6aadd617db6a65bcf01156e..eb4b088442da9c3e756d337cb6ac0f7e1601043e 100644 (file)
@@ -26,6 +26,7 @@ from collections import defaultdict
 from pathlib import Path
 from typing import Union
 
+from . import config as munet_config
 from . import linux
 
 
@@ -2493,7 +2494,15 @@ class Bridge(SharedNamespace, InterfaceMixin):
 class BaseMunet(LinuxNamespace):
     """Munet."""
 
-    def __init__(self, name="munet", isolated=True, pid=True, rundir=None, **kwargs):
+    def __init__(
+        self,
+        name="munet",
+        isolated=True,
+        pid=True,
+        rundir=None,
+        pytestconfig=None,
+        **kwargs,
+    ):
         """Create a Munet."""
         # logging.warning("BaseMunet: %s", name)
 
@@ -2562,6 +2571,8 @@ class BaseMunet(LinuxNamespace):
 
         roothost = self.rootcmd
 
+        self.cfgopt = munet_config.ConfigOptionsProxy(pytestconfig)
+
         super().__init__(
             name, mount=True, net=isolated, uts=isolated, pid=pid, unet=None, **kwargs
         )
index bf9092e53aa794d6c1a4eccb6cfde2c33c8063ed..e82a7d5b77293714c78485187437455313811ddd 100644 (file)
 class PytestConfig:
     """Pytest config duck-type-compatible object using argprase args."""
 
+    class Namespace:
+        """A namespace defined by a dictionary of values."""
+
+        def __init__(self, args):
+            self.args = args
+
+        def __getattr__(self, attr):
+            return self.args[attr] if attr in self.args else None
+
     def __init__(self, args):
         self.args = vars(args)
+        self.option = PytestConfig.Namespace(self.args)
 
     def getoption(self, name, default=None, skip=False):
         assert not skip
index b66e4d17da079051af7683a8170ce469f014a929..1b02f2e8ff166273c8b803634ef51f1a400ff168 100644 (file)
@@ -156,3 +156,57 @@ def merge_kind_config(kconf, config):
         if k not in new:
             new[k] = config[k]
     return new
+
+
+def cli_opt_list(option_list):
+    if not option_list:
+        return []
+    if isinstance(option_list, str):
+        return [x for x in option_list.split(",") if x]
+    return [x for x in option_list if x]
+
+
+def name_in_cli_opt_str(name, option_list):
+    ol = cli_opt_list(option_list)
+    return name in ol or "all" in ol
+
+
+class ConfigOptionsProxy:
+    """Proxy options object to fill in for any missing pytest config."""
+
+    class DefNoneObject:
+        """An object that returns None for any attribute access."""
+
+        def __getattr__(self, attr):
+            return None
+
+    def __init__(self, pytestconfig=None):
+        if isinstance(pytestconfig, ConfigOptionsProxy):
+            self.config = pytestconfig.config
+            self.option = self.config.option
+        else:
+            self.config = pytestconfig
+        if self.config:
+            self.option = self.config.option
+        else:
+            self.option = ConfigOptionsProxy.DefNoneObject()
+
+    def getoption(self, opt, defval=None):
+        if not self.config:
+            return defval
+
+        try:
+            return self.config.getoption(opt, default=defval)
+        except ValueError:
+            return defval
+
+    def get_option(self, opt, defval=None):
+        return self.getoption(opt, defval)
+
+    def get_option_list(self, opt):
+        value = self.get_option(opt, "")
+        return cli_opt_list(value)
+
+    def name_in_option_list(self, name, opt):
+        optlist = self.get_option_list(opt)
+        return "all" in optlist or name in optlist
index 5e79b04b8a73679a2bf6415b0d7d2c467ac54583..fecf709d1aaab385e5d1321db8fd83615f6c66a1 100644 (file)
@@ -423,37 +423,37 @@ class NodeMixin:
             stdout: file-like object with a ``name`` attribute, or a path to a file.
             stderr: file-like object with a ``name`` attribute, or a path to a file.
         """
-        if not self.unet or not self.unet.pytest_config:
+        if not self.unet:
             return
 
-        outopt = self.unet.pytest_config.getoption("--stdout")
+        outopt = self.unet.cfgopt.getoption("--stdout")
         outopt = outopt if outopt is not None else ""
         if outopt == "all" or self.name in outopt.split(","):
             outname = stdout.name if hasattr(stdout, "name") else stdout
             self.run_in_window(f"tail -F {outname}", title=f"O:{self.name}")
 
         if stderr:
-            erropt = self.unet.pytest_config.getoption("--stderr")
+            erropt = self.unet.cfgopt.getoption("--stderr")
             erropt = erropt if erropt is not None else ""
             if erropt == "all" or self.name in erropt.split(","):
                 errname = stderr.name if hasattr(stderr, "name") else stderr
                 self.run_in_window(f"tail -F {errname}", title=f"E:{self.name}")
 
     def pytest_hook_open_shell(self):
-        if not self.unet or not self.unet.pytest_config:
+        if not self.unet:
             return
 
         gdbcmd = self.config.get("gdb-cmd")
-        shellopt = self.unet.pytest_config.getoption("--gdb", "")
+        shellopt = self.unet.cfgopt.getoption("--gdb", "")
         should_gdb = gdbcmd and (shellopt == "all" or self.name in shellopt.split(","))
-        use_emacs = self.unet.pytest_config.getoption("--gdb-use-emacs", False)
+        use_emacs = self.unet.cfgopt.getoption("--gdb-use-emacs", False)
 
         if should_gdb and not use_emacs:
             cmds = self.config.get("gdb-target-cmds", [])
             for cmd in cmds:
                 gdbcmd += f" '-ex={cmd}'"
 
-            bps = self.unet.pytest_config.getoption("--gdb-breakpoints", "").split(",")
+            bps = self.unet.cfgopt.getoption("--gdb-breakpoints", "").split(",")
             for bp in bps:
                 gdbcmd += f" '-ex=b {bp}'"
 
@@ -497,7 +497,7 @@ class NodeMixin:
                     ]
                 )
 
-            bps = self.unet.pytest_config.getoption("--gdb-breakpoints", "").split(",")
+            bps = self.unet.cfgopt.getoption("--gdb-breakpoints", "").split(",")
             for bp in bps:
                 cmd = f"br {bp}"
                 self.cmd_raises(
@@ -520,8 +520,8 @@ class NodeMixin:
                 )
                 gdbcmd += f" '-ex={cmd}'"
 
-        shellopt = self.unet.pytest_config.getoption("--shell")
-        shellopt = shellopt if shellopt is not None else ""
+        shellopt = self.unet.cfgopt.getoption("--shell")
+        shellopt = shellopt if shellopt else ""
         if shellopt == "all" or self.name in shellopt.split(","):
             self.run_in_window("bash")
 
@@ -1968,7 +1968,7 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
                     con.cmd_raises(f"ip -6 route add default via {switch.ip6_address}")
         con.cmd_raises("ip link set lo up")
 
-        if self.unet.pytest_config and self.unet.pytest_config.getoption("--coverage"):
+        if self.unet.cfgopt.getoption("--coverage"):
             con.cmd_raises("mount -t debugfs none /sys/kernel/debug")
 
     async def gather_coverage_data(self):
@@ -2402,7 +2402,6 @@ class Munet(BaseMunet):
         self,
         rundir=None,
         config=None,
-        pytestconfig=None,
         pid=True,
         logger=None,
         **kwargs,
@@ -2433,8 +2432,6 @@ class Munet(BaseMunet):
             self.config_pathname = ""
             self.config_dirname = ""
 
-        self.pytest_config = pytestconfig
-
         # Done in BaseMunet now
         # # We need some way to actually get back to the root namespace
         # if not self.isolated:
@@ -2573,10 +2570,8 @@ ff02::2\tip6-allrouters
         #     # Let's hide podman details
         #     self.tmpfs_mount("/var/lib/containers/storage/overlay-containers")
 
-        shellopt = (
-            self.pytest_config.getoption("--shell") if self.pytest_config else None
-        )
-        shellopt = shellopt if shellopt is not None else ""
+        shellopt = self.cfgopt.getoption("--shell")
+        shellopt = shellopt if shellopt else ""
         if shellopt == "all" or "." in shellopt.split(","):
             self.run_in_window("bash")
 
@@ -2795,11 +2790,8 @@ ff02::2\tip6-allrouters
             x for x in hosts if hasattr(x, "has_ready_cmd") and x.has_ready_cmd()
         ]
 
-        if not self.pytest_config:
-            pcapopt = ""
-        else:
-            pcapopt = self.pytest_config.getoption("--pcap")
-            pcapopt = pcapopt if pcapopt else ""
+        pcapopt = self.cfgopt.getoption("--pcap")
+        pcapopt = pcapopt if pcapopt else ""
         if pcapopt == "all":
             pcapopt = self.switches.keys()
         if pcapopt:
@@ -2868,7 +2860,7 @@ ff02::2\tip6-allrouters
 
         self.logger.debug("%s: deleting.", self)
 
-        if self.pytest_config and self.pytest_config.getoption("--coverage"):
+        if self.cfgopt.getoption("--coverage"):
             nodes = (
                 x for x in self.hosts.values() if hasattr(x, "gather_coverage_data")
             )
@@ -2877,11 +2869,8 @@ ff02::2\tip6-allrouters
             except Exception as error:
                 logging.warning("Error gathering coverage data: %s", error)
 
-        if not self.pytest_config:
-            pause = False
-        else:
-            pause = bool(self.pytest_config.getoption("--pause-at-end"))
-            pause = pause or bool(self.pytest_config.getoption("--pause"))
+        pause = bool(self.cfgopt.getoption("--pause-at-end"))
+        pause = pause or bool(self.cfgopt.getoption("--pause"))
         if pause:
             try:
                 await async_pause_test("Before MUNET delete")
index f92138d7b82f421f71ff730f3cf8ac1afd20f92a..4fc0c75a60ed900446db85d1703048705f70d70c 100644 (file)
@@ -235,7 +235,7 @@ def load_kinds(args, search=None):
         if search is None:
             search = [cwd]
         with importlib.resources.path("munet", "kinds.yaml") as datapath:
-            search.append(str(datapath.parent))
+            search.insert(0, str(datapath.parent))
 
         configs = []
         if args_config: