Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # |
| 3 | # Copyright (c) 2022 Cisco and/or its affiliates. |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at: |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | # |
| 16 | # Build the Virtual Environment & run VPP unit tests |
| 17 | |
| 18 | import argparse |
| 19 | import glob |
| 20 | import logging |
| 21 | import os |
| 22 | from pathlib import Path |
| 23 | import signal |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 24 | from subprocess import Popen, PIPE, STDOUT, call |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 25 | import sys |
| 26 | import time |
| 27 | import venv |
Naveen Joy | 7498aad | 2022-09-20 11:38:33 -0700 | [diff] [blame] | 28 | import datetime |
Naveen Joy | e416893 | 2022-10-04 14:22:05 -0700 | [diff] [blame] | 29 | import re |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 30 | |
| 31 | |
| 32 | # Required Std. Path Variables |
| 33 | test_dir = os.path.dirname(os.path.realpath(__file__)) |
| 34 | ws_root = os.path.dirname(test_dir) |
| 35 | build_root = os.path.join(ws_root, "build-root") |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 36 | venv_dir = os.path.join(build_root, "test", "venv") |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 37 | venv_bin_dir = os.path.join(venv_dir, "bin") |
| 38 | venv_lib_dir = os.path.join(venv_dir, "lib") |
| 39 | venv_run_dir = os.path.join(venv_dir, "run") |
| 40 | venv_install_done = os.path.join(venv_run_dir, "venv_install.done") |
| 41 | papi_python_src_dir = os.path.join(ws_root, "src", "vpp-api", "python") |
| 42 | |
| 43 | # Path Variables Set after VPP Build/Install |
| 44 | vpp_build_dir = vpp_install_path = vpp_bin = vpp_lib = vpp_lib64 = None |
| 45 | vpp_plugin_path = vpp_test_plugin_path = ld_library_path = None |
| 46 | |
| 47 | # Pip version pinning |
| 48 | pip_version = "22.0.4" |
| 49 | pip_tools_version = "6.6.0" |
| 50 | |
Naveen Joy | 0a192ea | 2023-01-31 16:51:58 -0800 | [diff] [blame] | 51 | # Compiled pip requirements file |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 52 | pip_compiled_requirements_file = os.path.join(test_dir, "requirements-3.txt") |
| 53 | |
Dave Wallace | 7b8b465 | 2023-08-15 19:05:26 -0400 | [diff] [blame] | 54 | |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 55 | # Gracefully exit after executing cleanup scripts |
| 56 | # upon receiving a SIGINT or SIGTERM |
| 57 | def handler(signum, frame): |
| 58 | print("Received Signal {0}".format(signum)) |
| 59 | post_vm_test_run() |
| 60 | |
| 61 | |
| 62 | signal.signal(signal.SIGINT, handler) |
| 63 | signal.signal(signal.SIGTERM, handler) |
| 64 | |
| 65 | |
Naveen Joy | e416893 | 2022-10-04 14:22:05 -0700 | [diff] [blame] | 66 | def show_progress(stream, exclude_pattern=None): |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 67 | """ |
| 68 | Read lines from a subprocess stdout/stderr streams and write |
| 69 | to sys.stdout & the logfile |
Naveen Joy | e416893 | 2022-10-04 14:22:05 -0700 | [diff] [blame] | 70 | |
| 71 | arguments: |
| 72 | stream - subprocess stdout or stderr data stream |
| 73 | exclude_pattern - lines matching this reg-ex will be excluded |
| 74 | from stdout. |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 75 | """ |
| 76 | while True: |
| 77 | s = stream.readline() |
| 78 | if not s: |
| 79 | break |
| 80 | data = s.decode("utf-8") |
| 81 | # Filter the annoying SIGTERM signal from the output when VPP is |
| 82 | # terminated after a test run |
| 83 | if "SIGTERM" not in data: |
Naveen Joy | e416893 | 2022-10-04 14:22:05 -0700 | [diff] [blame] | 84 | if exclude_pattern is not None: |
| 85 | if bool(re.search(exclude_pattern, data)) is False: |
| 86 | sys.stdout.write(data) |
| 87 | else: |
| 88 | sys.stdout.write(data) |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 89 | logging.debug(data) |
| 90 | sys.stdout.flush() |
| 91 | stream.close() |
| 92 | |
| 93 | |
| 94 | class ExtendedEnvBuilder(venv.EnvBuilder): |
| 95 | """ |
| 96 | 1. Builds a Virtual Environment for running VPP unit tests |
| 97 | 2. Installs all necessary scripts, pkgs & patches into the vEnv |
| 98 | - python3, pip, pip-tools, papi, scapy patches & |
| 99 | test-requirement pkgs |
| 100 | """ |
| 101 | |
| 102 | def __init__(self, *args, **kwargs): |
| 103 | super().__init__(*args, **kwargs) |
| 104 | |
| 105 | def post_setup(self, context): |
| 106 | """ |
| 107 | Setup all packages that need to be pre-installed into the venv |
| 108 | prior to running VPP unit tests. |
| 109 | |
| 110 | :param context: The context of the virtual environment creation |
| 111 | request being processed. |
| 112 | """ |
| 113 | os.environ["VIRTUAL_ENV"] = context.env_dir |
| 114 | os.environ[ |
| 115 | "CUSTOM_COMPILE_COMMAND" |
| 116 | ] = "make test-refresh-deps (or update requirements.txt)" |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 117 | # Set the venv python executable & binary install path |
| 118 | env_exe = context.env_exe |
| 119 | bin_path = context.bin_path |
| 120 | # Packages/requirements to be installed in the venv |
| 121 | # [python-module, cmdline-args, package-name_or_requirements-file-name] |
| 122 | test_req = [ |
| 123 | ["pip", "install", "pip===%s" % pip_version], |
| 124 | ["pip", "install", "pip-tools===%s" % pip_tools_version], |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 125 | ["piptools", "sync", pip_compiled_requirements_file], |
| 126 | ["pip", "install", "-e", papi_python_src_dir], |
| 127 | ] |
| 128 | for req in test_req: |
| 129 | args = [env_exe, "-m"] |
| 130 | args.extend(req) |
| 131 | print(args) |
| 132 | p = Popen(args, stdout=PIPE, stderr=STDOUT, cwd=bin_path) |
| 133 | show_progress(p.stdout) |
| 134 | self.pip_patch() |
| 135 | |
| 136 | def pip_patch(self): |
| 137 | """ |
| 138 | Apply scapy patch files |
| 139 | """ |
| 140 | scapy_patch_dir = Path(os.path.join(test_dir, "patches", "scapy-2.4.3")) |
| 141 | scapy_source_dir = glob.glob( |
| 142 | os.path.join(venv_lib_dir, "python3.*", "site-packages") |
| 143 | )[0] |
| 144 | for f in scapy_patch_dir.iterdir(): |
| 145 | print("Applying patch: {}".format(os.path.basename(str(f)))) |
| 146 | args = ["patch", "--forward", "-p1", "-d", scapy_source_dir, "-i", str(f)] |
| 147 | print(args) |
| 148 | p = Popen(args, stdout=PIPE, stderr=STDOUT) |
| 149 | show_progress(p.stdout) |
| 150 | |
| 151 | |
| 152 | # Build VPP Release/Debug binaries |
| 153 | def build_vpp(debug=True, release=False): |
| 154 | """ |
| 155 | Install VPP Release(if release=True) or Debug(if debug=True) Binaries. |
| 156 | |
| 157 | Default is to build the debug binaries. |
| 158 | """ |
| 159 | global vpp_build_dir, vpp_install_path, vpp_bin, vpp_lib, vpp_lib64 |
| 160 | global vpp_plugin_path, vpp_test_plugin_path, ld_library_path |
| 161 | if debug: |
| 162 | print("Building VPP debug binaries") |
| 163 | args = ["make", "build"] |
| 164 | build = "build-vpp_debug-native" |
| 165 | install = "install-vpp_debug-native" |
| 166 | elif release: |
| 167 | print("Building VPP release binaries") |
| 168 | args = ["make", "build-release"] |
| 169 | build = "build-vpp-native" |
| 170 | install = "install-vpp-native" |
| 171 | p = Popen(args, stdout=PIPE, stderr=STDOUT, cwd=ws_root) |
| 172 | show_progress(p.stdout) |
| 173 | vpp_build_dir = os.path.join(build_root, build) |
| 174 | vpp_install_path = os.path.join(build_root, install) |
| 175 | vpp_bin = os.path.join(vpp_install_path, "vpp", "bin", "vpp") |
| 176 | vpp_lib = os.path.join(vpp_install_path, "vpp", "lib") |
| 177 | vpp_lib64 = os.path.join(vpp_install_path, "vpp", "lib64") |
| 178 | vpp_plugin_path = ( |
| 179 | os.path.join(vpp_lib, "vpp_plugins") |
| 180 | + ":" |
| 181 | + os.path.join(vpp_lib64, "vpp_plugins") |
| 182 | ) |
| 183 | vpp_test_plugin_path = ( |
| 184 | os.path.join(vpp_lib, "vpp_api_test_plugins") |
| 185 | + ":" |
| 186 | + os.path.join(vpp_lib64, "vpp_api_test_plugins") |
| 187 | ) |
| 188 | ld_library_path = os.path.join(vpp_lib) + ":" + os.path.join(vpp_lib64) |
| 189 | |
| 190 | |
| 191 | # Environment Vars required by the test framework, |
| 192 | # papi_provider & unittests |
| 193 | def set_environ(): |
| 194 | os.environ["WS_ROOT"] = ws_root |
| 195 | os.environ["BR"] = build_root |
| 196 | os.environ["VENV_PATH"] = venv_dir |
| 197 | os.environ["VENV_BIN"] = venv_bin_dir |
| 198 | os.environ["RND_SEED"] = str(time.time()) |
| 199 | os.environ["VPP_BUILD_DIR"] = vpp_build_dir |
| 200 | os.environ["VPP_BIN"] = vpp_bin |
| 201 | os.environ["VPP_PLUGIN_PATH"] = vpp_plugin_path |
| 202 | os.environ["VPP_TEST_PLUGIN_PATH"] = vpp_test_plugin_path |
| 203 | os.environ["VPP_INSTALL_PATH"] = vpp_install_path |
| 204 | os.environ["LD_LIBRARY_PATH"] = ld_library_path |
| 205 | os.environ["FAILED_DIR"] = "/tmp/vpp-failed-unittests/" |
| 206 | if not os.environ.get("TEST_JOBS"): |
| 207 | os.environ["TEST_JOBS"] = "1" |
| 208 | |
| 209 | |
| 210 | # Runs a test inside a spawned QEMU VM |
| 211 | # If a kernel image is not provided, a linux-image-kvm image is |
| 212 | # downloaded to the test_data_dir |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 213 | def vm_test_runner(test_name, kernel_image, test_data_dir, cpu_mask, mem, jobs="auto"): |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 214 | script = os.path.join(test_dir, "scripts", "run_vpp_in_vm.sh") |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 215 | os.environ["TEST_JOBS"] = str(jobs) |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 216 | p = Popen( |
| 217 | [script, test_name, kernel_image, test_data_dir, cpu_mask, mem], |
| 218 | stdout=PIPE, |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 219 | cwd=ws_root, |
| 220 | ) |
Naveen Joy | e416893 | 2022-10-04 14:22:05 -0700 | [diff] [blame] | 221 | # Show only the test result without clobbering the stdout. |
| 222 | # The VM console displays VPP stderr & Linux IPv6 netdev change |
| 223 | # messages, which is logged by default and can be excluded. |
| 224 | exclude_pattern = r"vpp\[\d+\]:|ADDRCONF\(NETDEV_CHANGE\):" |
| 225 | show_progress(p.stdout, exclude_pattern) |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 226 | post_vm_test_run() |
| 227 | |
| 228 | |
| 229 | def post_vm_test_run(): |
| 230 | # Revert the ownership of certain directories from root to the |
| 231 | # original user after running in QEMU |
| 232 | print("Running post test cleanup tasks") |
| 233 | dirs = ["/tmp/vpp-failed-unittests", os.path.join(ws_root, "test", "__pycache__")] |
| 234 | dirs.extend(glob.glob("/tmp/vpp-unittest-*")) |
| 235 | dirs.extend(glob.glob("/tmp/api_post_mortem.*")) |
| 236 | user = os.getlogin() |
| 237 | for dir in dirs: |
| 238 | if os.path.exists(dir) and Path(dir).owner() != user: |
| 239 | cmd = ["sudo", "chown", "-R", "{0}:{0}".format(user), dir] |
| 240 | p = Popen(cmd, stdout=PIPE, stderr=STDOUT) |
| 241 | show_progress(p.stdout) |
| 242 | |
| 243 | |
| 244 | def build_venv(): |
| 245 | # Builds a virtual env containing all the required packages and patches |
| 246 | # for running VPP unit tests |
| 247 | if not os.path.exists(venv_install_done): |
| 248 | env_builder = ExtendedEnvBuilder(clear=True, with_pip=True) |
| 249 | print("Creating a vEnv for running VPP unit tests in {}".format(venv_dir)) |
| 250 | env_builder.create(venv_dir) |
| 251 | # Write state to the venv run dir |
| 252 | Path(venv_run_dir).mkdir(exist_ok=True) |
| 253 | Path(venv_install_done).touch() |
| 254 | |
| 255 | |
| 256 | def expand_mix_string(s): |
| 257 | # Returns an expanded string computed from a mixrange string (s) |
| 258 | # E.g: If param s = '5-8,10,11' returns '5,6,7,8,10,11' |
| 259 | result = [] |
| 260 | for val in s.split(","): |
| 261 | if "-" in val: |
| 262 | start, end = val.split("-") |
| 263 | result.extend(list(range(int(start), int(end) + 1))) |
| 264 | else: |
| 265 | result.append(int(val)) |
| 266 | return ",".join(str(i) for i in set(result)) |
| 267 | |
| 268 | |
| 269 | def set_logging(test_data_dir, test_name): |
| 270 | Path(test_data_dir).mkdir(exist_ok=True) |
| 271 | log_file = "vm_{0}_{1}.log".format(test_name, str(time.time())[-5:]) |
| 272 | filename = "{0}/{1}".format(test_data_dir, log_file) |
| 273 | Path(filename).touch() |
| 274 | logging.basicConfig(filename=filename, level=logging.DEBUG) |
| 275 | |
| 276 | |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 277 | def run_tests_in_venv( |
| 278 | test, |
| 279 | jobs, |
| 280 | log_dir, |
| 281 | socket_dir="", |
| 282 | running_vpp=False, |
Naveen Joy | 5569a85 | 2022-10-17 15:07:49 -0700 | [diff] [blame] | 283 | extended=False, |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 284 | ): |
| 285 | """Runs tests in the virtual environment set by venv_dir. |
| 286 | |
| 287 | Arguments: |
| 288 | test: Name of the test to run |
| 289 | jobs: Maximum concurrent test jobs |
| 290 | log_dir: Directory location for storing log files |
| 291 | socket_dir: Use running VPP's socket files |
| 292 | running_vpp: True if tests are run against a running VPP |
Naveen Joy | 5569a85 | 2022-10-17 15:07:49 -0700 | [diff] [blame] | 293 | extended: Run extended tests |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 294 | """ |
| 295 | script = os.path.join(test_dir, "scripts", "run.sh") |
| 296 | args = [ |
| 297 | f"--venv-dir={venv_dir}", |
| 298 | f"--vpp-ws-dir={ws_root}", |
| 299 | f"--socket-dir={socket_dir}", |
| 300 | f"--filter={test}", |
| 301 | f"--jobs={jobs}", |
| 302 | f"--log-dir={log_dir}", |
Naveen Joy | 7498aad | 2022-09-20 11:38:33 -0700 | [diff] [blame] | 303 | f"--tmp-dir={log_dir}", |
Naveen Joy | e416893 | 2022-10-04 14:22:05 -0700 | [diff] [blame] | 304 | f"--cache-vpp-output", |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 305 | ] |
| 306 | if running_vpp: |
| 307 | args = args + [f"--use-running-vpp"] |
Naveen Joy | 5569a85 | 2022-10-17 15:07:49 -0700 | [diff] [blame] | 308 | if extended: |
| 309 | args = args + [f"--extended"] |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 310 | print(f"Running script: {script} " f"{' '.join(args)}") |
| 311 | process_args = [script] + args |
| 312 | call(process_args) |
| 313 | |
| 314 | |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 315 | if __name__ == "__main__": |
| 316 | # Build a Virtual Environment for running tests on host & QEMU |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 317 | # (TODO): Create a single config object by merging the below args with |
| 318 | # config.py after gathering dev use-cases. |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 319 | parser = argparse.ArgumentParser( |
| 320 | description="Run VPP Unit Tests", formatter_class=argparse.RawTextHelpFormatter |
| 321 | ) |
| 322 | parser.add_argument( |
| 323 | "--vm", |
| 324 | dest="vm", |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 325 | required=False, |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 326 | action="store_true", |
| 327 | help="Run Test Inside a QEMU VM", |
| 328 | ) |
| 329 | parser.add_argument( |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 330 | "--debug", |
| 331 | dest="debug", |
| 332 | required=False, |
| 333 | default=True, |
| 334 | action="store_true", |
| 335 | help="Run Tests on Debug Build", |
| 336 | ) |
| 337 | parser.add_argument( |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 338 | "--release", |
| 339 | dest="release", |
| 340 | required=False, |
| 341 | default=False, |
| 342 | action="store_true", |
| 343 | help="Run Tests on release Build", |
| 344 | ) |
| 345 | parser.add_argument( |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 346 | "-t", |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 347 | "--test", |
| 348 | dest="test_name", |
| 349 | required=False, |
| 350 | action="store", |
| 351 | default="", |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 352 | help="Test Name or Test filter", |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 353 | ) |
| 354 | parser.add_argument( |
| 355 | "--vm-kernel-image", |
| 356 | dest="kernel_image", |
| 357 | required=False, |
| 358 | action="store", |
| 359 | default="", |
| 360 | help="Kernel Image Selection to Boot", |
| 361 | ) |
| 362 | parser.add_argument( |
| 363 | "--vm-cpu-list", |
| 364 | dest="vm_cpu_list", |
| 365 | required=False, |
| 366 | action="store", |
| 367 | default="5-8", |
| 368 | help="Set CPU Affinity\n" |
| 369 | "E.g. 5-7,10 will schedule on processors " |
| 370 | "#5, #6, #7 and #10. (Default: 5-8)", |
| 371 | ) |
| 372 | parser.add_argument( |
| 373 | "--vm-mem", |
| 374 | dest="vm_mem", |
| 375 | required=False, |
| 376 | action="store", |
| 377 | default="2", |
| 378 | help="Guest Memory in Gibibytes\n" "E.g. 4 (Default: 2)", |
| 379 | ) |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 380 | parser.add_argument( |
| 381 | "--log-dir", |
| 382 | action="store", |
Naveen Joy | 7498aad | 2022-09-20 11:38:33 -0700 | [diff] [blame] | 383 | default=os.path.abspath(f"./test-run-{datetime.date.today()}"), |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 384 | help="directory where to store directories " |
Naveen Joy | 7498aad | 2022-09-20 11:38:33 -0700 | [diff] [blame] | 385 | "containing log files (default: ./test-run-YYYY-MM-DD)", |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 386 | ) |
| 387 | parser.add_argument( |
| 388 | "--jobs", |
| 389 | action="store", |
| 390 | default="auto", |
| 391 | help="maximum concurrent test jobs", |
| 392 | ) |
| 393 | parser.add_argument( |
| 394 | "-r", |
| 395 | "--use-running-vpp", |
| 396 | dest="running_vpp", |
| 397 | required=False, |
| 398 | action="store_true", |
| 399 | default=False, |
| 400 | help="Runs tests against a running VPP.", |
| 401 | ) |
| 402 | parser.add_argument( |
| 403 | "-d", |
| 404 | "--socket-dir", |
| 405 | dest="socket_dir", |
| 406 | required=False, |
| 407 | action="store", |
| 408 | default="", |
| 409 | help="Relative or absolute path of running VPP's socket directory " |
| 410 | "containing api.sock & stats.sock files.\n" |
| 411 | "Default: /var/run/vpp if VPP is started as the root user, else " |
| 412 | "/var/run/user/${uid}/vpp.", |
| 413 | ) |
Naveen Joy | 5569a85 | 2022-10-17 15:07:49 -0700 | [diff] [blame] | 414 | parser.add_argument( |
| 415 | "-e", |
| 416 | "--extended", |
| 417 | dest="extended", |
| 418 | required=False, |
| 419 | action="store_true", |
| 420 | default=False, |
| 421 | help="Run extended tests.", |
| 422 | ) |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 423 | args = parser.parse_args() |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 424 | vm_tests = False |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 425 | # Enable VM tests |
| 426 | if args.vm and args.test_name: |
| 427 | test_data_dir = "/tmp/vpp-vm-tests" |
| 428 | set_logging(test_data_dir, args.test_name) |
| 429 | vm_tests = True |
| 430 | elif args.vm and not args.test_name: |
| 431 | print("Error: The --test argument must be set for running VM tests") |
| 432 | sys.exit(1) |
| 433 | build_venv() |
| 434 | # Build VPP release or debug binaries |
| 435 | debug = False if args.release else True |
| 436 | build_vpp(debug, args.release) |
| 437 | set_environ() |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 438 | if args.running_vpp: |
| 439 | print("Tests will be run against a running VPP..") |
| 440 | elif not vm_tests: |
| 441 | print("Tests will be run by spawning a new VPP instance..") |
| 442 | # Run tests against a running VPP or a new instance of VPP |
| 443 | if not vm_tests: |
| 444 | run_tests_in_venv( |
| 445 | test=args.test_name, |
| 446 | jobs=args.jobs, |
| 447 | log_dir=args.log_dir, |
| 448 | socket_dir=args.socket_dir, |
| 449 | running_vpp=args.running_vpp, |
Naveen Joy | 5569a85 | 2022-10-17 15:07:49 -0700 | [diff] [blame] | 450 | extended=args.extended, |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 451 | ) |
| 452 | # Run tests against a VPP inside a VM |
| 453 | else: |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 454 | print("Running VPP unit test(s):{0} inside a QEMU VM".format(args.test_name)) |
| 455 | # Check Available CPUs & Usable Memory |
| 456 | cpus = expand_mix_string(args.vm_cpu_list) |
| 457 | num_cpus, usable_cpus = (len(cpus.split(",")), len(os.sched_getaffinity(0))) |
| 458 | if num_cpus > usable_cpus: |
| 459 | print(f"Error:# of CPUs:{num_cpus} > Avail CPUs:{usable_cpus}") |
| 460 | sys.exit(1) |
| 461 | avail_mem = int(os.popen("free -t -g").readlines()[-1].split()[-1]) |
| 462 | if int(args.vm_mem) > avail_mem: |
| 463 | print(f"Error: Mem Size:{args.vm_mem}G > Avail Mem:{avail_mem}G") |
| 464 | sys.exit(1) |
| 465 | vm_test_runner( |
Naveen Joy | c872cec | 2022-08-30 13:59:03 -0700 | [diff] [blame] | 466 | args.test_name, |
| 467 | args.kernel_image, |
| 468 | test_data_dir, |
| 469 | cpus, |
| 470 | f"{args.vm_mem}G", |
| 471 | args.jobs, |
Naveen Joy | 7ea7ab5 | 2021-05-11 10:31:18 -0700 | [diff] [blame] | 472 | ) |