From 4d6666b65173bd9bdd30490e3c743cd45b9177f8 Mon Sep 17 00:00:00 2001 From: rahulsasingh Date: Wed, 17 Jun 2026 12:57:30 +0200 Subject: [PATCH] Fixing the integration test failure issu --- .bazelrc | 4 ++ .github/workflows/integration_tests.yml | 5 ++ .../environments/qnx8_qemu/init.build | 1 + .../environments/qnx8_qemu/startup.sh | 1 - score/test/component/datarouter/BUILD | 1 - .../component/datarouter/filetransfer_app.cpp | 13 ++-- score/test/component/filters_app/BUILD | 1 + score/test/component/logging_plugin.py | 60 ++++++++++++------- 8 files changed, 58 insertions(+), 28 deletions(-) diff --git a/.bazelrc b/.bazelrc index b90e1ef5..05f7f9c8 100644 --- a/.bazelrc +++ b/.bazelrc @@ -72,6 +72,10 @@ build:x86_64-qnx --platforms=@score_bazel_platforms//:x86_64-qnx-sdp_8.0.0-posix build:x86_64-qnx --extra_toolchains=@score_qcc_x86_64_toolchain//:x86_64-qnx-sdp_8.0.0 build:x86_64-qnx --extra_toolchains=@score_qnx_x86_64_ifs_toolchain//:ifs-x86_64-qnx-sdp_8.0.0 build:x86_64-qnx --extra_toolchains=@score_toolchains_rust//toolchains/ferrocene:ferrocene_x86_64_pc_nto_qnx800 +# Integration tests require direct device access (KVM, TAP) — bypass linux-sandbox +test:x86_64-qnx --strategy=TestRunner=local +# All QEMU instances share one tap0/IP — tests must run one at a time +test:x86_64-qnx --local_test_jobs=1 # TODO arm64 when rust support is there diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index 75c6661e..321b58c9 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -117,6 +117,11 @@ jobs: if-no-files-found: warn retention-days: 7 + - name: Cleanup tap0 network interface + if: always() + run: | + sudo ip link delete tap0 2>/dev/null || true + - name: Cleanup QNX license if: always() run: sudo rm -rf /opt/score_qnx diff --git a/quality/integration_testing/environments/qnx8_qemu/init.build b/quality/integration_testing/environments/qnx8_qemu/init.build index 44428bc6..2fbb8fec 100644 --- a/quality/integration_testing/environments/qnx8_qemu/init.build +++ b/quality/integration_testing/environments/qnx8_qemu/init.build @@ -21,6 +21,7 @@ [+script] startup-script = { procmgr_symlink /dev/shmem /tmp + procmgr_symlink /tmp_ram/tmp_discovery /tmp_discovery display_msg Welcome to QNX OS 8.0 on x86_64 - score_logging component tests diff --git a/quality/integration_testing/environments/qnx8_qemu/startup.sh b/quality/integration_testing/environments/qnx8_qemu/startup.sh index 03343945..504133e1 100644 --- a/quality/integration_testing/environments/qnx8_qemu/startup.sh +++ b/quality/integration_testing/environments/qnx8_qemu/startup.sh @@ -58,6 +58,5 @@ fi echo "---> Adding /tmp_discovery folder" mkdir -p /tmp_ram/tmp_discovery -ln -s /tmp_ram/tmp_discovery /tmp_discovery /proc/boot/sshd -f /var/ssh/sshd_config diff --git a/score/test/component/datarouter/BUILD b/score/test/component/datarouter/BUILD index fe6c0212..5fe797f8 100644 --- a/score/test/component/datarouter/BUILD +++ b/score/test/component/datarouter/BUILD @@ -72,7 +72,6 @@ filegroup( py_logging_itf_test( name = "test_datarouter_filters", srcs = ["test_datarouter_filters.py"], - extra_oci_tars = ["//score/test/component/filters_app:filtertest_classid_pkg"], filesystem = "//score/test/component/filters_app:filtertest_filesystem", deps = ["@score_itf//score/itf/plugins/dlt"], ) diff --git a/score/test/component/datarouter/filetransfer_app.cpp b/score/test/component/datarouter/filetransfer_app.cpp index ab9c5732..870ebf68 100644 --- a/score/test/component/datarouter/filetransfer_app.cpp +++ b/score/test/component/datarouter/filetransfer_app.cpp @@ -15,7 +15,6 @@ #include "score/mw/log/logging.h" #include -#include #include #include #include @@ -57,11 +56,13 @@ int main() { std::stringstream filename; filename << "/tmp/filetransfer_test_" << i << ".txt"; - std::error_code ec; - std::filesystem::copy(original_file, filename.str(), ec); - if (ec) { - logger.LogError() << "Failed to copy file:" << ec.message(); - continue; + { + std::ifstream src(original_file, std::ios::binary); + std::ofstream dst(filename.str(), std::ios::binary | std::ios::trunc); + if (!src || !dst || !(dst << src.rdbuf())) { + logger.LogError() << "Failed to copy file:" << filename.str(); + continue; + } } file_transfer.TransferFile(filename.str(), false); diff --git a/score/test/component/filters_app/BUILD b/score/test/component/filters_app/BUILD index 65cc1fae..746bcb46 100644 --- a/score/test/component/filters_app/BUILD +++ b/score/test/component/filters_app/BUILD @@ -110,6 +110,7 @@ pkg_tar( visibility = ["//score/test/component:__subpackages__"], deps = [ ":filtertest_bin_pkg", + ":filtertest_classid_pkg", ":filtertest_config_pkg", ], ) diff --git a/score/test/component/logging_plugin.py b/score/test/component/logging_plugin.py index 8bc06356..8d94dc44 100644 --- a/score/test/component/logging_plugin.py +++ b/score/test/component/logging_plugin.py @@ -20,7 +20,7 @@ from contextlib import contextmanager import pytest -from score.itf.plugins.dlt.dlt_receive import Protocol +from score.itf.plugins.dlt.dlt_receive import DltReceive, Protocol from score.itf.plugins.dlt.dlt_window import DltLogRecord LOGGER = logging.getLogger(__name__) @@ -31,8 +31,9 @@ _DATAROUTER_READY_INTERVAL = 0.2 _QNX_DR_CMD = ( - "on -A nonroot,allow,pathspace -u 1000:1000 " - "/usr/bin/datarouter/datarouter --no_adaptive_runtime " + "cd /usr/bin/datarouter && " + "nohup on -A nonroot,allow,pathspace -u 1000:1000 " + "./datarouter --no_adaptive_runtime " "> /dev/null 2>&1 &" ) _QNX_DR_STOP_CMD = ( @@ -75,8 +76,21 @@ def _wait_for_datarouter(target, timeout=_DATAROUTER_READY_TIMEOUT): raise TimeoutError(f"Datarouter not ready within {timeout}s") +class _LocalDltReceiver: + """Exposes a local DLT file path via the same .dlt_file interface as DltReceiver.""" + + def __init__(self, local_path): + self.dlt_file = local_path + + def download_dlt(target, remote_path): - """Download a .dlt file from the target and return a DltLogRecord.""" + """Download a .dlt file from the target and return a DltLogRecord. + + If remote_path is already a local file (QNX HOST-side capture), returns it directly. + """ + if os.path.exists(remote_path): + LOGGER.info(f"Using local DLT file: {os.path.getsize(remote_path)} bytes") + return DltLogRecord(remote_path) local_dir = tempfile.mkdtemp(prefix="dlt_") local_path = os.path.join(local_dir, os.path.basename(remote_path)) target.download(remote_path, local_path) @@ -97,8 +111,8 @@ def docker_configuration(): def datarouter_on_target(target): """Start the datarouter on the target (Docker or QNX), yield, then stop it.""" if _is_qnx(target): - target.execute(_QNX_DR_CMD) try: + target.execute(_QNX_DR_CMD) _wait_for_datarouter(target) yield target finally: @@ -119,25 +133,31 @@ def datarouter_on_target(target): @pytest.fixture(scope="function") def dlt_capture(target, dlt_on_target, request): - """Start a DLT receiver. On QNX, binds to the host tap0 IP from dlt_config.""" + """Start a DLT receiver. On QNX, runs dlt-receive on the host; on Docker, on the target.""" @contextmanager def _start(protocol=Protocol.UDP, host_ip=None, multicast_ips=None): - if host_ip is None: - if _is_qnx(target): - try: - dlt_cfg = request.getfixturevalue("dlt_config") - host_ip = dlt_cfg.host_ip - except pytest.FixtureLookupError: - host_ip = target.get_ip() - else: - host_ip = target.get_ip() if multicast_ips is None: multicast_ips = DLT_MULTICAST_IPS - with dlt_on_target( - protocol, host_ip=host_ip, multicast_ips=multicast_ips - ) as receiver: - time.sleep(_DLT_RECEIVER_SETTLE_DELAY) - yield receiver + + if _is_qnx(target): + dlt_cfg = request.getfixturevalue("dlt_config") + effective_host_ip = host_ip or dlt_cfg.host_ip + with DltReceive( + protocol=protocol, + host_ip=effective_host_ip, + multicast_ips=multicast_ips, + binary_path=dlt_cfg.dlt_receive_path, + ) as receiver: + time.sleep(_DLT_RECEIVER_SETTLE_DELAY) + yield _LocalDltReceiver(receiver.file_name()) + else: + if host_ip is None: + host_ip = target.get_ip() + with dlt_on_target( + protocol, host_ip=host_ip, multicast_ips=multicast_ips + ) as receiver: + time.sleep(_DLT_RECEIVER_SETTLE_DELAY) + yield receiver return _start