144f6af7
test: e2e pins daemon MUX_KEY_FILE, and --key beating it at the call site
a73x 2026-08-09 13:21
Commit message
test/e2e.sh
| Old | New | ||
|---|---|---|---|
| @@ -40,6 +40,15 @@ D6PID="" | |||
| 40 | SOCK7="${TMPDIR:-/tmp}/muxd-e2e-raw-$$.sock" | 40 | SOCK7="${TMPDIR:-/tmp}/muxd-e2e-raw-$$.sock" |
| 41 | D7PID="" | 41 | D7PID="" |
| 42 | PWSH="${TMPDIR:-/tmp}/mux-e2e-pw-$$.sh" | 42 | PWSH="${TMPDIR:-/tmp}/mux-e2e-pw-$$.sh" |
| 43 | # M10 key-resolution daemons. Two, not one: the first scenario's client | ||
| 44 | # detaches and its daemon is killed, and the second must not be sharing | ||
| 45 | # either. Ports in bands of their own so a concurrent suite cannot collide. | ||
| 46 | SOCK9="${TMPDIR:-/tmp}/muxd-e2e-envkey-$$.sock" | ||
| 47 | D9PID="" | ||
| 48 | SOCK10="${TMPDIR:-/tmp}/muxd-e2e-flagwins-$$.sock" | ||
| 49 | D10PID="" | ||
| 50 | QPORT2=$(( 26000 + ($$ % 4000) )) | ||
| 51 | QPORT3=$(( 31000 + ($$ % 4000) )) | ||
| 43 | 52 | ||
| 44 | # One counter out of a MUX_PREDICT_STATS line. The client prints exactly one | 53 | # One counter out of a MUX_PREDICT_STATS line. The client prints exactly one |
| 45 | # such line on exit; every field is a key=value pair, so a rename or reorder | 54 | # such line on exit; every field is a key=value pair, so a rename or reorder |
| @@ -99,7 +108,10 @@ cleanup() { | |||
| 99 | [ -n "$D5PID" ] && kill "$D5PID" 2>/dev/null || true | 108 | [ -n "$D5PID" ] && kill "$D5PID" 2>/dev/null || true |
| 100 | [ -n "$D6PID" ] && kill "$D6PID" 2>/dev/null || true | 109 | [ -n "$D6PID" ] && kill "$D6PID" 2>/dev/null || true |
| 101 | [ -n "$D7PID" ] && kill "$D7PID" 2>/dev/null || true | 110 | [ -n "$D7PID" ] && kill "$D7PID" 2>/dev/null || true |
| 102 | rm -f "$SOCK5" "$SOCK6" "$SOCK7" "$PWSH" \ | 111 | [ -n "$D9PID" ] && kill "$D9PID" 2>/dev/null || true |
| 112 | [ -n "$D10PID" ] && kill "$D10PID" 2>/dev/null || true | ||
| 113 | rm -f "$SOCK9" "$SOCK10" "$OUT.env1" "$OUT.env2" \ | ||
| 114 | "$SOCK5" "$SOCK6" "$SOCK7" "$PWSH" \ | ||
| 103 | "$OUT.p1" "$OUT.p1.early" "$OUT.pb" "$OUT.pw" "$OUT.rw" "$OUT.pr" \ | 115 | "$OUT.p1" "$OUT.p1.early" "$OUT.pb" "$OUT.pw" "$OUT.rw" "$OUT.pr" \ |
| 104 | "$SOCK" "$SOCK2" "$SOCK3" "$SOCK4" "$SOCK4.second" "$QKEY" "$QKEY.bad" \ | 116 | "$SOCK" "$SOCK2" "$SOCK3" "$SOCK4" "$SOCK4.second" "$QKEY" "$QKEY.bad" \ |
| 105 | "$OUT" "$OUT.kill" "$OUT.re" "$OUT.a" \ | 117 | "$OUT" "$OUT.kill" "$OUT.re" "$OUT.a" \ |
| @@ -737,6 +749,64 @@ SNAPS_NQ=$("$MUXD" stats --sock "$SOCK4" | sed -n 's/.*snapshots=\([0-9]*\).*/\1 | |||
| 737 | 749 | ||
| 738 | kill "$D4PID" 2>/dev/null || true | 750 | kill "$D4PID" 2>/dev/null || true |
| 739 | D4PID="" | 751 | D4PID="" |
| 752 | |||
| 753 | # --- M10: the daemon's own key resolution, over a real handshake. | ||
| 754 | # | ||
| 755 | # 1. MUX_KEY_FILE with no --key anywhere. The daemon's env support had no | ||
| 756 | # automated coverage at all: envKey() reads the real environment, so | ||
| 757 | # only a daemon started with it set can prove the path works. | ||
| 758 | env MUX_KEY_FILE="$QKEY" "$MUXD" run --sock "$SOCK9" --shell /bin/sh \ | ||
| 759 | --quic "127.0.0.1:$QPORT2" --quic-idle-ms 3000 & | ||
| 760 | D9PID=$! | ||
| 761 | i=0 | ||
| 762 | while [ ! -S "$SOCK9" ] && [ "$i" -lt 50 ]; do sleep 0.1; i=$((i+1)); done | ||
| 763 | [ -S "$SOCK9" ] || { | ||
| 764 | echo "e2e FAIL: MUX_KEY_FILE daemon never bound its session socket"; exit 1; } | ||
| 765 | |||
| 766 | set +e | ||
| 767 | { printf 'printf "envkey-%%s\\n" ok\n'; sleep 2; printf '\034'; } | \ | ||
| 768 | timeout 30 "$MUX" "quic://127.0.0.1:$QPORT2" --key "$QKEY" \ | ||
| 769 | --quic-idle-ms 15000 > "$OUT.env1" 2>&1 | ||
| 770 | RC=$? | ||
| 771 | set -e | ||
| 772 | [ "$RC" -eq 0 ] || { | ||
| 773 | echo "e2e FAIL: quic attach to a MUX_KEY_FILE daemon exited $RC (want 0)" | ||
| 774 | cat "$OUT.env1"; exit 1; | ||
| 775 | } | ||
| 776 | grep -q "envkey-ok" "$OUT.env1" || { | ||
| 777 | echo "e2e FAIL: MUX_KEY_FILE daemon served no session"; cat "$OUT.env1"; exit 1; } | ||
| 778 | kill "$D9PID" 2>/dev/null || true | ||
| 779 | D9PID="" | ||
| 780 | |||
| 781 | # 2. --key AND MUX_KEY_FILE, naming different keys. The env names one the | ||
| 782 | # client does not have, so an attach that succeeds proves the FLAG won. | ||
| 783 | # This is the shape that catches the two being swapped at the call site | ||
| 784 | # in run() — pickKey's unit test pins the ordering inside the function | ||
| 785 | # and is blind to the order they are handed to it. | ||
| 786 | env MUX_KEY_FILE="$QKEY.wrong" "$MUXD" run --sock "$SOCK10" --shell /bin/sh \ | ||
| 787 | --quic "127.0.0.1:$QPORT3" --key "$QKEY" --quic-idle-ms 3000 & | ||
| 788 | D10PID=$! | ||
| 789 | i=0 | ||
| 790 | while [ ! -S "$SOCK10" ] && [ "$i" -lt 50 ]; do sleep 0.1; i=$((i+1)); done | ||
| 791 | [ -S "$SOCK10" ] || { | ||
| 792 | echo "e2e FAIL: --key-beats-env daemon never bound its session socket"; exit 1; } | ||
| 793 | |||
| 794 | set +e | ||
| 795 | { printf 'printf "flagwins-%%s\\n" ok\n'; sleep 2; printf '\034'; } | \ | ||
| 796 | timeout 30 "$MUX" "quic://127.0.0.1:$QPORT3" --key "$QKEY" \ | ||
| 797 | --quic-idle-ms 15000 > "$OUT.env2" 2>&1 | ||
| 798 | RC=$? | ||
| 799 | set -e | ||
| 800 | [ "$RC" -eq 0 ] || { | ||
| 801 | echo "e2e FAIL: --key did not beat MUX_KEY_FILE: attach exited $RC (want 0)" | ||
| 802 | cat "$OUT.env2"; exit 1; | ||
| 803 | } | ||
| 804 | grep -q "flagwins-ok" "$OUT.env2" || { | ||
| 805 | echo "e2e FAIL: --key-beats-env daemon served no session"; cat "$OUT.env2"; exit 1; } | ||
| 806 | kill "$D10PID" 2>/dev/null || true | ||
| 807 | D10PID="" | ||
| 808 | echo "e2e OK: daemon honours MUX_KEY_FILE, and --key beats it" | ||
| 809 | |||
| 740 | rm -f "$OUT.q" "$OUT.qc" "$OUT.qr" "$OUT.qa" "$OUT.qk" "$QKEY" "$QKEY.bad" "$QKEY.wrong" | 810 | rm -f "$OUT.q" "$OUT.qc" "$OUT.qr" "$OUT.qa" "$OUT.qk" "$QKEY" "$QKEY.bad" "$QKEY.wrong" |
| 741 | 811 | ||
| 742 | # ---- M9: prediction --------------------------------------------------- | 812 | # ---- M9: prediction --------------------------------------------------- |