From df66d7338542a12c62629592dd3fbadf864d7ae1 Mon Sep 17 00:00:00 2001 From: yuanyuyuan Date: Wed, 29 Jul 2026 18:22:48 +0800 Subject: [PATCH] test(ros): fail the interop job when it runs no tests The ROS interop step captured nextest's output with `complete` and never printed it, so a green job showed the command echo followed by "All ROS 2 tests passed!" and nothing in between. That banner could not be falsified: nextest exits 0 having run zero tests, and each interop test returns early -- still passing -- when check_ros2_available says no. Print the captured output and require a nextest summary reporting a non-zero count. Split out of #250, where it rode along because the swallowed output was found while gathering evidence for that fix. It is CI hygiene and has nothing to do with subscriber re-entrancy. --- scripts/test-ros.nu | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/scripts/test-ros.nu b/scripts/test-ros.nu index a0ff8c265..dc0e8484a 100755 --- a/scripts/test-ros.nu +++ b/scripts/test-ros.nu @@ -75,6 +75,18 @@ def run-ros-interop [] { # Try without verbose logging first (faster) let result = (do -i { run-cmd $cmd --distro $distro | complete }) + # Always surface the runner's own output. + # + # This used to capture with `complete` and then never print, so a passing + # ROS job logged the nextest command, produced not one line of test output, + # and printed "All ROS 2 tests passed!". That banner was + # unfalsifiable: nextest exits 0 when it runs *zero* tests, and each interop + # test additionally returns early (still passing) when `check_ros2_available` + # says no. Nothing in the log distinguished "57 interop tests passed against + # rmw_zenoh_cpp" from "the binary matched no tests". + print $result.stdout + print $result.stderr + # If tests failed, retry with trace logging for detailed diagnostics # This is CRITICAL for debugging interop issues - shows type hashes, key expressions, service calls if $result.exit_code != 0 { @@ -82,6 +94,26 @@ def run-ros-interop [] { $env.RUST_LOG = "hiroz=trace,rmw_zenoh_cpp=debug,warn" run-cmd $cmd --distro $distro } + + # An exit code of 0 is necessary but not sufficient — require evidence that + # tests actually ran. nextest's last line is + # `Summary [ 12.345s] 57 tests run: 57 passed, 0 skipped`. + let summary = ([$result.stdout, $result.stderr] | str join "\n" | lines + | where {|l| $l =~ 'tests run:' }) + + if ($summary | is-empty) { + error make { + msg: $"ROS interop run produced no nextest summary line, so it is unknown whether any test ran. Command: ($cmd)" + } + } + + let ran = ($summary | last | parse --regex '(?\d+) tests run' | get n.0 | into int) + if $ran == 0 { + error make { + msg: $"ROS interop run executed 0 tests -- a vacuous pass, not a pass. Command: ($cmd)" + } + } + print $"\n($ran) ROS interop tests ran against rmw_zenoh_cpp." } # ============================================================================