a73x

ff60cc02

test: every e2e poll budget rides TIME_SCALE

a73x   2026-09-01 13:45

Commit message
test: every e2e poll budget rides TIME_SCALE

Eleven hand-rolled loops counted bare literals, so coverage's 4x
scale never reached them; five become wait_grid, four go through a
new wait_until in e2e_lib, and the rest scale their literal in place
where the needle or the dump is deliberately different.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

test/e2e_01_boot.sh
Old New
@@ -735,12 +735,15 @@ D4PID=$DPID
735 # same match are two matches waiting to drift apart. 735 # same match are two matches waiting to drift apart.
736 udp_local_bound() { awk -v h="$1" '$2==h{f=1} END{exit !f}' /proc/net/udp; } 736 udp_local_bound() { awk -v h="$1" '$2==h{f=1} END{exit !f}' /proc/net/udp; }
737 i=0 737 i=0
738 # 50 x 0.1s, the same 5s every daemon wait in this file allows. 738 # 50 x 0.1s, the same 5s every daemon wait in this file allows — and scaled
739 while ! udp_local_bound "$QHEX" && [ "$i" -lt 50 ]; do 739 # by TIME_SCALE like every other budget, because under test/coverage.sh the
740 # traced daemon takes longer to reach its bind and a bare 5s reads the delay
741 # as "it never rebound".
742 while ! udp_local_bound "$QHEX" && [ "$i" -lt $(( 50 * TIME_SCALE )) ]; do
740 sleep 0.1; i=$((i+1)) 743 sleep 0.1; i=$((i+1))
741 done 744 done
742 udp_local_bound "$QHEX" || { 745 udp_local_bound "$QHEX" || {
743 echo "e2e FAIL: restarted daemon did not rebind udp 127.0.0.1:$QPORT ($QHEX) in 5s" 746 echo "e2e FAIL: restarted daemon did not rebind udp 127.0.0.1:$QPORT ($QHEX) in $(( 5 * TIME_SCALE ))s"
744 echo " daemon pid $D4PID: $(ps -o stat=,comm= -p "$D4PID" 2>/dev/null || echo gone)" 747 echo " daemon pid $D4PID: $(ps -o stat=,comm= -p "$D4PID" 2>/dev/null || echo gone)"
745 echo " /proc/net/udp lines mentioning the port:" 748 echo " /proc/net/udp lines mentioning the port:"
746 grep -i " $QHEX " /proc/net/udp || echo " (none)" 749 grep -i " $QHEX " /proc/net/udp || echo " (none)"
test/e2e_02_predict.sh
Old New
@@ -665,11 +665,7 @@ D13PID=$DPID
665 # the session goes quiet there (cat prints no prompt), history_rows is 77, 665 # the session goes quiet there (cat prints no prompt), history_rows is 77,
666 # and page 1 is rows 54..77. Every needle below is chosen against those 666 # and page 1 is rows 54..77. Every needle below is chosen against those
667 # numbers, which is why this wait is part of the scenario and not a nicety. 667 # numbers, which is why this wait is part of the scenario and not a nicety.
668 i=0 668 wait_grid "$SOCK13" "100" "tp1 session never finished seq"
669 until "$MUX" d dump --sock "$SOCK13" | grep -q "100"; do
670 i=$((i+1)); [ "$i" -lt 100 ] || { echo "e2e FAIL: tp1 session never finished seq"; exit 1; }
671 sleep 0.1
672 done
673 669
674 # MUX_PREDICT_STATS is exported into the FIXTURE's environment, not spelled 670 # MUX_PREDICT_STATS is exported into the FIXTURE's environment, not spelled
675 # as a `VAR=x cmd` prefix on the client: the fixture execve()s its child 671 # as a `VAR=x cmd` prefix on the client: the fixture execve()s its child
test/e2e_05_session.sh
Old New
@@ -333,7 +333,11 @@ while : ; do
333 D20PID=$! 333 D20PID=$!
334 defer_kill "$D20PID" 334 defer_kill "$D20PID"
335 _i=0 335 _i=0
336 while [ ! -S "$SOCK23" ] && kill -0 "$D20PID" 2>/dev/null && [ "$_i" -lt 60 ]; do 336 # Not wait_sock: this wait also watches the daemon's own pid, because a
337 # daemon that refused the udp port EXITS and the retry below wants to
338 # read its words now rather than after the full budget. The budget is
339 # scaled for wait_sock's reason all the same.
340 while [ ! -S "$SOCK23" ] && kill -0 "$D20PID" 2>/dev/null && [ "$_i" -lt $(( 60 * TIME_SCALE )) ]; do
337 sleep 0.1; _i=$((_i + 1)) 341 sleep 0.1; _i=$((_i + 1))
338 done 342 done
339 [ -S "$SOCK23" ] && break 343 [ -S "$SOCK23" ] && break
test/e2e_06_web.sh
Old New
@@ -411,14 +411,8 @@ SESS_BEFORE=$("$MUX" d stats --sock "$SOCK25" | sed -n 's/.*sessions=\([0-9]*\).
411 R=$(curl -s -H "Origin: $DWORIG" -X POST "$DWORIG/tiles/$DWID_A0") 411 R=$(curl -s -H "Origin: $DWORIG" -X POST "$DWORIG/tiles/$DWID_A0")
412 [ "$R" = '{"session":"1"}' ] || { 412 [ "$R" = '{"session":"1"}' ] || {
413 echo "e2e FAIL: host wall: spawn on A's tile returned $R, want session 1"; exit 1; } 413 echo "e2e FAIL: host wall: spawn on A's tile returned $R, want session 1"; exit 1; }
414 _i=0 414 wait_until 60 "host wall: the born session never became a tile; the wall holds:" \
415 while [ "$_i" -lt 60 ]; do 415 '[ -n "$(dw_id_of "--sock $SOCK25" 1)" ]' 'curl -s "$DWORIG/tiles"'
416 [ -n "$(dw_id_of "--sock $SOCK25" 1)" ] && break
417 sleep 0.1; _i=$((_i+1))
418 done
419 [ "$_i" -lt 60 ] || {
420 echo "e2e FAIL: host wall: the born session never became a tile; the wall holds:"
421 curl -s "$DWORIG/tiles"; exit 1; }
422 # Asked of the DAEMON, not of the hub: a hub reporting on a birth it made 416 # Asked of the DAEMON, not of the hub: a hub reporting on a birth it made
423 # cannot catch itself being wrong about whether a shell exists. 417 # cannot catch itself being wrong about whether a shell exists.
424 SESS_AFTER=$("$MUX" d stats --sock "$SOCK25" | sed -n 's/.*sessions=\([0-9]*\).*/\1/p') 418 SESS_AFTER=$("$MUX" d stats --sock "$SOCK25" | sed -n 's/.*sessions=\([0-9]*\).*/\1/p')
@@ -438,25 +432,16 @@ DWID_A1=$(dw_id_of "--sock $SOCK25" 1)
438 # `$$` — because a daemon reporting on its own children cannot catch itself 432 # `$$` — because a daemon reporting on its own children cannot catch itself
439 # being wrong about whether one is still there. 433 # being wrong about whether one is still there.
440 timeout 20 "$MUX" a send 'printf "bornpid-%s\n" $$\n' --sock "$SOCK25" --session 1 > /dev/null 2>&1 434 timeout 20 "$MUX" a send 'printf "bornpid-%s\n" $$\n' --sock "$SOCK25" --session 1 > /dev/null 2>&1
441 _i=0 435 wait_until 80 "host wall: the born session never said its own pid; it holds:" \
442 while [ "$_i" -lt 80 ]; do 436 'timeout 20 "$MUX" a capture --sock "$SOCK25" --session 1 > "$OUT.dwpid" 2>&1; grep -q "bornpid-[0-9]" "$OUT.dwpid"' \
443 timeout 20 "$MUX" a capture --sock "$SOCK25" --session 1 > "$OUT.dwpid" 2>&1 437 'cat "$OUT.dwpid"'
444 grep -q "bornpid-[0-9]" "$OUT.dwpid" && break
445 sleep 0.1; _i=$((_i+1))
446 done
447 DWSHELL=$(sed -n 's/.*bornpid-\([0-9][0-9]*\).*/\1/p' "$OUT.dwpid" | head -1) 438 DWSHELL=$(sed -n 's/.*bornpid-\([0-9][0-9]*\).*/\1/p' "$OUT.dwpid" | head -1)
448 [ -n "$DWSHELL" ] || { 439 [ -n "$DWSHELL" ] || {
449 echo "e2e FAIL: host wall: the born session never said its own pid; it holds:" 440 echo "e2e FAIL: host wall: the born session never said its own pid; it holds:"
450 cat "$OUT.dwpid"; exit 1; } 441 cat "$OUT.dwpid"; exit 1; }
451 timeout 20 "$MUX" a send 'exit\n' --sock "$SOCK25" --session 1 > /dev/null 2>&1 || true 442 timeout 20 "$MUX" a send 'exit\n' --sock "$SOCK25" --session 1 > /dev/null 2>&1 || true
452 _i=0 443 wait_until 80 "host wall: the ended session's tile never left; the wall holds:" \
453 while [ "$_i" -lt 80 ]; do 444 '! curl -s "$DWORIG/tiles" | grep -q "\"session\":\"1\""' 'curl -s "$DWORIG/tiles"'
454 curl -s "$DWORIG/tiles" | grep -q '"session":"1"' || break
455 sleep 0.1; _i=$((_i+1))
456 done
457 [ "$_i" -lt 80 ] || {
458 echo "e2e FAIL: host wall: the ended session's tile never left; the wall holds:"
459 curl -s "$DWORIG/tiles"; exit 1; }
460 # Asked of the OS, not of the daemon. 445 # Asked of the OS, not of the daemon.
461 [ ! -e "/proc/$DWSHELL" ] || { 446 [ ! -e "/proc/$DWSHELL" ] || {
462 echo "e2e FAIL: host wall: the shell pid $DWSHELL outlived its session per /proc" 447 echo "e2e FAIL: host wall: the shell pid $DWSHELL outlived its session per /proc"
@@ -470,14 +455,8 @@ done
470 R=$(curl -s -H "Origin: $DWORIG" -X POST "$DWORIG/tiles/$DWID_A0") 455 R=$(curl -s -H "Origin: $DWORIG" -X POST "$DWORIG/tiles/$DWID_A0")
471 [ "$R" = '{"session":"1"}' ] || { 456 [ "$R" = '{"session":"1"}' ] || {
472 echo "e2e FAIL: host wall: the second spawn returned $R, want session 1 again"; exit 1; } 457 echo "e2e FAIL: host wall: the second spawn returned $R, want session 1 again"; exit 1; }
473 _i=0 458 wait_until 60 "host wall: the second birth never became a tile; the wall holds:" \
474 while [ "$_i" -lt 60 ]; do 459 '[ -n "$(dw_id_of "--sock $SOCK25" 1)" ]' 'curl -s "$DWORIG/tiles"'
475 [ -n "$(dw_id_of "--sock $SOCK25" 1)" ] && break
476 sleep 0.1; _i=$((_i+1))
477 done
478 [ "$_i" -lt 60 ] || {
479 echo "e2e FAIL: host wall: the second birth never became a tile; the wall holds:"
480 curl -s "$DWORIG/tiles"; exit 1; }
481 [ "$(dw_id_of "--sock $SOCK25" 1)" != "$DWID_A1" ] || { 460 [ "$(dw_id_of "--sock $SOCK25" 1)" != "$DWID_A1" ] || {
482 echo "e2e FAIL: host wall: session 1 came back on the SAME id $DWID_A1" 461 echo "e2e FAIL: host wall: session 1 came back on the SAME id $DWID_A1"
483 curl -s "$DWORIG/tiles"; exit 1; } 462 curl -s "$DWORIG/tiles"; exit 1; }
test/e2e_08_mouse.sh
Old New
@@ -87,11 +87,7 @@ start_daemon "$SOCK33" "$OUT.whl.d" "wheel daemon never bound" --shell "$WHEELSH
87 D30PID=$DPID 87 D30PID=$DPID
88 # Attach only once seq has finished, for tp1's reason: the page the wheel 88 # Attach only once seq has finished, for tp1's reason: the page the wheel
89 # fetches has to be content this client was never sent. 89 # fetches has to be content this client was never sent.
90 i=0 90 wait_grid "$SOCK33" "100" "wheel session never finished seq"
91 until "$MUX" d dump --sock "$SOCK33" | grep -q "100"; do
92 i=$((i+1)); [ "$i" -lt 100 ] || { echo "e2e FAIL: wheel session never finished seq"; exit 1; }
93 sleep 0.1
94 done
95 # `\x1b[0m100`, not "100": the client asks its own terminal for mouse 91 # `\x1b[0m100`, not "100": the client asks its own terminal for mouse
96 # reporting with `\x1b[?1000h`, so a bare "100" is in this capture before 92 # reporting with `\x1b[?1000h`, so a bare "100" is in this capture before
97 # any row is. The SGR reset in front of it is the paint's, and nothing else 93 # any row is. The SGR reset in front of it is the paint's, and nothing else
@@ -157,11 +153,7 @@ EOF
157 chmod +x "$MOUSESH" 153 chmod +x "$MOUSESH"
158 start_daemon "$SOCK34" "$OUT.mse.d" "app-mouse daemon never bound" --shell "$MOUSESH" 154 start_daemon "$SOCK34" "$OUT.mse.d" "app-mouse daemon never bound" --shell "$MOUSESH"
159 D31PID=$DPID 155 D31PID=$DPID
160 i=0 156 wait_grid "$SOCK34" "app-holds-the-mouse" "app-mouse session never armed"
161 until "$MUX" d dump --sock "$SOCK34" | grep -q "app-holds-the-mouse"; do
162 i=$((i+1)); [ "$i" -lt 100 ] || { echo "e2e FAIL: app-mouse session never armed"; exit 1; }
163 sleep 0.1
164 done
165 # The modes are already set when this client attaches, so they arrive in 157 # The modes are already set when this client attaches, so they arrive in
166 # the attach's own term_modes and there is no race to settle for. The echo 158 # the attach's own term_modes and there is no race to settle for. The echo
167 # is the assertion: cat is in canonical mode with ECHOCTL, so bytes that 159 # is the assertion: cat is in canonical mode with ECHOCTL, so bytes that
@@ -226,9 +218,13 @@ EOF
226 chmod +x "$LESSSH" 218 chmod +x "$LESSSH"
227 start_daemon "$SOCK35" "$OUT.pgr.d" "pager daemon never bound" --shell "$LESSSH" 219 start_daemon "$SOCK35" "$OUT.pgr.d" "pager daemon never bound" --shell "$LESSSH"
228 D32PID=$DPID 220 D32PID=$DPID
221 # Not wait_grid: the needle is anchored (`-qx`, a row that is EXACTLY the
222 # file's last line, so a half-painted `2` does not pass) and the dump is
223 # trimmed to the last rows, because a pager's whole grid is 24 rows of
224 # numbers that say nothing about why it stopped short.
229 i=0 225 i=0
230 until "$MUX" d dump --sock "$SOCK35" | grep -qx "200"; do 226 until "$MUX" d dump --sock "$SOCK35" | grep -qx "200"; do
231 i=$((i+1)); [ "$i" -lt 100 ] || { 227 i=$((i+1)); [ "$i" -lt $(( 100 * TIME_SCALE )) ] || {
232 echo "e2e FAIL: pager never reached the end of the file:" 228 echo "e2e FAIL: pager never reached the end of the file:"
233 "$MUX" d dump --sock "$SOCK35" | tail -3; exit 1; } 229 "$MUX" d dump --sock "$SOCK35" | tail -3; exit 1; }
234 sleep 0.1 230 sleep 0.1
@@ -294,9 +290,12 @@ D33PID=$DPID
294 RC=$? 290 RC=$?
295 [ "$RC" -eq 0 ] || { 291 [ "$RC" -eq 0 ] || {
296 echo "e2e FAIL: pipe stdin: the client exited $RC:"; cat "$OUT.pipe"; exit 1; } 292 echo "e2e FAIL: pipe stdin: the client exited $RC:"; cat "$OUT.pipe"; exit 1; }
293 # Not wait_grid: this asks `mux a capture`, the agent surface, not
294 # `mux d dump` — the piped client is the thing under test, so the reading
295 # has to come down the same road an agent would use.
297 i=0 296 i=0
298 until timeout 20 "$MUX" a capture --sock "$SOCK36" 2>&1 | grep -qF -- "world"; do 297 until timeout 20 "$MUX" a capture --sock "$SOCK36" 2>&1 | grep -qF -- "world"; do
299 i=$((i+1)); [ "$i" -lt 100 ] || { 298 i=$((i+1)); [ "$i" -lt $(( 100 * TIME_SCALE )) ] || {
300 echo "e2e FAIL: pipe stdin: the piped line never reached the pty:" 299 echo "e2e FAIL: pipe stdin: the piped line never reached the pty:"
301 timeout 20 "$MUX" a capture --sock "$SOCK36"; exit 1; } 300 timeout 20 "$MUX" a capture --sock "$SOCK36"; exit 1; }
302 sleep 0.1 301 sleep 0.1
@@ -471,11 +470,7 @@ start_daemon "$SOCK41" "$OUT.zw.d" "wheel daemon never bound" --shell "$ZWHEELSH
471 D38PID=$DPID 470 D38PID=$DPID
472 # The wall attaches only once seq has finished, scenario 42's reason: the 471 # The wall attaches only once seq has finished, scenario 42's reason: the
473 # page the wheel fetches has to be content this tile was never sent. 472 # page the wheel fetches has to be content this tile was never sent.
474 i=0 473 wait_grid "$SOCK41" "wln100" "wheel: session never finished seq"
475 until "$MUX" d dump --sock "$SOCK41" | grep -q "wln100"; do
476 i=$((i+1)); [ "$i" -lt 100 ] || { echo "e2e FAIL: wheel: session never finished seq"; exit 1; }
477 sleep 0.1
478 done
479 set +e 474 set +e
480 no_saved_tree "$ZWSTATE" 475 no_saved_tree "$ZWSTATE"
481 XDG_STATE_HOME="$ZWSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 \ 476 XDG_STATE_HOME="$ZWSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 \
@@ -541,11 +536,7 @@ EOF
541 chmod +x "$ZMOUSESH" 536 chmod +x "$ZMOUSESH"
542 start_daemon "$SOCK42" "$OUT.zm2.d" "app-mouse daemon never bound" --shell "$ZMOUSESH" 537 start_daemon "$SOCK42" "$OUT.zm2.d" "app-mouse daemon never bound" --shell "$ZMOUSESH"
543 D39PID=$DPID 538 D39PID=$DPID
544 i=0 539 wait_grid "$SOCK42" "mapp-holds-the-mouse" "app mouse: session never armed"
545 until "$MUX" d dump --sock "$SOCK42" | grep -q "mapp-holds-the-mouse"; do
546 i=$((i+1)); [ "$i" -lt 100 ] || { echo "e2e FAIL: app mouse: session never armed"; exit 1; }
547 sleep 0.1
548 done
549 # The echo is the assertion: cat is in canonical mode with ECHOCTL, so bytes 540 # The echo is the assertion: cat is in canonical mode with ECHOCTL, so bytes
550 # that reach the pty come back as `^[[<64;10;5M` and bytes that do not, do 541 # that reach the pty come back as `^[[<64;10;5M` and bytes that do not, do
551 # not. The tile claims the terminal on its first pass, so the modes are 542 # not. The tile claims the terminal on its first pass, so the modes are
test/e2e_lib.sh
Old New
@@ -618,6 +618,40 @@ wait_sessions() {
618 exit 1 618 exit 1
619 } 619 }
620 620
621 # wait_until TENTHS LABEL PREDICATE [DUMP] — poll a shell PREDICATE until it
622 # succeeds, for TENTHS tenths of a second scaled by TIME_SCALE, then ASSERT
623 # it and print DUMP on failure. wait_grid's discipline for the waits whose
624 # subject is not a daemon grid — an HTTP body from the browser hub, a
625 # fixture's capture file. The budget is spelled in tenths because that is
626 # what the hand-rolled loops it replaces counted, so a conversion is one
627 # number moved and nothing else.
628 #
629 # PREDICATE and DUMP are EVALUATED ON EVERY TICK, so pass them single-quoted
630 # and let the expansion happen here: a `$(curl ...)` that the call site
631 # expanded once would poll its own first answer forever and time out on a
632 # wall that changed a tick later.
633 #
634 # eval rather than running "$@" as argv: every predicate these waits need is
635 # a pipeline or a command substitution, and neither survives being carried
636 # as a command and its arguments.
637 wait_until() {
638 _i=0
639 while [ "$_i" -lt $(( $1 * TIME_SCALE )) ]; do
640 # First command of an AND-OR list, which set -e exempts (wait_grid's
641 # shape): a predicate that is false on this tick is the normal case
642 # and must not abort the group.
643 eval "$3" && return 0
644 sleep 0.1; _i=$((_i+1))
645 done
646 echo "e2e FAIL: $2"
647 # `|| true` because the dump is read in the failure state that provoked
648 # it — a curl against a hub that died exits 7, and that status would
649 # become this function's under set -e, replacing the exit 1 the runner
650 # reads with a number that means something else.
651 if [ -n "${4:-}" ]; then eval "$4" || true; fi
652 exit 1
653 }
654
621 # --- tiles attach once each: did the daemon see a second? ------------- 655 # --- tiles attach once each: did the daemon see a second? -------------
622 # 656 #
623 # The focus model's whole claim is that a tile's connection is its own — 657 # The focus model's whole claim is that a tile's connection is its own —