From: jspewock@iol.unh.edu
To: dev@dpdk.org
Cc: Jeremy Spewock <jspewock@iol.unh.edu>
Subject: [RFC v2 1/2] dts: add smoke tests
Date: Fri, 12 May 2023 15:25:43 -0400 [thread overview]
Message-ID: <20230512192540.401-3-jspewock@iol.unh.edu> (raw)
In-Reply-To: <20230512192540.401-2-jspewock@iol.unh.edu>
From: Jeremy Spewock <jspewock@iol.unh.edu>
Adds a new test suite for running smoke tests that verify general
configuration aspects of the system under test. If any of these tests
fail, the DTS execution terminates as part of a "fail-fast" model.
Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu>
---
dts/conf.yaml | 9 ++
dts/framework/config/__init__.py | 21 +++++
dts/framework/config/conf_yaml_schema.json | 32 ++++++-
dts/framework/dts.py | 19 +++-
dts/framework/exception.py | 11 +++
dts/framework/remote_session/os_session.py | 6 +-
.../remote_session/remote/__init__.py | 28 ++++++
dts/framework/test_result.py | 13 ++-
dts/framework/test_suite.py | 24 ++++-
dts/framework/testbed_model/__init__.py | 5 +
.../interactive_apps/__init__.py | 6 ++
.../interactive_apps/interactive_command.py | 57 +++++++++++
.../interactive_apps/testpmd_driver.py | 24 +++++
dts/framework/testbed_model/node.py | 2 +
dts/framework/testbed_model/sut_node.py | 6 ++
dts/tests/TestSuite_smoke_tests.py | 94 +++++++++++++++++++
16 files changed, 348 insertions(+), 9 deletions(-)
create mode 100644 dts/framework/testbed_model/interactive_apps/__init__.py
create mode 100644 dts/framework/testbed_model/interactive_apps/interactive_command.py
create mode 100644 dts/framework/testbed_model/interactive_apps/testpmd_driver.py
create mode 100644 dts/tests/TestSuite_smoke_tests.py
diff --git a/dts/conf.yaml b/dts/conf.yaml
index a9bd8a3e..042ef954 100644
--- a/dts/conf.yaml
+++ b/dts/conf.yaml
@@ -10,13 +10,22 @@ executions:
compiler_wrapper: ccache
perf: false
func: true
+ nics: #physical devices to be used for testing
+ - addresses:
+ - "0000:11:00.0"
+ - "0000:11:00.1"
+ driver: "i40e"
+ vdevs: #names of virtual devices to be used for testing
+ - "crypto_openssl"
test_suites:
+ - smoke_tests
- hello_world
system_under_test: "SUT 1"
nodes:
- name: "SUT 1"
hostname: sut1.change.me.localhost
user: root
+ password: ""
arch: x86_64
os: linux
lcores: ""
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index ebb0823f..f3b8b6e3 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -106,6 +106,21 @@ def from_dict(d: dict) -> "NodeConfiguration":
hugepages=hugepage_config,
)
+@dataclass(slots=True, frozen=True)
+class NICConfiguration:
+ addresses: list[str]
+ driver: str
+
+ @staticmethod
+ def from_dict(d:dict) -> "NICConfiguration":
+ return NICConfiguration(
+ addresses=[addr for addr in d.get("addresses", [])],
+ driver=d.get("driver")
+ )
+ @staticmethod
+ def from_list(l:list[dict]) -> list["NICConfiguration"]:
+ return [] + [NICConfiguration.from_dict(x) for x in l]
+
@dataclass(slots=True, frozen=True)
class BuildTargetConfiguration:
@@ -157,6 +172,8 @@ class ExecutionConfiguration:
func: bool
test_suites: list[TestSuiteConfig]
system_under_test: NodeConfiguration
+ nics: list[NICConfiguration]
+ vdevs: list[str]
@staticmethod
def from_dict(d: dict, node_map: dict) -> "ExecutionConfiguration":
@@ -166,7 +183,9 @@ def from_dict(d: dict, node_map: dict) -> "ExecutionConfiguration":
test_suites: list[TestSuiteConfig] = list(
map(TestSuiteConfig.from_dict, d["test_suites"])
)
+ nic_conf: NICConfiguration = NICConfiguration.from_list(d['nics'])
sut_name = d["system_under_test"]
+ list_of_vdevs = d["vdevs"]
assert sut_name in node_map, f"Unknown SUT {sut_name} in execution {d}"
return ExecutionConfiguration(
@@ -174,7 +193,9 @@ def from_dict(d: dict, node_map: dict) -> "ExecutionConfiguration":
perf=d["perf"],
func=d["func"],
test_suites=test_suites,
+ nics=nic_conf,
system_under_test=node_map[sut_name],
+ vdevs=list_of_vdevs
)
diff --git a/dts/framework/config/conf_yaml_schema.json b/dts/framework/config/conf_yaml_schema.json
index ca2d4a1e..603859de 100644
--- a/dts/framework/config/conf_yaml_schema.json
+++ b/dts/framework/config/conf_yaml_schema.json
@@ -40,6 +40,18 @@
"mscv"
]
},
+ "single_nic" : {
+ "type":"object",
+ "description": "an object that holds nic information",
+ "properties": {
+ "addresses": {
+ "type":"array",
+ "items": {
+ "type":"string"
+ }
+ }
+ }
+ },
"build_target": {
"type": "object",
"description": "Targets supported by DTS",
@@ -97,7 +109,8 @@
"test_suite": {
"type": "string",
"enum": [
- "hello_world"
+ "hello_world",
+ "smoke_tests"
]
},
"test_target": {
@@ -211,6 +224,23 @@
]
}
},
+ "nics": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/single_nic"
+ }
+ ]
+ }
+ },
+ "vdevs": {
+ "description": "Names of vdevs to be used in execution",
+ "type": "array",
+ "items": {
+ "type":"string"
+ }
+ },
"system_under_test": {
"$ref": "#/definitions/node_name"
}
diff --git a/dts/framework/dts.py b/dts/framework/dts.py
index 05022845..0d03e158 100644
--- a/dts/framework/dts.py
+++ b/dts/framework/dts.py
@@ -5,6 +5,8 @@
import sys
+from .exception import BlockingTestSuiteError
+
from .config import CONFIGURATION, BuildTargetConfiguration, ExecutionConfiguration
from .logger import DTSLOG, getLogger
from .test_result import BuildTargetResult, DTSResult, ExecutionResult, Result
@@ -49,6 +51,7 @@ def run_all() -> None:
nodes[sut_node.name] = sut_node
if sut_node:
+ #SMOKE TEST EXECUTION GOES HERE!
_run_execution(sut_node, execution, result)
except Exception as e:
@@ -118,7 +121,7 @@ def _run_build_target(
try:
sut_node.set_up_build_target(build_target)
- result.dpdk_version = sut_node.dpdk_version
+ # result.dpdk_version = sut_node.dpdk_version
build_target_result.update_setup(Result.PASS)
except Exception as e:
dts_logger.exception("Build target setup failed.")
@@ -146,6 +149,7 @@ def _run_suites(
with possibly only a subset of test cases.
If no subset is specified, run all test cases.
"""
+ end_execution = False
for test_suite_config in execution.test_suites:
try:
full_suite_path = f"tests.TestSuite_{test_suite_config.test_suite}"
@@ -160,13 +164,24 @@ def _run_suites(
else:
for test_suite_class in test_suite_classes:
+ #HERE NEEDS CHANGING
test_suite = test_suite_class(
sut_node,
test_suite_config.test_cases,
execution.func,
build_target_result,
+ sut_node._build_target_config,
+ result
)
- test_suite.run()
+ try:
+ test_suite.run()
+ except BlockingTestSuiteError as e:
+ dts_logger.exception("An error occurred within a blocking TestSuite, execution will now end.")
+ result.add_error(e)
+ end_execution = True
+ #if a blocking test failed and we need to bail out of suite executions
+ if end_execution:
+ break
def _exit_dts() -> None:
diff --git a/dts/framework/exception.py b/dts/framework/exception.py
index ca353d98..4e3f63d1 100644
--- a/dts/framework/exception.py
+++ b/dts/framework/exception.py
@@ -25,6 +25,7 @@ class ErrorSeverity(IntEnum):
SSH_ERR = 4
DPDK_BUILD_ERR = 10
TESTCASE_VERIFY_ERR = 20
+ BLOCKING_TESTSUITE_ERR = 25
class DTSError(Exception):
@@ -144,3 +145,13 @@ def __init__(self, value: str):
def __str__(self) -> str:
return repr(self.value)
+
+class BlockingTestSuiteError(DTSError):
+ suite_name: str
+ severity: ClassVar[ErrorSeverity] = ErrorSeverity.BLOCKING_TESTSUITE_ERR
+
+ def __init__(self, suite_name:str) -> None:
+ self.suite_name = suite_name
+
+ def __str__(self) -> str:
+ return f"Blocking suite {self.suite_name} failed."
diff --git a/dts/framework/remote_session/os_session.py b/dts/framework/remote_session/os_session.py
index 4c48ae25..22776bc1 100644
--- a/dts/framework/remote_session/os_session.py
+++ b/dts/framework/remote_session/os_session.py
@@ -12,7 +12,9 @@
from framework.testbed_model import LogicalCore
from framework.utils import EnvVarsDict, MesonArgs
-from .remote import CommandResult, RemoteSession, create_remote_session
+from .remote import CommandResult, RemoteSession, create_remote_session, create_interactive_session
+
+from paramiko import SSHClient
class OSSession(ABC):
@@ -26,6 +28,7 @@ class OSSession(ABC):
name: str
_logger: DTSLOG
remote_session: RemoteSession
+ _interactive_session: SSHClient
def __init__(
self,
@@ -37,6 +40,7 @@ def __init__(
self.name = name
self._logger = logger
self.remote_session = create_remote_session(node_config, name, logger)
+ self._interactive_session = create_interactive_session(node_config, name, logger)
def close(self, force: bool = False) -> None:
"""
diff --git a/dts/framework/remote_session/remote/__init__.py b/dts/framework/remote_session/remote/__init__.py
index 8a151221..abca8edc 100644
--- a/dts/framework/remote_session/remote/__init__.py
+++ b/dts/framework/remote_session/remote/__init__.py
@@ -9,8 +9,36 @@
from .remote_session import CommandResult, RemoteSession
from .ssh_session import SSHSession
+from paramiko import SSHClient, AutoAddPolicy
+from framework.utils import GREEN
def create_remote_session(
node_config: NodeConfiguration, name: str, logger: DTSLOG
) -> RemoteSession:
return SSHSession(node_config, name, logger)
+
+def create_interactive_session(
+ node_config: NodeConfiguration, name: str, logger: DTSLOG
+) -> SSHClient:
+ """
+ Creates a paramiko SSH session that is designed to be used for interactive shells
+
+ This session is meant to be used on an "as needed" basis and may never be utilized
+ """
+ client: SSHClient = SSHClient()
+ client.set_missing_host_key_policy(AutoAddPolicy)
+ ip: str = node_config.hostname
+ logger.info(GREEN(f"Connecting to host {ip}"))
+ #Preset to 22 because paramiko doesn't accept None
+ port: int = 22
+ if ":" in node_config.hostname:
+ ip, port = node_config.hostname.split(":")
+ port = int(port)
+ client.connect(
+ ip,
+ username=node_config.user,
+ port=port,
+ password=node_config.password or "",
+ timeout=20 if port else 10
+ )
+ return client
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 74391982..77202ae2 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -8,6 +8,7 @@
import os.path
from collections.abc import MutableSequence
from enum import Enum, auto
+from typing import Dict
from .config import (
OS,
@@ -67,12 +68,13 @@ class Statistics(dict):
Using a dict provides a convenient way to format the data.
"""
- def __init__(self, dpdk_version):
+ def __init__(self, output_info: Dict[str, str] | None):
super(Statistics, self).__init__()
for result in Result:
self[result.name] = 0
self["PASS RATE"] = 0.0
- self["DPDK VERSION"] = dpdk_version
+ if output_info:
+ for info_key, info_val in output_info.items(): self[info_key] = info_val
def __iadd__(self, other: Result) -> "Statistics":
"""
@@ -258,6 +260,7 @@ class DTSResult(BaseResult):
"""
dpdk_version: str | None
+ output: dict | None
_logger: DTSLOG
_errors: list[Exception]
_return_code: ErrorSeverity
@@ -267,6 +270,7 @@ class DTSResult(BaseResult):
def __init__(self, logger: DTSLOG):
super(DTSResult, self).__init__()
self.dpdk_version = None
+ self.output = None
self._logger = logger
self._errors = []
self._return_code = ErrorSeverity.NO_ERR
@@ -296,7 +300,10 @@ def process(self) -> None:
for error in self._errors:
self._logger.debug(repr(error))
- self._stats_result = Statistics(self.dpdk_version)
+ self._stats_result = Statistics(self.output)
+ #add information gathered from the smoke tests to the statistics
+ # for info_key, info_val in smoke_test_info.items(): self._stats_result[info_key] = info_val
+ # print(self._stats_result)
self.add_stats(self._stats_result)
with open(self._stats_filename, "w+") as stats_file:
stats_file.write(str(self._stats_result))
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 0705f38f..1518fb8a 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -10,11 +10,14 @@
import inspect
import re
from types import MethodType
+from typing import Dict
-from .exception import ConfigurationError, SSHTimeoutError, TestCaseVerifyError
+from .config import BuildTargetConfiguration
+
+from .exception import BlockingTestSuiteError, ConfigurationError, SSHTimeoutError, TestCaseVerifyError
from .logger import DTSLOG, getLogger
from .settings import SETTINGS
-from .test_result import BuildTargetResult, Result, TestCaseResult, TestSuiteResult
+from .test_result import BuildTargetResult, DTSResult, Result, TestCaseResult, TestSuiteResult
from .testbed_model import SutNode
@@ -37,10 +40,12 @@ class TestSuite(object):
"""
sut_node: SutNode
+ is_blocking = False
_logger: DTSLOG
_test_cases_to_run: list[str]
_func: bool
_result: TestSuiteResult
+ _dts_result: DTSResult
def __init__(
self,
@@ -48,6 +53,8 @@ def __init__(
test_cases: list[str],
func: bool,
build_target_result: BuildTargetResult,
+ build_target_conf: BuildTargetConfiguration,
+ dts_result: DTSResult
):
self.sut_node = sut_node
self._logger = getLogger(self.__class__.__name__)
@@ -55,6 +62,8 @@ def __init__(
self._test_cases_to_run.extend(SETTINGS.test_cases)
self._func = func
self._result = build_target_result.add_test_suite(self.__class__.__name__)
+ self.build_target_info = build_target_conf
+ self._dts_result = dts_result
def set_up_suite(self) -> None:
"""
@@ -118,6 +127,9 @@ def run(self) -> None:
f"the next test suite may be affected."
)
self._result.update_setup(Result.ERROR, e)
+ if len(self._result.get_errors()) > 0 and self.is_blocking:
+ raise BlockingTestSuiteError(test_suite_name)
+
def _execute_test_suite(self) -> None:
"""
@@ -137,6 +149,7 @@ def _execute_test_suite(self) -> None:
f"Attempt number {attempt_nr} out of {all_attempts}."
)
self._run_test_case(test_case_method, test_case_result)
+
def _get_functional_test_cases(self) -> list[MethodType]:
"""
@@ -232,6 +245,11 @@ def _execute_test_case(
test_case_result.update(Result.SKIP)
raise KeyboardInterrupt("Stop DTS")
+ def write_to_statistics_file(self, output: Dict[str, str]):
+ if self._dts_result.output != None:
+ self._dts_result.output.update(output)
+ else:
+ self._dts_result.output = output
def get_test_suites(testsuite_module_path: str) -> list[type[TestSuite]]:
def is_test_suite(object) -> bool:
@@ -252,3 +270,5 @@ def is_test_suite(object) -> bool:
test_suite_class
for _, test_suite_class in inspect.getmembers(testcase_module, is_test_suite)
]
+
+
diff --git a/dts/framework/testbed_model/__init__.py b/dts/framework/testbed_model/__init__.py
index f54a9470..63f17cc3 100644
--- a/dts/framework/testbed_model/__init__.py
+++ b/dts/framework/testbed_model/__init__.py
@@ -20,3 +20,8 @@
)
from .node import Node
from .sut_node import SutNode
+
+from .interactive_apps import (
+ InteractiveScriptHandler,
+ TestpmdDriver
+)
diff --git a/dts/framework/testbed_model/interactive_apps/__init__.py b/dts/framework/testbed_model/interactive_apps/__init__.py
new file mode 100644
index 00000000..0382d7e0
--- /dev/null
+++ b/dts/framework/testbed_model/interactive_apps/__init__.py
@@ -0,0 +1,6 @@
+from .interactive_command import (
+ InteractiveScriptHandler
+)
+from .testpmd_driver import (
+ TestpmdDriver
+)
\ No newline at end of file
diff --git a/dts/framework/testbed_model/interactive_apps/interactive_command.py b/dts/framework/testbed_model/interactive_apps/interactive_command.py
new file mode 100644
index 00000000..7467911b
--- /dev/null
+++ b/dts/framework/testbed_model/interactive_apps/interactive_command.py
@@ -0,0 +1,57 @@
+# import paramiko
+from paramiko import SSHClient, Channel, channel
+from framework.settings import SETTINGS
+
+class InteractiveScriptHandler:
+
+ _ssh_client: SSHClient
+ _stdin: channel.ChannelStdinFile
+ _ssh_channel: Channel
+
+ def __init__(self, ssh_client: SSHClient, timeout:float = SETTINGS.timeout) -> None:
+ self._ssh_client = ssh_client
+ self._ssh_channel = self._ssh_client.invoke_shell()
+ self._stdin = self._ssh_channel.makefile_stdin("wb")
+ self._ssh_channel.settimeout(timeout)
+
+ def send_command(self, command:str) -> None:
+ """
+ Send command to channel without recording output.
+
+ This method will not verify any input or output, it will
+ simply assume the command succeeded
+ """
+ self._stdin.write(command + '\n')
+ self._stdin.flush()
+
+ def send_command_get_output(self, command:str, expect:str) -> str:
+ """
+ Send a command and get all output before the expected ending string.
+
+ **NOTE**
+ Lines that expect input are not included in the stdout buffer so they cannot be
+ used for expect. For example, if you were prompted to log into something
+ with a username and password, you cannot expect "username:" because it wont
+ yet be in the stdout buffer. A work around for this could be consuming an
+ extra newline character to force the current prompt into the stdout buffer.
+
+ *Return*
+ All output before expected string
+ """
+ stdout = self._ssh_channel.makefile("r")
+ self._stdin.write(command + '\n')
+ self._stdin.flush()
+ out:str = ""
+ for line in stdout:
+ out += str(line)
+ if expect in str(line):
+ break
+ stdout.close() #close the buffer to flush the output
+ return out
+
+ def close(self):
+ self._stdin.close()
+ self._ssh_channel.close()
+
+ def __del__(self):
+ self.close()
diff --git a/dts/framework/testbed_model/interactive_apps/testpmd_driver.py b/dts/framework/testbed_model/interactive_apps/testpmd_driver.py
new file mode 100644
index 00000000..1993eae6
--- /dev/null
+++ b/dts/framework/testbed_model/interactive_apps/testpmd_driver.py
@@ -0,0 +1,24 @@
+from framework.testbed_model.interactive_apps import InteractiveScriptHandler
+
+from pathlib import PurePath
+
+class TestpmdDriver:
+ prompt:str = "testpmd>"
+ interactive_handler: InteractiveScriptHandler
+
+ def __init__(self, handler: InteractiveScriptHandler, dpdk_build_dir:PurePath, eal_flags:str = "", cmd_line_options:str = "") -> None:
+ """
+ Sets the handler to drive the SSH session and starts testpmd
+ """
+ self.interactive_handler = handler
+ # self.interactive_handler.send_command("sudo su")
+ # self.interactive_handler.send_command("cd /root/testpmd-testing/dpdk/build")
+ self.interactive_handler.send_command_get_output(f"{dpdk_build_dir}/app/dpdk-testpmd {eal_flags} -- -i {cmd_line_options}\n", self.prompt)
+
+ def send_command(self, command:str, expect:str = prompt) -> str:
+ """
+ Specific way of handling the command for testpmd
+
+ An extra newline character is consumed in order to force the current line into the stdout buffer
+ """
+ return self.interactive_handler.send_command_get_output(command + "\n", expect)
\ No newline at end of file
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index d48fafe6..c5147e0e 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -40,6 +40,7 @@ class Node(object):
lcores: list[LogicalCore]
_logger: DTSLOG
_other_sessions: list[OSSession]
+ _execution_config: ExecutionConfiguration
def __init__(self, node_config: NodeConfiguration):
self.config = node_config
@@ -64,6 +65,7 @@ def set_up_execution(self, execution_config: ExecutionConfiguration) -> None:
"""
self._setup_hugepages()
self._set_up_execution(execution_config)
+ self._execution_config = execution_config
def _set_up_execution(self, execution_config: ExecutionConfiguration) -> None:
"""
diff --git a/dts/framework/testbed_model/sut_node.py b/dts/framework/testbed_model/sut_node.py
index 2b2b50d9..8c39a66d 100644
--- a/dts/framework/testbed_model/sut_node.py
+++ b/dts/framework/testbed_model/sut_node.py
@@ -14,6 +14,7 @@
from .hw import LogicalCoreCount, LogicalCoreList, VirtualDevice
from .node import Node
+from .interactive_apps import InteractiveScriptHandler
class SutNode(Node):
@@ -261,6 +262,11 @@ def run_dpdk_app(
return self.main_session.send_command(
f"{app_path} {eal_args}", timeout, verify=True
)
+ def create_interactive_session_handler(self) -> InteractiveScriptHandler:
+ """
+ Create a handler for interactive sessions
+ """
+ return InteractiveScriptHandler(self.main_session._interactive_session)
class EalParameters(object):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
new file mode 100644
index 00000000..bacf289d
--- /dev/null
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -0,0 +1,94 @@
+from framework.test_suite import TestSuite
+from framework.testbed_model.sut_node import SutNode
+
+from framework.testbed_model.interactive_apps import TestpmdDriver
+
+def get_compiler_version(compiler_name: str, sut_node: SutNode) -> str:
+ match compiler_name:
+ case "gcc":
+ return sut_node.main_session.send_command(f"{compiler_name} --version", 60).stdout.split("\n")[0]
+ case "clang":
+ return sut_node.main_session.send_command(f"{compiler_name} --version", 60).stdout.split("\n")[0]
+ case "msvc":
+ return sut_node.main_session.send_command(f"cl", 60).stdout
+ case "icc":
+ return sut_node.main_session.send_command(f"{compiler_name} -V", 60).stdout
+
+class SmokeTests(TestSuite):
+ is_blocking = True
+
+ def set_up_suite(self) -> None:
+ """
+ Setup:
+ build all DPDK
+ """
+ self.dpdk_build_dir_path = self.sut_node.remote_dpdk_build_dir
+
+
+ def test_unit_tests(self) -> None:
+ """
+ Test:
+ run the fast-test unit-test suite through meson
+ """
+ self.sut_node.main_session.send_command(f"meson test -C {self.dpdk_build_dir_path} --suite fast-tests", 300)
+
+ def test_driver_tests(self) -> None:
+ """
+ Test:
+ run the driver-test unit-test suite through meson
+ """
+ list_of_vdevs = ""
+ for dev in self.sut_node._execution_config.vdevs:
+ list_of_vdevs += f"{dev},"
+ print(list_of_vdevs)
+ if len(list_of_vdevs) > 0:
+ self.sut_node.main_session.send_command(f"meson test -C {self.dpdk_build_dir_path} --suite driver-tests --test-args \"--vdev {list_of_vdevs}\"", 300)
+ else:
+ self.sut_node.main_session.send_command(f"meson test -C {self.dpdk_build_dir_path} --suite driver-tests", 300)
+
+ def test_gather_info(self) -> None:
+ """
+ Test:
+ gather information about the system and send output to statistics.txt
+ """
+ out = {}
+
+ out['OS'] = self.sut_node.main_session.send_command("awk -F= '$1==\"NAME\" {print $2}' /etc/os-release", 60).stdout
+ out["OS VERSION"] = self.sut_node.main_session.send_command("awk -F= '$1==\"VERSION\" {print $2}' /etc/os-release", 60, True).stdout
+ out["COMPILER VERSION"] = get_compiler_version(self.build_target_info.compiler.name, self.sut_node)
+ out["DPDK VERSION"] = self.sut_node.dpdk_version
+ if self.build_target_info.os.name == "linux":
+ out['KERNEL VERSION'] = self.sut_node.main_session.send_command("uname -r", 60).stdout
+ elif self.build_target_info.os.name == "windows":
+ out['KERNEL VERSION'] = self.sut_node.main_session.send_command("uname -a", 60).stdout
+ self.write_to_statistics_file(out)
+
+
+
+ def test_start_testpmd(self) -> None:
+ """
+ Creates and instance of the testpmd driver to run the testpmd app
+ """
+ driver: TestpmdDriver = TestpmdDriver(self.sut_node.create_interactive_session_handler(), self.dpdk_build_dir_path)
+
+ print(driver.send_command("show port summary all"))
+
+ def test_device_bound_to_driver(self) -> None:
+ """
+ Test:
+ ensure that all drivers listed in the config are bound to the correct drivers
+ """
+ for nic in self.sut_node._execution_config.nics:
+ for address in nic.addresses:
+ out = self.sut_node.main_session.send_command(f"{self.dpdk_build_dir_path}/../usertools/dpdk-devbind.py --status | grep {address}", 60)
+ self.verify(
+ len(out.stdout) != 0,
+ f"Failed to find configured device ({address}) using dpdk-devbind.py",
+ )
+ for string in out.stdout.split(" "):
+ if 'drv=' in string:
+ self.verify(
+ string.split("=")[1] == nic.driver.strip(),
+ f'Driver for device {address} does not match driver listed in configuration (bound to {string.split("=")[1]})',
+ )
+
\ No newline at end of file
--
2.40.1
next prev parent reply other threads:[~2023-05-12 19:27 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-12 19:25 [RFC v2 0/2] add DTS " jspewock
2023-05-12 19:25 ` jspewock [this message]
2023-05-23 8:05 ` [RFC v2 1/2] dts: add " Juraj Linkeš
2023-05-23 8:33 ` Juraj Linkeš
2023-05-24 20:44 ` Jeremy Spewock
2023-05-25 8:33 ` Juraj Linkeš
2023-05-25 18:02 ` Jeremy Spewock
2023-05-26 7:36 ` Juraj Linkeš
2023-05-26 13:24 ` Jeremy Spewock
2023-05-24 10:03 ` Juraj Linkeš
2023-05-25 15:40 ` Jeremy Spewock
2023-05-12 19:25 ` [RFC v2 2/2] dts: added paramiko to dependencies jspewock
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230512192540.401-3-jspewock@iol.unh.edu \
--to=jspewock@iol.unh.edu \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).