a73x

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 pins daemon MUX_KEY_FILE, and --key beating it at the call site

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 ---------------------------------------------------