From 6d71a7779840ad172b620596a953b71c62f92829 Mon Sep 17 00:00:00 2001 From: Gabriel Brown Date: Wed, 26 Aug 2026 22:22:57 -0400 Subject: [PATCH] Test: Cover contract runner consent --- bin/panama | 2 +- tests/setup/test-runner-contract | 104 +++++++++++++++++++++++++++---- 2 files changed, 92 insertions(+), 14 deletions(-) diff --git a/bin/panama b/bin/panama index 4b64241..a2b3a18 100755 --- a/bin/panama +++ b/bin/panama @@ -57,7 +57,7 @@ header(){ printf '\n%s%s%s\n' "${MAGENTA}${BOLD}" "$*" "$RESET"; } # Ask a yes/no question. Returns 0 for yes, 1 for no. Default = no. confirm() { local prompt="$1" reply - printf '%s?%s %s %s[y/N]%s ' "${CYAN}${BOLD}" "$RESET" "$prompt" "$BOLD" "$RESET" + printf '%s?%s %s %s[y/N]%s ' "${CYAN}${BOLD}" "$RESET" "$prompt" "$BOLD" "$RESET" >&2 read -r reply || true [[ "$reply" =~ ^[Yy]([Ee][Ss])?$ ]] } diff --git a/tests/setup/test-runner-contract b/tests/setup/test-runner-contract index b65c40f..b2de9e6 100755 --- a/tests/setup/test-runner-contract +++ b/tests/setup/test-runner-contract @@ -38,6 +38,56 @@ run_panama() { status=$? } +run_panama_with_timeout() { + output="$(cd "$fixture" && TMPDIR="$fixture" PANAMA_TEST_TIMEOUT_SECONDS=1 PANAMA_TEST_FIXTURE="$fixture" "$fixture/bin/panama" "$@" &1)" + status=$? +} + +run_panama_tty_default_no() { + local command tty_stdout="$fixture/tty.stdout" + printf -v command 'cd %q && TMPDIR=%q PANAMA_TEST_FIXTURE=%q %q test composite > %q' \ + "$fixture" "$fixture" "$fixture" "$fixture/bin/panama" "$tty_stdout" + output="$(python3 - "$command" <<'PY' +import errno +import os +import pty +import sys + +command = sys.argv[1] +pid, terminal = pty.fork() +if pid == 0: + os.execv('/bin/bash', ['bash', '-lc', command]) + +chunks = [] +replied = False +while True: + try: + chunk = os.read(terminal, 1024) + except OSError as error: + if error.errno == errno.EIO: + break + raise + if not chunk: + break + chunks.append(chunk) + if not replied and b'[y/N]' in b''.join(chunks): + os.write(terminal, b'\n') + replied = True + +_, child_status = os.waitpid(pid, 0) +sys.stdout.buffer.write(b''.join(chunks)) +sys.exit(os.waitstatus_to_exitcode(child_status)) +PY +)" + status=$? +} + +assert_occurrences() { + local needle="$1" haystack="$2" expected="$3" actual + actual="$(grep -oF -- "$needle" <<<"$haystack" | wc -l)" + [[ "$actual" == "$expected" ]] || fail "expected $expected occurrence(s) of '$needle', got $actual\n$haystack" +} + mkdir -p "$fixture/bin" "$fixture/tests" "$fixture/config" cp "$repo_dir/bin/panama" "$fixture/bin/panama" chmod +x "$fixture/bin/panama" @@ -45,6 +95,8 @@ touch "$fixture/config/subject" git -C "$fixture" init --quiet cat > "$fixture/tests/contracts.manifest" <<'EOF' +# Maps the live desktop and reads compositor state. +live-compositor,live-desktop tests/composite-contract # Maps the live desktop. live-desktop tests/desktop-contract hermetic tests/fail-contract @@ -54,6 +106,8 @@ live-host tests/host-contract # Contacts a fixture endpoint. network tests/network-contract hermetic tests/pass-contract +# Elevates a fixture boundary. +privileged tests/privileged-contract hermetic tests/stderr-contract EOF @@ -96,24 +150,50 @@ printf 'desktop\n' >> "$PANAMA_TEST_FIXTURE/executions" # config/subject EOF +cat > "$fixture/tests/composite-contract" <<'EOF' +#!/usr/bin/env bash +printf 'composite\n' >> "$PANAMA_TEST_FIXTURE/executions" +# config/subject +EOF + cat > "$fixture/tests/network-contract" <<'EOF' #!/usr/bin/env bash printf 'network\n' >> "$PANAMA_TEST_FIXTURE/executions" EOF -chmod +x "$fixture/tests"/{desktop,fail,host,network,pass,stderr}-contract +cat > "$fixture/tests/privileged-contract" <<'EOF' +#!/usr/bin/env bash +printf 'privileged\n' >> "$PANAMA_TEST_FIXTURE/executions" +EOF + +chmod +x "$fixture/tests"/{composite,desktop,fail,hang,host,network,pass,privileged,stderr}-contract : > "$fixture/executions" +# A PTY-backed default-no confirmation remains visible when stdout is redirected +# but stdin and stderr are terminals. The fixture proves that one prompt gates +# the selected composite capability set without running its contract. +run_panama_tty_default_no +[[ $status -ne 0 ]] || fail 'TTY default-no prompt unexpectedly ran the fixture' +assert_execution '' +assert_contains 'Run 1 contract(s) requiring: live-compositor live-desktop?' "$output" +assert_occurrences 'Run 1 contract(s) requiring:' "$output" 1 +assert_contains 'No contracts were run.' "$(<"$fixture/tty.stdout")" +assert_not_contains 'Run 1 contract(s) requiring:' "$(<"$fixture/tty.stdout")" + # --safe must select hermetic entries from the manifest, not merely omit a -# legacy desktop list. The failing fixture makes the command nonzero, but all -# three selected hermetic contracts still run and every other capability skips. -run_panama test --safe +# legacy desktop list. The failing and timed-out fixtures make the command +# nonzero, but every selected hermetic contract still runs and each external +# capability reports its skipped count. +rm -f -- "$fixture/terminated" +run_panama_with_timeout test --safe [[ $status -ne 0 ]] || fail '--safe unexpectedly passed a failing fixture' -assert_execution $'fail\npass\nstderr' +assert_execution $'fail\nhang\npass\nstderr' +[[ -f "$fixture/terminated" ]] || fail '--safe did not run and terminate the hermetic hang fixture' assert_contains 'Skipped 1 live-host contract(s).' "$output" -assert_contains 'Skipped 0 live-compositor contract(s).' "$output" -assert_contains 'Skipped 1 live-desktop contract(s).' "$output" +assert_contains 'Skipped 1 live-compositor contract(s).' "$output" +assert_contains 'Skipped 2 live-desktop contract(s).' "$output" assert_contains 'Skipped 1 network contract(s).' "$output" +assert_contains 'Skipped 1 privileged contract(s).' "$output" reset_executions run_panama test desktop @@ -126,9 +206,9 @@ run_panama test --allow live-desktop desktop assert_execution 'desktop' reset_executions -run_panama test --allow live-desktop --allow live-host host +run_panama test --allow live-compositor --allow live-desktop composite [[ $status -eq 0 ]] || fail "repeatable grants failed: $output" -assert_execution 'host' +assert_execution 'composite' reset_executions run_panama test --allow live-desktop network @@ -142,11 +222,8 @@ for args in '--unknown' 'pass-contract second-pattern' '--allow unknown' '--safe [[ $status -eq 2 ]] || fail "usage error did not exit 2 for: $args\n$output" done -chmod +x "$fixture/tests/hang-contract" - reset_executions -output="$(cd "$fixture" && TMPDIR="$fixture" PANAMA_TEST_TIMEOUT_SECONDS=1 PANAMA_TEST_FIXTURE="$fixture" "$fixture/bin/panama" test hang &1)" -status=$? +run_panama_with_timeout test hang [[ $status -ne 0 ]] || fail 'timed-out contract unexpectedly passed' assert_execution 'hang' [[ -f "$fixture/terminated" ]] || fail 'timed-out contract was not terminated with TERM' @@ -178,6 +255,7 @@ output="$(cd "$fixture" && "$fixture/bin/panama" contracts config/subject 2>&1)" status=$? [[ $status -eq 0 ]] || fail "contracts lookup failed: $output" assert_contains 'tests/desktop-contract [live-desktop]' "$output" +assert_contains 'tests/composite-contract [live-compositor,live-desktop]' "$output" assert_contains 'tests/pass-contract [hermetic]' "$output" mv "$fixture/tests/contracts.manifest" "$fixture/tests/contracts.manifest.missing"