a73x

9ec2df21

test: x on a wall ends the focused tile's session and no other

a73x   2026-08-28 19:53

Commit message
test: x on a wall ends the focused tile's session and no other

The two-step leg holds one tile, so nothing said which session an `x`
reaches. Five tiles over two daemons, the chord aimed at digit 3 — neither
the first nor the last — the shell's death asked of the OS, the neighbours
asked of their daemons, and the tile's departure judged on the grid.

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" = "87" ] || { 180 [ "$OK_COUNT" = "88" ] || {
181 echo "e2e FAIL: $OK_COUNT scenario checkpoints ran, the pin says 87 —" 181 echo "e2e FAIL: $OK_COUNT scenario checkpoints ran, the pin says 88 —"
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_09_hosts.sh
Old New
@@ -411,6 +411,82 @@ pipe_waitexit "hosts x: the other client" 128
411 wait_sessions "$SOCKH1" 2 "hosts x: only xb ended" 411 wait_sessions "$SOCKH1" 2 "hosts x: only xb ended"
412 ok "x refuses while others are attached, then ends; the other client sees the exit" 412 ok "x refuses while others are attached, then ends; the other client sees the exit"
413 413
414 # ---- ...and on a WALL it ends the FOCUSED tile's session, only that one --
415 #
416 # The leg above holds ONE tile: it can say the two-step is a two-step and
417 # nothing at all about WHICH session an `x` reaches. Five tiles over two
418 # daemons here, and the one that takes the chord is neither the first nor
419 # the last — an `x` that ended the wall's first tile, the focus's
420 # neighbour, or the daemon's own default session passes a wall of one and
421 # dies here.
422 #
423 # `xm` is born LAST on daemon 1, so the daemon reports it third and the
424 # wall lays it out at digit 3 of 5 (both daemons' lists, in file order).
425 # The digit is not ASSUMED: the focused bar names the session it landed
426 # on, and the grep below is what makes a reordered fixture a failure
427 # instead of a leg that ends somebody else's shell and still passes.
428 pipe_mux "$OUT.hxm" "$OUT.hxm.err" env XDG_STATE_HOME="$HSTATE" timeout 40 \
429 "$MUX" --sock "$SOCKH1" --session xm
430 pipe_send 'echo xmpid=$$\n'
431 await_out "$OUT.hxm" "xmpid=" "hosts wall x: the shell pid never reached the client"
432 pipe_detach "hosts wall x setup"
433 wait_grid "$SOCKH1" "xmpid=" "hosts wall x: session xm's shell pid" xm
434 XMPID=$(dump_session "$SOCKH1" xm | sed -n 's/.*xmpid=\([0-9]*\).*/\1/p' | tail -1)
435 [ -n "$XMPID" ] || { echo "e2e FAIL: hosts wall x: session xm printed no pid"; exit 1; }
436 wait_sessions "$SOCKH1" 3 "hosts wall x: daemon 1 should hold 0, b and xm"
437
438 set +e
439 # The default cut over the two hosts' live lists is what makes digit 3 the
440 # third session in file order; a tree an earlier wall left here would be
441 # somebody else's ordering.
442 no_saved_tree "$HSTATE"
443 XDG_STATE_HOME="$HSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 44 \
444 --out "$OUT.hxmcap" --err "$OUT.hxmcap.err" -- "$MUX" > "$OUT.hxmpc" 2>&1 <<'EOF'
445 expect xmpid= 25000
446 settle 1500 25000
447 send \x1c3
448 expect 3> --sock 20000
449 send \x1cx
450 settle 2500 25000
451 send \x1cd
452 waitexit 15000
453 EOF
454 RC=$?
455 set -e
456 [ "$RC" -eq 0 ] || {
457 echo "e2e FAIL: hosts wall x: the wall leg exited $RC:"
458 cat "$OUT.hxmpc"; echo "--- stderr ---"; cat "$OUT.hxmcap.err"; exit 1; }
459 # WHICH tile digit 3 focused, before anything is read into the `x` that
460 # followed it. One press and not two, deliberately: nothing else holds this
461 # session, so the daemon's refusal has nothing to count and the first press
462 # is the accepted one — the leg above owns the two-step.
463 grep -q -- "3> --sock $SOCKH1#xm \[up\]" "$OUT.hxmcap" || {
464 echo "e2e FAIL: hosts wall x: digit 3 focused something other than"
465 echo " $SOCKH1#xm, so the x below was aimed at another session:"
466 grep -ao '[0-9]> --sock[^ ]* ' "$OUT.hxmcap" | sort -u | head; exit 1; }
467 # The OS, not the daemon: the shell the focused tile's session held is
468 # gone. A daemon reporting its own session table cannot catch itself
469 # leaving a shell behind.
470 wait_pid_gone "$XMPID" "hosts wall x: the focused tile's shell after x"
471 wait_sessions "$SOCKH1" 2 "hosts wall x: daemon 1 back to 0 and b"
472 wait_sessions "$SOCKH2" 2 "hosts wall x: the other daemon must be untouched"
473 # ...and the tile left on the next LIST, judged on the grid: the bar is in
474 # the stream either way, and only the render says what was still on the
475 # screen when the wall came down.
476 "$RENDER" --cols 80 --rows 44 < "$OUT.hxmcap" > "$OUT.hxmgrid" || {
477 echo "e2e FAIL: hosts wall x: render oracle failed"; cat "$OUT.hxmgrid"; exit 1; }
478 grep -q -- "--sock $SOCKH1#xm" "$OUT.hxmgrid" && {
479 echo "e2e FAIL: hosts wall x: the ended session still has a tile on the"
480 echo " final wall — a tile leaves on the next list:"
481 cat "$OUT.hxmgrid"; exit 1; }
482 for _hx in "$SOCKH1#0" "$SOCKH1#b" "$SOCKH2#0" "$SOCKH2#c"; do
483 grep -q -- "--sock $_hx" "$OUT.hxmgrid" || {
484 echo "e2e FAIL: hosts wall x: '$_hx' lost its tile when its neighbour"
485 echo " was ended:"
486 cat "$OUT.hxmgrid"; exit 1; }
487 done
488 ok "x on a wall ends the focused tile's session and no other, and that tile leaves the next list"
489
414 # ---- a daemon that goes and comes back re-creates NOTHING --------------- 490 # ---- a daemon that goes and comes back re-creates NOTHING ---------------
415 # 491 #
416 # The model's sharpest edge. Sessions live in the daemon, so a daemon that 492 # The model's sharpest edge. Sessions live in the daemon, so a daemon that