1# SPDX-License-Identifier: BSD-3-Clause 2# Copyright(c) 2023 University of New Hampshire 3 4"""Smoke test suite. 5 6Smoke tests are a class of tests which are used for validating a minimal set of important features. 7These are the most important features without which (or when they're faulty) the software wouldn't 8work properly. Thus, if any failure occurs while testing these features, 9there isn't that much of a reason to continue testing, as the software is fundamentally broken. 10 11These tests don't have to include only DPDK tests, as the reason for failures could be 12in the infrastructure (a faulty link between NICs or a misconfiguration). 13""" 14 15import re 16 17from framework.config import PortConfig 18from framework.remote_session.testpmd_shell import TestPmdShell 19from framework.settings import SETTINGS 20from framework.test_suite import TestSuite, func_test 21from framework.testbed_model.capability import TopologyType, requires 22from framework.utils import REGEX_FOR_PCI_ADDRESS 23 24 25@requires(topology_type=TopologyType.no_link) 26class TestSmokeTests(TestSuite): 27 """DPDK and infrastructure smoke test suite. 28 29 The test cases validate the most basic DPDK functionality needed for all other test suites. 30 The infrastructure also needs to be tested, as that is also used by all other test suites. 31 32 Attributes: 33 is_blocking: This test suite will block the execution of all other test suites 34 in the test run after it. 35 nics_in_node: The NICs present on the SUT node. 36 """ 37 38 is_blocking = True 39 # dicts in this list are expected to have two keys: 40 # "pci_address" and "current_driver" 41 nics_in_node: list[PortConfig] = [] 42 43 def set_up_suite(self) -> None: 44 """Set up the test suite. 45 46 Setup: 47 Set the build directory path and a list of NICs in the SUT node. 48 """ 49 self.dpdk_build_dir_path = self.sut_node.remote_dpdk_build_dir 50 self.nics_in_node = self.sut_node.config.ports 51 52 @func_test 53 def test_unit_tests(self) -> None: 54 """DPDK meson ``fast-tests`` unit tests. 55 56 Test that all unit test from the ``fast-tests`` suite pass. 57 The suite is a subset with only the most basic tests. 58 59 Test: 60 Run the ``fast-tests`` unit test suite through meson. 61 """ 62 self.sut_node.main_session.send_command( 63 f"meson test -C {self.dpdk_build_dir_path} --suite fast-tests -t 60", 64 480, 65 verify=True, 66 privileged=True, 67 ) 68 69 @func_test 70 def test_driver_tests(self) -> None: 71 """DPDK meson ``driver-tests`` unit tests. 72 73 Test that all unit test from the ``driver-tests`` suite pass. 74 The suite is a subset with driver tests. This suite may be run with virtual devices 75 configured in the test run configuration. 76 77 Test: 78 Run the ``driver-tests`` unit test suite through meson. 79 """ 80 vdev_args = "" 81 for dev in self.sut_node.virtual_devices: 82 vdev_args += f"--vdev {dev} " 83 vdev_args = vdev_args[:-1] 84 driver_tests_command = f"meson test -C {self.dpdk_build_dir_path} --suite driver-tests" 85 if vdev_args: 86 self._logger.info( 87 f"Running driver tests with the following virtual devices: {vdev_args}" 88 ) 89 driver_tests_command += f' --test-args "{vdev_args}"' 90 91 self.sut_node.main_session.send_command( 92 driver_tests_command, 93 300, 94 verify=True, 95 privileged=True, 96 ) 97 98 @func_test 99 def test_devices_listed_in_testpmd(self) -> None: 100 """Testpmd device discovery. 101 102 Test that the devices configured in the test run configuration are found in testpmd. 103 104 Test: 105 List all devices found in testpmd and verify the configured devices are among them. 106 """ 107 with TestPmdShell(self.sut_node) as testpmd: 108 dev_list = [str(x) for x in testpmd.get_devices()] 109 for nic in self.nics_in_node: 110 self.verify( 111 nic.pci in dev_list, 112 f"Device {nic.pci} was not listed in testpmd's available devices, " 113 "please check your configuration", 114 ) 115 116 @func_test 117 def test_device_bound_to_driver(self) -> None: 118 """Device driver in OS. 119 120 Test that the devices configured in the test run configuration are bound to 121 the proper driver. 122 123 Test: 124 List all devices with the ``dpdk-devbind.py`` script and verify that 125 the configured devices are bound to the proper driver. 126 """ 127 path_to_devbind = self.sut_node.path_to_devbind_script 128 129 all_nics_in_dpdk_devbind = self.sut_node.main_session.send_command( 130 f"{path_to_devbind} --status | awk '/{REGEX_FOR_PCI_ADDRESS}/'", 131 SETTINGS.timeout, 132 ).stdout 133 134 for nic in self.nics_in_node: 135 # This regular expression finds the line in the above string that starts 136 # with the address for the nic we are on in the loop and then captures the 137 # name of the driver in a group 138 devbind_info_for_nic = re.search( 139 f"{nic.pci}[^\\n]*drv=([\\d\\w-]*) [^\\n]*", 140 all_nics_in_dpdk_devbind, 141 ) 142 self.verify( 143 devbind_info_for_nic is not None, 144 f"Failed to find configured device ({nic.pci}) using dpdk-devbind.py", 145 ) 146 # We know this isn't None, but mypy doesn't 147 assert devbind_info_for_nic is not None 148 self.verify( 149 devbind_info_for_nic.group(1) == nic.os_driver_for_dpdk, 150 f"Driver for device {nic.pci} does not match driver listed in " 151 f"configuration (bound to {devbind_info_for_nic.group(1)})", 152 ) 153