diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-19 23:28:22 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-19 23:28:22 -0300 |
| commit | ba996acfcad1698adbf4a1834fe50e73b1c6cab9 (patch) | |
| tree | 282ba00ce5b10d7416aecb9f2f0f0a439340a57d /9player/test/adv_bridge_hostile.sh | |
| parent | b05abcba3ea09ea106ad28364c6e40a3ec31b890 (diff) | |
| download | cloud9-ba996acfcad1698adbf4a1834fe50e73b1c6cab9.tar.gz cloud9-ba996acfcad1698adbf4a1834fe50e73b1c6cab9.zip | |
Rename programs: 9player -> 9ns, introspect -> 9proc, app -> web (9web)
Directories, binaries, build options (-D9ns, -D9proc), step names, module
name (9proc), thread and fs names, env var NINEPLAYER_MOUNT -> NINE_MOUNT,
docs and test scripts. Browser assets move to web/static.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Diffstat (limited to '9player/test/adv_bridge_hostile.sh')
| -rwxr-xr-x | 9player/test/adv_bridge_hostile.sh | 181 |
1 files changed, 0 insertions, 181 deletions
diff --git a/9player/test/adv_bridge_hostile.sh b/9player/test/adv_bridge_hostile.sh deleted file mode 100755 index f1ee292..0000000 --- a/9player/test/adv_bridge_hostile.sh +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/env bash -# Hostile-server tests: 9player against 9player/test/adv_bridge_hostile.py in every -# misbehaviour mode. 9player must never crash (panic/segfault) and must turn -# each misbehaviour into an errno for the child. -# Usage: bash 9player/test/adv_bridge_hostile.sh <9player> <introspect> (introspect unused; part of zig build 9player-adv) -set -u -PLAYER=$(realpath "${1:?path to 9player}") -HERE=$(cd "$(dirname "$0")" && pwd) -SRV=$HERE/adv_bridge_hostile.py -TMP=$(mktemp -d "${TMPDIR:-/tmp}/9player-adv.XXXXXX") -M=/mnt/9p -FAILED=0 -PASSED=0 -SRVPID= - -cleanup() { [ -n "$SRVPID" ] && kill "$SRVPID" 2>/dev/null; pkill -f "adv_bridge_hostile.py $TMP" 2>/dev/null; rm -rf "$TMP"; } -trap cleanup EXIT - -if ! unshare -Urm true 2>/dev/null || [ ! -c /dev/fuse ]; then echo "SKIP: no user namespaces or /dev/fuse"; exit 0; fi - -pass() { PASSED=$((PASSED + 1)); echo "ok - $1"; } -fail() { FAILED=$((FAILED + 1)); echo "FAIL - $1"; shift; [ $# -gt 0 ] && printf ' %s\n' "$@"; } -expect_eq() { if [ "$2" = "$3" ]; then pass "$1"; else fail "$1" "expected: $(printf %q "$2")" "actual: $(printf %q "$3")"; fi; } -expect_contains() { case "$3" in *"$2"*) pass "$1" ;; *) fail "$1" "missing: $(printf %q "$2")" "in: $(printf %q "$3")" ;; esac; } - -start_server() { # mode - [ -n "$SRVPID" ] && { kill "$SRVPID" 2>/dev/null; wait "$SRVPID" 2>/dev/null; } - SOCK=$TMP/$1.sock - rm -f "$SOCK" - python3 "$SRV" "$SOCK" "$1" >"$TMP/$1.srv.out" 2>&1 </dev/null & - SRVPID=$! - for _ in $(seq 1 100); do [ -S "$SOCK" ] && return 0; sleep 0.02; done - echo "server for $1 did not start"; cat "$TMP/$1.srv.out"; exit 1 -} - -# run MODE SCRIPT [extra 9player args...]: starts the server, runs 9player; sets OUT, RC, STDERR. -run() { - local mode=$1 script=$2; shift 2 - start_server "$mode" - OUT=$(timeout 30 "$PLAYER" --unix "$SOCK" "$@" -- sh -c "$script" 2>"$TMP/stderr") - RC=$? - STDERR=$(cat "$TMP/stderr") -} - -# 9player must not die of a signal or panic. RC 124 = timeout(1) fired. -no_crash() { # name - if [ "$RC" -ge 128 ] || [ "$RC" -eq 124 ]; then fail "$1: 9player exit $RC" "$STDERR"; return; fi - case "$STDERR" in *panic*|*"Segmentation"*|*"integer overflow"*|*"reached unreachable"*|*"index out of bounds"*) fail "$1: crash text in stderr" "$STDERR";; *) pass "$1: no crash (exit $RC)";; esac -} - -echo "# sanity: the hostile server behaves in 'ok' mode" -run ok "cat $M/f"; expect_eq "ok: cat f" "hello world" "$OUT" -run ok "cat $M/d/g"; expect_eq "ok: nested" "in d" "$OUT" -run ok "cat $M/nope 2>&1 | sed 's/.*: //'"; expect_eq "ok: ENOENT" "No such file or directory" "$OUT" -run ok "head -c 1048576 $M/big | wc -c | grep -q 1048576 && echo yes"; expect_eq "ok: 1 MiB read matches" "yes" "$OUT" - -echo "# unlink + recreate with a recycled qid.path" -run ok "echo 1 > $M/a; rm $M/a; echo 2 > $M/a; cat $M/a; rm $M/a"; expect_eq "qid reuse: new content, not stale" "2" "$OUT" -run ok "echo 1 > $M/x; rm $M/x; mkdir $M/x; stat -c %F $M/x; rmdir $M/x"; expect_eq "qid reuse: fileādir on the same path" "directory" "$OUT" - -echo "# fids do not grow with the number of operations" -loop='i=0; while [ $i -lt N ]; do echo hi > M/t; cat M/t >/dev/null; mkdir M/dd; rmdir M/dd; rm M/t; i=$((i+1)); done; cat M/fids' -run ok "$(echo "$loop" | sed "s|N|20|; s|M/|$M/|g")"; a=$OUT -run ok "$(echo "$loop" | sed "s|N|200|; s|M/|$M/|g")"; b=$OUT -expect_eq "fids after 20 == after 200 iterations ($a)" "$a" "$b" -floop='i=0; while [ $i -lt N ]; do cat M/nope 2>/dev/null; echo x > M/fids 2>/dev/null; mkdir M/f 2>/dev/null; rm M/d 2>/dev/null; mv M/f M/d 2>/dev/null; i=$((i+1)); done; cat M/fids' -run ok "$(echo "$floop" | sed "s|N|20|; s|M/|$M/|g")"; a=$OUT -run ok "$(echo "$floop" | sed "s|N|200|; s|M/|$M/|g")"; b=$OUT -expect_eq "fids after 20 == after 200 failing iterations ($a)" "$a" "$b" - -echo "# rename over an existing file must not lose the target when the rename fails" -run rename_fail "echo A > $M/a; echo B > $M/b; mv $M/a $M/b 2>/dev/null; echo mv=\$?; cat $M/b; cat $M/a" -expect_contains "rename_fail: mv reports failure" "mv=1" "$OUT" -expect_contains "rename_fail: target b still has its content" "B" "$OUT" -expect_contains "rename_fail: source a still has its content" "A" "$OUT" - -echo "# protocol violations on a data read must yield an error, not a crash" -for mode in trunc short_frame huge_frame wrong_tag rread_big extra_reply close_mid renegotiate rwrite_big; do - if [ "$mode" = rwrite_big ]; then script="dd if=/dev/zero of=$M/f bs=10 count=1 2>&1; echo status=\$?"; else script="cat $M/f 2>&1; echo status=\$?"; fi - run "$mode" "$script" - no_crash "$mode" - expect_contains "$mode: child sees an error" "status=1" "$OUT" - case "$OUT" in *"Input/output error"*|*"not connected"*) pass "$mode: EIO/ENOTCONN";; *) fail "$mode: errno text" "$OUT";; esac -done - -echo "# protocol violations on lookup/stat" -for mode in wrong_type rwalk_many rstat_garbage rstat_overlong; do - run "$mode" "stat -c %s $M/f 2>&1; echo status=\$?" - no_crash "$mode" - expect_contains "$mode: child sees an error" "status=1" "$OUT" -done -run rwalk_zero "cat $M/nope 2>&1; echo status=\$?; cat $M/f 2>&1" -no_crash "rwalk_zero" -expect_contains "rwalk_zero: child sees an error" "status=1" "$OUT" -run rerror_big "cat $M/nope 2>&1; echo status=\$?; cat $M/f" -no_crash "rerror_big" -expect_contains "rerror_big: child sees an error" "status=1" "$OUT" -expect_contains "rerror_big: session survives a 64 KiB Rerror" "hello world" "$OUT" - -echo "# hostile stat contents" -run length_max "stat -c '%s %b' $M/f 2>&1; echo status=\$?" -no_crash "length_max" -expect_contains "length_max: stat succeeds with a saturated block count" "status=0" "$OUT" -run iounit_one "cat $M/f; head -c 3000 $M/big | wc -c" -no_crash "iounit_one" -expect_contains "iounit_one: read still complete" "hello world" "$OUT" -expect_contains "iounit_one: 3000 bytes" "3000" "$OUT" - -echo "# hostile directory listings" -run dir_split "ls $M 2>&1; echo status=\$?; cat $M/f" -no_crash "dir_split" -expect_contains "dir_split: readdir fails with EIO" "Input/output error" "$OUT" -expect_contains "dir_split: session survives" "hello world" "$OUT" -run dir_forever "ls $M 2>&1 | tail -c 200; echo status=\$?; cat $M/f; grep VmRSS /proc/\$PPID/status" -no_crash "dir_forever" -expect_contains "dir_forever: infinite directory is cut off with EIO" "Input/output error" "$OUT" -expect_contains "dir_forever: session survives" "hello world" "$OUT" -for mode in name_slash name_empty name_huge name_dots; do - run "$mode" "ls -a $M | tr '\n' ' '; echo; cat $M/f" - no_crash "$mode" - expect_contains "$mode: listing still works" "big d f fids" "$OUT" - expect_contains "$mode: file readable" "hello world" "$OUT" - case "$mode" in - name_slash) expect_eq "$mode: slash entry dropped" "" "$(printf '%s' "$OUT" | grep -o 'a/b')";; - name_dots) expect_eq "$mode: exactly one . and one .." "1 1" "$(printf '%s %s' "$(printf '%s\n' "$OUT" | head -1 | tr ' ' '\n' | grep -c '^\.$')" "$(printf '%s\n' "$OUT" | head -1 | tr ' ' '\n' | grep -c '^\.\.$')")";; - esac -done - -echo "# qid collisions" -run qid_collide "cat $M/f; cat $M/d/g; ls $M/d; stat -c %i $M/f $M/d 2>&1; echo status=\$?" -no_crash "qid_collide" -expect_contains "qid_collide: reads work" "hello world" "$OUT" -run qid_zero "cat $M/f; ls $M | tr '\n' ' '; echo; cat $M/d/g; echo status=\$?" -no_crash "qid_zero" -expect_contains "qid_zero: file with root's qid.path is still a readable file" "hello world" "$OUT" -expect_contains "qid_zero: root still lists" "big d f fids" "$OUT" -expect_contains "qid_zero: nested file readable" "in d" "$OUT" - -echo "# version negotiation" -run version_unknown "echo ran" -expect_eq "version_unknown: 9player refuses (125)" "125" "$RC" -run msize_tiny "cat $M/f 2>&1; echo status=\$?" -no_crash "msize_tiny" - -echo "# a server that never replies" -start_server never -# SIGTERM is forwarded to the child; once the child is gone 9player must leave the -# pending 9P reply behind and exit even though the server stays silent. -timeout -s TERM 3 "$PLAYER" --unix "$SOCK" -- sh -c "cat $M/f; echo unreachable" >"$TMP/never.out" 2>"$TMP/never.err" & -TPID=$! -sleep 4 -if kill -0 "$TPID" 2>/dev/null; then - fail "never: SIGTERM did not end 9player while a reply was outstanding"; kill -9 "$TPID" -else - pass "never: SIGTERM ends 9player even while the server is silent" -fi -wait "$TPID" 2>/dev/null -# Without a signal the mount hangs (documented v1 limitation) until the server dies. -timeout 30 "$PLAYER" --unix "$SOCK" -- sh -c "cat $M/f; echo unreachable" >"$TMP/never.out" 2>"$TMP/never.err" & -TPID=$! -sleep 1.5 -if kill -0 "$TPID" 2>/dev/null; then - pass "never: mount hangs while the server is silent (documented v1 limitation)" - kill "$SRVPID"; wait "$SRVPID" 2>/dev/null; SRVPID= - for _ in $(seq 1 50); do kill -0 "$TPID" 2>/dev/null || break; sleep 0.1; done - if kill -0 "$TPID" 2>/dev/null; then fail "never: 9player still alive after its server died"; kill -9 "$TPID"; else pass "never: killing the server unblocks 9player"; fi -else - wait "$TPID"; fail "never: 9player exited early ($?)" "$(cat "$TMP/never.err")" -fi - -echo "# interrupting a slow read (INTERRUPT must not confuse reply matching)" -run slow "cat $M/big > /dev/null; cat $M/f; cat $M/fids" --msize 8192 -base=$(printf '%s\n' "$OUT" | tail -1) -run slow "(cat $M/big > /dev/null & sleep 0.3; kill -INT \$!; wait \$!) 2>/dev/null; cat $M/f; cat $M/fids" --msize 8192 -no_crash "slow" -expect_contains "slow: read after interrupted read works" "hello world" "$OUT" -expect_eq "slow: fids after an interrupted read == after a complete one ($base)" "$base" "$(printf '%s\n' "$OUT" | tail -1)" - -echo -echo "passed=$PASSED failed=$FAILED" -[ "$FAILED" -eq 0 ] |
