From d497d80c90bc4b3b3258a8f9054027e366a66125 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Wed, 18 Feb 2026 13:53:29 +0100 Subject: [PATCH 01/21] Revert "fix: Use libstdc++ instead of libc++ for LLVM toolchain" This reverts commit 6935fea5ffe56e1ab48602ff718a57c6001569f8. --- MODULE.bazel | 3 --- 1 file changed, 3 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 70afafa7..c651ed71 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -78,9 +78,6 @@ llvm.toolchain( "-latomic", ]}, llvm_version = "19.1.7", - # Use libstdc++ instead of libc++ because libc++ doesn't support fancy pointers - # (like offset pointers) in std::basic_string, which is required for shared memory allocators - stdlib = {"": "stdc++"}, ) use_repo(llvm, "llvm_toolchain") From 545b618cc6dad5a4faefc42213f6cdbea44683a0 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Thu, 5 Feb 2026 17:30:14 +0100 Subject: [PATCH 02/21] Update S-CORE dependencies The new S-CORE GCC toolchain requires a very specific host platform to be manually selected. This is not suitable for our default toolchain setup. Therefore, we move this toolchain to a specific configuration and use an opensource GCC toolchain as alternative. --- .bazelrc | 15 +++-- MODULE.bazel | 186 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 118 insertions(+), 83 deletions(-) diff --git a/.bazelrc b/.bazelrc index eed1897a..ea1c9fdc 100644 --- a/.bazelrc +++ b/.bazelrc @@ -17,12 +17,15 @@ common --@score_logging//score/mw/log/flags:KRemote_Logging=False common --@score_baselibs//score/json:base_library=nlohmann common --@score_baselibs//score/memory/shared/flags:use_typedshmd=False common --//score/mw/com/flags:tracing_library=@score_baselibs//score/analysis/tracing/generic_trace_library/stub_implementation -common --extra_toolchains=@gcc_toolchain//:host_gcc_12 +common --extra_toolchains=@gcc_toolchain_x86_64//:cc_toolchain common --extra_toolchains=@score_toolchains_rust//toolchains/ferrocene:ferrocene_x86_64_unknown_linux_gnu build --incompatible_strict_action_env test --test_output=errors build --experimental_retain_test_configuration_across_testonly #https://github.com/bazelbuild/bazel/issues/6842 +common:linux_x86_64_score_gcc_12_2_0_posix --platforms=@score_bazel_platforms//:x86_64-linux-gcc_12.2.0-posix +common:linux_x86_64_score_gcc_12_2_0_posix --extra_toolchains=@score_gcc_x86_64_toolchain//:x86_64-linux + # In order to build for QNX, you need: # * An account on qnx.com # * An assigned QNX 8 license to your account @@ -30,17 +33,17 @@ build --experimental_retain_test_configuration_across_testonly #https://github.c # * The credentials for this account stored in your ~/.netrc (machine qnx.com) # * A license stored under `/opt/score_qnx/license/licenses` common:qnx_x86_64 --host_platform=@score_bazel_platforms//:x86_64-linux -common:qnx_x86_64 --platforms=@score_bazel_platforms//:x86_64-qnx8_0 +common:qnx_x86_64 --platforms=@score_bazel_platforms//:x86_64-qnx-sdp_8.0.0-posix common:qnx_x86_64 --extra_toolchains=@toolchains_qnx_ifs//:ifs_x86_64 -common:qnx_x86_64 --extra_toolchains=@toolchains_qnx_qcc//:qcc_x86_64 +common:qnx_x86_64 --extra_toolchains=@score_qcc_x86_64_toolchain//:x86_64-qnx-sdp_8.0.0 common:qnx_x86_64 --extra_toolchains=@score_toolchains_rust//toolchains/ferrocene:ferrocene_x86_64_pc_nto_qnx800 common:qnx_x86_64 --credential_helper=*.qnx.com=%workspace%/third_party/qnx_credential_helper.py common:qnx_x86_64 --sandbox_writable_path=/var/tmp common:qnx_arm64 --host_platform=@score_bazel_platforms//:x86_64-linux -common:qnx_arm64 --platforms=@score_bazel_platforms//:arm64-qnx8_0 +common:qnx_arm64 --platforms=@score_bazel_platforms//:aarch64-qnx-sdp_8.0.0-posix common:qnx_arm64 --extra_toolchains=@toolchains_qnx_ifs//:ifs_aarch64 -common:qnx_arm64 --extra_toolchains=@toolchains_qnx_qcc//:qcc_aarch64 +common:qnx_arm64 --extra_toolchains=@score_qcc_aarch64_toolchain//:aarch64-qnx-sdp_8.0.0 common:qnx_arm64 --extra_toolchains=@score_toolchains_rust//toolchains/ferrocene:ferrocene_aarch64_unknown_nto_qnx800 common:qnx_arm64 --credential_helper=*.qnx.com=%workspace%/third_party/qnx_credential_helper.py common:qnx_arm64 --sandbox_writable_path=/var/tmp @@ -62,6 +65,7 @@ coverage --experimental_use_llvm_covmap coverage --combined_report=lcov coverage --coverage_report_generator=@bazel_tools//tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator:Main coverage --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux +coverage --extra_toolchains=@ferrocene_x86_64_unknown_linux_gnu_llvm//:rust_ferrocene_toolchain coverage --test_env=COVERAGE_GCOV_OPTIONS=-bcu # TODO set toolchain feature once possible # These compile time options are required to cover abnormal termination cases. In GCC one can use `__gcc_dump()`, but this does not work with LLVM @@ -76,6 +80,7 @@ test:clang-tidy --aspects=//:tools/lint/linters.bzl%clang_tidy_aspect test:clang-tidy --output_groups=+rules_lint_report # Use LLVM toolchain for clang-tidy so it can find system headers test:clang-tidy --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux +test:clang-tidy --extra_toolchains=@ferrocene_x86_64_unknown_linux_gnu_llvm//:rust_ferrocene_toolchain import quality/sanitizer/sanitizer.bazelrc diff --git a/MODULE.bazel b/MODULE.bazel index c651ed71..e8061365 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -17,38 +17,75 @@ module( bazel_dep(name = "platforms", version = "1.0.0") -bazel_dep(name = "score_toolchains_gcc", version = "0.4", dev_dependency = True) +bazel_dep(name = "gcc_toolchain", version = "0.9.0", dev_dependency = True) -gcc = use_extension( - "@score_toolchains_gcc//extentions:gcc.bzl", - "gcc", - dev_dependency = True, +gcc_toolchains = use_extension("@gcc_toolchain//toolchain:module_extensions.bzl", "gcc_toolchains", dev_dependency = True) +gcc_toolchains.toolchain( + name = "gcc_toolchain_x86_64", + extra_ldflags = [ + "-lstdc++", + "-lrt", + "-latomic", + ], + gcc_version = "15.2.0", + target_arch = "x86_64", ) -gcc.toolchain( - sha256 = "457f5f20f57528033cb840d708b507050d711ae93e009388847e113b11bf3600", - strip_prefix = "x86_64-unknown-linux-gnu", - url = "https://github.com/eclipse-score/toolchains_gcc_packages/releases/download/0.0.1/x86_64-unknown-linux-gnu_gcc12.tar.gz", +use_repo(gcc_toolchains, "gcc_toolchain_x86_64") + +bazel_dep(name = "score_bazel_cpp_toolchains", version = "0.3.0", dev_dependency = True) +git_override( + module_name = "score_bazel_cpp_toolchains", + commit = "79982259df6dfa9d82cc458163a6d9b08bd24471", + remote = "https://github.com/eclipse-score/bazel_cpp_toolchains.git", ) -# TODO to be moved to toolchain. https://github.com/eclipse-score/toolchains_gcc/issues/11 -gcc.extra_features( - features = [ - "minimal_warnings", - "treat_warnings_as_errors", - ], +score_gcc = use_extension("@score_bazel_cpp_toolchains//extensions:gcc.bzl", "gcc", dev_dependency = True) +score_gcc.toolchain( + name = "score_gcc_x86_64_toolchain", + target_cpu = "x86_64", + target_os = "linux", + use_base_constraints_only = True, + use_default_package = True, + version = "12.2.0", ) -gcc.warning_flags( - minimal_warnings = [ - "-Wall", - "-Wno-error=deprecated-declarations", - ], - strict_warnings = [ - "-Wextra", - "-Wpedantic", - ], - treat_warnings_as_errors = ["-Werror"], +score_gcc.toolchain( + name = "score_qcc_x86_64_toolchain", + sdp_version = "8.0.0", + target_cpu = "x86_64", + target_os = "qnx", + use_default_package = True, + version = "12.2.0", +) +score_gcc.toolchain( + name = "score_qcc_aarch64_toolchain", + sdp_version = "8.0.0", + target_cpu = "aarch64", + target_os = "qnx", + use_default_package = True, + version = "12.2.0", +) +use_repo( + score_gcc, + "score_gcc_x86_64_toolchain", + "score_qcc_aarch64_toolchain", + "score_qcc_x86_64_toolchain", +) + +# For the moment we still need the old toolchain for ifs generation. +# Migrate once rules_imagefs is ready to be used (https://github.com/eclipse-score/rules_imagefs/pull/1). +bazel_dep(name = "score_toolchains_qnx", version = "0.0.7", dev_dependency = True) + +toolchains_qnx = use_extension( + "@score_toolchains_qnx//:extensions.bzl", + "toolchains_qnx", + dev_dependency = True, +) +toolchains_qnx.sdp( + sha256 = "f2e0cb21c6baddbcb65f6a70610ce498e7685de8ea2e0f1648f01b327f6bac63", + strip_prefix = "installation", + url = "https://www.qnx.com/download/download/79858/installation.tgz", ) -use_repo(gcc, "gcc_toolchain", "gcc_toolchain_gcc") +use_repo(toolchains_qnx, "toolchains_qnx_ifs") bazel_dep(name = "toolchains_llvm", version = "1.5.0", dev_dependency = True) @@ -81,6 +118,38 @@ llvm.toolchain( ) use_repo(llvm, "llvm_toolchain") +bazel_dep(name = "score_toolchains_rust", version = "0.7.0", dev_dependency = True) + +gcc_ferrocene = use_extension( + "@score_toolchains_rust//extensions:ferrocene_toolchain_ext.bzl", + "ferrocene_toolchain_ext", + dev_dependency = True, +) +gcc_ferrocene.toolchain( + name = "ferrocene_x86_64_unknown_linux_gnu_llvm", + coverage_tools_sha256 = "497958e925bc94833ea226d68f6d5ba38bd890f571c73e230141d2923e30dd94", + coverage_tools_strip_prefix = "779fbed05ae9e9fe2a04137929d99cc9b3d516fd/x86_64-unknown-linux-gnu", + coverage_tools_url = "https://github.com/eclipse-score/ferrocene_toolchain_builder/releases/download/1.0.1/coverage-tools-779fbed05ae9e9fe2a04137929d99cc9b3d516fd-x86_64-unknown-linux-gnu.tar.gz", + exec_triple = "x86_64-unknown-linux-gnu", + extra_rustc_flags = [ + "-Clink-arg=-Wl,--no-as-needed", + "-Clink-arg=-lc++", + "-Clink-arg=-lm", + "-Clink-arg=-lc", + ], + sha256 = "4c08b41eaafd39cff66333ca4d4646a5331c780050b8b9a8447353fcd301dddc", + target_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + ], + target_triple = "x86_64-unknown-linux-gnu", + url = "https://github.com/eclipse-score/ferrocene_toolchain_builder/releases/download/1.0.1/ferrocene-779fbed05ae9e9fe2a04137929d99cc9b3d516fd-x86_64-unknown-linux-gnu.tar.gz", +) +use_repo( + gcc_ferrocene, + "ferrocene_x86_64_unknown_linux_gnu_llvm", +) + # We use here a pre-compiled fully static and hermetic clang_format binary # and not the one provided by llvm_toolchain, because the one from llvm_toolchain is not fully hermetic (and different version for now) download_file = use_repo_rule("@download_utils//download/file:defs.bzl", "download_file") @@ -97,17 +166,14 @@ bazel_dep(name = "aspect_rules_lint", version = "1.13.0") bazel_dep(name = "googletest", version = "1.17.0.bcr.2") bazel_dep(name = "google_benchmark", version = "1.9.4") bazel_dep(name = "rules_rust", version = "0.61.0") -bazel_dep(name = "score_toolchains_rust", version = "0.2.0", dev_dependency = True) - git_override( - module_name = "score_toolchains_rust", - commit = "f3cc7820d47683bc356963f9aa6aeae80475f933", - remote = "https://github.com/eclipse-score/toolchains_rust.git", # Replace with actual repository URL + module_name = "rules_rust", + commit = "5fc56523d4ff4659f841f43092ba82e6df246edd", # Fix for QNX x86_64 toolchain + remote = "https://github.com/eclipse-score/rules_rust.git", ) bazel_dep(name = "buildifier_prebuilt", version = "8.2.0.2") -bazel_dep(name = "score_crates", version = "0.0.6", repo_name = "crate_index") - +bazel_dep(name = "score_crates", version = "0.0.7", repo_name = "crate_index") bazel_dep(name = "boost.program_options", version = "1.87.0") bazel_dep(name = "boost.interprocess", version = "1.87.0") bazel_dep(name = "download_utils", version = "1.0.1") @@ -131,42 +197,25 @@ download_archive( bazel_dep(name = "nlohmann_json", version = "3.11.3") bazel_dep(name = "bazel_skylib", version = "1.8.1") bazel_dep(name = "rules_doxygen", version = "2.5.0") -bazel_dep(name = "score_docs_as_code", version = "3.0.0") +bazel_dep(name = "score_docs_as_code", version = "3.0.1") -# Force score_docs_as_code to 3.0.0 to resolve compatibility conflict between score_logging and score_baselibs +# Force score_docs_as_code to 3.0.1 to resolve compatibility conflict between score_logging and score_baselibs single_version_override( module_name = "score_docs_as_code", - version = "3.0.0", + version = "3.0.1", ) # Apply patch to fix Doxyfile template for our use cases single_version_override( module_name = "rules_doxygen", - patches = ["//third_party/rule_doxygen:Doxyfile.patch"], patch_strip = 1, + patches = ["//third_party/rule_doxygen:Doxyfile.patch"], ) # Apply patch to fix visibility issue with interprocess_notification target -bazel_dep(name = "score_baselibs", version = "0.2.2") -git_override( - module_name = "score_baselibs", - commit = "6951cd2a3045fb7a053acf203833a17704c22ccf", - remote = "https://github.com/eclipse-score/baselibs.git", -) - -bazel_dep(name = "score_logging", version = "0.0.4") -git_override( - module_name = "score_logging", - commit = "d5267a5d89ca7462bec29c49d3b295a10ee834c3", - remote = "https://github.com/eclipse-score/logging.git", -) - -bazel_dep(name = "score_baselibs_rust", version = "0.0.1") -git_override( - module_name = "score_baselibs_rust", - commit = "9ee64ac85f2a990ef75b2858253ee44bfc1a7ab7", - remote = "https://github.com/eclipse-score/baselibs_rust.git", -) +bazel_dep(name = "score_baselibs", version = "0.2.4") +bazel_dep(name = "score_logging", version = "0.0.5") +bazel_dep(name = "score_baselibs_rust", version = "0.1.0") # Doxygen extension for documentation generation doxygen_extension = use_extension("@rules_doxygen//:extensions.bzl", "doxygen_extension") @@ -188,7 +237,6 @@ pip.parse( requirements_lock = "//:requirements_lock.txt", ) use_repo(pip, "score_communication_pip") - pip.parse( hub_name = "codeql_coding_standards_pip_hub", python_version = "3.12", @@ -196,7 +244,6 @@ pip.parse( ) use_repo(pip, "codeql_coding_standards_pip_hub") - # TRLC dependency for requirements traceability bazel_dep(name = "trlc", version = "0.0.0", dev_dependency = True) git_override( @@ -216,23 +263,7 @@ pip.parse( ) use_repo(pip, "lobster_dependencies") -bazel_dep(name = "score_toolchains_qnx", version = "0.0.6", dev_dependency = True) - -toolchains_qnx = use_extension( - "@score_toolchains_qnx//:extensions.bzl", - "toolchains_qnx", - dev_dependency = True, -) -toolchains_qnx.sdp( - sha256 = "f2e0cb21c6baddbcb65f6a70610ce498e7685de8ea2e0f1648f01b327f6bac63", - strip_prefix = "installation", - url = "https://www.qnx.com/download/download/79858/installation.tgz", -) -use_repo(toolchains_qnx, "toolchains_qnx_sdp") -use_repo(toolchains_qnx, "toolchains_qnx_ifs") -use_repo(toolchains_qnx, "toolchains_qnx_qcc") - -bazel_dep(name = "score_bazel_platforms", version = "0.0.4") +bazel_dep(name = "score_bazel_platforms", version = "0.1.1") bazel_dep(name = "rules_oci", version = "1.8.0") oci = use_extension("@rules_oci//oci:extensions.bzl", "oci") @@ -260,8 +291,7 @@ apt.install( use_repo(apt, "ubuntu24_04") bazel_dep(name = "rules_pkg", version = "1.1.0") - -bazel_dep(name = "score_tooling", version = "1.0.4") +bazel_dep(name = "score_tooling", version = "1.1.2") http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") From dd61ca7fd9f3a41fabf7cdb410b191879663d354 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Mon, 23 Feb 2026 13:43:52 +0100 Subject: [PATCH 03/21] Add appropriate development dependency flags Everything that is not strictly a depenedeny of our production targets is marked a development dependency. --- MODULE.bazel | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index e8061365..ee080c58 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -162,9 +162,11 @@ download_file( ) bazel_dep(name = "rules_cc", version = "0.1.1") -bazel_dep(name = "aspect_rules_lint", version = "1.13.0") -bazel_dep(name = "googletest", version = "1.17.0.bcr.2") -bazel_dep(name = "google_benchmark", version = "1.9.4") + +bazel_dep(name = "aspect_rules_lint", version = "1.13.0", dev_dependency = True) +bazel_dep(name = "googletest", version = "1.17.0.bcr.2", dev_dependency = True) +bazel_dep(name = "google_benchmark", version = "1.9.4", dev_dependency = True) + bazel_dep(name = "rules_rust", version = "0.61.0") git_override( module_name = "rules_rust", @@ -172,7 +174,8 @@ git_override( remote = "https://github.com/eclipse-score/rules_rust.git", ) -bazel_dep(name = "buildifier_prebuilt", version = "8.2.0.2") +bazel_dep(name = "buildifier_prebuilt", version = "8.2.0.2", dev_dependency = True) + bazel_dep(name = "score_crates", version = "0.0.7", repo_name = "crate_index") bazel_dep(name = "boost.program_options", version = "1.87.0") bazel_dep(name = "boost.interprocess", version = "1.87.0") @@ -196,8 +199,9 @@ download_archive( bazel_dep(name = "nlohmann_json", version = "3.11.3") bazel_dep(name = "bazel_skylib", version = "1.8.1") -bazel_dep(name = "rules_doxygen", version = "2.5.0") -bazel_dep(name = "score_docs_as_code", version = "3.0.1") + +bazel_dep(name = "rules_doxygen", version = "2.5.0", dev_dependency = True) +bazel_dep(name = "score_docs_as_code", version = "3.0.1", dev_dependency = True) # Force score_docs_as_code to 3.0.1 to resolve compatibility conflict between score_logging and score_baselibs single_version_override( @@ -222,7 +226,7 @@ doxygen_extension = use_extension("@rules_doxygen//:extensions.bzl", "doxygen_ex use_repo(doxygen_extension, "doxygen") # Python 3.12 toolchain for Bazel -bazel_dep(name = "rules_python", version = "1.5.1") +bazel_dep(name = "rules_python", version = "1.5.1", dev_dependency = True) python = use_extension("@rules_python//python/extensions:python.bzl", "python") python.toolchain( @@ -264,7 +268,8 @@ pip.parse( use_repo(pip, "lobster_dependencies") bazel_dep(name = "score_bazel_platforms", version = "0.1.1") -bazel_dep(name = "rules_oci", version = "1.8.0") + +bazel_dep(name = "rules_oci", version = "1.8.0", dev_dependency = True) oci = use_extension("@rules_oci//oci:extensions.bzl", "oci") oci.pull( @@ -276,7 +281,7 @@ oci.pull( ) use_repo(oci, "ubuntu_24_04") -bazel_dep(name = "rules_distroless", version = "0.6.1") +bazel_dep(name = "rules_distroless", version = "0.6.1", dev_dependency = True) apt = use_extension( "@rules_distroless//apt:extensions.bzl", @@ -290,7 +295,8 @@ apt.install( ) use_repo(apt, "ubuntu24_04") -bazel_dep(name = "rules_pkg", version = "1.1.0") +bazel_dep(name = "rules_pkg", version = "1.1.0", dev_dependency = True) + bazel_dep(name = "score_tooling", version = "1.1.2") http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") From e922def4ccfa39df16ff75c717ce3a63ab73640b Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Mon, 23 Feb 2026 14:04:42 +0100 Subject: [PATCH 04/21] Update non-S-CORE dependencies Bump dependencies based to reasonable versions. Development dependencies are bumped to a very high number. For these dependencies we are interested in the newest bug fixes and improvements. For non-development dependencies bump to a minimum version that does not restrict our users too much while giving us some fixes and improvements. --- MODULE.bazel | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index ee080c58..05841942 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -161,25 +161,21 @@ download_file( urls = ["https://github.com/muttleyxd/clang-tools-static-binaries/releases/download/master-2da3e7b/clang-format-19_linux-amd64"], ) -bazel_dep(name = "rules_cc", version = "0.1.1") +bazel_dep(name = "rules_cc", version = "0.1.5") -bazel_dep(name = "aspect_rules_lint", version = "1.13.0", dev_dependency = True) +bazel_dep(name = "aspect_rules_lint", version = "2.2.0", dev_dependency = True) bazel_dep(name = "googletest", version = "1.17.0.bcr.2", dev_dependency = True) -bazel_dep(name = "google_benchmark", version = "1.9.4", dev_dependency = True) +bazel_dep(name = "google_benchmark", version = "1.9.5", dev_dependency = True) -bazel_dep(name = "rules_rust", version = "0.61.0") -git_override( - module_name = "rules_rust", - commit = "5fc56523d4ff4659f841f43092ba82e6df246edd", # Fix for QNX x86_64 toolchain - remote = "https://github.com/eclipse-score/rules_rust.git", -) +bazel_dep(name = "rules_rust", version = "0.68.1-score") -bazel_dep(name = "buildifier_prebuilt", version = "8.2.0.2", dev_dependency = True) +bazel_dep(name = "buildifier_prebuilt", version = "8.2.1.2", dev_dependency = True) bazel_dep(name = "score_crates", version = "0.0.7", repo_name = "crate_index") bazel_dep(name = "boost.program_options", version = "1.87.0") bazel_dep(name = "boost.interprocess", version = "1.87.0") -bazel_dep(name = "download_utils", version = "1.0.1") + +bazel_dep(name = "download_utils", version = "1.2.2", dev_dependency = True) download_archive = use_repo_rule("@download_utils//download/archive:defs.bzl", "download_archive") @@ -200,7 +196,7 @@ download_archive( bazel_dep(name = "nlohmann_json", version = "3.11.3") bazel_dep(name = "bazel_skylib", version = "1.8.1") -bazel_dep(name = "rules_doxygen", version = "2.5.0", dev_dependency = True) +bazel_dep(name = "rules_doxygen", version = "2.6.1", dev_dependency = True) bazel_dep(name = "score_docs_as_code", version = "3.0.1", dev_dependency = True) # Force score_docs_as_code to 3.0.1 to resolve compatibility conflict between score_logging and score_baselibs @@ -281,7 +277,7 @@ oci.pull( ) use_repo(oci, "ubuntu_24_04") -bazel_dep(name = "rules_distroless", version = "0.6.1", dev_dependency = True) +bazel_dep(name = "rules_distroless", version = "0.6.2", dev_dependency = True) apt = use_extension( "@rules_distroless//apt:extensions.bzl", @@ -295,7 +291,7 @@ apt.install( ) use_repo(apt, "ubuntu24_04") -bazel_dep(name = "rules_pkg", version = "1.1.0", dev_dependency = True) +bazel_dep(name = "rules_pkg", version = "1.2.0", dev_dependency = True) bazel_dep(name = "score_tooling", version = "1.1.2") From 8501935620bbc33238c6d7ec476094a1bb932b11 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Mon, 16 Feb 2026 17:10:17 +0100 Subject: [PATCH 05/21] Drop manual selection of host platform for QNX configs Manually specifying the host platform can lead to tremendous problems if the specified host platform does match the actual platform. Removes the selection to let Bazel automatically select the appropriate host platform. --- .bazelrc | 2 -- 1 file changed, 2 deletions(-) diff --git a/.bazelrc b/.bazelrc index ea1c9fdc..adc5ca48 100644 --- a/.bazelrc +++ b/.bazelrc @@ -32,7 +32,6 @@ common:linux_x86_64_score_gcc_12_2_0_posix --extra_toolchains=@score_gcc_x86_64_ # * If you are applicable for "Free for non commercial use" see here: https://www.qnx.com/products/everywhere/ # * The credentials for this account stored in your ~/.netrc (machine qnx.com) # * A license stored under `/opt/score_qnx/license/licenses` -common:qnx_x86_64 --host_platform=@score_bazel_platforms//:x86_64-linux common:qnx_x86_64 --platforms=@score_bazel_platforms//:x86_64-qnx-sdp_8.0.0-posix common:qnx_x86_64 --extra_toolchains=@toolchains_qnx_ifs//:ifs_x86_64 common:qnx_x86_64 --extra_toolchains=@score_qcc_x86_64_toolchain//:x86_64-qnx-sdp_8.0.0 @@ -40,7 +39,6 @@ common:qnx_x86_64 --extra_toolchains=@score_toolchains_rust//toolchains/ferrocen common:qnx_x86_64 --credential_helper=*.qnx.com=%workspace%/third_party/qnx_credential_helper.py common:qnx_x86_64 --sandbox_writable_path=/var/tmp -common:qnx_arm64 --host_platform=@score_bazel_platforms//:x86_64-linux common:qnx_arm64 --platforms=@score_bazel_platforms//:aarch64-qnx-sdp_8.0.0-posix common:qnx_arm64 --extra_toolchains=@toolchains_qnx_ifs//:ifs_aarch64 common:qnx_arm64 --extra_toolchains=@score_qcc_aarch64_toolchain//:aarch64-qnx-sdp_8.0.0 From ed2dca1f47d0d748784ae4bc9401bac56de0c106 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Tue, 3 Feb 2026 16:54:31 +0100 Subject: [PATCH 06/21] Clean permissions of workflows and enable coverage reporting for PRs Reduce the permissions of all workflows as far as possible. Further, actively specify permissions as action to the codeql findings. This also enables us to run the coverage report workflow on PRs. --- ...ress_undefined_behavior_leak_sanitizer.yml | 2 + .github/workflows/automated_release.yml | 84 +++++++++---------- .github/workflows/build_and_test_host.yml | 2 + .github/workflows/build_and_test_qnx.yml | 1 - ...overage_report.yml => coverage_report.yml} | 31 +++---- .github/workflows/thread_sanitizer.yml | 2 + 6 files changed, 65 insertions(+), 57 deletions(-) rename .github/workflows/{release_coverage_report.yml => coverage_report.yml} (78%) diff --git a/.github/workflows/address_undefined_behavior_leak_sanitizer.yml b/.github/workflows/address_undefined_behavior_leak_sanitizer.yml index e68875e2..9117222b 100644 --- a/.github/workflows/address_undefined_behavior_leak_sanitizer.yml +++ b/.github/workflows/address_undefined_behavior_leak_sanitizer.yml @@ -25,6 +25,8 @@ on: jobs: build_and_test_asan_ubsan_lsan: runs-on: ubuntu-24.04 + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@v4.2.2 diff --git a/.github/workflows/automated_release.yml b/.github/workflows/automated_release.yml index 619917b2..92633b1e 100644 --- a/.github/workflows/automated_release.yml +++ b/.github/workflows/automated_release.yml @@ -45,6 +45,12 @@ jobs: echo "Release version tag: $RELEASE_VERSION" echo "release-tag=$RELEASE_VERSION" >> $GITHUB_OUTPUT + - name: Delete trigger tag + run: | + gh api repos/${{ github.repository }}/git/refs/tags/${{ github.ref_name }} -X DELETE + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Create draft release id: create-release uses: softprops/action-gh-release@v2 @@ -65,7 +71,6 @@ jobs: uses: ./.github/workflows/build_and_test_qnx.yml permissions: contents: read - pull-requests: read secrets: SCORE_QNX_LICENSE: ${{ secrets.SCORE_QNX_LICENSE }} SCORE_QNX_USER: ${{ secrets.SCORE_QNX_USER }} @@ -81,11 +86,27 @@ jobs: run-coverage-report: needs: create-draft-release - uses: ./.github/workflows/release_coverage_report.yml - with: - release_tag: ${{ needs.create-draft-release.outputs.release-tag }} + uses: ./.github/workflows/coverage_report.yml + + upload-coverage-report: + needs: + - create-draft-release + - run-coverage-report + runs-on: ubuntu-24.04 permissions: contents: write + steps: + - name: Download coverage report artifact + uses: actions/download-artifact@v4 + with: + name: ${{ needs.run-coverage-report.outputs.artifact-name }} + path: ./ + + - name: Upload coverage report to existing draft release + run: | + gh release upload "${{ needs.create-draft-release.outputs.release-tag }}" "${{ needs.run-coverage-report.outputs.artifact-name }}.zip" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} finalize-release: runs-on: ubuntu-24.04 @@ -96,46 +117,30 @@ jobs: - run-thread-sanitizer - run-address-sanitizer - run-coverage-report - if: always() + - upload-coverage-report + if: ${{ success() }} permissions: contents: write steps: - name: Checkout repository uses: actions/checkout@v4.2.2 - - name: Check workflow results - id: check-results + - name: Report success + if: steps.check-results.outputs.all-success == 'true' run: | - RESULT_HOST="${{ needs.run-build-and-test-host.result }}" - RESULT_QNX="${{ needs.run-build-and-test-qnx.result }}" - RESULT_TSAN="${{ needs.run-thread-sanitizer.result }}" - RESULT_ASAN="${{ needs.run-address-sanitizer.result }}" - RESULT_COVERAGE="${{ needs.run-coverage-report.result }}" - - echo "Build and test host: $RESULT_HOST" - echo "Build and test QNX: $RESULT_QNX" - echo "Thread sanitizer: $RESULT_TSAN" - echo "Address sanitizer: $RESULT_ASAN" - echo "Coverage report: $RESULT_COVERAGE" - - if [[ "$RESULT_HOST" == "success" ]] && \ - [[ "$RESULT_QNX" == "success" ]] && \ - [[ "$RESULT_TSAN" == "success" ]] && \ - [[ "$RESULT_ASAN" == "success" ]] && \ - [[ "$RESULT_COVERAGE" == "success" ]]; then - echo "all-success=true" >> $GITHUB_OUTPUT - else - echo "all-success=false" >> $GITHUB_OUTPUT - fi + echo "All workflows succeeded. Draft release ${{ needs.create-draft-release.outputs.release-tag }} is ready for manual publishing." - - name: Delete trigger tag - run: | - gh api repos/${{ github.repository }}/git/refs/tags/${{ github.ref_name }} -X DELETE - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + delete-release-on-failure: + runs-on: ubuntu-24.04 + needs: create-draft-release + if: ${{ failure() || cancelled() }} + permissions: + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v4.2.2 - - name: Delete draft release (on failure) - if: steps.check-results.outputs.all-success == 'false' + - name: Delete draft release due to failure run: | gh release delete ${{ needs.create-draft-release.outputs.release-tag }} --yes env: @@ -144,10 +149,5 @@ jobs: - name: Report failure if: steps.check-results.outputs.all-success == 'false' run: | - echo "❌ One or more workflows failed. Draft release has been deleted." - exit 1 - - - name: Report success - if: steps.check-results.outputs.all-success == 'true' - run: | - echo "✅ All workflows succeeded. Draft release ${{ needs.create-draft-release.outputs.release-tag }} is ready for manual publishing." + echo "One or more workflows failed. Draft release has been deleted." + exit 1 \ No newline at end of file diff --git a/.github/workflows/build_and_test_host.yml b/.github/workflows/build_and_test_host.yml index 88c889d2..395b049f 100644 --- a/.github/workflows/build_and_test_host.yml +++ b/.github/workflows/build_and_test_host.yml @@ -28,6 +28,8 @@ jobs: matrix: toolchain: ["@llvm_toolchain//:cc-toolchain-x86_64-linux", "@gcc_toolchain//:host_gcc_12"] runs-on: ubuntu-24.04 + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@v4.2.2 diff --git a/.github/workflows/build_and_test_qnx.yml b/.github/workflows/build_and_test_qnx.yml index 123b844c..23e6da22 100644 --- a/.github/workflows/build_and_test_qnx.yml +++ b/.github/workflows/build_and_test_qnx.yml @@ -48,7 +48,6 @@ jobs: runs-on: ubuntu-24.04 permissions: contents: read - pull-requests: read steps: - name: Checkout repository uses: actions/checkout@v4.2.2 diff --git a/.github/workflows/release_coverage_report.yml b/.github/workflows/coverage_report.yml similarity index 78% rename from .github/workflows/release_coverage_report.yml rename to .github/workflows/coverage_report.yml index f28797af..8e635a53 100644 --- a/.github/workflows/release_coverage_report.yml +++ b/.github/workflows/coverage_report.yml @@ -13,18 +13,21 @@ name: Coverage Report on: + pull_request: + types: [ opened, reopened, synchronize ] workflow_call: - inputs: - release_tag: - description: 'Release tag to upload artifacts to' - required: true - type: string + outputs: + artifact-name: + description: 'Name of the coverage report artifact' + value: ${{ jobs.coverage-report.outputs.artifact-name }} jobs: coverage-report: runs-on: ubuntu-24.04 permissions: contents: write # required to upload release assets + outputs: + artifact-name: ${{ steps.set-artifact-name.outputs.artifact-name }} steps: - name: Checkout Repository @@ -66,18 +69,18 @@ jobs: mkdir -p artifacts find bazel-testlogs/score/ -name 'test.xml' -print0 | xargs -0 -I{} cp --parents {} artifacts/ cp -r cpp_coverage artifacts/ - zip -r ${{ github.event.repository.name }}_coverage_report.zip artifacts/ + zip -r ${{ github.event.repository.name }}_coverage_report_${{ github.sha }}.zip artifacts/ shell: bash + - name: Set artifact name + id: set-artifact-name + run: | + echo "artifact-name=${{ github.event.repository.name }}_coverage_report_${{ github.sha }}" >> $GITHUB_OUTPUT + - name: Upload coverage artifacts uses: actions/upload-artifact@v4 with: - name: ${{ github.event.repository.name }}_coverage_report.zip - path: ${{ github.event.repository.name }}_coverage_report.zip + name: ${{ steps.set-artifact-name.outputs.artifact-name }} + path: ${{ github.event.repository.name }}_coverage_report_${{ github.sha }}.zip + - - name: Upload coverage report to existing draft release - run: | - # Upload the file to the existing release - gh release upload "${{ inputs.release_tag }}" "${{ github.event.repository.name }}_coverage_report.zip" - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/thread_sanitizer.yml b/.github/workflows/thread_sanitizer.yml index 2278d77f..2a5b810f 100644 --- a/.github/workflows/thread_sanitizer.yml +++ b/.github/workflows/thread_sanitizer.yml @@ -24,6 +24,8 @@ on: jobs: build_and_test_tsan: runs-on: ubuntu-24.04 + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@v4.2.2 From 745b283b640301ced9417cedfb0df0864aeb1e4e Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Mon, 16 Feb 2026 17:49:55 +0100 Subject: [PATCH 07/21] Simplify build_and_test_host to support more scenarios Makes workflow more versatile to support testing more toolchains. --- .github/workflows/build_and_test_host.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_and_test_host.yml b/.github/workflows/build_and_test_host.yml index 395b049f..ae0ae205 100644 --- a/.github/workflows/build_and_test_host.yml +++ b/.github/workflows/build_and_test_host.yml @@ -22,11 +22,14 @@ on: types: [checks_requested] workflow_call: jobs: - build_and_test_host: + build_and_test: strategy: fail-fast: false matrix: - toolchain: ["@llvm_toolchain//:cc-toolchain-x86_64-linux", "@gcc_toolchain//:host_gcc_12"] + param: + - "" # The default configuration + - "--extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux" + - "--config=linux_x86_64_score_gcc_12_2_0_posix" runs-on: ubuntu-24.04 permissions: contents: read @@ -44,7 +47,7 @@ jobs: uses: ./actions/unblock_user_namespace_for_linux_sandbox - name: Bazel build communication targets run: | - bazel build --extra_toolchains=${{ matrix.toolchain }} //... + bazel build ${{ matrix.param }} //... - name: Bazel test communication targets run: | - bazel test --extra_toolchains=${{ matrix.toolchain }} //... --build_tests_only + bazel test ${{ matrix.param }} //... --build_tests_only From 1f1d966606a67a429504502a5d1cfe7ae4c98ac6 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Tue, 17 Feb 2026 10:05:44 +0100 Subject: [PATCH 08/21] Alphabetically order packages in ubuntu image manifest --- .../environments/ubuntu24_04_docker/ubuntu24_04.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml index 3b8b9f5f..938fa197 100644 --- a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml +++ b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml @@ -27,6 +27,6 @@ archs: - "amd64" packages: - - "libatomic1" - "bash" - - "coreutils" # for commands like `ls` \ No newline at end of file + - "coreutils" # for commands like `ls` + - "libatomic1" \ No newline at end of file From 966c5cd334cd389edf858e84b368cfd7afa67452 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Tue, 17 Feb 2026 10:06:19 +0100 Subject: [PATCH 09/21] Add libstdc++6 to packages in Ubuntu image manifest --- .../ubuntu24_04_docker/ubuntu24_04.lock.json | 147 +++++++++++------- .../ubuntu24_04_docker/ubuntu24_04.yaml | 3 +- 2 files changed, 89 insertions(+), 61 deletions(-) diff --git a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.lock.json b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.lock.json index 22e0525a..4e0064f4 100644 --- a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.lock.json +++ b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.lock.json @@ -1,65 +1,5 @@ { "packages": [ - { - "arch": "amd64", - "dependencies": [ - { - "key": "libc6_2.39-0ubuntu2_amd64", - "name": "libc6", - "version": "2.39-0ubuntu2" - }, - { - "key": "libgcc-s1_14-20240221-2.1ubuntu1_amd64", - "name": "libgcc-s1", - "version": "14-20240221-2.1ubuntu1" - }, - { - "key": "gcc-14-base_14-20240221-2.1ubuntu1_amd64", - "name": "gcc-14-base", - "version": "14-20240221-2.1ubuntu1" - } - ], - "key": "libatomic1_14-20240221-2.1ubuntu1_amd64", - "name": "libatomic1", - "sha256": "e34b6e9e29e74bbf7414977e794a3d68968a4c8da6284d4c49bee857ae4155ce", - "urls": [ - "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/libatomic1_14-20240221-2.1ubuntu1_amd64.deb" - ], - "version": "14-20240221-2.1ubuntu1" - }, - { - "arch": "amd64", - "dependencies": [], - "key": "libc6_2.39-0ubuntu2_amd64", - "name": "libc6", - "sha256": "4bd128b75db38b7e9147c0333908e2c7fbc41631f284360f95118fe1c6c162f3", - "urls": [ - "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/glibc/libc6_2.39-0ubuntu2_amd64.deb" - ], - "version": "2.39-0ubuntu2" - }, - { - "arch": "amd64", - "dependencies": [], - "key": "libgcc-s1_14-20240221-2.1ubuntu1_amd64", - "name": "libgcc-s1", - "sha256": "ffc195df7e897aaec468e8f62b08660cc711c7449113102491fdd6baa6901f6d", - "urls": [ - "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/libgcc-s1_14-20240221-2.1ubuntu1_amd64.deb" - ], - "version": "14-20240221-2.1ubuntu1" - }, - { - "arch": "amd64", - "dependencies": [], - "key": "gcc-14-base_14-20240221-2.1ubuntu1_amd64", - "name": "gcc-14-base", - "sha256": "2e1ae2c2ccf2d1b6d09c657af1492a8b7a348e899f9ad25d4925b170571a0887", - "urls": [ - "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/gcc-14-base_14-20240221-2.1ubuntu1_amd64.deb" - ], - "version": "14-20240221-2.1ubuntu1" - }, { "arch": "amd64", "dependencies": [ @@ -123,6 +63,39 @@ ], "version": "5.16" }, + { + "arch": "amd64", + "dependencies": [], + "key": "libc6_2.39-0ubuntu2_amd64", + "name": "libc6", + "sha256": "4bd128b75db38b7e9147c0333908e2c7fbc41631f284360f95118fe1c6c162f3", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/glibc/libc6_2.39-0ubuntu2_amd64.deb" + ], + "version": "2.39-0ubuntu2" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "libgcc-s1_14-20240221-2.1ubuntu1_amd64", + "name": "libgcc-s1", + "sha256": "ffc195df7e897aaec468e8f62b08660cc711c7449113102491fdd6baa6901f6d", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/libgcc-s1_14-20240221-2.1ubuntu1_amd64.deb" + ], + "version": "14-20240221-2.1ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "gcc-14-base_14-20240221-2.1ubuntu1_amd64", + "name": "gcc-14-base", + "sha256": "2e1ae2c2ccf2d1b6d09c657af1492a8b7a348e899f9ad25d4925b170571a0887", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/gcc-14-base_14-20240221-2.1ubuntu1_amd64.deb" + ], + "version": "14-20240221-2.1ubuntu1" + }, { "arch": "amd64", "dependencies": [], @@ -289,6 +262,60 @@ "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/a/acl/libacl1_2.3.2-1_amd64.deb" ], "version": "2.3.2-1" + }, + { + "arch": "amd64", + "dependencies": [ + { + "key": "libc6_2.39-0ubuntu2_amd64", + "name": "libc6", + "version": "2.39-0ubuntu2" + }, + { + "key": "libgcc-s1_14-20240221-2.1ubuntu1_amd64", + "name": "libgcc-s1", + "version": "14-20240221-2.1ubuntu1" + }, + { + "key": "gcc-14-base_14-20240221-2.1ubuntu1_amd64", + "name": "gcc-14-base", + "version": "14-20240221-2.1ubuntu1" + } + ], + "key": "libatomic1_14-20240221-2.1ubuntu1_amd64", + "name": "libatomic1", + "sha256": "e34b6e9e29e74bbf7414977e794a3d68968a4c8da6284d4c49bee857ae4155ce", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/libatomic1_14-20240221-2.1ubuntu1_amd64.deb" + ], + "version": "14-20240221-2.1ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [ + { + "key": "libgcc-s1_14-20240221-2.1ubuntu1_amd64", + "name": "libgcc-s1", + "version": "14-20240221-2.1ubuntu1" + }, + { + "key": "libc6_2.39-0ubuntu2_amd64", + "name": "libc6", + "version": "2.39-0ubuntu2" + }, + { + "key": "gcc-14-base_14-20240221-2.1ubuntu1_amd64", + "name": "gcc-14-base", + "version": "14-20240221-2.1ubuntu1" + } + ], + "key": "libstdc-p--p-6_14-20240221-2.1ubuntu1_amd64", + "name": "libstdc++6", + "sha256": "3311c13f2e26c20369e937051c78f07c495f6112a0d6c32d3285b47021457ec2", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/libstdc++6_14-20240221-2.1ubuntu1_amd64.deb" + ], + "version": "14-20240221-2.1ubuntu1" } ], "version": 1 diff --git a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml index 938fa197..2bc4934d 100644 --- a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml +++ b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml @@ -29,4 +29,5 @@ archs: packages: - "bash" - "coreutils" # for commands like `ls` - - "libatomic1" \ No newline at end of file + - "libatomic1" + - "libstdc++6" From 3f3fbcdd974a5a76bb483abadb8c62475e1ae1f7 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Tue, 17 Feb 2026 10:07:11 +0100 Subject: [PATCH 10/21] Add additional exclusions in QNX build These targets fail with the QNX toolchains. Since both targets are about documentation, fixing this has very low priority. --- .github/workflows/build_and_test_qnx.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build_and_test_qnx.yml b/.github/workflows/build_and_test_qnx.yml index 23e6da22..584c61a1 100644 --- a/.github/workflows/build_and_test_qnx.yml +++ b/.github/workflows/build_and_test_qnx.yml @@ -41,10 +41,14 @@ jobs: incompatible_targets: - "-//score/mw/com/requirements/..." # Uninvestigated problem - "-//score/mw/com/performance_benchmarks/..." # Uninvestigated problem + - "-//score/mw/com/doc/..." # Uninvestigated problem + - "-//score/mw/com/design/..." # Uninvestigated problem - bazel-config: "qnx_arm64" incompatible_targets: - "-//score/mw/com/requirements/..." # Uninvestigated problem - "-//score/mw/com/performance_benchmarks/..." # Uninvestigated problem + - "-//score/mw/com/doc/..." # Uninvestigated problem + - "-//score/mw/com/design/..." # Uninvestigated problem runs-on: ubuntu-24.04 permissions: contents: read From e305f2ed2d8cc97dc61d8bcce4fce44f65f490c6 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Fri, 20 Feb 2026 16:03:55 +0100 Subject: [PATCH 11/21] Use canonical reproducable way of fetching codeql_coding_standards --- MODULE.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MODULE.bazel b/MODULE.bazel index 05841942..7cb00db1 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -309,6 +309,6 @@ git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "g git_repository( name = "codeql_coding_standards", build_file = "//third_party/codeql:codeql_coding_standards.BUILD", + commit = "781f1eecfa2fc9970fb08447588a0b4d19a7908d", remote = "https://github.com/github/codeql-coding-standards.git", - tag = "v2.52.0", ) From 6398da37ed13f713ac5a86e0d6b54c820a650244 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Wed, 18 Feb 2026 11:56:17 +0100 Subject: [PATCH 12/21] Enable sanitizer backtraces in integration tests Sanitizers rely on the addr2line utility to symbolize the backtraces in their reports. Adds this tool to the Ubuntu image. --- .../ubuntu24_04_docker/ubuntu24_04.lock.json | 246 ++++++++++++++++-- .../ubuntu24_04_docker/ubuntu24_04.yaml | 1 + 2 files changed, 220 insertions(+), 27 deletions(-) diff --git a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.lock.json b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.lock.json index 4e0064f4..7a4b1858 100644 --- a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.lock.json +++ b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.lock.json @@ -140,6 +140,225 @@ ], "version": "6.4+20240113-1ubuntu1" }, + { + "arch": "amd64", + "dependencies": [ + { + "key": "binutils-x86-64-linux-gnu_2.42-3ubuntu1_amd64", + "name": "binutils-x86-64-linux-gnu", + "version": "2.42-3ubuntu1" + }, + { + "key": "zlib1g_1-1.3.dfsg-3ubuntu1_amd64", + "name": "zlib1g", + "version": "1:1.3.dfsg-3ubuntu1" + }, + { + "key": "libc6_2.39-0ubuntu2_amd64", + "name": "libc6", + "version": "2.39-0ubuntu2" + }, + { + "key": "libgcc-s1_14-20240221-2.1ubuntu1_amd64", + "name": "libgcc-s1", + "version": "14-20240221-2.1ubuntu1" + }, + { + "key": "gcc-14-base_14-20240221-2.1ubuntu1_amd64", + "name": "gcc-14-base", + "version": "14-20240221-2.1ubuntu1" + }, + { + "key": "libzstd1_1.5.5-p-dfsg2-2_amd64", + "name": "libzstd1", + "version": "1.5.5+dfsg2-2" + }, + { + "key": "libstdc-p--p-6_14-20240221-2.1ubuntu1_amd64", + "name": "libstdc++6", + "version": "14-20240221-2.1ubuntu1" + }, + { + "key": "libsframe1_2.42-3ubuntu1_amd64", + "name": "libsframe1", + "version": "2.42-3ubuntu1" + }, + { + "key": "libjansson4_2.14-2_amd64", + "name": "libjansson4", + "version": "2.14-2" + }, + { + "key": "libgprofng0_2.42-3ubuntu1_amd64", + "name": "libgprofng0", + "version": "2.42-3ubuntu1" + }, + { + "key": "libbinutils_2.42-3ubuntu1_amd64", + "name": "libbinutils", + "version": "2.42-3ubuntu1" + }, + { + "key": "binutils-common_2.42-3ubuntu1_amd64", + "name": "binutils-common", + "version": "2.42-3ubuntu1" + }, + { + "key": "libctf0_2.42-3ubuntu1_amd64", + "name": "libctf0", + "version": "2.42-3ubuntu1" + }, + { + "key": "libctf-nobfd0_2.42-3ubuntu1_amd64", + "name": "libctf-nobfd0", + "version": "2.42-3ubuntu1" + } + ], + "key": "binutils_2.42-3ubuntu1_amd64", + "name": "binutils", + "sha256": "f047bb9c3db90cb28d334e2c5bcc0914e1688e6e14d37afeb52100917e87c107", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/b/binutils/binutils_2.42-3ubuntu1_amd64.deb" + ], + "version": "2.42-3ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "binutils-x86-64-linux-gnu_2.42-3ubuntu1_amd64", + "name": "binutils-x86-64-linux-gnu", + "sha256": "f68656486334d2d6e16c9ca296d99d175aa083979d7de03e1e62046f7774b117", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/b/binutils/binutils-x86-64-linux-gnu_2.42-3ubuntu1_amd64.deb" + ], + "version": "2.42-3ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "zlib1g_1-1.3.dfsg-3ubuntu1_amd64", + "name": "zlib1g", + "sha256": "35cfe44912765862374112e83c178c095448f247785772147c42c0c843b67c97", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/z/zlib/zlib1g_1.3.dfsg-3ubuntu1_amd64.deb" + ], + "version": "1:1.3.dfsg-3ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "libzstd1_1.5.5-p-dfsg2-2_amd64", + "name": "libzstd1", + "sha256": "7926bb8267652dd7df2c78c5e7541df6e62dbc10ed2efd4c2b869c75538b2ff1", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/libz/libzstd/libzstd1_1.5.5+dfsg2-2_amd64.deb" + ], + "version": "1.5.5+dfsg2-2" + }, + { + "arch": "amd64", + "dependencies": [ + { + "key": "libgcc-s1_14-20240221-2.1ubuntu1_amd64", + "name": "libgcc-s1", + "version": "14-20240221-2.1ubuntu1" + }, + { + "key": "libc6_2.39-0ubuntu2_amd64", + "name": "libc6", + "version": "2.39-0ubuntu2" + }, + { + "key": "gcc-14-base_14-20240221-2.1ubuntu1_amd64", + "name": "gcc-14-base", + "version": "14-20240221-2.1ubuntu1" + } + ], + "key": "libstdc-p--p-6_14-20240221-2.1ubuntu1_amd64", + "name": "libstdc++6", + "sha256": "3311c13f2e26c20369e937051c78f07c495f6112a0d6c32d3285b47021457ec2", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/libstdc++6_14-20240221-2.1ubuntu1_amd64.deb" + ], + "version": "14-20240221-2.1ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "libsframe1_2.42-3ubuntu1_amd64", + "name": "libsframe1", + "sha256": "58d05ca5a4fd1790835c5c136d2a4a499d7d2513150b708cf8e12603e8e17add", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/b/binutils/libsframe1_2.42-3ubuntu1_amd64.deb" + ], + "version": "2.42-3ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "libjansson4_2.14-2_amd64", + "name": "libjansson4", + "sha256": "55703f7b04f0235f6b86d67a3c4263a41e6cf30c2b5d5e1e00312368ebd49971", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/j/jansson/libjansson4_2.14-2_amd64.deb" + ], + "version": "2.14-2" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "libgprofng0_2.42-3ubuntu1_amd64", + "name": "libgprofng0", + "sha256": "0db398e08c159645833edad7b536f0afd67064cc2d1a9d9d3e9055d059760044", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/b/binutils/libgprofng0_2.42-3ubuntu1_amd64.deb" + ], + "version": "2.42-3ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "libbinutils_2.42-3ubuntu1_amd64", + "name": "libbinutils", + "sha256": "fa69181cf5034e7b136e666100963eba6fce7a835d4223b12b6c03f749420a0f", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/b/binutils/libbinutils_2.42-3ubuntu1_amd64.deb" + ], + "version": "2.42-3ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "binutils-common_2.42-3ubuntu1_amd64", + "name": "binutils-common", + "sha256": "26129a7c67435a2f6107f05112596b59be66dd90a8349f13e8a7602587a7374c", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/b/binutils/binutils-common_2.42-3ubuntu1_amd64.deb" + ], + "version": "2.42-3ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "libctf0_2.42-3ubuntu1_amd64", + "name": "libctf0", + "sha256": "16b279d18d5d8223c248d20ded7e8983e4dc577378d4af903e7d2b450251811b", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/b/binutils/libctf0_2.42-3ubuntu1_amd64.deb" + ], + "version": "2.42-3ubuntu1" + }, + { + "arch": "amd64", + "dependencies": [], + "key": "libctf-nobfd0_2.42-3ubuntu1_amd64", + "name": "libctf-nobfd0", + "sha256": "455bd3996749dc3b3b74c9e0fea6865d1806f2ae650d3b30c505ca3643ed3c18", + "urls": [ + "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/b/binutils/libctf-nobfd0_2.42-3ubuntu1_amd64.deb" + ], + "version": "2.42-3ubuntu1" + }, { "arch": "amd64", "dependencies": [ @@ -289,33 +508,6 @@ "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/libatomic1_14-20240221-2.1ubuntu1_amd64.deb" ], "version": "14-20240221-2.1ubuntu1" - }, - { - "arch": "amd64", - "dependencies": [ - { - "key": "libgcc-s1_14-20240221-2.1ubuntu1_amd64", - "name": "libgcc-s1", - "version": "14-20240221-2.1ubuntu1" - }, - { - "key": "libc6_2.39-0ubuntu2_amd64", - "name": "libc6", - "version": "2.39-0ubuntu2" - }, - { - "key": "gcc-14-base_14-20240221-2.1ubuntu1_amd64", - "name": "gcc-14-base", - "version": "14-20240221-2.1ubuntu1" - } - ], - "key": "libstdc-p--p-6_14-20240221-2.1ubuntu1_amd64", - "name": "libstdc++6", - "sha256": "3311c13f2e26c20369e937051c78f07c495f6112a0d6c32d3285b47021457ec2", - "urls": [ - "https://snapshot.ubuntu.com/ubuntu/20240301T030400Z/pool/main/g/gcc-14/libstdc++6_14-20240221-2.1ubuntu1_amd64.deb" - ], - "version": "14-20240221-2.1ubuntu1" } ], "version": 1 diff --git a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml index 2bc4934d..76fec7ec 100644 --- a/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml +++ b/quality/integration_testing/environments/ubuntu24_04_docker/ubuntu24_04.yaml @@ -28,6 +28,7 @@ archs: packages: - "bash" + - "binutils" # provides addr2line, required for backtraces in sanitizers - "coreutils" # for commands like `ls` - "libatomic1" - "libstdc++6" From 8803df3785583daf5f7b9e6bfb36c639400f75ac Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Wed, 18 Feb 2026 12:00:19 +0100 Subject: [PATCH 13/21] Introduce support for suppressions in sanitizers --- .../integration_testing.bzl | 8 +++ quality/sanitizer/BUILD | 67 +++++++++++++++++++ quality/sanitizer/asan.supp | 17 +++++ .../sanitizer/asan_ubsan_lsan.env.template | 3 + quality/sanitizer/constraints/BUILD | 49 ++++++++++++++ quality/sanitizer/flags/BUILD | 51 ++++++++++++++ quality/sanitizer/lsan.supp | 17 +++++ quality/sanitizer/sanitizer.bazelrc | 26 ++++--- quality/sanitizer/tsan.env.template | 1 + quality/sanitizer/tsan.supp | 27 ++++++++ quality/sanitizer/ubsan.supp | 17 +++++ quality/sanitizer/wrapper.sh | 17 +++++ 12 files changed, 291 insertions(+), 9 deletions(-) create mode 100644 quality/sanitizer/asan.supp create mode 100644 quality/sanitizer/asan_ubsan_lsan.env.template create mode 100644 quality/sanitizer/constraints/BUILD create mode 100644 quality/sanitizer/flags/BUILD create mode 100644 quality/sanitizer/lsan.supp create mode 100644 quality/sanitizer/tsan.env.template create mode 100644 quality/sanitizer/tsan.supp create mode 100644 quality/sanitizer/ubsan.supp create mode 100755 quality/sanitizer/wrapper.sh diff --git a/quality/integration_testing/integration_testing.bzl b/quality/integration_testing/integration_testing.bzl index 4d63560f..68738698 100644 --- a/quality/integration_testing/integration_testing.bzl +++ b/quality/integration_testing/integration_testing.bzl @@ -41,8 +41,16 @@ def integration_test(name, srcs, filesystem, **kwargs): "@platforms//cpu:x86_64": "amd64", }), os = "linux", + env = select({ + "//quality/sanitizer/flags:none": None, + "//quality/sanitizer/flags:any_sanitizer": "//quality/sanitizer:absolute_env", + }), tars = [ filesystem, + ] + select({ + "//quality/sanitizer/flags:none": [], + "//quality/sanitizer/flags:any_sanitizer": ["//quality/sanitizer:suppressions_pkg"], + }) + [ "@ubuntu24_04//:ubuntu24_04", ], target_compatible_with = LINUX_TARGET_COMPATIBLE_WITH, diff --git a/quality/sanitizer/BUILD b/quality/sanitizer/BUILD index beeeef85..bdaee0f1 100644 --- a/quality/sanitizer/BUILD +++ b/quality/sanitizer/BUILD @@ -11,6 +11,9 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +load("@rules_pkg//pkg:tar.bzl", "pkg_tar") +load("//bazel/rules:expand_template.bzl", "expand_template") + sh_test( name = "sanitizers_functional_test", srcs = ["sanitizers_functional_test.sh"], @@ -33,3 +36,67 @@ sh_test( ], deps = ["@bazel_tools//tools/bash/runfiles"], ) + +filegroup( + name = "env_template", + srcs = select({ + "//quality/sanitizer/flags:tsan": ["tsan.env.template"], + "//quality/sanitizer/flags:asan_ubsan_lsan": ["asan_ubsan_lsan.env.template"], + }), + target_compatible_with = ["//quality/sanitizer/constraints:any_sanitizer"], +) + +[ + expand_template( + name = name + "_env", + out = name + "_sanitizer.env", + substitutions = { + "%ROOT%": root, + }, + target_compatible_with = ["//quality/sanitizer/constraints:any_sanitizer"], + template = ":env_template", + visibility = ["//:__subpackages__"], + ) + for name, root in ( + [ + "absolute", + "/", + ], + [ + "relative", + "./", + ], + ) +] + +filegroup( + name = "suppressions", + srcs = select({ + "//quality/sanitizer/flags:tsan": ["tsan.supp"], + "//quality/sanitizer/flags:asan_ubsan_lsan": [ + "asan.supp", + "lsan.supp", + "ubsan.supp", + ], + }), + target_compatible_with = ["//quality/sanitizer/constraints:any_sanitizer"], +) + +pkg_tar( + name = "suppressions_pkg", + srcs = [":suppressions"], + mode = "0444", + package_dir = "quality/sanitizer", + target_compatible_with = ["//quality/sanitizer/constraints:any_sanitizer"], + visibility = ["//:__subpackages__"], +) + +sh_binary( + name = "wrapper", + srcs = ["wrapper.sh"], + data = [ + ":relative_env", + ":suppressions", + ], + target_compatible_with = ["//quality/sanitizer/constraints:any_sanitizer"], +) diff --git a/quality/sanitizer/asan.supp b/quality/sanitizer/asan.supp new file mode 100644 index 00000000..9050e0fe --- /dev/null +++ b/quality/sanitizer/asan.supp @@ -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 +# ******************************************************************************* + +# Suppressions for the AddressSanitizer +# See: https://clang.llvm.org/docs/AddressSanitizer.html#issue-suppression +# Every suppression requires a justification. +# Suppressions that share the same justification may be organized in a single block. diff --git a/quality/sanitizer/asan_ubsan_lsan.env.template b/quality/sanitizer/asan_ubsan_lsan.env.template new file mode 100644 index 00000000..1842d7a1 --- /dev/null +++ b/quality/sanitizer/asan_ubsan_lsan.env.template @@ -0,0 +1,3 @@ +ASAN_OPTIONS=exitcode=55 allow_addr2line=1 verbosity=1 coverage=1 check_initialization_order=1 detect_stack_use_after_return=1 print_stats=1 halt_on_error=1 allocator_may_return_null=1 detect_leaks=1 suppressions=%ROOT%quality/sanitizer/asan.supp +UBSAN_OPTIONS=exitcode=55 allow_addr2line=1 verbosity=1 coverage=1 print_stacktrace=1 halt_on_error=1 suppressions=%ROOT%quality/sanitizer/ubsan.supp +LSAN_OPTIONS=exitcode=55 suppressions=%ROOT%quality/sanitizer/lsan.supp diff --git a/quality/sanitizer/constraints/BUILD b/quality/sanitizer/constraints/BUILD new file mode 100644 index 00000000..8d7b7beb --- /dev/null +++ b/quality/sanitizer/constraints/BUILD @@ -0,0 +1,49 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +constraint_setting( + name = "dummy_setting", + default_constraint_value = ":always_true", +) + +constraint_value( + name = "always_true", + constraint_setting = ":dummy_setting", +) + +alias( + name = "any_sanitizer", + actual = select({ + "//quality/sanitizer/flags:any_sanitizer": ":always_true", + "//conditions:default": "@platforms//:incompatible", + }), + visibility = ["//:__subpackages__"], +) + +alias( + name = "no_asan_ubsan_lsan", + actual = select({ + "//quality/sanitizer/flags:asan_ubsan_lsan": "@platforms//:incompatible", + "//conditions:default": ":always_true", + }), + visibility = ["//:__subpackages__"], +) + +alias( + name = "no_tsan", + actual = select({ + "//quality/sanitizer/flags:tsan": "@platforms//:incompatible", + "//conditions:default": ":always_true", + }), + visibility = ["//:__subpackages__"], +) diff --git a/quality/sanitizer/flags/BUILD b/quality/sanitizer/flags/BUILD new file mode 100644 index 00000000..622e790a --- /dev/null +++ b/quality/sanitizer/flags/BUILD @@ -0,0 +1,51 @@ +# ******************************************************************************* +# 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("@bazel_skylib//lib:selects.bzl", "selects") +load("@bazel_skylib//rules:common_settings.bzl", "string_flag") + +string_flag( + name = "sanitizer", + build_setting_default = "none", + values = [ + "none", + "asan_ubsan_lsan", + "tsan", + ], +) + +config_setting( + name = "none", + flag_values = {":sanitizer": "none"}, + visibility = ["//:__subpackages__"], +) + +config_setting( + name = "asan_ubsan_lsan", + flag_values = {":sanitizer": "asan_ubsan_lsan"}, + visibility = ["//:__subpackages__"], +) + +config_setting( + name = "tsan", + flag_values = {":sanitizer": "tsan"}, + visibility = ["//:__subpackages__"], +) + +selects.config_setting_group( + name = "any_sanitizer", + match_any = [ + ":asan_ubsan_lsan", + ":tsan", + ], +) diff --git a/quality/sanitizer/lsan.supp b/quality/sanitizer/lsan.supp new file mode 100644 index 00000000..01fbf90f --- /dev/null +++ b/quality/sanitizer/lsan.supp @@ -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 +# ******************************************************************************* + +# Suppressions for the LeakSanitizer +# See: https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#suppressions +# Every suppression requires a justification. +# Suppressions that share the same justification may be organized in a single block. diff --git a/quality/sanitizer/sanitizer.bazelrc b/quality/sanitizer/sanitizer.bazelrc index d867d441..11c74d3a 100644 --- a/quality/sanitizer/sanitizer.bazelrc +++ b/quality/sanitizer/sanitizer.bazelrc @@ -11,27 +11,35 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -test:asan_ubsan_lsan --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux # todo: Extract to toolchain feature once possible -test:asan_ubsan_lsan --cxxopt -O0 -test:asan_ubsan_lsan --cxxopt -Og + +test:with_debug_symbols --cxxopt -gline-tables-only +test:with_debug_symbols --cxxopt -gcolumn-info +test:with_debug_symbols --strip=never + +test:asan_ubsan_lsan --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux +test:asan_ubsan_lsan --extra_toolchains=@ferrocene_x86_64_unknown_linux_gnu_llvm//:rust_ferrocene_toolchain +test:asan_ubsan_lsan --config=with_debug_symbols +test:asan_ubsan_lsan --run_under=//quality/sanitizer:wrapper +test:asan_ubsan_lsan --//quality/sanitizer/flags:sanitizer=asan_ubsan_lsan test:asan_ubsan_lsan --cxxopt -fsanitize=undefined,address,leak -test:asan_ubsan_lsan --cxxopt -fno-optimize-sibling-calls +test:asan_ubsan_lsan --cxxopt -fno-omit-frame-pointer +test:asan_ubsan_lsan --cxxopt -fno-common test:asan_ubsan_lsan --linkopt -fsanitize=undefined,address,leak test:asan_ubsan_lsan --linkopt -fsanitize-link-c++-runtime test:asan_ubsan_lsan --platform_suffix=asan_ubsan -test:asan_ubsan_lsan --test_env=ASAN_OPTIONS="exitcode=55 allow_addr2line=1 verbosity=1 coverage=1 check_initialization_order=1 detect_stack_use_after_return=1 print_stats=1 halt_on_error=1 allocator_may_return_null=1 detect_leaks=1" -test:asan_ubsan_lsan --test_env=UBSAN_OPTIONS="exitcode=55 allow_addr2line=1 verbosity=1 coverage=1 print_stacktrace=1 halt_on_error=1" test:asan --config=asan_ubsan_lsan test:ubsan --config=asan_ubsan_lsan test:lsan --config=asan_ubsan_lsan -test:tsan --cxxopt -O0 -test:tsan --cxxopt -Og test:tsan --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux +test:tsan --extra_toolchains=@ferrocene_x86_64_unknown_linux_gnu_llvm//:rust_ferrocene_toolchain +test:tsan --config=with_debug_symbols +test:tsan --run_under=//quality/sanitizer:wrapper +test:tsan --//quality/sanitizer/flags:sanitizer=tsan test:tsan --cxxopt -fsanitize=thread +test:tsan --cxxopt -O1 test:tsan --linkopt -fsanitize=thread test:tsan --linkopt -fsanitize-link-c++-runtime test:tsan --platform_suffix=tsan -test:tsan --test_env=TSAN_OPTIONS="exitcode=55 allow_addr2line=1 verbosity=1 coverage=1 detect_deadlocks=1 second_deadlock_stack=1 halt_on_error=0" diff --git a/quality/sanitizer/tsan.env.template b/quality/sanitizer/tsan.env.template new file mode 100644 index 00000000..e2cac276 --- /dev/null +++ b/quality/sanitizer/tsan.env.template @@ -0,0 +1 @@ +TSAN_OPTIONS=exitcode=55 allow_addr2line=1 verbosity=1 coverage=1 detect_deadlocks=1 second_deadlock_stack=1 halt_on_error=0 suppressions=%ROOT%quality/sanitizer/tsan.supp diff --git a/quality/sanitizer/tsan.supp b/quality/sanitizer/tsan.supp new file mode 100644 index 00000000..24e3398b --- /dev/null +++ b/quality/sanitizer/tsan.supp @@ -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 +# ******************************************************************************* + +# Suppressions for the ThreadSanitizer +# See: https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions +# Every suppression requires a justification. +# Suppressions that share the same justification may be organized in a single block. + + +# Standard library false positives (caused by a stdlib built without tsan instrumentation) +# We accept this because building the stdlib with instrumentation is currently out of scope. +race:include/c++/v1/ios + +# TODO ticket +race:> +called_from_lib:sample_ptr_test_rs +called_from_lib:sample_allocatee_ptr_test_rs diff --git a/quality/sanitizer/ubsan.supp b/quality/sanitizer/ubsan.supp new file mode 100644 index 00000000..0b1a39ad --- /dev/null +++ b/quality/sanitizer/ubsan.supp @@ -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 +# ******************************************************************************* + +# Suppressions for the UndefinedBehaviorSanitizer +# See: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#runtime-suppressions +# Every suppression requires a justification. +# Suppressions that share the same justification may be organized in a single block. diff --git a/quality/sanitizer/wrapper.sh b/quality/sanitizer/wrapper.sh new file mode 100755 index 00000000..57ffb061 --- /dev/null +++ b/quality/sanitizer/wrapper.sh @@ -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 +# ******************************************************************************* + +IFS=' +' +export $(cat quality/sanitizer/relative_sanitizer.env) +$@ From 05946612d7a566b07e561b6d9c7b62cd7c6557fe Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Fri, 20 Feb 2026 11:12:05 +0100 Subject: [PATCH 14/21] Provide better information to bazel about integration_test size Bazel requires more information about test size to determine concurrent execution capabilities. --- quality/integration_testing/integration_testing.bzl | 8 ++++++++ quality/integration_testing/test/BUILD | 1 + score/mw/com/test/bigdata/integration_test/BUILD | 2 +- .../integration_test/BUILD | 2 +- .../concurrent_skeleton_creation/integration_test/BUILD | 2 +- .../com/test/data_slots_read_only/integration_test/BUILD | 2 +- .../com/test/field_initial_value/integration_test/BUILD | 1 + .../mw/com/test/find_any_semantics/integration_test/BUILD | 2 +- score/mw/com/test/generic_proxy/integration_test/BUILD | 2 +- score/mw/com/test/inotify/integration_test/BUILD | 1 - score/mw/com/test/multiple_proxies/integration_test/BUILD | 2 +- .../checks_number_of_allocations/integration_test/BUILD | 2 +- .../consumer_restart/integration_test/BUILD | 2 +- .../provider_restart/integration_test/BUILD | 1 - .../integration_test/BUILD | 2 +- .../integration_test/BUILD | 2 +- .../receive_handler_unsubscribe/integration_test/BUILD | 2 +- .../com/test/receive_handler_usage/integration_test/BUILD | 2 +- .../test/reserving_skeleton_slots/integration_test/BUILD | 2 +- .../separate_reception_threads/integration_test/BUILD | 2 +- .../integration_test/BUILD | 2 +- .../integration_test/BUILD | 2 +- .../integration_test/BUILD | 2 +- .../integration_test/BUILD | 2 +- .../com/test/shared_memory_storage/integration_test/BUILD | 2 +- .../mw/com/test/subscribe_handler/integration_test/BUILD | 2 +- .../com/test/unsubscribe_deadlock/integration_test/BUILD | 2 +- 27 files changed, 32 insertions(+), 24 deletions(-) diff --git a/quality/integration_testing/integration_testing.bzl b/quality/integration_testing/integration_testing.bzl index 68738698..c4f39aef 100644 --- a/quality/integration_testing/integration_testing.bzl +++ b/quality/integration_testing/integration_testing.bzl @@ -106,6 +106,14 @@ def integration_test(name, srcs, filesystem, **kwargs): }), ) + # Tests spin up docker or qemu which requires a significant amount of system resources. + if "size" not in kwargs: + kwargs["size"] = "enormous" + + # While we require a significant amount of system resources, the tests are still short. + if "timeout" not in kwargs: + kwargs["timeout"] = "short" + py_test( name = "_test_internal_docker_{}".format(name), srcs = [ diff --git a/quality/integration_testing/test/BUILD b/quality/integration_testing/test/BUILD index 04a1ae9e..61da2b03 100644 --- a/quality/integration_testing/test/BUILD +++ b/quality/integration_testing/test/BUILD @@ -34,6 +34,7 @@ pkg_tar( integration_test( name = "test_hello_world", + timeout = "moderate", srcs = [ "test_hello_world.py", ], diff --git a/score/mw/com/test/bigdata/integration_test/BUILD b/score/mw/com/test/bigdata/integration_test/BUILD index 12a3c3ec..90be536d 100644 --- a/score/mw/com/test/bigdata/integration_test/BUILD +++ b/score/mw/com/test/bigdata/integration_test/BUILD @@ -22,7 +22,7 @@ pkg_tar( integration_test( name = "test_bigdata_exchange", - size = "small", + timeout = "moderate", srcs = [ "test_bigdata.py", ], diff --git a/score/mw/com/test/check_values_created_from_config/integration_test/BUILD b/score/mw/com/test/check_values_created_from_config/integration_test/BUILD index d5faee4d..6b08c5ef 100644 --- a/score/mw/com/test/check_values_created_from_config/integration_test/BUILD +++ b/score/mw/com/test/check_values_created_from_config/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "test_check_values_created_from_config", - size = "small", + timeout = "moderate", srcs = ["test_check_values_created_from_config.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/concurrent_skeleton_creation/integration_test/BUILD b/score/mw/com/test/concurrent_skeleton_creation/integration_test/BUILD index 57665dca..4282175c 100644 --- a/score/mw/com/test/concurrent_skeleton_creation/integration_test/BUILD +++ b/score/mw/com/test/concurrent_skeleton_creation/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "concurrent_skeleton_creation", - size = "small", + timeout = "moderate", srcs = ["test_concurrent_skeleton_creation.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/data_slots_read_only/integration_test/BUILD b/score/mw/com/test/data_slots_read_only/integration_test/BUILD index e1b3afd8..177bca33 100644 --- a/score/mw/com/test/data_slots_read_only/integration_test/BUILD +++ b/score/mw/com/test/data_slots_read_only/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "data_slots_read_only", - size = "small", + timeout = "moderate", srcs = ["test_data_slots_read_only.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/field_initial_value/integration_test/BUILD b/score/mw/com/test/field_initial_value/integration_test/BUILD index bd4a9181..456cf2f7 100644 --- a/score/mw/com/test/field_initial_value/integration_test/BUILD +++ b/score/mw/com/test/field_initial_value/integration_test/BUILD @@ -23,6 +23,7 @@ pkg_tar( integration_test( name = "test_field_initial_value", + timeout = "moderate", srcs = [ "test_field_initial_value.py", ], diff --git a/score/mw/com/test/find_any_semantics/integration_test/BUILD b/score/mw/com/test/find_any_semantics/integration_test/BUILD index 5213ee68..2e06e8a4 100644 --- a/score/mw/com/test/find_any_semantics/integration_test/BUILD +++ b/score/mw/com/test/find_any_semantics/integration_test/BUILD @@ -24,7 +24,7 @@ pkg_tar( integration_test( name = "test_find_any_semantics", - size = "small", + timeout = "moderate", srcs = ["test_find_any_semantics.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/generic_proxy/integration_test/BUILD b/score/mw/com/test/generic_proxy/integration_test/BUILD index 8a347ed4..e42d1917 100644 --- a/score/mw/com/test/generic_proxy/integration_test/BUILD +++ b/score/mw/com/test/generic_proxy/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "generic_proxy", - size = "small", + timeout = "moderate", srcs = ["test_generic_proxy.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/inotify/integration_test/BUILD b/score/mw/com/test/inotify/integration_test/BUILD index 2fda49c1..4d981f4c 100644 --- a/score/mw/com/test/inotify/integration_test/BUILD +++ b/score/mw/com/test/inotify/integration_test/BUILD @@ -23,7 +23,6 @@ pkg_tar( integration_test( name = "inotify", - size = "small", srcs = ["test_inotify.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/multiple_proxies/integration_test/BUILD b/score/mw/com/test/multiple_proxies/integration_test/BUILD index e0fec0de..6e2e22a1 100644 --- a/score/mw/com/test/multiple_proxies/integration_test/BUILD +++ b/score/mw/com/test/multiple_proxies/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "multiple_proxies", - size = "small", + timeout = "moderate", srcs = ["test_multiple_proxies.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/partial_restart/checks_number_of_allocations/integration_test/BUILD b/score/mw/com/test/partial_restart/checks_number_of_allocations/integration_test/BUILD index 93b81947..22853964 100644 --- a/score/mw/com/test/partial_restart/checks_number_of_allocations/integration_test/BUILD +++ b/score/mw/com/test/partial_restart/checks_number_of_allocations/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "check_number_of_allocations", - size = "small", + timeout = "moderate", srcs = ["test_check_number_of_allocations.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/partial_restart/consumer_restart/integration_test/BUILD b/score/mw/com/test/partial_restart/consumer_restart/integration_test/BUILD index fbdb02b1..8e2f9ed5 100644 --- a/score/mw/com/test/partial_restart/consumer_restart/integration_test/BUILD +++ b/score/mw/com/test/partial_restart/consumer_restart/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "consumer_restart", - size = "small", + timeout = "moderate", srcs = ["test_consumer_restart.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/partial_restart/provider_restart/integration_test/BUILD b/score/mw/com/test/partial_restart/provider_restart/integration_test/BUILD index 59f2b407..bb9bc7d2 100644 --- a/score/mw/com/test/partial_restart/provider_restart/integration_test/BUILD +++ b/score/mw/com/test/partial_restart/provider_restart/integration_test/BUILD @@ -23,7 +23,6 @@ pkg_tar( integration_test( name = "provider_restart", - size = "small", srcs = ["test_provider_restart.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/partial_restart/provider_restart_max_subscribers/integration_test/BUILD b/score/mw/com/test/partial_restart/provider_restart_max_subscribers/integration_test/BUILD index b05e5d07..97ac9add 100644 --- a/score/mw/com/test/partial_restart/provider_restart_max_subscribers/integration_test/BUILD +++ b/score/mw/com/test/partial_restart/provider_restart_max_subscribers/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "provider_restart_max_subscribers", - size = "small", + timeout = "moderate", srcs = ["test_provider_restart_max_subscribers.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/partial_restart/proxy_restart_shall_not_affect_other_proxies/integration_test/BUILD b/score/mw/com/test/partial_restart/proxy_restart_shall_not_affect_other_proxies/integration_test/BUILD index c6ffbd5d..b10754fe 100644 --- a/score/mw/com/test/partial_restart/proxy_restart_shall_not_affect_other_proxies/integration_test/BUILD +++ b/score/mw/com/test/partial_restart/proxy_restart_shall_not_affect_other_proxies/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "proxy_restart_shall_not_affect_other_proxies", - size = "small", + timeout = "moderate", srcs = ["test_proxy_restart_shall_not_affect_other_proxies.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/receive_handler_unsubscribe/integration_test/BUILD b/score/mw/com/test/receive_handler_unsubscribe/integration_test/BUILD index 4971f49a..4ab8f618 100644 --- a/score/mw/com/test/receive_handler_unsubscribe/integration_test/BUILD +++ b/score/mw/com/test/receive_handler_unsubscribe/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "receive_handler_unsubscribe", - size = "small", + timeout = "moderate", srcs = ["test_receive_handler_unsubscribe.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/receive_handler_usage/integration_test/BUILD b/score/mw/com/test/receive_handler_usage/integration_test/BUILD index 08aa76ce..63e16731 100644 --- a/score/mw/com/test/receive_handler_usage/integration_test/BUILD +++ b/score/mw/com/test/receive_handler_usage/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "test_receive_handler_usage", - size = "small", + timeout = "moderate", srcs = ["test_receive_handler_usage.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/reserving_skeleton_slots/integration_test/BUILD b/score/mw/com/test/reserving_skeleton_slots/integration_test/BUILD index e37c3b77..2fd5adfe 100644 --- a/score/mw/com/test/reserving_skeleton_slots/integration_test/BUILD +++ b/score/mw/com/test/reserving_skeleton_slots/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "reserving_skeleton_slots", - size = "small", + timeout = "moderate", srcs = ["test_reserving_skeleton_slots.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/separate_reception_threads/integration_test/BUILD b/score/mw/com/test/separate_reception_threads/integration_test/BUILD index 2a8ab28f..b156c969 100644 --- a/score/mw/com/test/separate_reception_threads/integration_test/BUILD +++ b/score/mw/com/test/separate_reception_threads/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "separate_reception_threads", - size = "small", + timeout = "moderate", srcs = ["test_separate_reception_threads.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/service_discovery_during_consumer_crash/integration_test/BUILD b/score/mw/com/test/service_discovery_during_consumer_crash/integration_test/BUILD index 50b07244..8a7a374e 100644 --- a/score/mw/com/test/service_discovery_during_consumer_crash/integration_test/BUILD +++ b/score/mw/com/test/service_discovery_during_consumer_crash/integration_test/BUILD @@ -20,7 +20,7 @@ load("//quality/integration_testing:integration_testing.bzl", "integration_test" integration_test( name = "service_discovery_during_consumer_crash", - size = "small", + timeout = "moderate", srcs = ["test_service_discovery_during_consumer_crash.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/service_discovery_during_provider_crash/integration_test/BUILD b/score/mw/com/test/service_discovery_during_provider_crash/integration_test/BUILD index f1bb718b..139122fa 100644 --- a/score/mw/com/test/service_discovery_during_provider_crash/integration_test/BUILD +++ b/score/mw/com/test/service_discovery_during_provider_crash/integration_test/BUILD @@ -20,7 +20,7 @@ load("//quality/integration_testing:integration_testing.bzl", "integration_test" integration_test( name = "service_discovery_during_provider_crash", - size = "small", + timeout = "moderate", srcs = ["test_service_discovery_during_provider_crash.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/service_discovery_offer_and_search/integration_test/BUILD b/score/mw/com/test/service_discovery_offer_and_search/integration_test/BUILD index a83581df..a3e7c985 100644 --- a/score/mw/com/test/service_discovery_offer_and_search/integration_test/BUILD +++ b/score/mw/com/test/service_discovery_offer_and_search/integration_test/BUILD @@ -24,7 +24,7 @@ pkg_tar( integration_test( name = "test_service_discovery_offer_and_search", - size = "small", + timeout = "moderate", srcs = ["test_service_discovery_offer_and_search.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/service_discovery_search_and_offer/integration_test/BUILD b/score/mw/com/test/service_discovery_search_and_offer/integration_test/BUILD index dea57714..9639c7f1 100644 --- a/score/mw/com/test/service_discovery_search_and_offer/integration_test/BUILD +++ b/score/mw/com/test/service_discovery_search_and_offer/integration_test/BUILD @@ -24,7 +24,7 @@ pkg_tar( integration_test( name = "test_service_discovery_search_and_offer", - size = "small", + timeout = "moderate", srcs = ["test_service_discovery_search_and_offer.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/shared_memory_storage/integration_test/BUILD b/score/mw/com/test/shared_memory_storage/integration_test/BUILD index 9cc8aad3..9098f00e 100644 --- a/score/mw/com/test/shared_memory_storage/integration_test/BUILD +++ b/score/mw/com/test/shared_memory_storage/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "shared_memory_storage", - size = "small", + timeout = "moderate", srcs = ["test_shared_memory_storage.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/subscribe_handler/integration_test/BUILD b/score/mw/com/test/subscribe_handler/integration_test/BUILD index 2690bcf1..81deae37 100644 --- a/score/mw/com/test/subscribe_handler/integration_test/BUILD +++ b/score/mw/com/test/subscribe_handler/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "subscribe_handler", - size = "small", + timeout = "moderate", srcs = ["test_subscribe_handler.py"], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/unsubscribe_deadlock/integration_test/BUILD b/score/mw/com/test/unsubscribe_deadlock/integration_test/BUILD index 858954e5..b32ae443 100644 --- a/score/mw/com/test/unsubscribe_deadlock/integration_test/BUILD +++ b/score/mw/com/test/unsubscribe_deadlock/integration_test/BUILD @@ -23,7 +23,7 @@ pkg_tar( integration_test( name = "unsubscribe_deadlock", - size = "small", + timeout = "moderate", srcs = ["test_unsubscribe_deadlock.py"], filesystem = ":filesystem", ) From 91a6479f2adaa9e4ddd48f5ac54ee929047b9ade Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Fri, 20 Feb 2026 13:42:00 +0100 Subject: [PATCH 15/21] Do not duplicate logs in integration tests --- quality/integration_testing/BUILD | 2 +- .../integration_testing/integration_testing.bzl | 17 +++++++++++++++-- quality/integration_testing/main.py | 13 ++++++------- quality/integration_testing/pytest.toml | 16 ++++++++++++++++ quality/integration_testing/requirements.txt | 1 + requirements_lock.txt | 3 +++ 6 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 quality/integration_testing/pytest.toml diff --git a/quality/integration_testing/BUILD b/quality/integration_testing/BUILD index c0c8220b..ec02daea 100644 --- a/quality/integration_testing/BUILD +++ b/quality/integration_testing/BUILD @@ -13,7 +13,7 @@ # This is not a `py_library`, since we need it as "main" in a `py_test` exports_files( - ["main.py"], + ["main.py", "pytest.toml"], ) filegroup( diff --git a/quality/integration_testing/integration_testing.bzl b/quality/integration_testing/integration_testing.bzl index c4f39aef..c4692699 100644 --- a/quality/integration_testing/integration_testing.bzl +++ b/quality/integration_testing/integration_testing.bzl @@ -23,6 +23,7 @@ def _extend_list_in_kwargs(kwargs, key, values): def integration_test(name, srcs, filesystem, **kwargs): pytest_bootstrap = Label("//quality/integration_testing:main.py") + pytest_toml = Label("//quality/integration_testing:pytest.toml") image_name = "_image_{}".format(name) image_tarball = "_image_{}_tarball".format(name) repo_tag = "{}:latest".format(name) @@ -114,6 +115,18 @@ def integration_test(name, srcs, filesystem, **kwargs): if "timeout" not in kwargs: kwargs["timeout"] = "short" + _extend_list_in_kwargs( + kwargs, + "data", + [pytest_toml], + ) + + _extend_list_in_kwargs( + kwargs, + "target_compatible_with", + LINUX_TARGET_COMPATIBLE_WITH, + ) + py_test( name = "_test_internal_docker_{}".format(name), srcs = [ @@ -121,10 +134,10 @@ def integration_test(name, srcs, filesystem, **kwargs): ] + srcs, main = pytest_bootstrap, deps = [ + requirement("bazel-runfiles"), requirement("pytest"), "//quality/integration_testing/environments/ubuntu24_04_docker:docker", ], - target_compatible_with = LINUX_TARGET_COMPATIBLE_WITH, tags = ["manual"], **kwargs ) @@ -136,10 +149,10 @@ def integration_test(name, srcs, filesystem, **kwargs): ] + srcs, main = pytest_bootstrap, deps = [ + requirement("bazel-runfiles"), requirement("pytest"), "//quality/integration_testing/environments/qnx8_qemu:qemu", ], - target_compatible_with = LINUX_TARGET_COMPATIBLE_WITH, tags = ["manual"], **kwargs ) diff --git a/quality/integration_testing/main.py b/quality/integration_testing/main.py index 39f1f6f9..34a44716 100644 --- a/quality/integration_testing/main.py +++ b/quality/integration_testing/main.py @@ -14,15 +14,9 @@ import sys import pytest import logging +from runfiles import Runfiles logger = logging.getLogger(__name__) -logging.basicConfig( - level=logging.DEBUG, # Capture all levels DEBUG and above - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - handlers=[ - logging.StreamHandler() # Also log to console - ] -) def get_output_dir(): @@ -59,4 +53,9 @@ def get_output_dir(): # This is the common main function, that is used by _all_ integration tests. args = sys.argv[1:] args += [f"--junitxml={os.path.join(get_output_dir(), 'integration-testing-results.xml')}"] + + r = Runfiles.Create() + ini_path = r.Rlocation("_main/quality/integration_testing/pytest.toml") + args += ["-c", ini_path] + sys.exit(pytest.main(args)) diff --git a/quality/integration_testing/pytest.toml b/quality/integration_testing/pytest.toml new file mode 100644 index 00000000..6c4d70df --- /dev/null +++ b/quality/integration_testing/pytest.toml @@ -0,0 +1,16 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +[pytest] + +log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" diff --git a/quality/integration_testing/requirements.txt b/quality/integration_testing/requirements.txt index fa492d30..a10fbcc3 100644 --- a/quality/integration_testing/requirements.txt +++ b/quality/integration_testing/requirements.txt @@ -10,5 +10,6 @@ # # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +bazel-runfiles==1.8.4 docker==7.1.0 pytest==8.4.1 diff --git a/requirements_lock.txt b/requirements_lock.txt index 9ab11092..b89fafbd 100644 --- a/requirements_lock.txt +++ b/requirements_lock.txt @@ -18,6 +18,9 @@ babel==2.18.0 \ # via # pydata-sphinx-theme # sphinx +bazel-runfiles==1.8.4 \ + --hash=sha256:2c9c91d9f20f89642f00d533525f179586f8892af8aa451d71265824a6569582 + # via -r ./quality/integration_testing/requirements.txt beautifulsoup4==4.14.3 \ --hash=sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb \ --hash=sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86 From 3bd2d18ff98130da4367007d028abc24c79cfe22 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Fri, 20 Feb 2026 18:11:17 +0100 Subject: [PATCH 16/21] Suppress findings of thread sanitizer Some findings of the thread sanitizer are not easy to fix. For these findings tickets were created and the test was disabled. --- score/mw/com/impl/plumbing/rust/BUILD | 4 ++++ .../partial_restart/consumer_restart/integration_test/BUILD | 2 ++ .../partial_restart/provider_restart/integration_test/BUILD | 2 ++ .../provider_restart_max_subscribers/integration_test/BUILD | 2 ++ .../integration_test/BUILD | 2 ++ 5 files changed, 12 insertions(+) diff --git a/score/mw/com/impl/plumbing/rust/BUILD b/score/mw/com/impl/plumbing/rust/BUILD index dac06876..e10b79ce 100644 --- a/score/mw/com/impl/plumbing/rust/BUILD +++ b/score/mw/com/impl/plumbing/rust/BUILD @@ -51,6 +51,8 @@ rust_test( "//score/mw/com/impl/plumbing/rust/test_support:test_helper_size_ffi_rs", "//score/mw/com/impl/plumbing/rust/test_support:test_utils_rs", ], + # Disabled for thread sanitizer because of detected race (Ticket-246891) + target_compatible_with = ["//quality/sanitizer/constraints:no_tsan"], ) rust_test( @@ -63,4 +65,6 @@ rust_test( "//score/mw/com/impl/plumbing/rust/test_support:test_utils_rs", "@crate_index//:libc", ], + # Disabled for thread sanitizer because of detected race (Ticket-246891) + target_compatible_with = ["//quality/sanitizer/constraints:no_tsan"], ) diff --git a/score/mw/com/test/partial_restart/consumer_restart/integration_test/BUILD b/score/mw/com/test/partial_restart/consumer_restart/integration_test/BUILD index 8e2f9ed5..93af8fba 100644 --- a/score/mw/com/test/partial_restart/consumer_restart/integration_test/BUILD +++ b/score/mw/com/test/partial_restart/consumer_restart/integration_test/BUILD @@ -26,4 +26,6 @@ integration_test( timeout = "moderate", srcs = ["test_consumer_restart.py"], filesystem = ":filesystem", + # Disabled for thread sanitizer because of detected race (Ticket-246892) + target_compatible_with = ["//quality/sanitizer/constraints:no_tsan"], ) diff --git a/score/mw/com/test/partial_restart/provider_restart/integration_test/BUILD b/score/mw/com/test/partial_restart/provider_restart/integration_test/BUILD index bb9bc7d2..67f4638e 100644 --- a/score/mw/com/test/partial_restart/provider_restart/integration_test/BUILD +++ b/score/mw/com/test/partial_restart/provider_restart/integration_test/BUILD @@ -25,4 +25,6 @@ integration_test( name = "provider_restart", srcs = ["test_provider_restart.py"], filesystem = ":filesystem", + # Disabled for thread sanitizer because of detected race (Ticket-246892) + target_compatible_with = ["//quality/sanitizer/constraints:no_tsan"], ) diff --git a/score/mw/com/test/partial_restart/provider_restart_max_subscribers/integration_test/BUILD b/score/mw/com/test/partial_restart/provider_restart_max_subscribers/integration_test/BUILD index 97ac9add..912d4a10 100644 --- a/score/mw/com/test/partial_restart/provider_restart_max_subscribers/integration_test/BUILD +++ b/score/mw/com/test/partial_restart/provider_restart_max_subscribers/integration_test/BUILD @@ -26,4 +26,6 @@ integration_test( timeout = "moderate", srcs = ["test_provider_restart_max_subscribers.py"], filesystem = ":filesystem", + # Disabled for thread sanitizer because of detected race (Ticket-246892) + target_compatible_with = ["//quality/sanitizer/constraints:no_tsan"], ) diff --git a/score/mw/com/test/service_discovery_during_consumer_crash/integration_test/BUILD b/score/mw/com/test/service_discovery_during_consumer_crash/integration_test/BUILD index 8a7a374e..a1171d5a 100644 --- a/score/mw/com/test/service_discovery_during_consumer_crash/integration_test/BUILD +++ b/score/mw/com/test/service_discovery_during_consumer_crash/integration_test/BUILD @@ -23,6 +23,8 @@ integration_test( timeout = "moderate", srcs = ["test_service_discovery_during_consumer_crash.py"], filesystem = ":filesystem", + # Disabled for thread sanitizer because of detected race (Ticket-246892) + target_compatible_with = ["//quality/sanitizer/constraints:no_tsan"], ) pkg_tar( From 69bf111fa8f8865c6ddaa3b848d6b73fb588a878 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Tue, 3 Feb 2026 18:22:09 +0100 Subject: [PATCH 17/21] Fix ABI test for LLVM LLVM toolchain uses the builtin libc++ to remain hermetic. This implementation of the standard library does not support fancy pointers (like offset pointers) in std::basic_string. This is required for shared memory allocators though. The correct solution would be to provide a sysroot to the LLVM toolchain that contains libstdc++. Because of the amount of effort to achieve this we take the shortcut for the moment and deactivate the problematic code. --- .../our/name_space/impl_type_somestruct.h | 14 +++++++------- score/mw/com/test/api/generated_api_test.cpp | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/score/mw/com/test/api/api_under_test/our/name_space/impl_type_somestruct.h b/score/mw/com/test/api/api_under_test/our/name_space/impl_type_somestruct.h index a1276056..789d781c 100644 --- a/score/mw/com/test/api/api_under_test/our/name_space/impl_type_somestruct.h +++ b/score/mw/com/test/api/api_under_test/our/name_space/impl_type_somestruct.h @@ -41,7 +41,7 @@ struct SomeStruct const std::uint16_t& bar_param, const ::our::name_space::SomeArray& access_array_param, const ::our::name_space::MultiDimArray& multi_dim_array_param, -#ifndef __QNX__ +#if !defined(__QNX__) && !defined(__clang__) ::score::memory::shared::String const& access_string_param, #endif ::our::name_space::SomeVector const& access_vector_param, @@ -53,7 +53,7 @@ struct SomeStruct bar{bar_param}, access_array{access_array_param}, multi_dim_array{multi_dim_array_param}, -#ifndef __QNX__ +#if !defined(__QNX__) && !defined(__clang__) access_string{access_string_param}, #endif access_vector{access_vector_param, allocator}, @@ -68,7 +68,7 @@ struct SomeStruct bar{other.bar}, access_array{other.access_array}, multi_dim_array{other.multi_dim_array}, -#ifndef __QNX__ +#if !defined(__QNX__) && !defined(__clang__) access_string{other.access_string}, #endif access_vector{other.access_vector, allocator}, @@ -83,7 +83,7 @@ struct SomeStruct bar{std::move(other.bar)}, access_array{std::move(other.access_array)}, multi_dim_array{std::move(other.multi_dim_array)}, -#ifndef __QNX__ +#if !defined(__QNX__) && !defined(__clang__) access_string{std::move(other.access_string)}, #endif access_vector{std::move(other.access_vector), allocator}, @@ -97,7 +97,7 @@ struct SomeStruct std::uint16_t bar; ::our::name_space::SomeArray access_array; ::our::name_space::MultiDimArray multi_dim_array; -#ifndef __QNX__ +#if !defined(__QNX__) && !defined(__clang__) ::score::memory::shared::String access_string; #endif ::our::name_space::SomeVector access_vector; @@ -113,7 +113,7 @@ struct SomeStruct fun(bar); fun(access_array); fun(multi_dim_array); -#ifndef __QNX__ +#if !defined(__QNX__) && !defined(__clang__) fun(access_string); #endif fun(access_vector); @@ -129,7 +129,7 @@ struct SomeStruct fun.template Visit(); fun.template Visit(); fun.template Visit(); -#ifndef __QNX__ +#if !defined(__QNX__) && !defined(__clang__) fun.template Visit(); #endif fun.template Visit(); diff --git a/score/mw/com/test/api/generated_api_test.cpp b/score/mw/com/test/api/generated_api_test.cpp index adf7c94e..4157b88a 100644 --- a/score/mw/com/test/api/generated_api_test.cpp +++ b/score/mw/com/test/api/generated_api_test.cpp @@ -168,7 +168,7 @@ TEST(API, ArrayDeclarationWithMultiDimArray) "Wrong underlying type"); } -#ifndef __QNX__ +#if !defined(__QNX__) && !defined(__clang__) // TODO String type not supported due to a bug in the LLVM STL for QNX: [Ticket-54614] TEST(API, StringIsSupported) { From 9f7bf94dc2da9f62208b62fcc0a5fcc1269e9bc9 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Tue, 17 Feb 2026 15:19:47 +0100 Subject: [PATCH 18/21] Fix flakiness of integration tests (1/2) Many of the integration tests had race conditions. Most expected that the service is there once the client searches for it. But there was no synchronization between the skeleton offer being made available and the client doing a one-time FindService call. Switches to StartFindService to effectively synchronize the service discovery. --- ...values_created_from_config_application.cpp | 61 ++++++++++++++----- .../com/test/field_initial_value/client.cpp | 13 +++- .../receive_handler_usage_application.cpp | 16 ++++- .../client.cpp | 2 +- .../client.cpp | 2 +- score/mw/com/test/smokeyeyes/smokeyeyes.cpp | 13 +++- .../unsubscribe_deadlock_application.cpp | 16 ++++- 7 files changed, 95 insertions(+), 28 deletions(-) diff --git a/score/mw/com/test/check_values_created_from_config/check_values_created_from_config_application.cpp b/score/mw/com/test/check_values_created_from_config/check_values_created_from_config_application.cpp index b2913e8c..dff5f02c 100644 --- a/score/mw/com/test/check_values_created_from_config/check_values_created_from_config_application.cpp +++ b/score/mw/com/test/check_values_created_from_config/check_values_created_from_config_application.cpp @@ -127,7 +127,8 @@ class ConfigParser score::mw::com::impl::ServiceTypeDeployment type_deployment_{score::cpp::blank{}}; }; -const std::string kInterprocessNotificationShmPath{"/lock"}; +const std::string kInterprocessNotificationFromSkeletonToProxyShmPath{"/lock_skeleton_to_proxy"}; +const std::string kInterprocessNotificationFromProxyToSkeletonShmPath{"/lock_proxy_to_skeleton"}; } // namespace @@ -198,48 +199,78 @@ int main(int argc, const char** argv) if (mode == "send" || mode == "skeleton") { std::cout << "Creating interprocess notification ..."; - auto interprocess_notification_result = - score::mw::com::test::SharedMemoryObjectCreator::CreateObject( - kInterprocessNotificationShmPath); - if (!interprocess_notification_result.has_value()) + auto interprocess_notification_proxy_to_skeleton_result = + score::mw::com::test::SharedMemoryObjectCreator::CreateOrOpenObject( + kInterprocessNotificationFromProxyToSkeletonShmPath); + if (!interprocess_notification_proxy_to_skeleton_result.has_value()) { std::stringstream ss; ss << "Creating interprocess notification object on skeleton side failed:" - << interprocess_notification_result.error().ToString(); + << interprocess_notification_proxy_to_skeleton_result.error().ToString(); std::cout << ss.str() << std::endl; return EXIT_FAILURE; } + const score::mw::com::test::SharedMemoryObjectGuard + interprocess_notification_proxy_to_skeleton_guard{interprocess_notification_proxy_to_skeleton_result.value()}; + auto interprocess_notification_skeleton_to_proxy_result = + score::mw::com::test::SharedMemoryObjectCreator::CreateOrOpenObject( + kInterprocessNotificationFromSkeletonToProxyShmPath); + if (!interprocess_notification_skeleton_to_proxy_result.has_value()) + { + std::stringstream ss; + ss << "Creating interprocess notification object on skeleton side failed:" + << interprocess_notification_skeleton_to_proxy_result.error().ToString(); + std::cout << ss.str() << std::endl; + return EXIT_FAILURE; + } const score::mw::com::test::SharedMemoryObjectGuard - interprocess_notification_guard{interprocess_notification_result.value()}; + interprocess_notification_skeleton_to_proxy_guard{interprocess_notification_skeleton_to_proxy_result.value()}; + return event_sender_receiver.RunAsSkeletonCheckValuesCreatedFromConfig( instance_specifier, shared_memory_path.value(), - interprocess_notification_result.value().GetObject(), + interprocess_notification_proxy_to_skeleton_result.value().GetObject(), + interprocess_notification_skeleton_to_proxy_result.value().GetObject(), stop_source); } else if (mode == "recv" || mode == "proxy") { - auto interprocess_notification_result = + auto interprocess_notification_proxy_to_skeleton_result = score::mw::com::test::SharedMemoryObjectCreator::CreateOrOpenObject( - kInterprocessNotificationShmPath); - if (!interprocess_notification_result.has_value()) + kInterprocessNotificationFromProxyToSkeletonShmPath); + if (!interprocess_notification_proxy_to_skeleton_result.has_value()) { std::stringstream ss; - ss << "Creating or opening interprocess notification object on proxy side failed:" - << interprocess_notification_result.error().ToString(); + ss << "Creating interprocess notification object on proxy side failed:" + << interprocess_notification_proxy_to_skeleton_result.error().ToString(); std::cout << ss.str() << std::endl; return EXIT_FAILURE; } + const score::mw::com::test::SharedMemoryObjectGuard + interprocess_notification_proxy_to_skeleton_guard{interprocess_notification_proxy_to_skeleton_result.value()}; + auto interprocess_notification_skeleton_to_proxy_result = + score::mw::com::test::SharedMemoryObjectCreator::CreateOrOpenObject( + kInterprocessNotificationFromSkeletonToProxyShmPath); + if (!interprocess_notification_skeleton_to_proxy_result.has_value()) + { + std::stringstream ss; + ss << "Creating interprocess notification object on proxy side failed:" + << interprocess_notification_skeleton_to_proxy_result.error().ToString(); + std::cout << ss.str() << std::endl; + return EXIT_FAILURE; + } const score::mw::com::test::SharedMemoryObjectGuard - interprocess_notification_guard{interprocess_notification_result.value()}; + interprocess_notification_skeleton_to_proxy_guard{interprocess_notification_skeleton_to_proxy_result.value()}; + return event_sender_receiver.RunAsProxyCheckValuesCreatedFromConfig( instance_specifier, map_api_lanes_element_fq_id.value(), dummy_element_fq_id.value(), shared_memory_name.value(), - interprocess_notification_result.value().GetObject(), + interprocess_notification_skeleton_to_proxy_result.value().GetObject(), + interprocess_notification_proxy_to_skeleton_result.value().GetObject(), stop_token); } else diff --git a/score/mw/com/test/field_initial_value/client.cpp b/score/mw/com/test/field_initial_value/client.cpp index 2dc281b5..25bca2f5 100644 --- a/score/mw/com/test/field_initial_value/client.cpp +++ b/score/mw/com/test/field_initial_value/client.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -42,14 +43,22 @@ int run_client(const std::size_t num_retries, const std::chrono::milliseconds re } auto instance_specifier = std::move(instance_specifier_result).value(); - auto lola_proxy_handles_result = TestDataProxy::FindService(std::move(instance_specifier)); + std::promise> service_discovery_promise{}; + auto service_discovery_future = service_discovery_promise.get_future(); + auto lola_proxy_handles_result = TestDataProxy::StartFindService( + [moved_service_discovery_promise = std::move(service_discovery_promise)](auto handles, auto handle) mutable { + moved_service_discovery_promise.set_value(handles); + TestDataProxy::StopFindService(handle); + }, + std::move(instance_specifier)); + if (!lola_proxy_handles_result.has_value()) { std::cerr << "Unable to get handles, terminating\n"; return -1; } - auto lola_proxy_handles = lola_proxy_handles_result.value(); + auto lola_proxy_handles = service_discovery_future.get(); if (lola_proxy_handles.empty()) { std::cerr << "Unable to find lola service, terminating\n"; diff --git a/score/mw/com/test/receive_handler_usage/receive_handler_usage_application.cpp b/score/mw/com/test/receive_handler_usage/receive_handler_usage_application.cpp index 75144c9a..652bf93f 100644 --- a/score/mw/com/test/receive_handler_usage/receive_handler_usage_application.cpp +++ b/score/mw/com/test/receive_handler_usage/receive_handler_usage_application.cpp @@ -22,8 +22,10 @@ #include #include + #include #include +#include #include namespace @@ -66,7 +68,14 @@ score::Result CreateAndOfferSkeleton( score::Result CreateProxy(const score::mw::com::InstanceSpecifier& instance_specifier) { - auto handles_result = score::mw::com::test::BigDataProxy::FindService(instance_specifier); + std::promise> service_discovery_promise{}; + auto service_discovery_future = service_discovery_promise.get_future(); + auto handles_result = score::mw::com::test::BigDataProxy::StartFindService( + [moved_service_discovery_promise = std::move(service_discovery_promise)](auto handles, auto handle) mutable { + moved_service_discovery_promise.set_value(handles); + score::mw::com::test::BigDataProxy::StopFindService(handle); + }, + std::move(instance_specifier)); if (!handles_result.has_value()) { std::cerr << "Error finding service for instance specifier" << instance_specifier.ToString() << ": " @@ -74,7 +83,8 @@ score::Result CreateProxy(const score::mw::c return score::MakeUnexpected(handles_result.error()); } - if (handles_result.value().empty()) + const auto handles = service_discovery_future.get(); + if (handles.empty()) { std::cerr << "NO instance found for instance specifier" << instance_specifier.ToString() << " although service instance has been successfully offered! Terminating!" << std::endl; @@ -82,7 +92,7 @@ score::Result CreateProxy(const score::mw::c score::mw::com::impl::MakeError(score::mw::com::impl::ComErrc::kServiceNotAvailable)); } - return score::mw::com::test::BigDataProxy::Create(handles_result.value().front()); + return score::mw::com::test::BigDataProxy::Create(handles.front()); } bool ReceiveHandlerActions(score::mw::com::test::BigDataProxy& proxy) diff --git a/score/mw/com/test/service_discovery_offer_and_search/client.cpp b/score/mw/com/test/service_discovery_offer_and_search/client.cpp index e3b53e52..4fa06e46 100644 --- a/score/mw/com/test/service_discovery_offer_and_search/client.cpp +++ b/score/mw/com/test/service_discovery_offer_and_search/client.cpp @@ -40,7 +40,7 @@ int run_client(const score::cpp::stop_token& stop_token) sync_coordinator.Wait(stop_token); ProxyObserver proxy_observer(kInstanceSpecifierStringClient); - const auto find_service_handle_result = proxy_observer.StartServiceDiscovery(kNumberOfOfferedServices, stop_token); + const auto find_service_handle_result = proxy_observer.StartServiceDiscovery(kNumberOfOfferedServices); if (!find_service_handle_result.has_value()) { std::cerr << "unable to start service discovery" << find_service_handle_result.error().Message() << std::endl; diff --git a/score/mw/com/test/service_discovery_search_and_offer/client.cpp b/score/mw/com/test/service_discovery_search_and_offer/client.cpp index 816ccacf..30f718a1 100644 --- a/score/mw/com/test/service_discovery_search_and_offer/client.cpp +++ b/score/mw/com/test/service_discovery_search_and_offer/client.cpp @@ -38,7 +38,7 @@ int run_client(const score::cpp::stop_token& stop_token) using score::mw::com::test::TestDataProxy; ProxyObserver proxy_observer(kInstanceSpecifierString); - const auto find_service_handle_result = proxy_observer.StartServiceDiscovery(kNumberOfOfferedServices, stop_token); + const auto find_service_handle_result = proxy_observer.StartServiceDiscovery(kNumberOfOfferedServices); if (!find_service_handle_result.has_value()) { std::cerr << "unable to start service discovery" << find_service_handle_result.error().Message() << std::endl; diff --git a/score/mw/com/test/smokeyeyes/smokeyeyes.cpp b/score/mw/com/test/smokeyeyes/smokeyeyes.cpp index fc56ba4f..150751d7 100644 --- a/score/mw/com/test/smokeyeyes/smokeyeyes.cpp +++ b/score/mw/com/test/smokeyeyes/smokeyeyes.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -237,14 +238,20 @@ int run_receiver(SharedState& shared_state, return -4; } - Result> handles_result = - DataProxy::FindService(std::move(instance_specifier_result).value()); + std::promise> service_discovery_promise{}; + auto service_discovery_future = service_discovery_promise.get_future(); + auto handles_result = DataProxy::StartFindService( + [moved_service_discovery_promise = std::move(service_discovery_promise)](auto handles, auto handle) mutable { + moved_service_discovery_promise.set_value(handles); + DataProxy::StopFindService(handle); + }, + std::move(instance_specifier_result).value()); if (!handles_result.has_value()) { std::cerr << "FindService returned an error, terminating!\n"; return -4; } - handles = std::move(handles_result.value()); + handles = std::move(service_discovery_future.get()); if (handles.empty()) { // If we didn't find a service yet (because the sender is still busy spawning clients), we back off diff --git a/score/mw/com/test/unsubscribe_deadlock/unsubscribe_deadlock_application.cpp b/score/mw/com/test/unsubscribe_deadlock/unsubscribe_deadlock_application.cpp index 78b67444..8d09c79e 100644 --- a/score/mw/com/test/unsubscribe_deadlock/unsubscribe_deadlock_application.cpp +++ b/score/mw/com/test/unsubscribe_deadlock/unsubscribe_deadlock_application.cpp @@ -22,8 +22,10 @@ #include #include + #include #include +#include #include #include @@ -54,7 +56,14 @@ void CreateAndOfferSkeleton(const score::mw::com::InstanceSpecifier& instance_sp score::Result CreateProxy(const score::mw::com::InstanceSpecifier& instance_specifier) { - auto handles_result = score::mw::com::test::BigDataProxy::FindService(instance_specifier); + std::promise> service_discovery_promise{}; + auto service_discovery_future = service_discovery_promise.get_future(); + auto handles_result = score::mw::com::test::BigDataProxy::StartFindService( + [moved_service_discovery_promise = std::move(service_discovery_promise)](auto handles, auto handle) mutable { + moved_service_discovery_promise.set_value(handles); + score::mw::com::test::BigDataProxy::StopFindService(handle); + }, + std::move(instance_specifier)); if (!handles_result.has_value()) { std::cerr << "Error finding service for instance specifier" << instance_specifier.ToString() << ": " @@ -62,7 +71,8 @@ score::Result CreateProxy(const score::mw::c return score::MakeUnexpected(handles_result.error()); } - if (handles_result.value().empty()) + const auto handles = service_discovery_future.get(); + if (handles.empty()) { std::cerr << "NO instance found for instance specifier" << instance_specifier.ToString() << " although service instance has been successfully offered! Terminating!" << std::endl; @@ -70,7 +80,7 @@ score::Result CreateProxy(const score::mw::c score::mw::com::impl::MakeError(score::mw::com::impl::ComErrc::kServiceNotAvailable)); } - return score::mw::com::test::BigDataProxy::Create(handles_result.value().front()); + return score::mw::com::test::BigDataProxy::Create(handles.front()); } /** From 4323e9741127e897c82a455a81bc0b4f61ab2e22 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Tue, 17 Feb 2026 15:21:16 +0100 Subject: [PATCH 19/21] Fix flakiness of integration tests (2/2) StartFindService does not provide incremental updates of new service offers. Instead, it gives the full list of existing service offers at that current moment. User applications must filter out the diff on their own. Uses an unordered_map to correctly filter for individual service offers. --- .../common_test_resources/proxy_observer.h | 14 +++++++------- .../sample_sender_receiver.cpp | 19 +++++++++++++++---- .../sample_sender_receiver.h | 6 ++++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/score/mw/com/test/common_test_resources/proxy_observer.h b/score/mw/com/test/common_test_resources/proxy_observer.h index 394ee8f9..2edd38fe 100644 --- a/score/mw/com/test/common_test_resources/proxy_observer.h +++ b/score/mw/com/test/common_test_resources/proxy_observer.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include namespace score::mw::com::test { @@ -50,10 +50,10 @@ class ProxyObserver } } - Result StartServiceDiscovery(std::size_t required_number_of_services, - const score::cpp::stop_token& stop_token) noexcept + Result StartServiceDiscovery(std::size_t required_number_of_services) noexcept { - auto callback = [this, required_number_of_services, &stop_token](auto service_handle_container, auto) noexcept { + auto callback = [this, required_number_of_services](auto service_handle_container, + auto find_service_handle) noexcept { std::cout << "handler called" << std::endl; for (auto& handle : service_handle_container) { @@ -61,7 +61,7 @@ class ProxyObserver if (lola_proxy_result.has_value()) { std::cout << "successfully created lola proxy" << std::endl; - proxies_.push_back(std::move(lola_proxy_result.value())); + proxies_.insert({handle, std::move(lola_proxy_result.value())}); } else { @@ -72,8 +72,8 @@ class ProxyObserver { std::cout << "Requested number of proxies created" << std::endl; promise_.SetValue(); + Proxy::StopFindService(find_service_handle); } - stop_token.stop_requested(); }; handle_ = Proxy::StartFindService(callback, instance_specifier_result_.value()); @@ -95,7 +95,7 @@ class ProxyObserver private: score::Result instance_specifier_result_; - std::vector proxies_{}; + std::unordered_map proxies_{}; concurrency::InterruptiblePromise promise_{}; // handle has deleted default constructor Result handle_ = MakeUnexpected(score::mw::com::impl::ComErrc::kUnsetFailure); diff --git a/score/mw/com/test/common_test_resources/sample_sender_receiver.cpp b/score/mw/com/test/common_test_resources/sample_sender_receiver.cpp index d993f512..b90681ac 100644 --- a/score/mw/com/test/common_test_resources/sample_sender_receiver.cpp +++ b/score/mw/com/test/common_test_resources/sample_sender_receiver.cpp @@ -736,7 +736,8 @@ int EventSenderReceiver::RunAsSkeletonCheckEventSlots(const score::mw::com::Inst int EventSenderReceiver::RunAsSkeletonCheckValuesCreatedFromConfig( const score::mw::com::InstanceSpecifier& instance_specifier, const std::string& shared_memory_path, - score::os::InterprocessNotification& interprocess_notification, + score::os::InterprocessNotification& interprocess_notification_from_proxy, + score::os::InterprocessNotification& interprocess_notification_to_proxy, score::cpp::stop_source stop_source) { TestDestructor test_destructor(stop_source); @@ -770,8 +771,10 @@ int EventSenderReceiver::RunAsSkeletonCheckValuesCreatedFromConfig( return EXIT_FAILURE; } + interprocess_notification_to_proxy.notify(); + // Wait until proxy has finished before exiting. - if (!interprocess_notification.waitWithAbort(stop_token)) + if (!interprocess_notification_from_proxy.waitWithAbort(stop_token)) { // Abort happened std::cerr << "Request stop on stop token. Exiting.\n"; @@ -790,7 +793,8 @@ int EventSenderReceiver::RunAsProxyCheckValuesCreatedFromConfig( const score::mw::com::impl::lola::ElementFqId map_api_lanes_element_fq_id_from_config, const score::mw::com::impl::lola::ElementFqId dummy_data_element_fq_id_from_config, const std::string& shared_memory_path, - score::os::InterprocessNotification& interprocess_notification, + score::os::InterprocessNotification& interprocess_notification_from_skeleton, + score::os::InterprocessNotification& interprocess_notification_to_skeleton, score::cpp::stop_token stop_token) { // create special mmap mock to intercept/catch shm_open calls @@ -798,6 +802,13 @@ int EventSenderReceiver::RunAsProxyCheckValuesCreatedFromConfig( // activate our mock BEFORE instantiating BigDataProxy, which will lead to opening/mapping shm. os::Mman::set_testing_instance(mman_mock); + if (!interprocess_notification_from_skeleton.waitWithAbort(stop_token)) + { + // Abort happened + std::cerr << "Request stop on stop token. Exiting.\n"; + return EXIT_FAILURE; + } + auto handle_result = GetHandleFromSpecifier(instance_specifier, stop_token); if (!handle_result.has_value()) { @@ -852,7 +863,7 @@ int EventSenderReceiver::RunAsProxyCheckValuesCreatedFromConfig( std::cout << "and terminating, bye bye\n"; // Tell the skeleton that the proxy has finished. - interprocess_notification.notify(); + interprocess_notification_to_skeleton.notify(); return EXIT_SUCCESS; } diff --git a/score/mw/com/test/common_test_resources/sample_sender_receiver.h b/score/mw/com/test/common_test_resources/sample_sender_receiver.h index 385cdfbf..00f07701 100644 --- a/score/mw/com/test/common_test_resources/sample_sender_receiver.h +++ b/score/mw/com/test/common_test_resources/sample_sender_receiver.h @@ -48,7 +48,8 @@ class EventSenderReceiver int RunAsSkeletonCheckValuesCreatedFromConfig(const score::mw::com::InstanceSpecifier& instance_specifier, const std::string& shared_memory_path, - score::os::InterprocessNotification& interprocess_notification, + score::os::InterprocessNotification& interprocess_notification_from_proxy, + score::os::InterprocessNotification& interprocess_notification_to_proxy, score::cpp::stop_source stop_source); int RunAsSkeletonWaitForProxy(const score::mw::com::InstanceSpecifier& instance_specifier, @@ -79,7 +80,8 @@ class EventSenderReceiver const score::mw::com::impl::lola::ElementFqId map_api_lanes_element_fq_id_from_config, const score::mw::com::impl::lola::ElementFqId dummy_data_element_fq_id_from_config, const std::string& shared_memory_path, - score::os::InterprocessNotification& interprocess_notification, + score::os::InterprocessNotification& interprocess_notification_from_skeleton, + score::os::InterprocessNotification& interprocess_notification_to_skeleton, score::cpp::stop_token stop_token); int RunAsProxyCheckSubscribeHandler(const score::mw::com::InstanceSpecifier& instance_specifier, From 19268e3df924bf62135bc632c9fc40f7f4c7647d Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Thu, 19 Feb 2026 11:07:11 +0100 Subject: [PATCH 20/21] Fix lock inversion Thread sanitizer highlighted a lock inversion in this test. By adding a lock that spans the FindServiceHandler and the creation of a proxy, we get this inversion. The handler runs under a lock held in the service discovery. The proxy also calls the service discovery. Connecting both creates the lock inversion. Solves the lock inversion by storing the handle required for the proxy creation locally and then unlocking the mutex before the proxy creation. --- .../shared_memory_storage_application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/score/mw/com/test/shared_memory_storage/shared_memory_storage_application.cpp b/score/mw/com/test/shared_memory_storage/shared_memory_storage_application.cpp index 03555307..72a2bb76 100644 --- a/score/mw/com/test/shared_memory_storage/shared_memory_storage_application.cpp +++ b/score/mw/com/test/shared_memory_storage/shared_memory_storage_application.cpp @@ -298,9 +298,9 @@ int main(int argc, const char** argv) }); SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(proxy_creation_data.handle != nullptr, "Service handle shouldn't be nullptr"); - - auto proxy_result = score::mw::com::test::BigDataProxy::Create(*proxy_creation_data.handle); + auto handle = *proxy_creation_data.handle; proxy_creation_lock.unlock(); + auto proxy_result = score::mw::com::test::BigDataProxy::Create(handle); if (!proxy_result.has_value()) { std::cerr << "Proxy: Unable to construct BigDataProxy: " << proxy_result.error() << ", bailing!\n"; From 288db03adac03fb050cfc75c540fadb7e59e07bc Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Fri, 20 Feb 2026 13:47:45 +0100 Subject: [PATCH 21/21] Fix data race in transaction log set When multiple proxies try to do a rollback at the same time, the rollback may be performed multiple times. Fixes the data race by making the relevant flag atomic. --- score/mw/com/impl/bindings/lola/transaction_log_set.cpp | 2 +- score/mw/com/impl/bindings/lola/transaction_log_set.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/score/mw/com/impl/bindings/lola/transaction_log_set.cpp b/score/mw/com/impl/bindings/lola/transaction_log_set.cpp index f4354087..76cc57e2 100644 --- a/score/mw/com/impl/bindings/lola/transaction_log_set.cpp +++ b/score/mw/com/impl/bindings/lola/transaction_log_set.cpp @@ -43,7 +43,7 @@ void TransactionLogSet::TransactionLogNode::Reset() noexcept { SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(!transaction_log_.ContainsTransactions(), "Cannot Reset TransactionLog as it still contains some old transactions."); - needs_rollback_ = false; + needs_rollback_.GetUnderlying() = false; Release(); } diff --git a/score/mw/com/impl/bindings/lola/transaction_log_set.h b/score/mw/com/impl/bindings/lola/transaction_log_set.h index 353adfc2..a2a28243 100644 --- a/score/mw/com/impl/bindings/lola/transaction_log_set.h +++ b/score/mw/com/impl/bindings/lola/transaction_log_set.h @@ -103,7 +103,7 @@ class TransactionLogSet void MarkNeedsRollback(const bool needs_rollback) noexcept { - needs_rollback_ = needs_rollback; + needs_rollback_.GetUnderlying() = needs_rollback; } TransactionLogId GetTransactionLogId() const noexcept @@ -131,7 +131,7 @@ class TransactionLogSet /// /// Will be set on Proxy::Create by the first Proxy in the same process with the same transaction_log_id. Will /// be cleared once Rollback is called on transaction_log. - bool needs_rollback_; + CopyableAtomic needs_rollback_; /// \brief Expresses, who (which proxy process) currently owns this transaction log. An (initially set) value /// of kInvalidTransactionLogId means, that it is not yet owned by anybody.