tests: update run.py to skip building vpp when running tests 39/42839/4
authorNaveen Joy <najoy@cisco.com>
Fri, 18 Apr 2025 00:58:28 +0000 (17:58 -0700)
committerDamjan Marion <dmarion@0xa5.net>
Wed, 23 Apr 2025 08:23:41 +0000 (08:23 +0000)
Use make to build vpp before running tests using run.py. Also, fixes
an issue when running tests against an exisiting vpp caused due to
asfframework refactoring.

Type: test

Change-Id: I252a4083db6384caf799095d07f79a9f01240358
Signed-off-by: Naveen Joy <najoy@cisco.com>
test/asf/asfframework.py
test/framework.py
test/run.py [changed mode: 0755->0644]
test/scripts/run_vpp_in_vm.sh
test/vpp_running.py

index 7670a07..8983826 100644 (file)
@@ -23,6 +23,7 @@ from traceback import format_exception
 from logging import FileHandler, DEBUG, Formatter
 from enum import Enum
 from abc import ABC, abstractmethod
+from vpp_running import use_running
 
 from config import config, max_vpp_cpus
 import hook as hookmodule
@@ -103,49 +104,58 @@ def pump_output(testclass):
     """pump output from vpp stdout/stderr to proper queues"""
     stdout_fragment = ""
     stderr_fragment = ""
-    while not testclass.pump_thread_stop_flag.is_set():
-        readable = select.select(
-            [
-                testclass.vpp.stdout.fileno(),
-                testclass.vpp.stderr.fileno(),
-                testclass.pump_thread_wakeup_pipe[0],
-            ],
-            [],
-            [],
-        )[0]
-        if testclass.vpp.stdout.fileno() in readable:
-            read = os.read(testclass.vpp.stdout.fileno(), 102400)
-            if len(read) > 0:
-                split = read.decode("ascii", errors="backslashreplace").splitlines(True)
-                if len(stdout_fragment) > 0:
-                    split[0] = "%s%s" % (stdout_fragment, split[0])
-                if len(split) > 0 and split[-1].endswith("\n"):
-                    limit = None
-                else:
-                    limit = -1
-                    stdout_fragment = split[-1]
-                testclass.vpp_stdout_deque.extend(split[:limit])
-                if not config.cache_vpp_output:
-                    for line in split[:limit]:
-                        testclass.logger.info("VPP STDOUT: %s" % line.rstrip("\n"))
-        if testclass.vpp.stderr.fileno() in readable:
-            read = os.read(testclass.vpp.stderr.fileno(), 102400)
-            if len(read) > 0:
-                split = read.decode("ascii", errors="backslashreplace").splitlines(True)
-                if len(stderr_fragment) > 0:
-                    split[0] = "%s%s" % (stderr_fragment, split[0])
-                if len(split) > 0 and split[-1].endswith("\n"):
-                    limit = None
-                else:
-                    limit = -1
-                    stderr_fragment = split[-1]
-
-                testclass.vpp_stderr_deque.extend(split[:limit])
-                if not config.cache_vpp_output:
-                    for line in split[:limit]:
-                        testclass.logger.error("VPP STDERR: %s" % line.rstrip("\n"))
-                        # ignoring the dummy pipe here intentionally - the
-                        # flag will take care of properly terminating the loop
+    # catch and ignore pump thread exception when running tests
+    # against a running vpp
+    try:
+        while not testclass.pump_thread_stop_flag.is_set():
+            readable = select.select(
+                [
+                    testclass.vpp.stdout.fileno(),
+                    testclass.vpp.stderr.fileno(),
+                    testclass.pump_thread_wakeup_pipe[0],
+                ],
+                [],
+                [],
+            )[0]
+            if testclass.vpp.stdout.fileno() in readable:
+                read = os.read(testclass.vpp.stdout.fileno(), 102400)
+                if len(read) > 0:
+                    split = read.decode("ascii", errors="backslashreplace").splitlines(
+                        True
+                    )
+                    if len(stdout_fragment) > 0:
+                        split[0] = "%s%s" % (stdout_fragment, split[0])
+                    if len(split) > 0 and split[-1].endswith("\n"):
+                        limit = None
+                    else:
+                        limit = -1
+                        stdout_fragment = split[-1]
+                    testclass.vpp_stdout_deque.extend(split[:limit])
+                    if not config.cache_vpp_output:
+                        for line in split[:limit]:
+                            testclass.logger.info("VPP STDOUT: %s" % line.rstrip("\n"))
+            if testclass.vpp.stderr.fileno() in readable:
+                read = os.read(testclass.vpp.stderr.fileno(), 102400)
+                if len(read) > 0:
+                    split = read.decode("ascii", errors="backslashreplace").splitlines(
+                        True
+                    )
+                    if len(stderr_fragment) > 0:
+                        split[0] = "%s%s" % (stderr_fragment, split[0])
+                    if len(split) > 0 and split[-1].endswith("\n"):
+                        limit = None
+                    else:
+                        limit = -1
+                        stderr_fragment = split[-1]
+
+                    testclass.vpp_stderr_deque.extend(split[:limit])
+                    if not config.cache_vpp_output:
+                        for line in split[:limit]:
+                            testclass.logger.error("VPP STDERR: %s" % line.rstrip("\n"))
+                            # ignoring the dummy pipe here intentionally - the
+                            # flag will take care of properly terminating the loop
+    except AttributeError:
+        pass
 
 
 def _is_platform_aarch64():
@@ -260,6 +270,7 @@ class CPUInterface(ABC):
         cls.cpus = cpus
 
 
+@use_running
 class VppAsfTestCase(CPUInterface, unittest.TestCase):
     """This subclass is a base class for VPP test cases that are implemented as
     classes. It provides methods to create and run test case.
index 62fa1fe..05d1018 100644 (file)
@@ -38,7 +38,6 @@ from util import ppp, is_core_present
 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
 from scapy.layers.inet6 import ICMPv6DestUnreach, ICMPv6EchoRequest
 from scapy.layers.inet6 import ICMPv6EchoReply
-from vpp_running import use_running
 from asfframework import VppAsfTestCase
 
 
@@ -82,7 +81,6 @@ class _PacketInfo(object):
         return index and src and dst and data
 
 
-@use_running
 class VppTestCase(VppAsfTestCase):
     """This subclass is a base class for VPP test cases that are implemented as
     classes. It provides methods to create and run test case.
old mode 100755 (executable)
new mode 100644 (file)
index 66764b7..2e7e9c4
@@ -20,47 +20,15 @@ import glob
 import logging
 import os
 from pathlib import Path
-import signal
-from subprocess import Popen, PIPE, STDOUT, call
+from subprocess import Popen, PIPE, STDOUT, run, CalledProcessError
 import sys
 import time
-import venv
-import datetime
 import re
 
 
-# Required Std. Path Variables
-test_dir = os.path.dirname(os.path.realpath(__file__))
-ws_root = os.path.dirname(test_dir)
-build_root = os.path.join(ws_root, "build-root")
-venv_dir = os.path.join(build_root, "test", "venv")
-venv_bin_dir = os.path.join(venv_dir, "bin")
-venv_lib_dir = os.path.join(venv_dir, "lib")
-venv_run_dir = os.path.join(venv_dir, "run")
-venv_install_done = os.path.join(venv_run_dir, "venv_install.done")
-papi_python_src_dir = os.path.join(ws_root, "src", "vpp-api", "python")
-
-# Path Variables Set after VPP Build/Install
-vpp_build_dir = vpp_install_path = vpp_bin = vpp_lib = vpp_lib64 = None
-vpp_plugin_path = vpp_test_plugin_path = ld_library_path = None
-
-# Pip version pinning
-pip_version = "22.0.4"
-pip_tools_version = "6.6.0"
-
-# Compiled pip requirements file
-pip_compiled_requirements_file = os.path.join(test_dir, "requirements-3.txt")
-
-
-# Gracefully exit after executing cleanup scripts
-# upon receiving a SIGINT or SIGTERM
-def handler(signum, frame):
-    print("Received Signal {0}".format(signum))
-    post_vm_test_run()
-
-
-signal.signal(signal.SIGINT, handler)
-signal.signal(signal.SIGTERM, handler)
+base_dir = Path(__file__).resolve().parent
+ws_root = base_dir.parent
+run_sh = base_dir / "scripts" / "run.sh"
 
 
 def show_progress(stream, exclude_pattern=None):
@@ -91,130 +59,90 @@ def show_progress(stream, exclude_pattern=None):
     stream.close()
 
 
-class ExtendedEnvBuilder(venv.EnvBuilder):
-    """
-    1. Builds a Virtual Environment for running VPP unit tests
-    2. Installs all necessary scripts, pkgs & patches into the vEnv
-         - python3, pip, pip-tools, papi, scapy patches &
-           test-requirement pkgs
-    """
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-    def post_setup(self, context):
-        """
-        Setup all packages that need to be pre-installed into the venv
-        prior to running VPP unit tests.
-
-        :param context: The context of the virtual environment creation
-                        request being processed.
-        """
-        os.environ["VIRTUAL_ENV"] = context.env_dir
-        os.environ["CUSTOM_COMPILE_COMMAND"] = (
-            "make test-refresh-deps (or update requirements.txt)"
-        )
-        # Set the venv python executable & binary install path
-        env_exe = context.env_exe
-        bin_path = context.bin_path
-        # Packages/requirements to be installed in the venv
-        # [python-module, cmdline-args, package-name_or_requirements-file-name]
-        test_req = [
-            ["pip", "install", "pip===%s" % pip_version],
-            ["pip", "install", "pip-tools===%s" % pip_tools_version],
-            ["piptools", "sync", pip_compiled_requirements_file],
-            ["pip", "install", "-e", papi_python_src_dir],
-        ]
-        for req in test_req:
-            args = [env_exe, "-m"]
-            args.extend(req)
-            print(args)
-            p = Popen(args, stdout=PIPE, stderr=STDOUT, cwd=bin_path)
-            show_progress(p.stdout)
-        self.pip_patch()
-
-    def pip_patch(self):
-        """
-        Apply scapy patch files
-        """
-        scapy_patch_dir = Path(os.path.join(test_dir, "patches", "scapy-2.4.3"))
-        scapy_source_dir = glob.glob(
-            os.path.join(venv_lib_dir, "python3.*", "site-packages")
-        )[0]
-        for f in scapy_patch_dir.iterdir():
-            print("Applying patch: {}".format(os.path.basename(str(f))))
-            args = ["patch", "--forward", "-p1", "-d", scapy_source_dir, "-i", str(f)]
-            print(args)
-            p = Popen(args, stdout=PIPE, stderr=STDOUT)
-            show_progress(p.stdout)
-
-
-# Build VPP Release/Debug binaries
-def build_vpp(debug=True, release=False):
-    """
-    Install VPP Release(if release=True) or Debug(if debug=True) Binaries.
-
-    Default is to build the debug binaries.
-    """
-    global vpp_build_dir, vpp_install_path, vpp_bin, vpp_lib, vpp_lib64
-    global vpp_plugin_path, vpp_test_plugin_path, ld_library_path
-    if debug:
-        print("Building VPP debug binaries")
-        args = ["make", "build"]
-        build = "build-vpp_debug-native"
-        install = "install-vpp_debug-native"
-    elif release:
-        print("Building VPP release binaries")
-        args = ["make", "build-release"]
-        build = "build-vpp-native"
-        install = "install-vpp-native"
-    p = Popen(args, stdout=PIPE, stderr=STDOUT, cwd=ws_root)
-    show_progress(p.stdout)
-    vpp_build_dir = os.path.join(build_root, build)
-    vpp_install_path = os.path.join(build_root, install)
-    vpp_bin = os.path.join(vpp_install_path, "vpp", "bin", "vpp")
-    vpp_lib = os.path.join(vpp_install_path, "vpp", "lib")
-    vpp_lib64 = os.path.join(vpp_install_path, "vpp", "lib64")
-    vpp_plugin_path = (
-        os.path.join(vpp_lib, "vpp_plugins")
-        + ":"
-        + os.path.join(vpp_lib64, "vpp_plugins")
-    )
-    vpp_test_plugin_path = (
-        os.path.join(vpp_lib, "vpp_api_test_plugins")
-        + ":"
-        + os.path.join(vpp_lib64, "vpp_api_test_plugins")
-    )
-    ld_library_path = os.path.join(vpp_lib) + ":" + os.path.join(vpp_lib64)
-
-
-# Environment Vars required by the test framework,
-# papi_provider & unittests
-def set_environ():
-    os.environ["WS_ROOT"] = ws_root
-    os.environ["BR"] = build_root
-    os.environ["VENV_PATH"] = venv_dir
-    os.environ["VENV_BIN"] = venv_bin_dir
-    os.environ["RND_SEED"] = str(time.time())
-    os.environ["VPP_BUILD_DIR"] = vpp_build_dir
-    os.environ["VPP_BIN"] = vpp_bin
-    os.environ["VPP_PLUGIN_PATH"] = vpp_plugin_path
-    os.environ["VPP_TEST_PLUGIN_PATH"] = vpp_test_plugin_path
-    os.environ["VPP_INSTALL_PATH"] = vpp_install_path
-    os.environ["LD_LIBRARY_PATH"] = ld_library_path
-    os.environ["FAILED_DIR"] = "/tmp/vpp-failed-unittests/"
-    if not os.environ.get("TEST_JOBS"):
-        os.environ["TEST_JOBS"] = "1"
+def get_env(args):
+    """Build and return test environment variables."""
+    defaults = {
+        "FAILED_DIR": "/tmp/vpp-failed-unittests/",
+        "V": "1",
+        "SKIP_FILTER": "",
+        "RETRIES": "0",
+        "WS_ROOT": str(ws_root),
+        "BR": str(ws_root / "build-root"),
+        "VENV_PATH": str(ws_root / "build-root" / "test" / "venv"),
+        "VPP_BUILD_DIR": str(ws_root / "build-root" / "build-vpp-native" / "vpp"),
+        "VPP_INSTALL_PATH": str(ws_root / "build-root" / "install-vpp-native"),
+        "VPP_BIN": str(
+            ws_root / "build-root" / "install-vpp-native" / "vpp" / "bin" / "vpp"
+        ),
+        "VPP_PLUGIN_PATH": str(
+            ws_root
+            / "build-root"
+            / "install-vpp-native"
+            / "vpp"
+            / "include"
+            / "vpp_plugins"
+        ),
+        "VPP_TEST_PLUGIN_PATH": str(
+            ws_root
+            / "build-root"
+            / "install-vpp-native"
+            / "vpp"
+            / "include"
+            / "vpp_plugins"
+        ),
+        "LD_LIBRARY_PATH": str(
+            ws_root / "build-root" / "install-vpp-native" / "vpp" / "lib"
+        ),
+        "TAG": "vpp_debug",
+        "RND_SEED": str(time.time()),
+        "VPP_WORKER_COUNT": "",
+        "TEST": args.test_name,
+        "TEST_JOBS": args.jobs,
+        "SOCKET_DIR": args.socket_dir,
+        "PYTHON_OPTS": "",
+        "EXTENDED": args.extended,
+        "USE_RUNNING_VPP": args.running_vpp,
+        "LOG_DIR": args.log_dir,
+        "VM_KERNEL_IMAGE": args.kernel_image,
+        "VM_CPU_LIST": args.vm_cpu_list,
+        "VM_MEM": args.vm_mem,
+        "VM_TEST": args.vm,
+    }
+    # Update values for defaults from environment variables
+    # If a variable is set in os.environ, it takes priority over the defaults
+    return {key: os.environ.get(key, default) for key, default in defaults.items()}
 
 
 # Runs a test inside a spawned QEMU VM
 # If a kernel image is not provided, a linux-image-kvm image is
 # downloaded to the test_data_dir
-def vm_test_runner(test_name, kernel_image, test_data_dir, cpu_mask, mem, jobs="auto"):
-    script = os.path.join(test_dir, "scripts", "run_vpp_in_vm.sh")
+def vm_test_runner(
+    test_name, kernel_image, test_data_dir, cpu_mask, mem, jobs="auto", env=None
+):
+    """Runs a test inside a spawned QEMU VM."""
+    run_vpp_in_vm_sh = base_dir / "scripts" / "run_vpp_in_vm.sh"
+    # Set the environment variables required for running a VM test
     os.environ["TEST_JOBS"] = str(jobs)
+    os.environ["WS_ROOT"] = str(ws_root)
+    os.environ["BR"] = env["BR"]
+    os.environ["VPP_TEST_DATA_DIR"] = str(test_data_dir)
+    os.environ["VPP_BUILD_DIR"] = env["VPP_BUILD_DIR"]
+    os.environ["VPP_INSTALL_PATH"] = env["VPP_INSTALL_PATH"]
+    os.environ["VPP_BIN"] = env["VPP_BIN"]
+    os.environ["VPP_PLUGIN_PATH"] = env["VPP_PLUGIN_PATH"]
+    os.environ["VPP_TEST_PLUGIN_PATH"] = env["VPP_TEST_PLUGIN_PATH"]
+    os.environ["LD_LIBRARY_PATH"] = env["LD_LIBRARY_PATH"]
+    os.environ["RND_SEED"] = env["RND_SEED"]
+    os.environ["VENV_PATH"] = env["VENV_PATH"]
+    os.environ["TAG"] = env["TAG"]
+    os.environ["VPP_WORKER_COUNT"] = env["VPP_WORKER_COUNT"]
+    os.environ["FAILED_DIR"] = env["FAILED_DIR"]
+    os.environ["SKIP_FILTER"] = env["SKIP_FILTER"]
+    if not run_vpp_in_vm_sh.is_file():
+        print(f"Error: script {base_dir}/scripts/run_vpp_in_vm.sh not found.")
+        sys.exit(1)
     p = Popen(
-        [script, test_name, kernel_image, test_data_dir, cpu_mask, mem],
+        [run_vpp_in_vm_sh, test_name, kernel_image, test_data_dir, cpu_mask, mem],
         stdout=PIPE,
         cwd=ws_root,
     )
@@ -242,15 +170,21 @@ def post_vm_test_run():
 
 
 def build_venv():
-    # Builds a virtual env containing all the required packages and patches
-    # for running VPP unit tests
-    if not os.path.exists(venv_install_done):
-        env_builder = ExtendedEnvBuilder(clear=True, with_pip=True)
-        print("Creating a vEnv for running VPP unit tests in {}".format(venv_dir))
-        env_builder.create(venv_dir)
-        # Write state to the venv run dir
-        Path(venv_run_dir).mkdir(exist_ok=True)
-        Path(venv_install_done).touch()
+    """Setup the Python virtual environment via vpp Makefile."""
+    print(
+        f"Setting up Python virtual environment using Makefile in "
+        f"{ws_root}/test/venv..."
+    )
+
+    if not ws_root.is_dir():
+        print(f"Error: WS_ROOT directory not valid at {ws_root}")
+        sys.exit(1)
+
+    try:
+        run(["make", "test-dep"], cwd=str(ws_root), check=True)
+    except CalledProcessError as e:
+        print(f"Failed to set up test virtualenv using Makefile: {e}")
+        sys.exit(e.returncode)
 
 
 def expand_mix_string(s):
@@ -274,51 +208,50 @@ def set_logging(test_data_dir, test_name):
     logging.basicConfig(filename=filename, level=logging.DEBUG)
 
 
-def run_tests_in_venv(
-    test,
-    jobs,
-    log_dir,
-    socket_dir="",
-    running_vpp=False,
-    extended=False,
-):
-    """Runs tests in the virtual environment set by venv_dir.
+def run_tests_in_venv(env):
+    """Runs tests in the Python virtual environment.
 
     Arguments:
-    test: Name of the test to run
-    jobs: Maximum concurrent test jobs
-    log_dir: Directory location for storing log files
-    socket_dir: Use running VPP's socket files
-    running_vpp: True if tests are run against a running VPP
-    extended: Run extended tests
+    env: A dictionary of environment variables for the test run.
     """
-    script = os.path.join(test_dir, "scripts", "run.sh")
+    if not run_sh.is_file():
+        print("Error: scripts/run.sh not found.")
+        sys.exit(1)
     args = [
-        f"--venv-dir={venv_dir}",
-        f"--vpp-ws-dir={ws_root}",
-        f"--socket-dir={socket_dir}",
-        f"--filter={test}",
-        f"--jobs={jobs}",
-        f"--log-dir={log_dir}",
-        f"--tmp-dir={log_dir}",
-        f"--cache-vpp-output",
+        f"--venv-dir={env['VENV_PATH']}",
+        f"--vpp-ws-dir={env['WS_ROOT']}",
+        f"--vpp-tag={env['TAG']}",
+        f"--failed-dir={env['FAILED_DIR']}",
+        f"--verbose={env['V']}",
+        f"--jobs={env['TEST_JOBS']}",
+        f"--filter={env['TEST']}",
+        f"--skip-filter={env['SKIP_FILTER']}",
+        f"--retries={env['RETRIES']}",
+        f"--rnd-seed={env['RND_SEED']}",
+        f"--vpp-worker-count={env['VPP_WORKER_COUNT']}",
+        f"--python-opts={env['PYTHON_OPTS']}",
+        f"--log-dir={env['LOG_DIR']}",
+        f"--tmp-dir={env['LOG_DIR']}",
+        "--keep-pcaps",
+        "--cache-vpp-output",
     ]
-    if running_vpp:
-        args = args + [f"--use-running-vpp"]
-    if extended:
-        args = args + [f"--extended"]
-    print(f"Running script: {script} " f"{' '.join(args)}")
-    process_args = [script] + args
-    call(process_args)
+    if env["USE_RUNNING_VPP"]:
+        args = args + ["--use-running-vpp"] + [f"--socket-dir={env['SOCKET_DIR']}"]
+    if env["EXTENDED"]:
+        args = args + ["--extended"]
+    try:
+        print(f"Running: {run_sh} {' '.join(args)}")
+        run([str(run_sh)] + args, check=True)
+    except CalledProcessError as e:
+        print(f"\nrun.sh failed with exit code {e.returncode}...")
+        sys.exit(e.returncode)
 
 
 if __name__ == "__main__":
     # Build a Virtual Environment for running tests on host & QEMU
     # (TODO): Create a single config object by merging the below args with
     # config.py after gathering dev use-cases.
-    parser = argparse.ArgumentParser(
-        description="Run VPP Unit Tests", formatter_class=argparse.RawTextHelpFormatter
-    )
+    parser = argparse.ArgumentParser(description="Run VPP Unit Tests")
     parser.add_argument(
         "--vm",
         dest="vm",
@@ -326,22 +259,6 @@ if __name__ == "__main__":
         action="store_true",
         help="Run Test Inside a QEMU VM",
     )
-    parser.add_argument(
-        "--debug",
-        dest="debug",
-        required=False,
-        default=True,
-        action="store_true",
-        help="Run Tests on Debug Build",
-    )
-    parser.add_argument(
-        "--release",
-        dest="release",
-        required=False,
-        default=False,
-        action="store_true",
-        help="Run Tests on release Build",
-    )
     parser.add_argument(
         "-t",
         "--test",
@@ -380,9 +297,9 @@ if __name__ == "__main__":
     parser.add_argument(
         "--log-dir",
         action="store",
-        default=os.path.abspath(f"./test-run-{datetime.date.today()}"),
+        default="/tmp/vpp-failed-unittests/",
         help="directory where to store directories "
-        "containing log files (default: ./test-run-YYYY-MM-DD)",
+        "default: /tmp/vpp-failed-unittests/",
     )
     parser.add_argument(
         "--jobs",
@@ -431,24 +348,14 @@ if __name__ == "__main__":
         print("Error: The --test argument must be set for running VM tests")
         sys.exit(1)
     build_venv()
-    # Build VPP release or debug binaries
-    debug = False if args.release else True
-    build_vpp(debug, args.release)
-    set_environ()
+    env = get_env(args)
     if args.running_vpp:
         print("Tests will be run against a running VPP..")
     elif not vm_tests:
         print("Tests will be run by spawning a new VPP instance..")
     # Run tests against a running VPP or a new instance of VPP
     if not vm_tests:
-        run_tests_in_venv(
-            test=args.test_name,
-            jobs=args.jobs,
-            log_dir=args.log_dir,
-            socket_dir=args.socket_dir,
-            running_vpp=args.running_vpp,
-            extended=args.extended,
-        )
+        run_tests_in_venv(env)
     # Run tests against a VPP inside a VM
     else:
         print("Running VPP unit test(s):{0} inside a QEMU VM".format(args.test_name))
@@ -469,4 +376,5 @@ if __name__ == "__main__":
             cpus,
             f"{args.vm_mem}G",
             args.jobs,
+            env,
         )
index 6f8742b..8a546f3 100755 (executable)
@@ -161,7 +161,7 @@ mount -t 9p tmp9p /tmp
 modprobe -a vhost_net
 ${VENV_PATH}/bin/python3 ${WS_ROOT}/test/run_tests.py --filter=${TEST} --jobs=${TEST_JOBS} \
 --failed-dir=${FAILED_DIR} --venv-dir=${VENV_PATH} --vpp-ws-dir=${WS_ROOT} --extended \
---vpp-tag=vpp_debug --cache-vpp-output
+--vpp-tag=vpp_debug --cache-vpp-output --skip-filter=${SKIP_FILTER}
 poweroff -f
 _EOF_
 
index 43377b6..70ae020 100644 (file)
@@ -19,6 +19,10 @@ def use_running(cls):
     cls -- VPPTestCase Class
     """
     if config.running_vpp:
+        print(
+            f"Test will be run against a ****running VPP**** as "
+            f"config.running_vpp={config.running_vpp}"
+        )
         if os.path.isdir(config.socket_dir):
             RunningVPP.socket_dir = config.socket_dir
         else:
@@ -28,7 +32,7 @@ def use_running(cls):
         cls.get_api_sock_path = RunningVPP.get_api_sock_path
         cls.get_memif_sock_path = RunningVPP.get_memif_sock_path
         cls.run_vpp = RunningVPP.run_vpp
-        cls.quit_vpp = RunningVPP.quit_vpp
+        cls.quit = RunningVPP.terminate
         cls.vpp = RunningVPP
         cls.running_vpp = True
     return cls
@@ -56,18 +60,25 @@ class RunningVPP:
 
     @classmethod
     def run_vpp(cls):
-        """VPP is already running -- skip this action."""
-        pass
-
-    @classmethod
-    def quit_vpp(cls):
-        """Indicate quitting to framework by setting returncode=1."""
-        cls.returncode = 1
+        """Exit if VPP is not already running."""
+        if not cls.is_running_vpp():
+            print(
+                "Error: VPP is not running, but --use-running-vpp arg used."
+                "Please start VPP before running the tests against it."
+            )
+            sys.exit(1)
 
     @classmethod
     def terminate(cls):
-        """Indicate termination to framework by setting returncode=1."""
+        """Don't terminate a running VPP. Just cleanup papi resources."""
         cls.returncode = 1
+        if hasattr(cls, "vapi"):
+            print("Cleaning up PAPI resources on %s", cls.__name__)
+            print(cls.vapi.vpp.get_stats())
+            print("Disconnecting class vapi client on %s", cls.__name__)
+            cls.vapi.disconnect()
+            print("Deleting class vapi attribute on %s", cls.__name__)
+            del cls.vapi
 
     @classmethod
     def get_default_socket_dir(cls):