d5e04be1
test: a refused birth paints [refused] and the wall stays up
a73x 2026-08-28 19:53
Commit message
test/e2e.sh
| Old | New | ||
|---|---|---|---|
| @@ -177,8 +177,8 @@ done | |||
| 177 | # one of those and adds a convergence point would be pinning a fact every | 177 | # one of those and adds a convergence point would be pinning a fact every |
| 178 | # leg above already establishes. | 178 | # leg above already establishes. |
| 179 | 179 | ||
| 180 | [ "$OK_COUNT" = "88" ] || { | 180 | [ "$OK_COUNT" = "89" ] || { |
| 181 | echo "e2e FAIL: $OK_COUNT scenario checkpoints ran, the pin says 88 —" | 181 | echo "e2e FAIL: $OK_COUNT scenario checkpoints ran, the pin says 89 —" |
| 182 | echo " a scenario was added (update the pin) or silently lost" | 182 | echo " a scenario was added (update the pin) or silently lost" |
| 183 | exit 1 | 183 | exit 1 |
| 184 | } | 184 | } |
test/e2e_13_birth.sh
| Old | New | ||
|---|---|---|---|
| @@ -672,3 +672,94 @@ grep -q "lfd-two" "$OUT.lfdsess1" && { | |||
| 672 | assert_stopped "$SOCK74" "$D74PID" "lowest-free-digit" "$OUT.lfdstop" | 672 | assert_stopped "$SOCK74" "$D74PID" "lowest-free-digit" "$OUT.lfdstop" |
| 673 | D74PID="" | 673 | D74PID="" |
| 674 | ok "a new tile takes the lowest free digit, and the daemon takes the name back" | 674 | ok "a new tile takes the lowest free digit, and the daemon takes the name back" |
| 675 | |||
| 676 | # ---- a birth the DAEMON refuses narrates, and the wall stays up --------- | ||
| 677 | # | ||
| 678 | # `.refused` is a live tile state and the only one with no CLI spelling | ||
| 679 | # left to reach it: `mux TARGET#session` is gone, so what used to drive | ||
| 680 | # this leg went with it and the state word rested on a unit test of | ||
| 681 | # `labelText` — which pins the STRING, not that a refused pump ever | ||
| 682 | # reaches it. | ||
| 683 | # | ||
| 684 | # The refusal is the client TABLE, not the session table, and that is what | ||
| 685 | # makes this cheap: every tile is its own attach and so its own client | ||
| 686 | # slot, so a daemon holding eight sessions on a terminal with room for ten | ||
| 687 | # stripes has eight tiles and no slot left. The picker's Enter dials a | ||
| 688 | # ninth, the daemon refuses it before any replay frame, and the pump paints | ||
| 689 | # `[refused]` on that tile's bar on its way out. | ||
| 690 | # | ||
| 691 | # Two claims, and the second is the newer one: the wall STAYS. A refused | ||
| 692 | # picker birth used to take mux down with it (rc 1 on a terminal); a tile | ||
| 693 | # that keeps the wall (`Tile.keeps_wall`) leaves the eight standing, which | ||
| 694 | # is what the marker typed after the refusal proves — it reaches a session | ||
| 695 | # because there is still a wall to type into. | ||
| 696 | SOCK75="${TMPDIR:-/tmp}/muxd-e2e-reftile-$$.sock" | ||
| 697 | defer_sock "$SOCK75" | ||
| 698 | RTSTATE="${TMPDIR:-/tmp}/mux-e2e-reftile-state-$$" | ||
| 699 | defer_rm "$RTSTATE" | ||
| 700 | start_daemon "$SOCK75" "$OUT.rt.d" "refused-tile daemon never bound" --shell /bin/sh | ||
| 701 | D75PID=$DPID | ||
| 702 | # Seven more, so the daemon holds eight sessions with its own `0`: exactly | ||
| 703 | # max_clients, so the wall fills the table and the ninth attach is the one | ||
| 704 | # under test. The fills detach as they go and leave the slots free. | ||
| 705 | fill_sessions "$SOCK75" "$OUT.rtfill" f 1 7 | ||
| 706 | wait_sessions "$SOCK75" 8 "refused-tile: the daemon should hold eight sessions" | ||
| 707 | mkdir -p "$RTSTATE/mux" | ||
| 708 | printf -- '--sock %s\n' "$SOCK75" > "$RTSTATE/mux/hosts" | ||
| 709 | no_saved_tree "$RTSTATE" | ||
| 710 | set +e | ||
| 711 | # Tall and not wide, the hosts group's shape and for its reason: 80 columns | ||
| 712 | # is under the aspect rule's `cols >= 2 * rows`, so the cut is stacked and | ||
| 713 | # every bar gets the full width — beside, eight stripes are nine columns | ||
| 714 | # each and `labelText` spends them all on the state word. Forty-four rows | ||
| 715 | # over eight stripes leaves room for a ninth (three rows each, two of | ||
| 716 | # content under a bar): the WALL is not what refuses here, and a terminal | ||
| 717 | # that ran out of stripes first would say `[no room on the wall for another | ||
| 718 | # tile]` and never dial at all. | ||
| 719 | XDG_STATE_HOME="$RTSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 44 \ | ||
| 720 | --out "$OUT.rtcap" --err "$OUT.rtcap.err" -- "$MUX" > "$OUT.rtpc" 2>&1 <<'EOF' | ||
| 721 | expect [up] 25000 | ||
| 722 | settle 2000 25000 | ||
| 723 | send \x1cs | ||
| 724 | expect Enter/c new session 15000 | ||
| 725 | send \r | ||
| 726 | expect [refused] 25000 | ||
| 727 | settle 1500 20000 | ||
| 728 | send printf 'rt-%s\n' alive\n | ||
| 729 | expect rt-alive 20000 | ||
| 730 | settle 500 15000 | ||
| 731 | send \x1cd | ||
| 732 | waitexit 15000 | ||
| 733 | EOF | ||
| 734 | RC=$? | ||
| 735 | set -e | ||
| 736 | # The exit code IS the second claim: a wall that ended on the refusal would | ||
| 737 | # be gone before the marker, and this is where that shows. | ||
| 738 | [ "$RC" -eq 0 ] || { | ||
| 739 | echo "e2e FAIL: refused-tile: the wall exited $RC — a refused birth must" | ||
| 740 | echo " leave the tiles that were already up standing:" | ||
| 741 | cat "$OUT.rtpc"; echo "--- stderr ---"; cat "$OUT.rtcap.err"; exit 1; } | ||
| 742 | # The narration, off the STREAM: the refused tile vanishes on the pass | ||
| 743 | # after it paints, so the final grid is not where the word lives. | ||
| 744 | grep -qF -- "[refused]" "$OUT.rtcap" || { | ||
| 745 | echo "e2e FAIL: refused-tile: no tile ever wore the refused state word:" | ||
| 746 | grep -ao '\[[a-z ]*\]' "$OUT.rtcap" | sort -u | head; exit 1; } | ||
| 747 | # ...and the refusal created nothing. A daemon that refused the attach but | ||
| 748 | # kept the session would leave a session nobody can see — the worse of the | ||
| 749 | # two failures, and invisible to the screen. | ||
| 750 | wait_sessions "$SOCK75" 8 "refused-tile: a refused birth must leave no session behind" | ||
| 751 | # The marker landed in a session on the wall, asked of the DAEMON: the | ||
| 752 | # eight tiles outlived the ninth. Which one holds it is the focus's | ||
| 753 | # business — the refusal puts the focus back on the tile it was born from | ||
| 754 | # — so every session is asked and one hit is the claim. | ||
| 755 | RTWHERE="" | ||
| 756 | for _rt in 0 f1 f2 f3 f4 f5 f6 f7; do | ||
| 757 | if dump_session "$SOCK75" "$_rt" 2>/dev/null | grep -q "rt-alive"; then RTWHERE="$_rt"; fi | ||
| 758 | done | ||
| 759 | [ -n "$RTWHERE" ] || { | ||
| 760 | echo "e2e FAIL: refused-tile: the marker typed after the refusal reached no" | ||
| 761 | echo " session — the wall did not survive its own refused birth:" | ||
| 762 | cat "$OUT.rtpc"; exit 1; } | ||
| 763 | assert_stopped "$SOCK75" "$D75PID" "refused-tile" "$OUT.rtstop" | ||
| 764 | D75PID="" | ||
| 765 | ok "a birth the daemon refuses paints [refused] and leaves the wall standing" | ||