From 61b72a17e51b62e71adf0c6cf54ccad220268e16 Mon Sep 17 00:00:00 2001 From: Daniel Thwaites Date: Wed, 22 Jul 2026 15:34:32 +0100 Subject: [PATCH 1/6] Run integration tests on QNX via QEMU --- .bazelrc | 15 +- MODULE.bazel | 5 + MODULE.bazel.lock | 2 - examples/demo_verification/test_examples.py | 2 +- tests/utils/bazel/integration.bzl | 24 +- tests/utils/environments/BUILD | 22 - tests/utils/environments/x86_64-qnx/BUILD | 33 ++ .../utils/environments/x86_64-qnx/init.build | 414 ++++++++++++++++++ .../environments/x86_64-qnx/qemu_config.json | 18 + .../testing_utils/run_until_file_deployed.py | 2 +- tests/utils/testing_utils/setup_test.py | 4 +- 11 files changed, 500 insertions(+), 41 deletions(-) create mode 100644 tests/utils/environments/x86_64-qnx/BUILD create mode 100644 tests/utils/environments/x86_64-qnx/init.build create mode 100644 tests/utils/environments/x86_64-qnx/qemu_config.json diff --git a/.bazelrc b/.bazelrc index 53b505bd8..56a7dd4ec 100644 --- a/.bazelrc +++ b/.bazelrc @@ -86,9 +86,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_toolchains_rust//toolchains/ferrocene:ferrocene_x86_64_pc_nto_qnx800 build:x86_64-qnx --extra_toolchains=@score_qnx_x86_64_ifs_toolchain//:ifs-x86_64-qnx-sdp_8.0.0 -test:x86_64-qnx --run_under=@score_qnx_unit_tests//src:run_under_qnx -test:x86_64-qnx --test_tag_filters=-skip_local # see https://github.com/eclipse-score/lifecycle/issues/272 -test:x86_64-qnx --test_lang_filters=cc,rust +build:x86_64-qnx --define config=x86_64-qnx +# test:x86_64-qnx --run_under=@score_qnx_unit_tests//src:run_under_qnx +# test:x86_64-qnx --test_tag_filters=-skip_local # see https://github.com/eclipse-score/lifecycle/issues/272 +# test:x86_64-qnx --test_lang_filters=cc,rust # Target configuration for CPU:AArch64|OS:QNX build (do not use it in case of system toolchains!) build:arm64-qnx --config=stub @@ -98,10 +99,10 @@ build:arm64-qnx --platforms=@score_bazel_platforms//:aarch64-qnx-sdp_8.0.0-posix build:arm64-qnx --extra_toolchains=@score_qcc_aarch64_toolchain//:aarch64-qnx-sdp_8.0.0 build:arm64-qnx --extra_toolchains=@score_toolchains_rust//toolchains/ferrocene:ferrocene_aarch64_unknown_nto_qnx800 build:arm64-qnx --extra_toolchains=@score_qnx_aarch64_ifs_toolchain//:ifs-aarch64-qnx-sdp_8.0.0 -test:arm64-qnx --run_under=@score_qnx_unit_tests//src:run_under_qnx -test:arm64-qnx --test_tag_filters=-skip_local # see https://github.com/eclipse-score/lifecycle/issues/272 -test:arm64-qnx --test_timeout=300 -test:arm64-qnx --test_lang_filters=cc,rust +# test:arm64-qnx --run_under=@score_qnx_unit_tests//src:run_under_qnx +# test:arm64-qnx --test_tag_filters=-skip_local # see https://github.com/eclipse-score/lifecycle/issues/272 +# test:arm64-qnx --test_timeout=300 +# test:arm64-qnx --test_lang_filters=cc,rust # Ferrocene Rust coverage config diff --git a/MODULE.bazel b/MODULE.bazel index ab45b22bb..1cdb3b079 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -163,6 +163,11 @@ pip.parse( use_repo(pip, "score_lifecycle_pip") bazel_dep(name = "score_itf", version = "0.5.0", dev_dependency = True) +git_override( + module_name = "score_itf", + branch = "fix/qemu-pid", + remote = "https://github.com/etas-contrib/score_itf.git", +) oci = use_extension("@rules_oci//oci:extensions.bzl", "oci", dev_dependency = True) oci.pull( diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 949af6f47..86245c5b3 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -968,8 +968,6 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/4.6.1/MODULE.bazel": "0dae734ea8a99970a7417829b3115af02717b29f0fc40a8ebd3c1afcc71e1e21", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/4.6.1/source.json": "3299daf219b15ba4aff6ca801385abebe0aaf364f71e391cd76cf9d38f3741f6", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_format_checker/0.1.1/MODULE.bazel": "1acc254faa90e9f97b79ac69af25b6c21c561f8d6079914f6352b9b20d26bd37", - "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_itf/0.5.0/MODULE.bazel": "d3ae40173462419b4e14e3fea96a49eab8822be7292f94890beb8cc73173eaa1", - "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_itf/0.5.0/source.json": "3c0fcd761e221bc33e6ebbeb0f92ce71b5d6f1f946b60ccf4fe7cf3a4c00d211", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_platform/0.1.0/MODULE.bazel": "cc9eae86e76f2a930510ed6e50ec991bb5661687e24881685b39c322087adf6f", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_platform/0.1.1/MODULE.bazel": "eb086ba99f9319371fbbd0a9252dfd27b0817039b88bd4d691602974b1ada005", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_platform/0.6.2/MODULE.bazel": "e88e7d086a08e1b451a68b60038b8b1f3c028aae7efc0bc9d8b39b6261ba040d", diff --git a/examples/demo_verification/test_examples.py b/examples/demo_verification/test_examples.py index 70bdc7f7b..6b8ee53c9 100644 --- a/examples/demo_verification/test_examples.py +++ b/examples/demo_verification/test_examples.py @@ -138,7 +138,7 @@ def test_examples(target, setup_test, remote_test_dir): _assert_not_running(target, "cpp_supervised_app") _step("Stopping launch manager (SIGTERM)") - res, _ = target.execute(f"kill -15 -{lm_proc.pid()}") + res, _ = target.execute(f"kill -TERM {lm_proc.pid()}") assert res == 0, "Failed to send SIGTERM to launch manager process group" time.sleep(0.5) assert not lm_proc.is_running(), "Launch manager did not stop after SIGTERM" diff --git a/tests/utils/bazel/integration.bzl b/tests/utils/bazel/integration.bzl index 6267f513e..f46a55519 100644 --- a/tests/utils/bazel/integration.bzl +++ b/tests/utils/bazel/integration.bzl @@ -73,25 +73,39 @@ def integration_test( name = name, srcs = srcs, tags = kwargs.pop("tags", []) + [ + # The QEMU plugin uses a hardcoded port so we can only run one test at a time. + # The Docker plugin works in parallel but tags cannot be conditional. + "exclusive", "integration", - "no-asan", # The test container does not ship the sanitizer runtime; daemon fails to start. + # The test container does not ship the sanitizer runtime; daemon fails to start. + "no-asan", ], deps = kwargs.pop("deps", []) + all_requirements + [ "@score_tooling//python_basics/score_pytest:attribute_plugin", "//tests/utils/testing_utils", ], data = kwargs.pop("data", []) + [":environment"] + select({ - "//config:host": [], - "//conditions:default": ["//tests/utils/environments:test_environment"], + "//config:x86_64-linux": [ + "//tests/utils/environments/x86_64-linux", + ], + "//config:x86_64-qnx": [ + "//tests/utils/environments/x86_64-qnx:qemu_config.json", + "//tests/utils/environments/x86_64-qnx:qemu_image", + ], + "//conditions:default": [], }), args = kwargs.pop("args", []) + [ "--score-test-binary-path=$(locations :environment)", "--score-test-remote-directory={}/tests/{}".format(install_prefix, name), ] + select({ "//config:x86_64-linux": [ - "--docker-image-bootstrap=$(location //tests/utils/environments:test_environment)", + "--docker-image-bootstrap=$(location //tests/utils/environments/x86_64-linux)", "--docker-image=score_itf_examples:latest", ], + "//config:x86_64-qnx": [ + "--qemu-config=$(location //tests/utils/environments/x86_64-qnx:qemu_config.json)", + "--qemu-image=$(location //tests/utils/environments/x86_64-qnx:qemu_image)", + ], "//config:host": [ "--local-dir=/tmp/score_itf_host/{}".format(name), ], @@ -99,7 +113,7 @@ def integration_test( }), plugins = ["//tests/utils/plugins:integration_plugin"] + select({ "//config:x86_64-linux": ["@score_itf//score/itf/plugins:docker_plugin"], - "//config:x86_64-qnx": ["@score_itf//score/itf/plugins/qemu"], + "//config:x86_64-qnx": ["@score_itf//score/itf/plugins:qemu_plugin"], "//config:host": ["//tests/utils/plugins:localhost_plugin"], "//conditions:default": [], }), diff --git a/tests/utils/environments/BUILD b/tests/utils/environments/BUILD index 2c85cdb51..bf049e025 100644 --- a/tests/utils/environments/BUILD +++ b/tests/utils/environments/BUILD @@ -15,25 +15,3 @@ exports_files( ["ecu_logging_config.json"], visibility = ["//tests/utils/environments:__subpackages__"], ) - -# Empty target for native builds -filegroup( - name = "empty_target", - srcs = [], - visibility = [ - "//examples:__subpackages__", - "//tests:__subpackages__", - ], -) - -alias( - name = "test_environment", - actual = select({ - "//config:x86_64-linux": "//tests/utils/environments/x86_64-linux", - "//conditions:default": ":empty_target", - }), - visibility = [ - "//examples:__subpackages__", - "//tests:__subpackages__", - ], -) diff --git a/tests/utils/environments/x86_64-qnx/BUILD b/tests/utils/environments/x86_64-qnx/BUILD new file mode 100644 index 000000000..bad1ddc04 --- /dev/null +++ b/tests/utils/environments/x86_64-qnx/BUILD @@ -0,0 +1,33 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +load("@rules_pkg//pkg:mappings.bzl", "pkg_files") +load("@score_rules_imagefs//rules/qnx:ifs.bzl", "qnx_ifs") + +exports_files( + ["qemu_config.json"], + visibility = ["//tests:__subpackages__"], +) + +pkg_files( + name = "logging_config.json", + srcs = ["//tests/utils/environments:ecu_logging_config.json"], + prefix = "/etc", +) + +qnx_ifs( + name = "qemu_image", + srcs = [":logging_config.json"], + build_file = ":init.build", + visibility = ["//tests:__subpackages__"], +) diff --git a/tests/utils/environments/x86_64-qnx/init.build b/tests/utils/environments/x86_64-qnx/init.build new file mode 100644 index 000000000..2c651e270 --- /dev/null +++ b/tests/utils/environments/x86_64-qnx/init.build @@ -0,0 +1,414 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +# This file originates from https://github.com/eclipse-score/communication/blob/8826549731f455fad66bd8f54292e3355bf046c3/quality/integration_testing/environments/qnx8_qemu/init_x86_64.build +# with some modifications + +[-optional] + +[image=0x3600000] +[virtual=x86_64,multiboot] boot = { + startup-x86 -v -D8250..115200 -zz + PATH=/proc/boot + LD_LIBRARY_PATH=/proc/boot + [+keeplinked] procnto-smp-instr +} + +[+script] startup-script = { + display_msg Welcome to QNX OS 8.0 on x86_64 tweaked for S-CORE! + # These env variables get inherited by all programs which follow + SYSNAME=nto + TERM=qansi + + devc-ser8250 & + waitfor /dev/ser1 + reopen /dev/ser1 + + /proc/boot/startup.sh + + [+session] /bin/sh & +} + +[uid=0 gid=0 perms=0700] startup.sh = { + # Enable logging via slogger2 + echo "---> Starting slogger2" + slogger2 -m -s 253952 -G 7 -V -g 486 + waitfor /dev/slog2 + + # PCI server required for virtio-net (QEMU networking) + echo "---> Starting PCI Services" + pci-server --config=/proc/boot/pci_server.cfg + waitfor /dev/pci + + # Required to support POSIX pipes (used e.g. by service discovery) + echo "---> Starting Pipe" + pipe + waitfor /dev/pipe + + # Start random number generator service (provides /dev/random + # needed by C++ std::random_device and other consumers). + echo "---> Starting Random" + random + waitfor /dev/random + + # Service discovery depends on inotify, which requires fsevmgr + echo "---> Starting fsevmgr" + fsevmgr + waitfor /dev/fsnotify + + # Create a RAM disk and mount it at /tmp + echo "---> Starting devb-ram" + devb-ram ram capacity=1 blk ramdisk=128m,cache=512k,vnode=256 2>/dev/null + waitfor /dev/ram0 + + echo "---> Mounting RAM disk" + mkqnx6fs -q /dev/ram0 + mount /dev/ram0 /tmp + chmod 777 /tmp + + # Pseudo-terminal driver needed by sshd + echo "---> Starting devc-pty" + devc-pty -n 32 + + # Networking stack for SSH-based ITF test harness communication + echo "---> Starting Networking" + io-sock -m phy -m pci -d vtnet_pci + waitfor /dev/socket + + echo "---> Configuring network interface" + if_up -p vtnet0 + ifconfig vtnet0 10.0.2.15 netmask 255.255.255.0 + sysctl -w net.inet.icmp.bmcastecho=1 + sysctl -w qnx.sec.droproot=33:33 + + echo "---> Setting hostname" + hostname qnx-score + + # SSH daemon - ITF test harness communicates via SSH + echo "---> Starting SSH daemon" + /proc/boot/sshd -f /var/ssh/sshd_config +} + +[uid=0 gid=0 perms=0444] /etc/qcrypto.conf { + # Minimal qcrypto configuration for the random service. + # Uses the OpenSSL 3 plugin for cryptographic operations. + # The library auto-prepends "qcrypto-" to the plugin name, + # so "openssl-3" resolves to "qcrypto-openssl-3.so". + [random] + openssl-3 tags=random +} + +# dynamic loader +/usr/lib/ldqnx-64.so.2=ldqnx-64.so.2 + +cam-disk.so # CAM disk driver for storage devices +fs-qnx6.so # QNX6 file system support +io-blk.so # Block I/O manager +libc++.so.2 # C++ standard library +libc.so # C standard library (essential) +libc.so.6 # Main C library (malloc, printf, file I/O, etc.) +libcam.so.2 # CAM library for device access +libcrypto.so.3 # OpenSSL 3 crypto library (needed by qcrypto-openssl-3 plugin) +libexpat.so.2 # XML parser library (needed by PCI subsystem) +libfsnotify.so.1 # File system notification library +libgcc_s.so.1 # GCC runtime support library +libiconv.so.1 # Character encoding conversion library +libjail.so.1 # Jail/sandbox library (needed by sshd) +libm.so # Math library +libpam.so.2 # PAM authentication library (needed by sshd) +libpci.so.3.0 # PCI access library (needed by pci-server) +libqcrypto.so.1.0 # QNX cryptographic library +libqh.so.1 # QNX helper library +libqnxnoexcept.so=${QNXNOEXCEPT_LIBRARY} +libregex.so.1 # Regular expression library +libsecpol.so.1 # Security policy library +libslog2.so.1 # System logging library (slog2_* functions) +libslog2parse.so.1 # System log parsing library +libsocket.so.4 # Socket library (needed by libcrypto) +libssl.so.3 # OpenSSL TLS library (needed by sshd) +libz.so # Zlib compression library + +# qcrypto plugin loaded by the random service at runtime +[search=${QNX_TARGET}/x86_64/lib/dll] qcrypto-openssl-3.so + +############################################# +### NETWORKING COMPONENTS ### +############################################# +io-sock # Network stack manager +mods-pci.so # PCI network module +mods-phy.so # PHY network module +devs-vtnet_pci.so # VirtIO network PCI driver (QEMU) + +[type=link] /bin/sh=/proc/boot/ksh # Create symbolic link: sh -> ksh (standard shell link) +[type=link] /bin/ls=/proc/boot/ls # Link ls to IFS version for compatibility + +toybox # Minimal Unix utilities collection (replaces many GNU tools) +[type=link] cp=toybox # Copy files and directories +[type=link] ls=toybox # List directory contents +[type=link] cat=toybox # Display file contents +[type=link] chmod=toybox # Change file permissions +[type=link] rm=toybox # Remove files and directories +[type=link] dd=toybox # Convert and copy files with specified I/O block size +[type=link] echo=toybox # Display text +[type=link] grep=toybox # Search text patterns in files +[type=link] mkdir=toybox # Create directories +[type=link] ascii=toybox # Display ASCII character set +[type=link] base64=toybox # Base64 encoding/decoding utility +[type=link] basename=toybox # Extract filename from path +[type=link] bc=toybox # Basic calculator +[type=link] bunzip2=toybox # Decompress bzip2 files +[type=link] bzcat=toybox # Display contents of bzip2 files +[type=link] cal=toybox # Display calendar +[type=link] chgrp=toybox # Change group ownership +[type=link] chown=toybox # Change file ownership +[type=link] cksum=toybox # Calculate checksums +[type=link] clear=toybox # Clear terminal screen +[type=link] cmp=toybox # Compare files byte by byte +[type=link] comm=toybox # Compare sorted files line by line +[type=link] cpio=toybox # Copy files to/from archives +[type=link] crc32=toybox # Calculate CRC32 checksums +[type=link] cut=toybox # Extract columns from files +[type=link] date=toybox # Display or set system date +[type=link] diff=toybox # Compare files line by line +[type=link] dirname=toybox # Extract directory from path +[type=link] dos2unix=toybox # Convert DOS line endings to Unix +[type=link] du=toybox # Display disk usage +[type=link] egrep=toybox # Extended grep with regular expressions +[type=link] env=toybox # Display or set environment variables +[type=link] expand=toybox # Convert tabs to spaces +[type=link] expr=toybox # Evaluate expressions +[type=link] false=toybox # Return false status +[type=link] fgrep=toybox # Fast grep for fixed strings +[type=link] file=toybox # Determine file type +[type=link] find=toybox # Search for files and directories +[type=link] fmt=toybox # Format text paragraphs +[type=link] groups=toybox # Display user group membership +[type=link] gunzip=toybox # Decompress gzip files +[type=link] gzip=toybox # Compress files with gzip +[type=link] hd=toybox # Hexadecimal dump (alias for hexdump) +[type=link] head=toybox # Display first lines of files +[type=link] hexdump=toybox # Display files in hexadecimal format +[type=link] id=toybox # Display user and group IDs +[type=link] install=toybox # Copy files and set attributes +[type=link] link=toybox # Create hard links +[type=link] logname=toybox # Display login name +[type=link] md5sum=toybox # Calculate MD5 checksums +[type=link] mkfifo=toybox # Create named pipes (FIFOs) +[type=link] mktemp=toybox # Create temporary files/directories +[type=link] more=toybox # Display files page by page +[type=link] mv=toybox # Move/rename files and directories +[type=link] nl=toybox # Number lines in files +[type=link] nohup=toybox # Run commands immune to hangups +[type=link] od=toybox # Dump files in octal format +[type=link] paste=toybox # Merge lines from files +[type=link] patch=toybox # Apply patches to files +[type=link] printenv=toybox # Print environment variables +[type=link] printf=toybox # Format and print data +[type=link] pwd=toybox # Print working directory +[type=link] readlink=toybox # Display target of symbolic links +[type=link] realpath=toybox # Display absolute path +[type=link] rmdir=toybox # Remove empty directories +[type=link] sed=toybox # Stream editor for filtering/transforming text +[type=link] seq=toybox # Generate sequences of numbers +[type=link] sha1sum=toybox # Calculate SHA1 checksums +[type=link] sleep=toybox # Suspend execution for specified time +[type=link] sort=toybox # Sort lines in text files +[type=link] split=toybox # Split files into pieces +[type=link] stat=toybox # Display file/filesystem status +[type=link] strings=toybox # Extract printable strings from files +[type=link] tail=toybox # Display last lines of files +[type=link] tar=toybox # Extract compressed archives +[type=link] tee=toybox # Copy input to files and stdout +[type=link] test=toybox # Evaluate conditional expressions +[type=link] time=toybox # Time command execution +[type=link] timeout=toybox # Run command with time limit +[type=link] touch=toybox # Update file timestamps +[type=link] tr=toybox # Translate or delete characters +[type=link] true=toybox # Return true status +[type=link] truncate=toybox # Truncate files to specified size +[type=link] tty=toybox # Display terminal name +[type=link] uname=toybox # Display system information +[type=link] uniq=toybox # Remove duplicate lines +[type=link] unix2dos=toybox # Convert Unix line endings to DOS +[type=link] unlink=toybox # Remove files (system call interface) +[type=link] uudecode=toybox # Decode uuencoded files +[type=link] uuencode=toybox # Encode files using uuencoding +[type=link] uuidgen=toybox # Generate UUIDs +[type=link] wc=toybox # Count lines, words, and characters +[type=link] which=toybox # Locate commands in PATH +[type=link] whoami=toybox # Display current username +[type=link] xargs=toybox # Execute commands from standard input +[type=link] xxd=toybox # Make hexdump or reverse +[type=link] yes=toybox # Output string repeatedly +[type=link] zcat=toybox # Display contents of compressed files +[type=link] nc=toybox # Netcat for network connections and packet streaming +[type=link] netcat=toybox # Netcat alias for network connections +[type=link] waitfor=on # Create symbolic link: waitfor -> on (waits for resources to become available) +[type=link] ability=on # Create symbolic link: ability -> on (manages process abilities/privileges) +[type=link] setconf=getconf # Create symbolic link: setconf -> getconf (sets configuration parameters) +[type=link] libslog2.so=libslog2.so.1 # Create version-neutral symbolic link +[type=link] libsocket.so=libsocket.so.4 # Create version-neutral symbolic link +[type=link] libqh.so=libqh.so.1 # Create version-neutral symbolic link +[type=link] qcrypto-openssl.so=qcrypto-openssl-3.so + +############################################# +### Tools ### +############################################# +devb-ram # RAM disk block device manager +devc-pty # Pseudo-terminal driver (needed by sshd) +devc-ser8250 # Serial port driver for 8250/16550 UART controllers (console access) +fsevmgr # File system event manager +getconf # Get system configuration values +hostname # Set/display system hostname +if_up # Bring network interface up +ifconfig # Configure network interfaces +ksh # Korn shell - provides command-line interface and scripting +ln # Create file links +mkqnx6fs # Create QNX6 file systems +mount # File system mount utility - mounts/unmounts file systems +on # Command execution utility - runs commands with specific options +pci-server # PCI server (required for virtio-net) +pdebug # Process debugger +pidin # Process information display - shows running processes (like 'ps' on Linux) +pipe # Named pipe manager +random # Random number generator service (/dev/random, /dev/urandom) +route # Manage network routing tables +slay # Kill or modify a process by name or ID +slog2info # System log viewer - displays logged messages +slogger2 # System logging daemon - collects and manages log messages +sshd # SSH daemon (ITF test harness communicates via SSH) +sysctl # View/modify kernel parameters + +/usr/lib/ssh/sftp-server=${QNX_TARGET}/${PROCESSOR}/usr/libexec/sftp-server # SFTP server (file transfer for ITF) +/usr/libexec/sshd-session=${QNX_TARGET}/${PROCESSOR}/usr/libexec/sshd-session # SSH session handler (required by OpenSSH 9.8+) + +############################################# +### PCI COMPONENTS ### +############################################# +pci/pci_hw-Intel_x86.so +pci/pci_slog2.so +pci/pci_cap-0x05.so +pci/pci_cap-0x10.so +pci/pci_cap-0x11.so +pci/pci_strings.so +pci/pci_bkwd_compat.so +pci/pci_debug2.so + +############################################# +### SYSTEM DIRECTORIES ### +############################################# +[gid=0 uid=0 dperms=755 type=dir] /var/chroot/sshd +[gid=0 uid=0 dperms=700 type=dir] /var/ssh + +[perms=0444] pci_server.cfg = { +[buscfg] +DO_BUS_CONFIG=no + +[envars] +PCI_DEBUG_MODULE=pci_debug2.so +PCI_HW_MODULE=pci_hw-Intel_x86.so +PCI_HW_CONFIG_FILE=/proc/boot/pci_hw.cfg +} + +[perms=0444] pci_hw.cfg = { +[interrupts] +B0:D17:F0 A 18 +B0:D17:F0 B 19 +B0:D17:F0 C 16 +B0:D17:F0 D 17 +B3:D0:F0 A 18 +B3:D0:F0 B 19 +B3:D0:F0 C 16 +B3:D0:F0 D 17 +} + +[uid=0 gid=0 perms=0444] /etc/passwd = { +root::0:0:Superuser:/:/bin/sh +qnxuser::1000:1000:QNX User:/:/bin/sh +sshd::15:6:sshd:/:/bin/false +} + +[uid=0 gid=0 perms=0444] /etc/group = { +root::0:root +qnxuser::1000:qnxuser +sshd::6:sshd +} + +[uid=0 gid=0 perms=0444] /etc/profile = { +export TERM=qansi +export PATH=/proc/boot +export LD_LIBRARY_PATH=/proc/boot +export MAGIC=/system/etc/magic +} + +[uid=0 gid=0 perms=0400] /var/ssh/ssh_host_rsa_key = { +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn +NhAAAAAwEAAQAAAYEArR4LKpPGS2mqmnj+d4Y/0DLdYUVQ7hBaR/aYnNbZFUvO3nOFixa4 +u8pjRQbNFsERvY8o3Q1+SEg/xq+WC4vxhS9bjfMOxO29ncicvcDZR9kVOc/dNCLv6amdOy +9V/wN8rb7vy5KhPKF/uubj/HmcwRYZAYV3spR7C4OpN1tSZFBu/rcOYYYC7VxKcshEj8Yt +8QX7Bil+MIJHPLu7HTktgxDSp4Y3NUORoV9In1qM+rTJsxDHr3gfCOaN4OnQElwS7RfXx2 +BFcvA3d4JreynHocpLWUO6rrs1qjCsQZFPqQwBC7SDn8eiKy0XH+yPpioUaJ6L+YFqrk3c +KxijWKP5/aDuCQrw230mLtWatspHpNUXQSN1FQby6kqLUSV8gXX7lS91AMjdb3sqJ9ebxJ +xGARbp8ow1yRtTfqk6H04q2QgVQZ/Idso3TzQokt0K/feEdj7SwH3LsaAeMWPyo0WLUOk1 +8j46LUEayluF4UcIm8dnjoTywW9A/MS1C+2p4eTbAAAFeAU74GcFO+BnAAAAB3NzaC1yc2 +EAAAGBAK0eCyqTxktpqpp4/neGP9Ay3WFFUO4QWkf2mJzW2RVLzt5zhYsWuLvKY0UGzRbB +Eb2PKN0NfkhIP8avlguL8YUvW43zDsTtvZ3InL3A2UfZFTnP3TQi7+mpnTsvVf8DfK2+78 +uSoTyhf7rm4/x5nMEWGQGFd7KUewuDqTdbUmRQbv63DmGGAu1cSnLIRI/GLfEF+wYpfjCC +Rzy7ux05LYMQ0qeGNzVDkaFfSJ9ajPq0ybMQx694HwjmjeDp0BJcEu0X18dgRXLwN3eCa3 +spx6HKS1lDuq67NaowrEGRT6kMAQu0g5/HoistFx/sj6YqFGiei/mBaq5N3CsYo1ij+f2g +7gkK8Nt9Ji7VmrbKR6TVF0EjdRUG8upKi1ElfIF1+5UvdQDI3W97KifXm8ScRgEW6fKMNc +kbU36pOh9OKtkIFUGfyHbKN080KJLdCv33hHY+0sB9y7GgHjFj8qNFi1DpNfI+Oi1BGspb +heFHCJvHZ46E8sFvQPzEtQvtqeHk2wAAAAMBAAEAAAGAQMkziJWQ6fv7Wp/ZK0XUb8f5TU +Oxi8YW40OHzXoh93RNULaOzYSNUcnl6Jko+1D5oKUIt+Eq10Yih+qCDoQquJsGelLxvgTy +py/CaMjZB6hX5zDBKZfBjQJq0xFd73eQmz0PZHHVYWlW8c0imQOyBBiO9yDJsM0cVyzIkO +zeIqhvQWekPB74zXdybQ5BikSyQLbqQF4a2XCH1FS1K7SQMbKEAymZU5eb0nZkKS6r/87U +hOzMrgAYLS6K/hbCRXyrAlz61x2hMKTngb/ERWWilqJSGlF8Q4p2LmIxyUnll/C2cq2dvU +gMARPvZ3DL/QFl4fhLa20vTg83CQNaw6zuEAhTP8lmvDP+4DhtqUPno1T7161OpEHD/ZRb +oiwXmkwg+0yiR8a9OFiolAhwiqPhqC1W39+coEutjpbXQ1uJVoC0kWHMY9biBa7cb9Cxrq +boYLOs31sLhTWTrHgIgpsf/FSWYLF5hknZKpVhWQsfowyCtjn6uvVh+bcfUwOMCDthAAAA +wQDSHJTmW6o6uK53KE6t4c7x+G/qO2Y6FSRQuAbojL1o7gG0SYDFRR3k5fMQ/zqQ1pWrqR +5Im+InsfO5KG9489z/SCIXwPq6zev8WJjZV2P3A8qTBPzEeYmicZtJGH/sBuk8Oj/CdOKV ++GBzkqJdxruiNzLEIGS1gjserT6YJxmA5Q/j1Hiz+bSf66cHhGzmQ092tQ+gGvWPtbFn+D +YQVbp1GW8E6lbAOBew7IDcWp7LVDZuShBrDvFWtsaupZ7wYxoAAADBAOXzYeYNyrKsFCju +Qh1Bj0uVOf8lVvygGOzFA/OdqWuRr/h2aPsNYJFbdIiP61mvVd1umJ8BQDiXNlm/YpXOXu +jOm9a8BVKpMTtoohEkUbqBtv9vx+XHnhLCFYYL4GHJ9Dhj50L3djf++/HkahtZJlTkpSbt +/ukoZKI1m8MgpyC3xk2UDu1yWNizT2l1L7RnE+ZO4b5U9cONANiYBD8jcnZAvh4ld3ojo0 +iNXEVEGAKIodMUsgASxGwmoxuX3ugJIwAAAMEAwLp7eVBjg27eflRNYuW8akfDyq9zB1rp +YGo3GbPytb14WVJuyNL1tJ/B/rdFBg0IXf1FQJEL99kKJP5yDxjOx9kyXBhIWjm8arz39h +uw0wrsuRl2rrCfMABGS51GohtYmKETZ6x7/2n3l6iz/5mhRN8hW0JluJhKtj6ogO6GZERr +PTYwQs+9Q7QI1cPx7G5cEPhWhEd+OmKZuXRjhMQQ+ADj/lnUAhhGQatM9/bohJOdObWCRl +Fu+/MLbJQuA1zpAAAAAAEC +-----END OPENSSH PRIVATE KEY----- +} + +[uid=0 gid=0 perms=0444] /var/ssh/sshd_config = { +Port 22 +Protocol 2 +HostKey /var/ssh/ssh_host_rsa_key +AllowTcpForwarding yes +Subsystem sftp /usr/lib/ssh/sftp-server +PasswordAuthentication yes +PermitEmptyPasswords yes +PubkeyAuthentication no +ChallengeResponseAuthentication no +HostbasedAuthentication no +PermitRootLogin yes +PermitUserEnvironment yes +PidFile none +LogLevel DEBUG +StrictModes no +UseDNS no +MaxAuthTries 3 +LoginGraceTime 30 +} \ No newline at end of file diff --git a/tests/utils/environments/x86_64-qnx/qemu_config.json b/tests/utils/environments/x86_64-qnx/qemu_config.json new file mode 100644 index 000000000..1b19d57ab --- /dev/null +++ b/tests/utils/environments/x86_64-qnx/qemu_config.json @@ -0,0 +1,18 @@ +{ + "networks": [ + { + "name": "lo", + "ip_address": "127.0.0.1", + "gateway": "127.0.0.1" + } + ], + "ssh_port": 2222, + "qemu_num_cores": 2, + "qemu_ram_size": "1G", + "port_forwarding": [ + { + "host_port": 2222, + "guest_port": 22 + } + ] +} \ No newline at end of file diff --git a/tests/utils/testing_utils/run_until_file_deployed.py b/tests/utils/testing_utils/run_until_file_deployed.py index 348964d7b..d51bd0a30 100644 --- a/tests/utils/testing_utils/run_until_file_deployed.py +++ b/tests/utils/testing_utils/run_until_file_deployed.py @@ -62,7 +62,7 @@ def run_until_file_deployed( # Kill the entire process group so that children (e.g. the actual # daemon binary launched under fakeroot) receive SIGTERM and can # run their cleanup code before exiting. - kill_cmd = f"kill -15 -{proc.pid()}" + kill_cmd = f"kill -TERM {proc.pid()}" res, _ = target.execute(kill_cmd) assert res == 0, "Couldn't kill lcm" exit_code = proc.wait() # Raises RuntimeError if it does not stop diff --git a/tests/utils/testing_utils/setup_test.py b/tests/utils/testing_utils/setup_test.py index d5a1ef6b9..04cae0e0e 100644 --- a/tests/utils/testing_utils/setup_test.py +++ b/tests/utils/testing_utils/setup_test.py @@ -34,9 +34,7 @@ def setup_test(request, target): res, _ = target.execute(f"mkdir -p {extract_dir}") assert res != 1, f"Couldn't create directory {extract_dir}" - target.upload( - bin_path.resolve(), remote_tar - ) # Need to resolve for https://github.com/eclipse-score/itf/pull/71 + target.upload(str(bin_path), str(remote_tar)) res, _ = target.execute(f"tar -xf {remote_tar} -C {extract_dir}") assert res == 0, f"Couldn't extract tar {remote_tar}" From 0a404c858d51a9ad7a7a190b82ad800c51029fa1 Mon Sep 17 00:00:00 2001 From: Daniel Thwaites Date: Wed, 22 Jul 2026 15:47:26 +0100 Subject: [PATCH 2/6] Avoid `junitparser` dependency in tests Our Bazel toolchain for Python does not work with QNX, so we need to use built-in libraries to parse the results instead. --- BUILD | 1 - requirements.in | 3 --- requirements_lock.txt | 3 --- tests/integration/BUILD | 20 -------------------- tests/integration/requirements.txt | 2 -- tests/utils/testing_utils/BUILD | 2 -- tests/utils/testing_utils/test_results.py | 9 ++++++--- 7 files changed, 6 insertions(+), 34 deletions(-) delete mode 100644 tests/integration/requirements.txt diff --git a/BUILD b/BUILD index 0e81af46c..9cf660fb9 100644 --- a/BUILD +++ b/BUILD @@ -38,7 +38,6 @@ compile_pip_requirements( src = "requirements.in", data = [ "//scripts/config_mapping:pip_requirements", - "//tests/integration:pip_requirements", ], extra_args = [ "--no-annotate", diff --git a/requirements.in b/requirements.in index 0e423780f..704d2939b 100644 --- a/requirements.in +++ b/requirements.in @@ -1,5 +1,2 @@ # Python dependencies for generating lifecycle configuration files -r ./scripts/config_mapping/requirements.txt - --r ./tests/integration/requirements.txt - diff --git a/requirements_lock.txt b/requirements_lock.txt index bb48c8e32..bec97068f 100644 --- a/requirements_lock.txt +++ b/requirements_lock.txt @@ -16,9 +16,6 @@ jsonschema==4.23.0 \ jsonschema-specifications==2023.12.1 \ --hash=sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc \ --hash=sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c -junitparser==5.0.0 \ - --hash=sha256:9e279f2214dc74b6a86b22db757abda2e8e66e819fe882dad5b392d57024cd26 \ - --hash=sha256:f15e292877258d7c5755d672ce86f82c3622c7ea4c2f44f55de44ed7518484d3 packaging==26.0 \ --hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \ --hash=sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529 diff --git a/tests/integration/BUILD b/tests/integration/BUILD index b82493d65..ca5de742e 100644 --- a/tests/integration/BUILD +++ b/tests/integration/BUILD @@ -10,23 +10,3 @@ # # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* - -load("@rules_python//python:pip.bzl", "compile_pip_requirements") -load("@score_lifecycle_pip//:requirements.bzl", "requirement") -load("@score_tooling//python_basics:defs.bzl", "score_virtualenv") - -filegroup( - name = "pip_requirements", - srcs = ["requirements.txt"], - visibility = ["//:__pkg__"], -) - -# Only pass packages that don't overlap with pip_tooling (which already -# provides: iniconfig, packaging, pluggy, pygments, pytest). -score_virtualenv( - name = "python_tc_venv", - reqs = [ - requirement("junitparser"), - ], - venv_name = ".python_tc_venv", -) diff --git a/tests/integration/requirements.txt b/tests/integration/requirements.txt deleted file mode 100644 index eb44c7019..000000000 --- a/tests/integration/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pytest -junitparser diff --git a/tests/utils/testing_utils/BUILD b/tests/utils/testing_utils/BUILD index 3cc5ad7a1..acb13d75d 100644 --- a/tests/utils/testing_utils/BUILD +++ b/tests/utils/testing_utils/BUILD @@ -11,7 +11,6 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* load("@rules_python//python:defs.bzl", "py_library") -load("@score_lifecycle_pip//:requirements.bzl", "requirement") py_library( name = "testing_utils", @@ -25,7 +24,6 @@ py_library( "//tests:__subpackages__", ], deps = [ - requirement("junitparser"), "@score_itf//score/itf/core/process", "@score_itf//score/itf/core/target", ], diff --git a/tests/utils/testing_utils/test_results.py b/tests/utils/testing_utils/test_results.py index 15934db40..eb28d5066 100644 --- a/tests/utils/testing_utils/test_results.py +++ b/tests/utils/testing_utils/test_results.py @@ -12,9 +12,9 @@ # ******************************************************************************* from pathlib import Path from typing import Set +from xml.etree import ElementTree import pytest -from junitparser import JUnitXml def download_xml_results(target, remote_dir: Path, local_dir: Path): @@ -41,8 +41,11 @@ def get_failing_files(path: Path): failing_files = set() all_files = set() for file in path.glob("*.xml"): - xml = JUnitXml.fromfile(str(file)) - if xml.failures > 0 or xml.errors > 0: + test_suites = ElementTree.parse(str(file)).getroot() + failures = int(test_suites.attrib["failures"]) + errors = int(test_suites.attrib["errors"]) + + if failures > 0 or errors > 0: failing_files.add(file.name) all_files.add(file.name) From d4437906915a1bfe70667a2f8c5b17e5e763e92a Mon Sep 17 00:00:00 2001 From: Daniel Thwaites Date: Thu, 23 Jul 2026 09:30:07 +0100 Subject: [PATCH 3/6] Mark some build targets as incompatible with QNX --- tests/integration/process_fd_leak/BUILD | 3 +++ tests/utils/environments/x86_64-linux/BUILD | 2 ++ tests/utils/environments/x86_64-qnx/BUILD | 11 +++++++++-- tests/utils/plugins/BUILD | 4 ++++ tests/utils/testing_utils/BUILD | 1 + 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/integration/process_fd_leak/BUILD b/tests/integration/process_fd_leak/BUILD index 1cd769e83..4b146f235 100644 --- a/tests/integration/process_fd_leak/BUILD +++ b/tests/integration/process_fd_leak/BUILD @@ -20,6 +20,7 @@ cc_binary( "get_fds.hpp", "native.cpp", ], + target_compatible_with = ["@platforms//os:linux"], deps = [ "//tests/utils/test_helper", "@googletest//:gtest_main", @@ -34,6 +35,7 @@ cc_binary( "get_fds.hpp", "reporting.cpp", ], + target_compatible_with = ["@platforms//os:linux"], deps = [ "//score/launch_manager:lifecycle_cc", "//tests/utils/test_helper", @@ -48,6 +50,7 @@ cc_binary( "control_client.cpp", "get_fds.hpp", ], + target_compatible_with = ["@platforms//os:linux"], deps = [ "//score/launch_manager:control_cc", "//score/launch_manager:lifecycle_cc", diff --git a/tests/utils/environments/x86_64-linux/BUILD b/tests/utils/environments/x86_64-linux/BUILD index 2a59e59ff..3faeeb227 100644 --- a/tests/utils/environments/x86_64-linux/BUILD +++ b/tests/utils/environments/x86_64-linux/BUILD @@ -29,6 +29,7 @@ pkg_tar( oci_image( name = "image", base = "@debian-test-runtime", + target_compatible_with = ["@platforms//os:linux"], tars = [":ecu_logging_config_layer"], ) @@ -36,6 +37,7 @@ oci_load( name = "x86_64-linux", image = ":image", repo_tags = ["score_itf_examples:latest"], + target_compatible_with = ["@platforms//os:linux"], visibility = [ "//examples:__subpackages__", "//tests:__subpackages__", diff --git a/tests/utils/environments/x86_64-qnx/BUILD b/tests/utils/environments/x86_64-qnx/BUILD index bad1ddc04..afd23652c 100644 --- a/tests/utils/environments/x86_64-qnx/BUILD +++ b/tests/utils/environments/x86_64-qnx/BUILD @@ -16,7 +16,10 @@ load("@score_rules_imagefs//rules/qnx:ifs.bzl", "qnx_ifs") exports_files( ["qemu_config.json"], - visibility = ["//tests:__subpackages__"], + visibility = [ + "//examples:__subpackages__", + "//tests:__subpackages__", + ], ) pkg_files( @@ -29,5 +32,9 @@ qnx_ifs( name = "qemu_image", srcs = [":logging_config.json"], build_file = ":init.build", - visibility = ["//tests:__subpackages__"], + target_compatible_with = ["@platforms//os:qnx"], + visibility = [ + "//examples:__subpackages__", + "//tests:__subpackages__", + ], ) diff --git a/tests/utils/plugins/BUILD b/tests/utils/plugins/BUILD index 26ade5a61..858adf8c9 100644 --- a/tests/utils/plugins/BUILD +++ b/tests/utils/plugins/BUILD @@ -16,6 +16,7 @@ load("@score_itf//bazel:py_itf_plugin.bzl", "py_itf_plugin") py_library( name = "localhost", srcs = ["localhost.py"], + target_compatible_with = ["@platforms//os:linux"], visibility = ["//visibility:public"], deps = [ "@score_itf//score/itf/core/process", @@ -28,12 +29,14 @@ py_itf_plugin( name = "localhost_plugin", enabled_plugins = ["tests.utils.plugins.localhost"], py_library = ":localhost", + target_compatible_with = ["@platforms//os:linux"], visibility = ["//visibility:public"], ) py_library( name = "integration", srcs = ["integration.py"], + target_compatible_with = ["@platforms//os:linux"], visibility = ["//visibility:public"], deps = [ "@score_itf//score/itf/plugins:core", @@ -44,5 +47,6 @@ py_itf_plugin( name = "integration_plugin", enabled_plugins = ["tests.utils.plugins.integration"], py_library = ":integration", + target_compatible_with = ["@platforms//os:linux"], visibility = ["//visibility:public"], ) diff --git a/tests/utils/testing_utils/BUILD b/tests/utils/testing_utils/BUILD index acb13d75d..e24741ebc 100644 --- a/tests/utils/testing_utils/BUILD +++ b/tests/utils/testing_utils/BUILD @@ -19,6 +19,7 @@ py_library( "setup_test.py", "test_results.py", ], + target_compatible_with = ["@platforms//os:linux"], visibility = [ "//examples:__subpackages__", "//tests:__subpackages__", From 3dad47507c95c2420d82087330d38e6c2f048348 Mon Sep 17 00:00:00 2001 From: Daniel Thwaites Date: Thu, 23 Jul 2026 15:00:17 +0100 Subject: [PATCH 4/6] Work around QNX unit test flags breaking integration tests With proper use of Bazel platforms rather than configs, I think it would be possible to do this in a much cleaner way. However that would require deeper changes across our codebase and possibly in the test frameworks as well. --- .bazelrc | 15 ++++++++------- .github/workflows/qnx8.yml | 10 ++++++---- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.bazelrc b/.bazelrc index 56a7dd4ec..559eda119 100644 --- a/.bazelrc +++ b/.bazelrc @@ -87,9 +87,10 @@ build:x86_64-qnx --extra_toolchains=@score_qcc_x86_64_toolchain//:x86_64-qnx-sdp build:x86_64-qnx --extra_toolchains=@score_toolchains_rust//toolchains/ferrocene:ferrocene_x86_64_pc_nto_qnx800 build:x86_64-qnx --extra_toolchains=@score_qnx_x86_64_ifs_toolchain//:ifs-x86_64-qnx-sdp_8.0.0 build:x86_64-qnx --define config=x86_64-qnx -# test:x86_64-qnx --run_under=@score_qnx_unit_tests//src:run_under_qnx -# test:x86_64-qnx --test_tag_filters=-skip_local # see https://github.com/eclipse-score/lifecycle/issues/272 -# test:x86_64-qnx --test_lang_filters=cc,rust + +build:unit-tests-x86_64-qnx --config=x86_64-qnx +test:unit-tests-x86_64-qnx --run_under=@score_qnx_unit_tests//src:run_under_qnx +test:unit-tests-x86_64-qnx --test_tag_filters=-skip_local # see https://github.com/eclipse-score/lifecycle/issues/272 # Target configuration for CPU:AArch64|OS:QNX build (do not use it in case of system toolchains!) build:arm64-qnx --config=stub @@ -99,10 +100,10 @@ build:arm64-qnx --platforms=@score_bazel_platforms//:aarch64-qnx-sdp_8.0.0-posix build:arm64-qnx --extra_toolchains=@score_qcc_aarch64_toolchain//:aarch64-qnx-sdp_8.0.0 build:arm64-qnx --extra_toolchains=@score_toolchains_rust//toolchains/ferrocene:ferrocene_aarch64_unknown_nto_qnx800 build:arm64-qnx --extra_toolchains=@score_qnx_aarch64_ifs_toolchain//:ifs-aarch64-qnx-sdp_8.0.0 -# test:arm64-qnx --run_under=@score_qnx_unit_tests//src:run_under_qnx -# test:arm64-qnx --test_tag_filters=-skip_local # see https://github.com/eclipse-score/lifecycle/issues/272 -# test:arm64-qnx --test_timeout=300 -# test:arm64-qnx --test_lang_filters=cc,rust + +build:unit-tests-arm64-qnx --config=arm64-qnx +test:unit-tests-arm64-qnx --run_under=@score_qnx_unit_tests//src:run_under_qnx +test:unit-tests-arm64-qnx --test_tag_filters=-skip_local # see https://github.com/eclipse-score/lifecycle/issues/272 # Ferrocene Rust coverage config diff --git a/.github/workflows/qnx8.yml b/.github/workflows/qnx8.yml index e4b443a35..57197a9a1 100644 --- a/.github/workflows/qnx8.yml +++ b/.github/workflows/qnx8.yml @@ -29,11 +29,13 @@ jobs: matrix: include: - bazel-config: x86_64-qnx - bazel-test-target: >- - //score/... + bazel-test-target: //examples/... //tests/... + - bazel-config: unit-tests-x86_64-qnx + bazel-test-target: //score/... - bazel-config: arm64-qnx - bazel-test-target: >- - //score/... + bazel-test-target: //examples/... //tests/... + - bazel-config: unit-tests-arm64-qnx + bazel-test-target: //score/... extra-bazel-test-flags: "--test_timeout=120,600,1800,7200" # Increase test timeout due to QEMU emulation uses: eclipse-score/cicd-workflows/.github/workflows/qnx-build.yml@af347722c7ae3ed85518895c11268d96ac728f62 permissions: From 5c5115400b513da97bbc884b2dad96ae93644c15 Mon Sep 17 00:00:00 2001 From: Daniel Thwaites Date: Fri, 24 Jul 2026 15:39:32 +0100 Subject: [PATCH 5/6] Work around eclipse-score/itf#125 --- tests/utils/bazel/integration.bzl | 108 ++++++++++++++++++------------ 1 file changed, 66 insertions(+), 42 deletions(-) diff --git a/tests/utils/bazel/integration.bzl b/tests/utils/bazel/integration.bzl index f46a55519..56f6d0b89 100644 --- a/tests/utils/bazel/integration.bzl +++ b/tests/utils/bazel/integration.bzl @@ -69,53 +69,77 @@ def integration_test( pkg_tar(name = "environment", srcs = [":binaries", ":files"]) + final_deps = kwargs.pop("deps", []) + all_requirements + [ + "@score_tooling//python_basics/score_pytest:attribute_plugin", + "//tests/utils/testing_utils", + ] + final_data = kwargs.pop("data", []) + [":environment"] + select({ + "//config:x86_64-linux": [ + "//tests/utils/environments/x86_64-linux", + ], + "//config:x86_64-qnx": [ + "//tests/utils/environments/x86_64-qnx:qemu_config.json", + "//tests/utils/environments/x86_64-qnx:qemu_image", + ], + "//conditions:default": [], + }) + final_args = kwargs.pop("args", []) + [ + "--score-test-binary-path=$(locations :environment)", + "--score-test-remote-directory={}/tests/{}".format(install_prefix, name), + ] + select({ + "//config:x86_64-linux": [ + "--docker-image-bootstrap=$(location //tests/utils/environments/x86_64-linux)", + "--docker-image=score_itf_examples:latest", + ], + "//config:x86_64-qnx": [ + "--qemu-config=$(location //tests/utils/environments/x86_64-qnx:qemu_config.json)", + "--qemu-image=$(location //tests/utils/environments/x86_64-qnx:qemu_image)", + ], + "//config:host": [ + "--local-dir=/tmp/score_itf_host/{}".format(name), + ], + "//conditions:default": [], + }) + final_plugins = ["//tests/utils/plugins:integration_plugin"] + select({ + "//config:x86_64-linux": ["@score_itf//score/itf/plugins:docker_plugin"], + "//config:x86_64-qnx": ["@score_itf//score/itf/plugins:qemu_plugin"], + "//config:host": ["//tests/utils/plugins:localhost_plugin"], + "//conditions:default": [], + }) + + # The QEMU plugin uses a hardcoded port so we can only run one test at a time. + # See https://github.com/eclipse-score/itf/issues/125. + # However we should not unnecessarily slow down Docker tests by adding the + # exclusive tag all the time. Bazel does not allow select() to be used in tags. + # So we have to create two separate targets and skip whichever is not needed. + py_itf_test( name = name, srcs = srcs, - tags = kwargs.pop("tags", []) + [ - # The QEMU plugin uses a hardcoded port so we can only run one test at a time. - # The Docker plugin works in parallel but tags cannot be conditional. - "exclusive", + tags = [ "integration", - # The test container does not ship the sanitizer runtime; daemon fails to start. - "no-asan", + "no-asan", # The test container does not ship the sanitizer runtime; daemon fails to start. ], - deps = kwargs.pop("deps", []) + all_requirements + [ - "@score_tooling//python_basics/score_pytest:attribute_plugin", - "//tests/utils/testing_utils", + deps = final_deps, + data = final_data, + args = final_args, + plugins = final_plugins, + target_compatible_with = ["@platforms//os:linux"], + **kwargs + ) + + py_itf_test( + name = "{}_QNX".format(name), + srcs = srcs, + tags = [ + "exclusive", # The QEMU plugin uses a hardcoded port so we can only run one test at a time. + "integration", + "no-asan", # The test container does not ship the sanitizer runtime; daemon fails to start. ], - data = kwargs.pop("data", []) + [":environment"] + select({ - "//config:x86_64-linux": [ - "//tests/utils/environments/x86_64-linux", - ], - "//config:x86_64-qnx": [ - "//tests/utils/environments/x86_64-qnx:qemu_config.json", - "//tests/utils/environments/x86_64-qnx:qemu_image", - ], - "//conditions:default": [], - }), - args = kwargs.pop("args", []) + [ - "--score-test-binary-path=$(locations :environment)", - "--score-test-remote-directory={}/tests/{}".format(install_prefix, name), - ] + select({ - "//config:x86_64-linux": [ - "--docker-image-bootstrap=$(location //tests/utils/environments/x86_64-linux)", - "--docker-image=score_itf_examples:latest", - ], - "//config:x86_64-qnx": [ - "--qemu-config=$(location //tests/utils/environments/x86_64-qnx:qemu_config.json)", - "--qemu-image=$(location //tests/utils/environments/x86_64-qnx:qemu_image)", - ], - "//config:host": [ - "--local-dir=/tmp/score_itf_host/{}".format(name), - ], - "//conditions:default": [], - }), - plugins = ["//tests/utils/plugins:integration_plugin"] + select({ - "//config:x86_64-linux": ["@score_itf//score/itf/plugins:docker_plugin"], - "//config:x86_64-qnx": ["@score_itf//score/itf/plugins:qemu_plugin"], - "//config:host": ["//tests/utils/plugins:localhost_plugin"], - "//conditions:default": [], - }), + deps = final_deps, + data = final_data, + args = final_args, + plugins = final_plugins, + target_compatible_with = ["@platforms//os:qnx"], **kwargs ) From 5d8df15f7072399984dee31b0868a83f9bdcf5ae Mon Sep 17 00:00:00 2001 From: Daniel Thwaites Date: Wed, 29 Jul 2026 13:41:45 +0100 Subject: [PATCH 6/6] Mention QEMU tests in README --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index a417e163a..30198b92b 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,22 @@ bazel build --config=x86_64-qnx //... bazel build --config=arm64-qnx //... ``` +Integration tests via [QEMU](https://www.qemu.org/): + +```sh +bazel test --config=x86_64-qnx //tests/integration/... +``` + +Unit tests via [QEMU](https://www.qemu.org/): + +```sh +bazel test --config=unit-tests-x86_64-qnx //score/... +``` + +A different flag is needed for unit tests because the emulation is configured +using `--run_under`, which applies to all targets, even those that should run +natively on the host. + **Linux** ```sh