From 4816b990a4bd537c50b0d737e275b7834cb2569d Mon Sep 17 00:00:00 2001 From: BMW Engineer Date: Wed, 18 Jun 2025 16:33:43 +0200 Subject: [PATCH 1/6] Project import generated by Copybara. GIT_ORIGIN_SPP_REV_ID: 552f817aa8c7ea110d45c6a37e992812701c4b96 --- itf/plugins/xtf_common/__init__.py | 12 ++++++++++++ itf/plugins/xtf_common/bunch.py | 27 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 itf/plugins/xtf_common/__init__.py create mode 100644 itf/plugins/xtf_common/bunch.py diff --git a/itf/plugins/xtf_common/__init__.py b/itf/plugins/xtf_common/__init__.py new file mode 100644 index 0000000..6bdeed2 --- /dev/null +++ b/itf/plugins/xtf_common/__init__.py @@ -0,0 +1,12 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* diff --git a/itf/plugins/xtf_common/bunch.py b/itf/plugins/xtf_common/bunch.py new file mode 100644 index 0000000..05d1a88 --- /dev/null +++ b/itf/plugins/xtf_common/bunch.py @@ -0,0 +1,27 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +class Bunch: + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + def __repr__(self): + return str(self.__dict__) + + def __str__(self): + return str(self.__dict__) + + def get(self, *args, **kwargs): + return self.__dict__.get(*args, **kwargs) + + def update(self, **kwargs): + self.__dict__.update(kwargs) From 78d24ad7b675b0338f93115f67bf812732eca129 Mon Sep 17 00:00:00 2001 From: BMW Engineer Date: Tue, 11 Mar 2025 16:54:39 +0100 Subject: [PATCH 2/6] Project import generated by Copybara. GIT_ORIGIN_SPP_REV_ID: a26bdcc22e4f47a30bb01cba2dbe621e6af0ebd4 --- itf/plugins/base/__init__.py | 12 ++ itf/plugins/base/base_plugin.py | 88 +++++++++++ itf/plugins/base/constants.py | 17 +++ itf/plugins/base/os/config.py | 105 +++++++++++++ itf/plugins/base/os/operating_system.py | 26 ++++ itf/plugins/base/target/__init__.py | 12 ++ itf/plugins/base/target/config/__init__.py | 19 +++ .../base/target/config/base_processor.py | 140 ++++++++++++++++++ itf/plugins/base/target/config/config.py | 103 +++++++++++++ itf/plugins/base/target/config/ecu.py | 73 +++++++++ .../target/config/performance_processor.py | 88 +++++++++++ .../base/target/config/safety_processor.py | 58 ++++++++ itf/plugins/utils/__init__.py | 13 ++ itf/plugins/utils/utils.py | 19 +++ 14 files changed, 773 insertions(+) create mode 100644 itf/plugins/base/__init__.py create mode 100644 itf/plugins/base/base_plugin.py create mode 100644 itf/plugins/base/constants.py create mode 100644 itf/plugins/base/os/config.py create mode 100644 itf/plugins/base/os/operating_system.py create mode 100644 itf/plugins/base/target/__init__.py create mode 100644 itf/plugins/base/target/config/__init__.py create mode 100644 itf/plugins/base/target/config/base_processor.py create mode 100644 itf/plugins/base/target/config/config.py create mode 100644 itf/plugins/base/target/config/ecu.py create mode 100644 itf/plugins/base/target/config/performance_processor.py create mode 100644 itf/plugins/base/target/config/safety_processor.py create mode 100644 itf/plugins/utils/__init__.py create mode 100644 itf/plugins/utils/utils.py diff --git a/itf/plugins/base/__init__.py b/itf/plugins/base/__init__.py new file mode 100644 index 0000000..6bdeed2 --- /dev/null +++ b/itf/plugins/base/__init__.py @@ -0,0 +1,12 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* diff --git a/itf/plugins/base/base_plugin.py b/itf/plugins/base/base_plugin.py new file mode 100644 index 0000000..af326b4 --- /dev/null +++ b/itf/plugins/base/base_plugin.py @@ -0,0 +1,88 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +import logging +import pytest + +from itf.plugins.base.constants import TEST_CONFIG_KEY, TARGET_CONFIG_KEY +from itf.plugins.base.target.config import load_configuration, target_ecu_argparse +from itf.plugins.base.os.operating_system import OperatingSystem +from itf.plugins.utils import padder +from itf.plugins.xtf_common.bunch import Bunch + + +logger = logging.getLogger(__name__) + + +def pytest_addoption(parser): + parser.addoption( + "--target_config", + action="store", + default="", + help="Path to json file with target configurations.", + ) + parser.addoption( + "--ecu", + action="store", + required=True, + nargs="?", + help="Target ECU for testing", + ) + parser.addoption( + "--os", + action="store", + default=OperatingSystem.LINUX, + type=OperatingSystem.argparse, + choices=OperatingSystem, + nargs="?", + help="Operating System to run", + ) + parser.addoption("--qemu", action="store_true", help="Run tests with QEMU image") + parser.addoption("--qvp", action="store_true", help="Run tests with QVP") + parser.addoption("--hw", action="store_true", help="Run tests against connected HW") + + +@pytest.hookimpl(hookwrapper=True, tryfirst=True) +def pytest_sessionstart(session): + logger.info("Starting session in base_plugin.py ...") + print(padder("live log sessionstart")) + session.stash[TEST_CONFIG_KEY] = __make_test_config(session.config) + session.stash[TARGET_CONFIG_KEY] = __make_target_config(session.stash[TEST_CONFIG_KEY]) + session.ecu_name = session.stash[TEST_CONFIG_KEY].ecu.sut.ecu_name.lower() + yield + + +@pytest.fixture(scope="session") +def test_config_fixture(request): + return request.session.stash[TEST_CONFIG_KEY] + + +@pytest.fixture(scope="session") +def target_config_fixture(request): + target_config = request.session.stash[TARGET_CONFIG_KEY] + yield target_config + + +def __make_test_config(config): + load_configuration(config.getoption("target_config")) + return Bunch( + ecu=target_ecu_argparse(config.getoption("ecu")), + os=config.getoption("os"), + qemu=config.getoption("qemu"), + qvp=config.getoption("qvp"), + hw=config.getoption("hw"), + ) + + +def __make_target_config(test_config): + target_config = test_config.ecu.sut + return target_config diff --git a/itf/plugins/base/constants.py b/itf/plugins/base/constants.py new file mode 100644 index 0000000..ff42929 --- /dev/null +++ b/itf/plugins/base/constants.py @@ -0,0 +1,17 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +import pytest +from itf.plugins.xtf_common.bunch import Bunch + +TEST_CONFIG_KEY = pytest.StashKey[Bunch]() +TARGET_CONFIG_KEY = pytest.StashKey[Bunch]() diff --git a/itf/plugins/base/os/config.py b/itf/plugins/base/os/config.py new file mode 100644 index 0000000..9a4fb53 --- /dev/null +++ b/itf/plugins/base/os/config.py @@ -0,0 +1,105 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +# pylint: disable=invalid-name +from itf.plugins.xtf_common.bunch import Bunch + + + +DIAGNOSTICS_COMMON = { + "df_h": { + "description": "Disk usage", + "command": "df -h", + }, + "ls_l_dev": { + "description": "List devices", + "command": "ls -l /dev/", + }, + "netstat_r": { + "description": "Networking status - routing", + "command": "netstat -r", + } +} + + +DIAGNOSTICS_LINUX = { + "ps_aux": { + "description": "Processes - currently running", + "command": "ps aux", + }, + "top_b_n_1": { + "description": "Processes - resources consumption", + "command": "top -b -n 1", + }, + "journalctl": { + "description": "Query the systemd journal", + "command": "journalctl", + }, + "netstat_tul": { + "description": "Networking status - TCP/UDP Listening Ports", + "command": "netstat -tul", + }, + "netstat_xln": { + "description": "Networking status - active Unix domain sockets", + "command": "netstat -xln", + }, + "ip_a": { + "description": "Networking status - interfaces", + "command": "ip a", + }, + "iptables_L": { + "description": "Firewall rules", + "command": "iptables -S", + }, + "systemd_analyze_plot": { + "description": "Systemd startup time plot", + "command": "systemd-analyze plot", + "extension": "svg", + } +} +DIAGNOSTICS_LINUX.update(DIAGNOSTICS_COMMON) + + +DIAGNOSTICS_QNX = { + "ps_A": { + "description": "Processes - currently running", + "command": "ps -A", + }, + "top_i_1": { + "description": "Processes - resources consumption", + "command": "top -b -i 1", + }, + "netstat": { + "description": "Networking status - active Unix domain, IPv4 and IPv6 sockets", + "command": "netstat", + } +} +DIAGNOSTICS_QNX.update(DIAGNOSTICS_COMMON) + + +def os_config(name, diagnostics, ssh_uses_ext_ip): + return Bunch( + name=name, + diagnostics=diagnostics, + ssh_uses_ext_ip=ssh_uses_ext_ip, + ) + + +operating_system = Bunch( + linux=os_config("linux", DIAGNOSTICS_LINUX, False), + qnx=os_config("qnx", DIAGNOSTICS_QNX, False), +) + + +global_os_config = Bunch( + os=operating_system, +) diff --git a/itf/plugins/base/os/operating_system.py b/itf/plugins/base/os/operating_system.py new file mode 100644 index 0000000..a1b2c50 --- /dev/null +++ b/itf/plugins/base/os/operating_system.py @@ -0,0 +1,26 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +from enum import Enum +from itf.plugins.base.os.config import global_os_config as os_config + +class OperatingSystem(Enum): + LINUX = os_config.os.linux + QNX = os_config.os.qnx + UNSPECIFIED = {} + + @staticmethod + def argparse(s): + try: + return OperatingSystem[s.upper()] + except KeyError: + return s diff --git a/itf/plugins/base/target/__init__.py b/itf/plugins/base/target/__init__.py new file mode 100644 index 0000000..6bdeed2 --- /dev/null +++ b/itf/plugins/base/target/__init__.py @@ -0,0 +1,12 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* diff --git a/itf/plugins/base/target/config/__init__.py b/itf/plugins/base/target/config/__init__.py new file mode 100644 index 0000000..de19f5c --- /dev/null +++ b/itf/plugins/base/target/config/__init__.py @@ -0,0 +1,19 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +from .config import load_configuration +from .config import target_ecu_argparse + +from .config import ECUS +from .config import PERFORMANCE_PROCESSORS +from .config import SAFETY_PROCESSORS +from .config import OTHER_PROCESSORS diff --git a/itf/plugins/base/target/config/base_processor.py b/itf/plugins/base/target/config/base_processor.py new file mode 100644 index 0000000..737dc60 --- /dev/null +++ b/itf/plugins/base/target/config/base_processor.py @@ -0,0 +1,140 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +import json + + +class BaseProcessor: + def __init__( + self, + name: str, + ip_address: str = None, + diagnostic_ip_address: str = None, + diagnostic_address: int = None, + serial_device: str = None, + use_doip: bool = False, + params: dict = None, + ): + """Initialize the BaseProcessor class. + + :param str name: The name of the processor. + :param str ip_address: The IP address of the processor. + :param str diagnostic_ip_address: The internal IP address for diagnostics. + :param int diagnostic_address: The diagnostic address of the processor. + :param str serial_device: The serial device for the processor. + :param bool use_doip: Flag to indicate if DoIP is used + :param dict params: Additional parameters for the processor. + """ + self.__name = name + self.__ip_address = ip_address + self.__diagnostic_ip_address = diagnostic_ip_address + self.__diagnostic_address = diagnostic_address + self.__serial_device = serial_device + self.__use_doip = use_doip + self.__params = params + if params: + self.__dict__.update(**params) + + @property + def name(self): + return self.__name + + @property + def ip_address(self): + return self.__ip_address + + @ip_address.setter + def ip_address(self, value): + self.__ip_address = value + + @property + def diagnostic_ip_address(self): + return self.__diagnostic_ip_address + + @property + def diagnostic_address(self): + return self.__diagnostic_address + + @property + def serial_device(self): + return self.__serial_device + + @property + def use_doip(self): + return self.__use_doip + + @use_doip.setter + def use_doip(self, value): + self.__use_doip = value + + @property + def params(self): + return self.__params + + def get_param(self, param_name: str): + """Get a specific parameter by name. + + :param str param_name: The name of the parameter. + :return: The value of the parameter. + """ + if self.__dict__ is not None: + return self.__dict__[param_name] + return None + + def set_param(self, param_name: str, param_value): + """Add or update a parameter in the processor's parameters. + + :param str param_name: The name of the parameter. + :param param_value: The value of the parameter. + """ + self.__params[param_name] = param_value + if self.__dict__ is not None: + self.__dict__[param_name] = param_value + + def get(self, *args, **kwargs): + return self.__dict__.get(args, kwargs) + + def update(self, processor): + """Update the current processor with another processor's parameters. + + :param BaseProcessor processor: The BaseProcessor instance to update from. + """ + self.__ip_address = processor.ip_address + self.__diagnostic_ip_address = processor.diagnostic_ip_address + self.__diagnostic_address = processor.diagnostic_address + self.__serial_device = processor.serial_device + self.__use_doip = processor.use_doip + if processor.params: + self.__dict__.update(**processor.params) + if self.__params: + self.__params.update(processor.params) + else: + self.__params = processor.params + + def __str__(self): + return f"{self.__name.upper()} ({json.dumps(self.__dict__, indent=4)})" + + def __repr__(self): + return f"{self.__name.upper()} ({json.dumps(self.__dict__, indent=4)})" + + def __eq__(self, other): + if isinstance(other, BaseProcessor): + return self.__name == other.name + return False + + def __ne__(self, other): + if isinstance(other, BaseProcessor): + return self.name != other.name + return True + + def __hash__(self): + return hash(self.__name) diff --git a/itf/plugins/base/target/config/config.py b/itf/plugins/base/target/config/config.py new file mode 100644 index 0000000..c1e0a36 --- /dev/null +++ b/itf/plugins/base/target/config/config.py @@ -0,0 +1,103 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +import json +import logging + +from itf.plugins.base.target.config.base_processor import BaseProcessor +from itf.plugins.base.target.config.performance_processor import PerformanceProcessor +from itf.plugins.base.target.config.safety_processor import SafetyProcessor +from itf.plugins.base.target.config.ecu import Ecu + + +logger = logging.getLogger(__name__) + +PERFORMANCE_PROCESSORS = {} +SAFETY_PROCESSORS = {} +OTHER_PROCESSORS = {} +ECUS = {} + + +def load_configuration(config_file: str): + """ + Load the configuration from a JSON file. + param config_file: The path to the configuration file. + """ + logger.info(f"Loading configuration from {config_file}") + with open(config_file, "r") as file: + config = json.load(file) + for ecu_name, ecu_config in config.items(): + + performance_processor = None + if "performance_processor" in ecu_config: + perf_config = ecu_config.get("performance_processor") + performance_processor = PerformanceProcessor( + name=perf_config["name"], + ip_address=perf_config["ip_address"], + ext_ip_address=perf_config["ext_ip_address"], + diagnostic_ip_address=perf_config["diagnostic_ip_address"], + diagnostic_address=int(perf_config["diagnostic_address"], 16), + serial_device=perf_config["serial_device"], + network_interfaces=perf_config["network_interfaces"], + ecu_name=perf_config["ecu_name"], + params=perf_config.get("params", {}), + ) + PERFORMANCE_PROCESSORS[perf_config["name"]] = performance_processor + + safety_processor = None + if "safety_processor" in ecu_config: + safety_config = ecu_config.get("safety_processor") + safety_processor = SafetyProcessor( + name=safety_config["name"], + ip_address=safety_config["ip_address"], + diagnostic_ip_address=safety_config["diagnostic_ip_address"], + diagnostic_address=int(safety_config["diagnostic_address"], 16), + serial_device=safety_config["serial_device"], + use_doip=safety_config.get("use_doip", False), + params=safety_config.get("params", {}), + ) + SAFETY_PROCESSORS[safety_config["name"]] = safety_processor + + other_processors = [] + for other_name, other_config in ecu_config.get("other_processors", {}).items(): + other_processor = BaseProcessor( + name=other_name, + ip_address=other_config["ip_address"], + diagnostic_ip_address=other_config["diagnostic_ip_address"], + diagnostic_address=int(other_config["diagnostic_address"], 16), + serial_device=other_config["serial_device"], + use_doip=other_config.get("use_doip", False), + params=other_config.get("params", {}), + ) + OTHER_PROCESSORS[other_name] = other_processor + other_processors.append(other_processor) + + ECUS[ecu_name] = Ecu( + name=ecu_name, + sut=performance_processor, + sc=safety_processor, + others=other_processors, + ) + + +def target_ecu_argparse(ecu: str): + """ + Convert a string to a TargetECU object. + + param ecu: The string representation of the ECU. + return: The corresponding TargetECU object. + raise RuntimeError: If the ECU is not supported. + """ + try: + return ECUS[ecu.upper()] + except KeyError as error: + raise RuntimeError(f"Unsupported ECU '{ecu}' specified. Supported ECUs are: {ECUS.keys()}") from error diff --git a/itf/plugins/base/target/config/ecu.py b/itf/plugins/base/target/config/ecu.py new file mode 100644 index 0000000..918b4db --- /dev/null +++ b/itf/plugins/base/target/config/ecu.py @@ -0,0 +1,73 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +from typing import List +from itf.plugins.base.target.config.base_processor import BaseProcessor +from itf.plugins.base.target.config.performance_processor import PerformanceProcessor +from itf.plugins.base.target.config.safety_processor import SafetyProcessor + + +class Ecu: + + # pylint: disable=dangerous-default-value + def __init__( + self, name: str, + sut: PerformanceProcessor, + sc: SafetyProcessor, + others: List[BaseProcessor] = [] + ): + """Initialize the Ecu class. + + :param str name: The name of the ECU. + :param sut: The SUT (Software Under Test) processor. + :param sc: The Safety Controller processor. + :param others: A list of other processors associated with the ECU. + """ + self.__name = name + self.__sut = sut + self.__sc = sc + self.__others = others + + @property + def name(self): + return self.__name + + @property + def sut(self): + return self.__sut + + @property + def sc(self): # pylint: disable=invalid-name + return self.__sc + + @property + def others(self): + return self.__others + + def __str__(self): + return str(self.__name).upper() + + def __repr__(self): + return str(self) + + def __eq__(self, other): + if isinstance(other, Ecu): + return self.__name == other.name + return False + + def __ne__(self, other): + if isinstance(other, Ecu): + return self.__name != other.name + return True + + def __hash__(self): + return hash(self.__name) diff --git a/itf/plugins/base/target/config/performance_processor.py b/itf/plugins/base/target/config/performance_processor.py new file mode 100644 index 0000000..6c8de8a --- /dev/null +++ b/itf/plugins/base/target/config/performance_processor.py @@ -0,0 +1,88 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +from itf.plugins.base.target.config.base_processor import BaseProcessor + + +class PerformanceProcessor(BaseProcessor): + + # pylint: disable=dangerous-default-value + def __init__( + self, + name: str, + ip_address: str = None, + ext_ip_address: str = None, + diagnostic_ip_address: str = None, + diagnostic_address: int = 0, + serial_device: str = None, + network_interfaces: list = [], + ecu_name: str = None, + params: dict = None, + ): + """Initialize the PerformanceProcessor class. + + :param str name: The name of the processor. + :param str ip_address: The IP address of the processor. + :param str ext_ip_address: The external IP address of the processor. + :param str diagnostic_ip_address: The internal IP address for diagnostics. + :param int diagnostic_address: The diagnostic address of the processor. + :param str serial_device: The serial device for the processor. + :param list network_interfaces: The network interfaces for the processor. + :param str ecu_name: The ECU name for the processor. + :param dict params: Additional parameters for the processor. + """ + super().__init__( + name=name, + ip_address=ip_address, + diagnostic_ip_address=diagnostic_ip_address, + diagnostic_address=diagnostic_address, + serial_device=serial_device, + params=params, + ) + self.__ext_ip_address = ext_ip_address + self.__network_interfaces = network_interfaces + self.__ecu_name = ecu_name + + @property + def ext_ip_address(self): + return self.__ext_ip_address + + @property + def ecu_name(self): + return self.__ecu_name + + @property + def network_interfaces(self): + return self.__network_interfaces + + def update(self, processor): + """Update the current processor with another processor's parameters. + + :param PerformanceProcessor processor: The PerformanceProcessor instance to update from. + """ + super().update(processor) + self.__ext_ip_address = processor.ext_ip_address + self.__network_interfaces = processor.network_interfaces + self.__ecu_name = processor.ecu_name + + def __eq__(self, other): + if isinstance(other, PerformanceProcessor): + return super().__eq__(other) + return False + + def __ne__(self, other): + if isinstance(other, PerformanceProcessor): + return super().__ne__(other) + return True + + def __hash__(self): # pylint: disable=useless-super-delegation + return super().__hash__() diff --git a/itf/plugins/base/target/config/safety_processor.py b/itf/plugins/base/target/config/safety_processor.py new file mode 100644 index 0000000..8417791 --- /dev/null +++ b/itf/plugins/base/target/config/safety_processor.py @@ -0,0 +1,58 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +from itf.plugins.base.target.config.base_processor import BaseProcessor + + +class SafetyProcessor(BaseProcessor): + def __init__( + self, + name: str, + ip_address: str = None, + diagnostic_ip_address: str = None, + diagnostic_address: int = 0, + serial_device: str = None, + use_doip: bool = False, + params: dict = None, + ): + """Initialize the SafetyProcessor class. + + :param str name: The name of the processor. + :param str ip_address: The IP address of the processor. + :param str diagnostic_ip_address: The internal IP address for diagnostics. + :param int diagnostic_address: The diagnostic address of the processor. + :param str serial_device: The serial device for the processor. + :param bool use_doip: Flag to indicate if DoIP is used. + :param dict params: Additional parameters for the processor. + """ + super().__init__( + name=name, + ip_address=ip_address, + diagnostic_ip_address=diagnostic_ip_address, + diagnostic_address=diagnostic_address, + serial_device=serial_device, + use_doip=use_doip, + params=params, + ) + + def __eq__(self, other): + if isinstance(other, SafetyProcessor): + return super().__eq__(other) + return False + + def __ne__(self, other): + if isinstance(other, SafetyProcessor): + return super().__ne__(other) + return True + + def __hash__(self): # pylint: disable=useless-super-delegation + return super().__hash__() diff --git a/itf/plugins/utils/__init__.py b/itf/plugins/utils/__init__.py new file mode 100644 index 0000000..3bdea4d --- /dev/null +++ b/itf/plugins/utils/__init__.py @@ -0,0 +1,13 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +from .utils import padder diff --git a/itf/plugins/utils/utils.py b/itf/plugins/utils/utils.py new file mode 100644 index 0000000..f7e242b --- /dev/null +++ b/itf/plugins/utils/utils.py @@ -0,0 +1,19 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +CONSOLE_WIDTH = 80 + +def padder(string, length=CONSOLE_WIDTH): + str_len = len(string) + left = round((length - 2 - str_len) / 2) + right = length - 2 - str_len - left + return f'{left*"-"} {string} {right*"-"}' From 8cb78dfdb541c4e59b82c27969350a16cfbf2d52 Mon Sep 17 00:00:00 2001 From: BMW Engineer Date: Tue, 11 Mar 2025 16:54:39 +0100 Subject: [PATCH 3/6] Project import generated by Copybara. GIT_ORIGIN_SPP_REV_ID: 53d78cdfcb357e8bb6c9ed9d527860d34c177be7 --- itf/plugins/base/os/config.py | 7 +++---- itf/plugins/base/os/operating_system.py | 1 + itf/plugins/base/target/config/config.py | 1 - itf/plugins/base/target/config/ecu.py | 6 +++--- itf/plugins/base/target/config/performance_processor.py | 1 - itf/plugins/utils/utils.py | 1 + 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/itf/plugins/base/os/config.py b/itf/plugins/base/os/config.py index 9a4fb53..5093f8d 100644 --- a/itf/plugins/base/os/config.py +++ b/itf/plugins/base/os/config.py @@ -14,7 +14,6 @@ from itf.plugins.xtf_common.bunch import Bunch - DIAGNOSTICS_COMMON = { "df_h": { "description": "Disk usage", @@ -27,7 +26,7 @@ "netstat_r": { "description": "Networking status - routing", "command": "netstat -r", - } + }, } @@ -64,7 +63,7 @@ "description": "Systemd startup time plot", "command": "systemd-analyze plot", "extension": "svg", - } + }, } DIAGNOSTICS_LINUX.update(DIAGNOSTICS_COMMON) @@ -81,7 +80,7 @@ "netstat": { "description": "Networking status - active Unix domain, IPv4 and IPv6 sockets", "command": "netstat", - } + }, } DIAGNOSTICS_QNX.update(DIAGNOSTICS_COMMON) diff --git a/itf/plugins/base/os/operating_system.py b/itf/plugins/base/os/operating_system.py index a1b2c50..4df55b8 100644 --- a/itf/plugins/base/os/operating_system.py +++ b/itf/plugins/base/os/operating_system.py @@ -13,6 +13,7 @@ from enum import Enum from itf.plugins.base.os.config import global_os_config as os_config + class OperatingSystem(Enum): LINUX = os_config.os.linux QNX = os_config.os.qnx diff --git a/itf/plugins/base/target/config/config.py b/itf/plugins/base/target/config/config.py index c1e0a36..b8050ca 100644 --- a/itf/plugins/base/target/config/config.py +++ b/itf/plugins/base/target/config/config.py @@ -36,7 +36,6 @@ def load_configuration(config_file: str): with open(config_file, "r") as file: config = json.load(file) for ecu_name, ecu_config in config.items(): - performance_processor = None if "performance_processor" in ecu_config: perf_config = ecu_config.get("performance_processor") diff --git a/itf/plugins/base/target/config/ecu.py b/itf/plugins/base/target/config/ecu.py index 918b4db..bdafca5 100644 --- a/itf/plugins/base/target/config/ecu.py +++ b/itf/plugins/base/target/config/ecu.py @@ -17,13 +17,13 @@ class Ecu: - # pylint: disable=dangerous-default-value def __init__( - self, name: str, + self, + name: str, sut: PerformanceProcessor, sc: SafetyProcessor, - others: List[BaseProcessor] = [] + others: List[BaseProcessor] = [], ): """Initialize the Ecu class. diff --git a/itf/plugins/base/target/config/performance_processor.py b/itf/plugins/base/target/config/performance_processor.py index 6c8de8a..8b3dbbe 100644 --- a/itf/plugins/base/target/config/performance_processor.py +++ b/itf/plugins/base/target/config/performance_processor.py @@ -14,7 +14,6 @@ class PerformanceProcessor(BaseProcessor): - # pylint: disable=dangerous-default-value def __init__( self, diff --git a/itf/plugins/utils/utils.py b/itf/plugins/utils/utils.py index f7e242b..a263f81 100644 --- a/itf/plugins/utils/utils.py +++ b/itf/plugins/utils/utils.py @@ -12,6 +12,7 @@ # ******************************************************************************* CONSOLE_WIDTH = 80 + def padder(string, length=CONSOLE_WIDTH): str_len = len(string) left = round((length - 2 - str_len) / 2) From fb503c3b6eae1c0cecf0a928efd3ca143a03fc51 Mon Sep 17 00:00:00 2001 From: Dragan Bjedov Date: Tue, 24 Jun 2025 16:12:35 +0200 Subject: [PATCH 4/6] Added bazel folders to gititgnore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 82e3824..bd47a7d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ bazel-* MODULE.bazel.lock .ruff_cache + +bazel-* From e7b545878dd331610fb8addafe094661fe0f5797 Mon Sep 17 00:00:00 2001 From: Dragan Bjedov Date: Tue, 24 Jun 2025 16:13:01 +0200 Subject: [PATCH 5/6] Ruff linter line lenght set to 120 --- .ruff.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/.ruff.toml b/.ruff.toml index e69de29..f11cf63 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -0,0 +1 @@ +line-length = 120 From ffd9893986d3f7ba21dce4585550b4c7a29d5cc0 Mon Sep 17 00:00:00 2001 From: Dragan Bjedov Date: Tue, 24 Jun 2025 16:14:02 +0200 Subject: [PATCH 6/6] Fixed lint issues in docker.py --- itf/plugins/docker.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/itf/plugins/docker.py b/itf/plugins/docker.py index 08a8b8c..f14d36f 100644 --- a/itf/plugins/docker.py +++ b/itf/plugins/docker.py @@ -38,15 +38,11 @@ def pytest_addoption(parser): def docker(request): docker_image_bootstrap = request.config.getoption("docker_image_bootstrap") if docker_image_bootstrap: - logger.info( - f"Executing custom image bootstrap command: {docker_image_bootstrap}" - ) + logger.info(f"Executing custom image bootstrap command: {docker_image_bootstrap}") subprocess.run([docker_image_bootstrap], check=True) docker_image = request.config.getoption("docker_image") client = pypi_docker.from_env() - container = client.containers.run( - docker_image, "sleep infinity", detach=True, auto_remove=True, init=True - ) + container = client.containers.run(docker_image, "sleep infinity", detach=True, auto_remove=True, init=True) yield container container.stop(timeout=1)