From cbd241d7f1b33248501010cbaac50b07785373b8 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Fri, 28 Aug 2026 16:41:38 +0200 Subject: [PATCH] fix(tests): venue-parity interface probes must not pipe into grep -q MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two layer-5 interface probes tested for a substring by piping the captured output into `grep -q`. Under `set -o pipefail` (line 32) that turns a SATISFIED contract into a probe failure whenever the payload is larger than the pipe buffer: `grep -q` exits at the first match, and the writer takes EPIPE on the remainder, so the pipeline reports the writer's non-zero status even though the match succeeded. Observed on macos-15-intel: test_venue_parity_contract.sh: line 404: printf: write error: Broken pipe INTERFACE CONTRACT: scripts/ci/smoke-artifact.sh --help must exit 0 and print a Usage: block (rc=0) VENUE PARITY CONTRACT VIOLATED — interface probes failed (layer 5) rc=0 and the Usage: block was present — the match is exactly what made grep exit early. `smoke-artifact.sh --help` is 698 bytes against a 512-byte PIPE_BUF, and prints `Usage:` on its first line, so the writer is killed at the earliest possible moment. Whether the remaining write lands before grep exits is a scheduling race, which is why this only ever showed up on one runner. Replace both pipelines with in-shell `case` matching: no subprocess, no pipe, no race, and a strictly literal match (the second probe's "--help." was previously a regex whose `.` matched any character). Verified: the contract passes (18 --help entries, 8 strict-flag entries), and the matcher still returns 0 for output with no Usage: block, so the probe can still fail. Signed-off-by: Martin Vogel --- tests/test_venue_parity_contract.sh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/test_venue_parity_contract.sh b/tests/test_venue_parity_contract.sh index b609a1493..4bcd694d7 100755 --- a/tests/test_venue_parity_contract.sh +++ b/tests/test_venue_parity_contract.sh @@ -401,7 +401,16 @@ test-infrastructure/vm/win.sh case "$entry" in *.py) out=$(cd "$ROOT" && python3 "$entry" --help 2>&1) && rc=0 || rc=$? ;; esac - if [ "$rc" -ne 0 ] || ! printf '%s' "$out" | grep -q "Usage:"; then + # Substring test in-shell: piping into `grep -q` is unsafe under + # `set -o pipefail` because grep exits at the first match and the + # writer takes EPIPE on any payload larger than the pipe buffer, + # turning a SATISFIED contract into a probe failure (macOS, 698-byte + # --help vs a 512-byte PIPE_BUF). + case "$out" in + *"Usage:"*) has_usage=1 ;; + *) has_usage=0 ;; + esac + if [ "$rc" -ne 0 ] || [ "$has_usage" -eq 0 ]; then echo "INTERFACE CONTRACT: $entry --help must exit 0 and print a Usage: block (rc=$rc)" >&2 probe_failures=1 fi @@ -422,7 +431,11 @@ scripts/smoke-invariants.sh " for entry in $STRICT_ENTRIES; do out=$(cd "$ROOT" && bash "$entry" --definitely-not-a-flag 2>&1) && rc=0 || rc=$? - if [ "$rc" -ne 2 ] || ! printf '%s' "$out" | grep -q "Please consult --help."; then + case "$out" in + *"Please consult --help."*) has_hint=1 ;; + *) has_hint=0 ;; + esac + if [ "$rc" -ne 2 ] || [ "$has_hint" -eq 0 ]; then echo "INTERFACE CONTRACT: $entry must reject unknown flags with exit 2 + 'Please consult --help.' (rc=$rc)" >&2 probe_failures=1 fi