a0915d2d
test: the non-tty scenarios wait for their output instead of sleeping for it
a73x 2026-08-22 10:09
Commit message
test/e2e.sh
| Old | New | ||
|---|---|---|---|
| @@ -210,15 +210,13 @@ HQPORT=$(( 11000 + ($$ % 4000) )) | |||
| 210 | HDEADPORT=$(( 16000 + ($$ % 4000) )) | 210 | HDEADPORT=$(( 16000 + ($$ % 4000) )) |
| 211 | HAPID="" | 211 | HAPID="" |
| 212 | HDPID="" | 212 | HDPID="" |
| 213 | # The three handoff clients that run in the BACKGROUND. Each is already | 213 | # The pipe_mux client in flight, and its FIFO. Bounded by its own |
| 214 | # bounded by its own `timeout`, which stays the primary guarantee; these | 214 | # `timeout`, which stays the primary guarantee; this is the trap's backstop |
| 215 | # are the trap's backstop for the window where a scenario exits between | 215 | # for a scenario that exits between pipe_mux and pipe_detach, leaving a |
| 216 | # the launch and the wait, leaving a client the shell would otherwise | 216 | # client the shell would otherwise orphan. Declared here so the trap can |
| 217 | # orphan. Declared here so the trap can read them under `set -u`. | 217 | # read them under `set -u`. |
| 218 | H1PID="" | 218 | PIPE_PID="" |
| 219 | H3PID="" | 219 | PIPE_IN="" |
| 220 | H4PID="" | ||
| 221 | H5PID="" | ||
| 222 | # M-web. Three daemons (the passivity pin's, the hub-basic one, and the | 220 | # M-web. Three daemons (the passivity pin's, the hub-basic one, and the |
| 223 | # tear scenario's two incarnations share SOCK20), two hub processes, and | 221 | # tear scenario's two incarnations share SOCK20), two hub processes, and |
| 224 | # a port band of its own following the 5000-spacing convention — INSIDE | 222 | # a port band of its own following the 5000-spacing convention — INSIDE |
| @@ -605,6 +603,107 @@ wait_sock() { | |||
| 605 | } | 603 | } |
| 606 | } | 604 | } |
| 607 | 605 | ||
| 606 | # pipe_mux OUT ERR CMD... — a client on a plain pipe, and the pipe kept | ||
| 607 | # open. ERR is the stderr capture, "" to leave it on the suite's own. | ||
| 608 | # The suite's non-tty scenarios used to be `{ printf cmd; sleep 2; printf | ||
| 609 | # detach; } | "$MUX"`: two seconds bought for output that lands in | ||
| 610 | # milliseconds (measured: the needle is in the capture 2ms after the send), | ||
| 611 | # and 120s of the suite's runtime was exactly that purchase. Here the stdin | ||
| 612 | # is a FIFO held open on fd 9, so a scenario sends, then WAITS FOR THE NEEDLE | ||
| 613 | # with await_out, then detaches — the same assertion it was going to make | ||
| 614 | # anyway, moved to where it ends the wait. fd 9 is opened read-write so | ||
| 615 | # neither the open nor the client's EOF blocks on the other side; the client | ||
| 616 | # sees EOF only when pipe_detach closes it. | ||
| 617 | # | ||
| 618 | # Not for the scenarios that pace on purpose: the prediction legs snapshot | ||
| 619 | # the capture N ms after a keystroke, and a sleep there IS the test. | ||
| 620 | pipe_mux() { | ||
| 621 | PIPE_OUT="$1"; PIPE_ERR="$2"; shift 2 | ||
| 622 | PIPE_IN="$PIPE_OUT.in" | ||
| 623 | rm -f "$PIPE_IN" | ||
| 624 | mkfifo "$PIPE_IN" | ||
| 625 | exec 9<>"$PIPE_IN" | ||
| 626 | if [ -n "$PIPE_ERR" ]; then | ||
| 627 | "$@" < "$PIPE_IN" > "$PIPE_OUT" 2> "$PIPE_ERR" & | ||
| 628 | else | ||
| 629 | "$@" < "$PIPE_IN" > "$PIPE_OUT" & | ||
| 630 | fi | ||
| 631 | PIPE_PID=$! | ||
| 632 | } | ||
| 633 | |||
| 634 | # pipe_send FMT [ARGS] — printf into the open client, same spelling the | ||
| 635 | # inline blocks used so a conversion moves the format string verbatim. | ||
| 636 | pipe_send() { | ||
| 637 | # shellcheck disable=SC2059 | ||
| 638 | printf "$@" >&9 | ||
| 639 | } | ||
| 640 | |||
| 641 | # await_out FILE NEEDLE LABEL — wait_for with the verdict attached: FAIL | ||
| 642 | # with the capture when NEEDLE never comes (5s, scaled). The same `grep -q` | ||
| 643 | # the scenario asserts with afterwards, so waiting on it costs no new claim. | ||
| 644 | await_out() { | ||
| 645 | wait_for "$1" "$2" 5 || { | ||
| 646 | echo "e2e FAIL: $3; never saw '$2' in $1, which holds:" | ||
| 647 | cat "$1" | ||
| 648 | exit 1 | ||
| 649 | } | ||
| 650 | } | ||
| 651 | |||
| 652 | # repaints FILE — how many full repaints (ESC[2J) a capture holds. The | ||
| 653 | # first paint after a reconnect is always a full one (interact.zig | ||
| 654 | # `repaint_after_resync`), so a count that rose is the resume itself, seen | ||
| 655 | # from the terminal's side. Keystrokes typed into a tear are dropped, not | ||
| 656 | # held, so a scenario that tears the transport must see this before it | ||
| 657 | # types again. | ||
| 658 | repaints() { | ||
| 659 | _clr=$(printf '\033[2J') | ||
| 660 | grep -a -F -o "$_clr" "$1" 2>/dev/null | wc -l | ||
| 661 | } | ||
| 662 | |||
| 663 | # await_repaint FILE BASELINE LABEL — wait until repaints FILE exceeds | ||
| 664 | # BASELINE (5s, scaled), FAIL with the capture otherwise. | ||
| 665 | await_repaint() { | ||
| 666 | _i=0 | ||
| 667 | while [ "$(repaints "$1")" -le "$2" ] && [ "$_i" -lt $(( 50 * TIME_SCALE )) ]; do | ||
| 668 | sleep 0.1; _i=$((_i+1)) | ||
| 669 | done | ||
| 670 | [ "$(repaints "$1")" -gt "$2" ] || { | ||
| 671 | echo "e2e FAIL: $3; no repaint after the tear in $1, which holds:" | ||
| 672 | cat "$1" | ||
| 673 | exit 1 | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | # pipe_detach [LABEL] — the Ctrl-\ chord, then EOF, then the client's own | ||
| 678 | # exit, which must be 0: a foreground `| "$MUX"` under set -e asserted that | ||
| 679 | # by accident, and this asserts it on purpose. LABEL names the client in | ||
| 680 | # the verdict; PIPE_RC is left for a scenario with more to say. | ||
| 681 | pipe_detach() { | ||
| 682 | printf '\034\034' >&9 | ||
| 683 | pipe_waitexit "$@" | ||
| 684 | } | ||
| 685 | |||
| 686 | # pipe_waitexit [LABEL [WANT]] — the client leaves on its own (its session | ||
| 687 | # ended); wait for that, then release the FIFO. Stdin stays open until the | ||
| 688 | # exit so the client never sees an EOF it was not sent. WANT is the exit | ||
| 689 | # status the scenario means (default 0): the exit-semantics legs want the | ||
| 690 | # shell's own. | ||
| 691 | pipe_waitexit() { | ||
| 692 | set +e | ||
| 693 | wait "$PIPE_PID" | ||
| 694 | PIPE_RC=$? | ||
| 695 | set -e | ||
| 696 | exec 9>&- | ||
| 697 | PIPE_PID="" | ||
| 698 | rm -f "$PIPE_IN" | ||
| 699 | [ "$PIPE_RC" -eq "${2:-0}" ] || { | ||
| 700 | echo "e2e FAIL: ${1:-piped client} exited $PIPE_RC (want ${2:-0}; 124 means it hung)" | ||
| 701 | cat "$PIPE_OUT" | ||
| 702 | if [ -n "$PIPE_ERR" ]; then cat "$PIPE_ERR"; fi | ||
| 703 | exit 1 | ||
| 704 | } | ||
| 705 | } | ||
| 706 | |||
| 608 | # dump_session SOCK [NAME] — `muxd dump` against one session (M18). An | 707 | # dump_session SOCK [NAME] — `muxd dump` against one session (M18). An |
| 609 | # EMPTY or absent NAME passes no --session flag AT ALL rather than an empty | 708 | # EMPTY or absent NAME passes no --session flag AT ALL rather than an empty |
| 610 | # one, and that is the load-bearing part: no tail is the wire's own | 709 | # one, and that is the load-bearing part: no tail is the wire's own |
| @@ -1126,10 +1225,10 @@ cleanup() { | |||
| 1126 | # The backgrounded clients, by tracked pid. Their `timeout` bounds them | 1225 | # The backgrounded clients, by tracked pid. Their `timeout` bounds them |
| 1127 | # anyway; this only shortens the wait on a run that failed between a | 1226 | # anyway; this only shortens the wait on a run that failed between a |
| 1128 | # launch and its wait. | 1227 | # launch and its wait. |
| 1129 | [ -n "$H1PID" ] && kill "$H1PID" 2>/dev/null || true | 1228 | # Whatever pipe_mux client a failing scenario left mid-flight, and the |
| 1130 | [ -n "$H3PID" ] && kill "$H3PID" 2>/dev/null || true | 1229 | # FIFO that was its stdin. |
| 1131 | [ -n "$H4PID" ] && kill "$H4PID" 2>/dev/null || true | 1230 | [ -n "$PIPE_PID" ] && kill "$PIPE_PID" 2>/dev/null || true |
| 1132 | [ -n "$H5PID" ] && kill "$H5PID" 2>/dev/null || true | 1231 | [ -n "$PIPE_IN" ] && rm -f "$PIPE_IN" || true |
| 1133 | [ -n "${MUXD:-}" ] && "$MUXD" stop --sock "$SOCK16" >/dev/null 2>&1 || true | 1232 | [ -n "${MUXD:-}" ] && "$MUXD" stop --sock "$SOCK16" >/dev/null 2>&1 || true |
| 1134 | [ -n "${MUXD:-}" ] && "$MUXD" stop --sock "$SOCK17" >/dev/null 2>&1 || true | 1233 | [ -n "${MUXD:-}" ] && "$MUXD" stop --sock "$SOCK17" >/dev/null 2>&1 || true |
| 1135 | # M-web: hubs and daemons by tracked pid, then stop-by-socket for any | 1234 | # M-web: hubs and daemons by tracked pid, then stop-by-socket for any |
| @@ -1516,15 +1615,13 @@ DPID=$! | |||
| 1516 | 1615 | ||
| 1517 | wait_sock "$SOCK" "$OUT.d1.d" "socket never appeared" | 1616 | wait_sock "$SOCK" "$OUT.d1.d" "socket never appeared" |
| 1518 | 1617 | ||
| 1519 | # Client with piped stdio: types a command, waits, detaches with the | 1618 | # Client with piped stdio: types a command, waits for its output, detaches |
| 1520 | # Ctrl-\ chord (\034\034 — prefix, then prefix again for detach). | 1619 | # with the Ctrl-\ chord (prefix, then prefix again for detach). |
| 1521 | { printf 'printf "e2e-%%s\\n" works\n'; sleep 2; printf '\034\034'; } | \ | 1620 | pipe_mux "$OUT" "" timeout 30 "$MUX" --sock "$SOCK" |
| 1522 | timeout 30 "$MUX" --sock "$SOCK" > "$OUT" | 1621 | pipe_send 'printf "e2e-%%s\\n" works\n' |
| 1523 | |||
| 1524 | # 1. The client's rendered output must contain the command's result. | 1622 | # 1. The client's rendered output must contain the command's result. |
| 1525 | grep -q "e2e-works" "$OUT" || { | 1623 | await_out "$OUT" "e2e-works" "client render missing output" |
| 1526 | echo "e2e FAIL: client render missing output; got:"; cat "$OUT"; exit 1; | 1624 | pipe_detach |
| 1527 | } | ||
| 1528 | 1625 | ||
| 1529 | # 2. The daemon kept the session; its grid must match. | 1626 | # 2. The daemon kept the session; its grid must match. |
| 1530 | "$MUXD" dump --sock "$SOCK" | grep -q "e2e-works" || { | 1627 | "$MUXD" dump --sock "$SOCK" | grep -q "e2e-works" || { |
| @@ -1561,12 +1658,12 @@ ok "convergence control fires on a doctored stream" | |||
| 1561 | # The escapes are doubled because they are written by the SESSION's shell, | 1658 | # The escapes are doubled because they are written by the SESSION's shell, |
| 1562 | # not by this one: what goes down the pipe is the literal text | 1659 | # not by this one: what goes down the pipe is the literal text |
| 1563 | # `printf "\033[1;31mstyled-%s\033[0m\n" red bold`. | 1660 | # `printf "\033[1;31mstyled-%s\033[0m\n" red bold`. |
| 1564 | { printf 'printf "\\033[1;31mstyled-%%s\\033[0m\\n" red bold\n'; sleep 2; printf '\034\034'; } | \ | 1661 | pipe_mux "$OUT.st" "" timeout 30 "$MUX" --sock "$SOCK" |
| 1565 | timeout 30 "$MUX" --sock "$SOCK" > "$OUT.st" | 1662 | pipe_send 'printf "\\033[1;31mstyled-%%s\\033[0m\\n" red bold\n' |
| 1663 | await_out "$OUT.st" "styled-bold" "the second styled row never reached the client" | ||
| 1664 | pipe_detach | ||
| 1566 | grep -q "styled-red" "$OUT.st" || { | 1665 | grep -q "styled-red" "$OUT.st" || { |
| 1567 | echo "e2e FAIL: styled output never reached the client"; cat "$OUT.st"; exit 1; } | 1666 | echo "e2e FAIL: styled output never reached the client"; cat "$OUT.st"; exit 1; } |
| 1568 | grep -q "styled-bold" "$OUT.st" || { | ||
| 1569 | echo "e2e FAIL: the second styled row never reached the client"; cat "$OUT.st"; exit 1; } | ||
| 1570 | # The plain leg would pass on a bled attribute — same glyphs, wrong colours. | 1667 | # The plain leg would pass on a bled attribute — same glyphs, wrong colours. |
| 1571 | # The --vt leg inside assert_converged is the one that speaks here. | 1668 | # The --vt leg inside assert_converged is the one that speaks here. |
| 1572 | assert_converged "$OUT.st" "$SOCK" "styled content" | 1669 | assert_converged "$OUT.st" "$SOCK" "styled content" |
| @@ -1624,13 +1721,11 @@ rm_swept "$OUT.a" "$OUT.b" | |||
| 1624 | # XDG_RUNTIME_DIR is pointed at nothing so the test cannot pass by environment | 1721 | # XDG_RUNTIME_DIR is pointed at nothing so the test cannot pass by environment |
| 1625 | # luck: if --via ever silently fell back to the default socket path, that path | 1722 | # luck: if --via ever silently fell back to the default socket path, that path |
| 1626 | # would resolve to a directory that does not exist and the session would fail | 1723 | # would resolve to a directory that does not exist and the session would fail |
| 1627 | # instead of quietly attaching over the local socket. `|| true` keeps set -e | 1724 | # instead of quietly attaching over the local socket. |
| 1628 | # from aborting before the labelled diagnostic below runs. | 1725 | pipe_mux "$OUT.via" "" env XDG_RUNTIME_DIR=/nonexistent-mux-e2e "$MUX" --via "$MUXD proxy --sock $SOCK" |
| 1629 | { sleep 0.5; printf 'printf "m6-%%s\\n" via-pipe\n'; sleep 2; printf '\034\034'; } | \ | 1726 | pipe_send 'printf "m6-%%s\\n" via-pipe\n' |
| 1630 | XDG_RUNTIME_DIR=/nonexistent-mux-e2e "$MUX" --via "$MUXD proxy --sock $SOCK" > "$OUT.via" || true | 1727 | await_out "$OUT.via" "m6-via-pipe" "--via transport" |
| 1631 | grep -q "m6-via-pipe" "$OUT.via" || { | 1728 | pipe_detach |
| 1632 | echo "e2e FAIL: --via transport"; cat "$OUT.via"; exit 1; | ||
| 1633 | } | ||
| 1634 | kill -0 "$DPID" || { echo "e2e FAIL: daemon died in --via scenario"; exit 1; } | 1729 | kill -0 "$DPID" || { echo "e2e FAIL: daemon died in --via scenario"; exit 1; } |
| 1635 | assert_converged "$OUT.via" "$SOCK" "via transport" | 1730 | assert_converged "$OUT.via" "$SOCK" "via transport" |
| 1636 | rm_swept "$OUT.via" | 1731 | rm_swept "$OUT.via" |
| @@ -1743,21 +1838,18 @@ rm_swept "$OUT.abort" "$SOCK2" | |||
| 1743 | # resume renders "m7-after" perfectly well, so only `snapshots` holding | 1838 | # resume renders "m7-after" perfectly well, so only `snapshots` holding |
| 1744 | # still across the tear proves the resume was a delta — which is the whole | 1839 | # still across the tear proves the resume was a delta — which is the whole |
| 1745 | # milestone claim. | 1840 | # milestone claim. |
| 1746 | set +e | 1841 | pipe_mux "$OUT.m7" "$OUT.m7.err" env XDG_RUNTIME_DIR=/nonexistent-mux-e2e timeout 40 \ |
| 1747 | { sleep 0.5; printf 'printf "m7-%%s\\n" before\n'; sleep 8; \ | 1842 | "$MUX" --via "$MUXD proxy --sock $SOCK" |
| 1748 | printf 'printf "m7-%%s\\n" after\n'; sleep 2.5; printf '\034\034'; } | \ | 1843 | pipe_send 'printf "m7-%%s\\n" before\n' |
| 1749 | XDG_RUNTIME_DIR=/nonexistent-mux-e2e timeout 40 \ | ||
| 1750 | "$MUX" --via "$MUXD proxy --sock $SOCK" > "$OUT.m7" 2> "$OUT.m7.err" & | ||
| 1751 | M7PID=$! | ||
| 1752 | set -e | ||
| 1753 | 1844 | ||
| 1754 | # Tear only once the session is provably live and idle: the marker is the | 1845 | # Tear only once the session is provably live and idle: the marker is the |
| 1755 | # shell's own output, so seeing it means attached, drained, mid-sleep. | 1846 | # shell's own output, so seeing it means attached and drained. |
| 1756 | wait_for "$OUT.m7" "m7-before" 20 || { | 1847 | wait_for "$OUT.m7" "m7-before" 20 || { |
| 1757 | echo "e2e FAIL: m7 pre-tear output never arrived" | 1848 | echo "e2e FAIL: m7 pre-tear output never arrived" |
| 1758 | cat "$OUT.m7" "$OUT.m7.err" 2>/dev/null; exit 1; | 1849 | cat "$OUT.m7" "$OUT.m7.err" 2>/dev/null; exit 1; |
| 1759 | } | 1850 | } |
| 1760 | SNAPS_BEFORE=$("$MUXD" stats --sock "$SOCK" | sed -n 's/.*snapshots=\([0-9]*\).*/\1/p') | 1851 | SNAPS_BEFORE=$("$MUXD" stats --sock "$SOCK" | sed -n 's/.*snapshots=\([0-9]*\).*/\1/p') |
| 1852 | PAINTS_BEFORE=$(repaints "$OUT.m7") | ||
| 1761 | PPID_PROXY=$(proxy_pid "$SOCK") | 1853 | PPID_PROXY=$(proxy_pid "$SOCK") |
| 1762 | [ -n "$PPID_PROXY" ] || { echo "e2e FAIL: could not find the proxy to kill"; exit 1; } | 1854 | [ -n "$PPID_PROXY" ] || { echo "e2e FAIL: could not find the proxy to kill"; exit 1; } |
| 1763 | kill -9 "$PPID_PROXY" | 1855 | kill -9 "$PPID_PROXY" |
| @@ -1765,19 +1857,10 @@ kill -9 "$PPID_PROXY" | |||
| 1765 | # proving survives, so say so out loud rather than inferring it later. | 1857 | # proving survives, so say so out loud rather than inferring it later. |
| 1766 | kill -0 "$DPID" || { echo "e2e FAIL: the tear killed the daemon, not the proxy"; exit 1; } | 1858 | kill -0 "$DPID" || { echo "e2e FAIL: the tear killed the daemon, not the proxy"; exit 1; } |
| 1767 | 1859 | ||
| 1768 | set +e | 1860 | await_repaint "$OUT.m7" "$PAINTS_BEFORE" "m7 client never resumed after the transport was killed" |
| 1769 | wait "$M7PID" | 1861 | pipe_send 'printf "m7-%%s\\n" after\n' |
| 1770 | RC=$? | 1862 | await_out "$OUT.m7" "m7-after" "m7 client did not resume after the transport was killed" |
| 1771 | set -e | 1863 | pipe_detach "m7 client" |
| 1772 | [ "$RC" -eq 0 ] || { | ||
| 1773 | echo "e2e FAIL: m7 client exited $RC after a transport tear (want 0)" | ||
| 1774 | cat "$OUT.m7" "$OUT.m7.err" 2>/dev/null; exit 1; | ||
| 1775 | } | ||
| 1776 | grep -q "m7-before" "$OUT.m7" || { echo "e2e FAIL: m7 pre-tear output missing"; exit 1; } | ||
| 1777 | grep -q "m7-after" "$OUT.m7" || { | ||
| 1778 | echo "e2e FAIL: m7 client did not resume after the transport was killed" | ||
| 1779 | cat "$OUT.m7" "$OUT.m7.err" 2>/dev/null; exit 1; | ||
| 1780 | } | ||
| 1781 | SNAPS_AFTER=$("$MUXD" stats --sock "$SOCK" | sed -n 's/.*snapshots=\([0-9]*\).*/\1/p') | 1864 | SNAPS_AFTER=$("$MUXD" stats --sock "$SOCK" | sed -n 's/.*snapshots=\([0-9]*\).*/\1/p') |
| 1782 | [ -n "$SNAPS_BEFORE" ] && [ -n "$SNAPS_AFTER" ] || { | 1865 | [ -n "$SNAPS_BEFORE" ] && [ -n "$SNAPS_AFTER" ] || { |
| 1783 | echo "e2e FAIL: could not read the snapshots counter"; exit 1; | 1866 | echo "e2e FAIL: could not read the snapshots counter"; exit 1; |
| @@ -1797,12 +1880,8 @@ rm_swept "$OUT.m7" "$OUT.m7.err" | |||
| 1797 | D3PID=$! | 1880 | D3PID=$! |
| 1798 | wait_sock "$SOCK3" "$OUT.d3a.d" "restart-scenario socket never appeared" | 1881 | wait_sock "$SOCK3" "$OUT.d3a.d" "restart-scenario socket never appeared" |
| 1799 | 1882 | ||
| 1800 | set +e | 1883 | pipe_mux "$OUT.m7b" "$OUT.m7b.err" timeout 40 "$MUX" --sock "$SOCK3" |
| 1801 | { sleep 0.5; printf 'printf "m7b-%%s\\n" pre-restart\n'; sleep 8; \ | 1884 | pipe_send 'printf "m7b-%%s\\n" pre-restart\n' |
| 1802 | printf 'printf "m7b-%%s\\n" post-restart\n'; sleep 3; printf '\034\034'; } | \ | ||
| 1803 | timeout 40 "$MUX" --sock "$SOCK3" > "$OUT.m7b" 2> "$OUT.m7b.err" & | ||
| 1804 | M7BPID=$! | ||
| 1805 | set -e | ||
| 1806 | wait_for "$OUT.m7b" "m7b-pre-restart" 20 || { | 1885 | wait_for "$OUT.m7b" "m7b-pre-restart" 20 || { |
| 1807 | echo "e2e FAIL: m7b pre-restart output never arrived" | 1886 | echo "e2e FAIL: m7b pre-restart output never arrived" |
| 1808 | cat "$OUT.m7b" "$OUT.m7b.err" 2>/dev/null; exit 1; | 1887 | cat "$OUT.m7b" "$OUT.m7b.err" 2>/dev/null; exit 1; |
| @@ -1810,24 +1889,17 @@ wait_for "$OUT.m7b" "m7b-pre-restart" 20 || { | |||
| 1810 | 1889 | ||
| 1811 | # SIGKILL leaves the socket file behind; the new daemon's stale-socket | 1890 | # SIGKILL leaves the socket file behind; the new daemon's stale-socket |
| 1812 | # recovery (ECONNREFUSED + S_ISSOCK -> unlink) is what lets it rebind here. | 1891 | # recovery (ECONNREFUSED + S_ISSOCK -> unlink) is what lets it rebind here. |
| 1892 | PAINTS_BEFORE=$(repaints "$OUT.m7b") | ||
| 1813 | hardkill "$D3PID" | 1893 | hardkill "$D3PID" |
| 1814 | sleep 0.5 | 1894 | sleep 0.5 |
| 1815 | "$MUXD" run --sock "$SOCK3" --shell /bin/sh > "$OUT.d3b.d" 2>&1 & | 1895 | "$MUXD" run --sock "$SOCK3" --shell /bin/sh > "$OUT.d3b.d" 2>&1 & |
| 1816 | D3PID=$! | 1896 | D3PID=$! |
| 1817 | wait_sock "$SOCK3" "$OUT.d3b.d" "daemon did not rebind the stale socket" | 1897 | wait_sock "$SOCK3" "$OUT.d3b.d" "daemon did not rebind the stale socket" |
| 1818 | 1898 | ||
| 1819 | set +e | 1899 | await_repaint "$OUT.m7b" "$PAINTS_BEFORE" "m7b client never resumed into the restarted daemon" |
| 1820 | wait "$M7BPID" | 1900 | pipe_send 'printf "m7b-%%s\\n" post-restart\n' |
| 1821 | RC=$? | 1901 | await_out "$OUT.m7b" "m7b-post-restart" "m7b client did not resume into the restarted daemon" |
| 1822 | set -e | 1902 | pipe_detach "m7b client" |
| 1823 | [ "$RC" -eq 0 ] || { | ||
| 1824 | echo "e2e FAIL: m7b client exited $RC across a daemon restart (want 0)" | ||
| 1825 | cat "$OUT.m7b" "$OUT.m7b.err" 2>/dev/null; exit 1; | ||
| 1826 | } | ||
| 1827 | grep -q "m7b-post-restart" "$OUT.m7b" || { | ||
| 1828 | echo "e2e FAIL: m7b client did not resume into the restarted daemon" | ||
| 1829 | cat "$OUT.m7b" "$OUT.m7b.err" 2>/dev/null; exit 1; | ||
| 1830 | } | ||
| 1831 | # The fresh session really is fresh: a new daemon means a new shell, so the | 1903 | # The fresh session really is fresh: a new daemon means a new shell, so the |
| 1832 | # pre-restart marker cannot be in its grid. If it were, we would be looking | 1904 | # pre-restart marker cannot be in its grid. If it were, we would be looking |
| 1833 | # at a client that reconnected to something with the old session's history — | 1905 | # at a client that reconnected to something with the old session's history — |
| @@ -1968,8 +2040,10 @@ grep -q "already listening" "$OUT.q" || { | |||
| 1968 | 2040 | ||
| 1969 | # ...and the daemon is still an ordinary daemon: the session runs and the | 2041 | # ...and the daemon is still an ordinary daemon: the session runs and the |
| 1970 | # unix-socket path is unaffected by the listener sharing its poll loop. | 2042 | # unix-socket path is unaffected by the listener sharing its poll loop. |
| 1971 | { printf 'printf "quic-%%s\\n" flags-ok\n'; sleep 2; printf '\034\034'; } | \ | 2043 | pipe_mux "$OUT.q" "" "$MUX" --sock "$SOCK4" |
| 1972 | "$MUX" --sock "$SOCK4" > "$OUT.q" | 2044 | pipe_send 'printf "quic-%%s\\n" flags-ok\n' |
| 2045 | await_out "$OUT.q" "quic-flags-ok" "quic-flags-ok never reached the client" | ||
| 2046 | pipe_detach | ||
| 1973 | grep -q "quic-flags-ok" "$OUT.q" || { | 2047 | grep -q "quic-flags-ok" "$OUT.q" || { |
| 1974 | echo "e2e FAIL: --quic daemon did not serve an ordinary socket client"; cat "$OUT.q"; exit 1; | 2048 | echo "e2e FAIL: --quic daemon did not serve an ordinary socket client"; cat "$OUT.q"; exit 1; |
| 1975 | } | 2049 | } |
| @@ -1984,16 +2058,10 @@ assert_converged "$OUT.q" "$SOCK4" "quic daemon serves sockets" | |||
| 1984 | # 1. Attach, run something, detach. The whole point of the milestone in one | 2058 | # 1. Attach, run something, detach. The whole point of the milestone in one |
| 1985 | # scenario: the wire protocol did not change, so this must behave exactly | 2059 | # scenario: the wire protocol did not change, so this must behave exactly |
| 1986 | # as the socket client does. | 2060 | # as the socket client does. |
| 1987 | set +e | 2061 | pipe_mux "$OUT.qc" "$OUT.qc.err" timeout 30 "$MUX" "quic://127.0.0.1:$QPORT" --key "$QKEY" --quic-idle-ms 15000 |
| 1988 | { printf 'printf "quic-%%s\\n" attach-ok\n'; sleep 2; printf '\034\034'; } | \ | 2062 | pipe_send 'printf "quic-%%s\\n" attach-ok\n' |
| 1989 | timeout 30 "$MUX" "quic://127.0.0.1:$QPORT" --key "$QKEY" \ | 2063 | await_out "$OUT.qc" "quic-attach-ok" "quic-attach-ok never reached the client" |
| 1990 | --quic-idle-ms 15000 > "$OUT.qc" 2> "$OUT.qc.err" | 2064 | pipe_detach "quic:// client" |
| 1991 | RC=$? | ||
| 1992 | set -e | ||
| 1993 | [ "$RC" -eq 0 ] || { | ||
| 1994 | echo "e2e FAIL: quic:// client exited $RC (want 0)" | ||
| 1995 | cat "$OUT.qc" "$OUT.qc.err" 2>/dev/null; exit 1; | ||
| 1996 | } | ||
| 1997 | grep -q "quic-attach-ok" "$OUT.qc" || { | 2065 | grep -q "quic-attach-ok" "$OUT.qc" || { |
| 1998 | echo "e2e FAIL: quic:// client render missing output" | 2066 | echo "e2e FAIL: quic:// client render missing output" |
| 1999 | cat "$OUT.qc" "$OUT.qc.err" 2>/dev/null; exit 1; | 2067 | cat "$OUT.qc" "$OUT.qc.err" 2>/dev/null; exit 1; |
| @@ -2008,16 +2076,10 @@ assert_converged "$OUT.qc" "$SOCK4" "quic attach" | |||
| 2008 | # because a client that detached deliberately holds nothing to resume | 2076 | # because a client that detached deliberately holds nothing to resume |
| 2009 | # from. The counter is what tells that apart from a delta. | 2077 | # from. The counter is what tells that apart from a delta. |
| 2010 | SNAPS_RA=$("$MUXD" stats --sock "$SOCK4" | sed -n 's/.*snapshots=\([0-9]*\).*/\1/p') | 2078 | SNAPS_RA=$("$MUXD" stats --sock "$SOCK4" | sed -n 's/.*snapshots=\([0-9]*\).*/\1/p') |
| 2011 | set +e | 2079 | pipe_mux "$OUT.qc" "$OUT.qc.err" timeout 30 "$MUX" "quic://127.0.0.1:$QPORT" --key "$QKEY" --quic-idle-ms 15000 |
| 2012 | { printf 'printf "quic-%%s\\n" reattached\n'; sleep 2; printf '\034\034'; } | \ | 2080 | pipe_send 'printf "quic-%%s\\n" reattached\n' |
| 2013 | timeout 30 "$MUX" "quic://127.0.0.1:$QPORT" --key "$QKEY" \ | 2081 | await_out "$OUT.qc" "quic-reattached" "quic-reattached never reached the client" |
| 2014 | --quic-idle-ms 15000 > "$OUT.qc" 2> "$OUT.qc.err" | 2082 | pipe_detach "quic:// reattach" |
| 2015 | RC=$? | ||
| 2016 | set -e | ||
| 2017 | [ "$RC" -eq 0 ] || { | ||
| 2018 | echo "e2e FAIL: quic:// reattach exited $RC (want 0)" | ||
| 2019 | cat "$OUT.qc" "$OUT.qc.err" 2>/dev/null; exit 1; | ||
| 2020 | } | ||
| 2021 | # The earlier marker is still on the grid this client was handed, which is | 2083 | # The earlier marker is still on the grid this client was handed, which is |
| 2022 | # the session having survived the detach rather than a new shell. | 2084 | # the session having survived the detach rather than a new shell. |
| 2023 | grep -q "quic-attach-ok" "$OUT.qc" || { | 2085 | grep -q "quic-attach-ok" "$OUT.qc" || { |
| @@ -2116,37 +2178,23 @@ QMS=$(( (QT1 - QT0) / 1000000 )) | |||
| 2116 | SNAPS_BEFORE=$("$MUXD" stats --sock "$SOCK4" | sed -n 's/.*snapshots=\([0-9]*\).*/\1/p') | 2178 | SNAPS_BEFORE=$("$MUXD" stats --sock "$SOCK4" | sed -n 's/.*snapshots=\([0-9]*\).*/\1/p') |
| 2117 | [ -n "$SNAPS_BEFORE" ] || { echo "e2e FAIL: could not read snapshots before the tear"; exit 1; } | 2179 | [ -n "$SNAPS_BEFORE" ] || { echo "e2e FAIL: could not read snapshots before the tear"; exit 1; } |
| 2118 | 2180 | ||
| 2119 | set +e | 2181 | pipe_mux "$OUT.qr" "$OUT.qr.err" timeout 40 "$MUX" "quic://127.0.0.1:$QPORT" --key "$QKEY" \ |
| 2120 | { printf 'printf "quic-%%s\\n" pre-tear\n'; sleep 9; printf '\034\034'; } | \ | 2182 | --quic-idle-ms 1500 |
| 2121 | timeout 40 "$MUX" "quic://127.0.0.1:$QPORT" --key "$QKEY" \ | 2183 | pipe_send 'printf "quic-%%s\\n" pre-tear\n' |
| 2122 | --quic-idle-ms 1500 > "$OUT.qr" 2> "$OUT.qr.err" & | 2184 | await_out "$OUT.qr" "quic-pre-tear" "quic reconnect client never got its pre-tear marker" |
| 2123 | QRPID=$! | ||
| 2124 | set -e | ||
| 2125 | wait_for "$OUT.qr" "quic-pre-tear" 20 || { | ||
| 2126 | echo "e2e FAIL: quic reconnect client never got its pre-tear marker" | ||
| 2127 | cat "$OUT.qr" "$OUT.qr.err" 2>/dev/null; exit 1; | ||
| 2128 | } | ||
| 2129 | 2185 | ||
| 2130 | # Held well past the 1500ms idle timeout, so the client cannot mistake it | ||
| 2131 | # for a slow moment. | ||
| 2132 | kill -STOP "$D4PID" | ||
| 2133 | # Twice the 1500ms idle timeout: long enough that the client cannot mistake | 2186 | # Twice the 1500ms idle timeout: long enough that the client cannot mistake |
| 2134 | # it for a slow moment, short enough not to pad the suite. | 2187 | # it for a slow moment, short enough not to pad the suite. |
| 2188 | kill -STOP "$D4PID" | ||
| 2135 | sleep 3 | 2189 | sleep 3 |
| 2136 | kill -CONT "$D4PID" | 2190 | kill -CONT "$D4PID" |
| 2137 | 2191 | ||
| 2138 | set +e | 2192 | # The session is alive on the far side of the tear only if a NEW round trip |
| 2139 | wait "$QRPID" | 2193 | # completes: the pre-tear marker is already in the capture and proves |
| 2140 | RC=$? | 2194 | # nothing about the reconnect. |
| 2141 | set -e | 2195 | pipe_send 'printf "quic-%%s\\n" post-tear\n' |
| 2142 | [ "$RC" -eq 0 ] || { | 2196 | await_out "$OUT.qr" "quic-post-tear" "quic client lost its session across the tear" |
| 2143 | echo "e2e FAIL: quic client exited $RC across a tear (want 0)" | 2197 | pipe_detach "quic client" |
| 2144 | cat "$OUT.qr" "$OUT.qr.err" 2>/dev/null; exit 1; | ||
| 2145 | } | ||
| 2146 | grep -q "quic-pre-tear" "$OUT.qr" || { | ||
| 2147 | echo "e2e FAIL: quic client lost its session across the tear" | ||
| 2148 | cat "$OUT.qr" "$OUT.qr.err" 2>/dev/null; exit 1; | ||
| 2149 | } | ||
| 2150 | 2198 | ||
| 2151 | # The counter is the only witness to HOW the resume was served: a snapshot | 2199 | # The counter is the only witness to HOW the resume was served: a snapshot |
| 2152 | # renders identically to a delta, so markers cannot tell them apart. One | 2200 | # renders identically to a delta, so markers cannot tell them apart. One |
| @@ -2170,18 +2218,15 @@ assert_converged "$OUT.qr" "$SOCK4" "quic delta resume" | |||
| 2170 | # the restarted daemon must be able to rebind the UDP port at all — there | 2218 | # the restarted daemon must be able to rebind the UDP port at all — there |
| 2171 | # is no SO_REUSEADDR any more, so anything lingering from the killed | 2219 | # is no SO_REUSEADDR any more, so anything lingering from the killed |
| 2172 | # process would show up as a bind failure rather than as silent sharing. | 2220 | # process would show up as a bind failure rather than as silent sharing. |
| 2173 | set +e | 2221 | pipe_mux "$OUT.qk" "$OUT.qk.err" timeout 40 "$MUX" "quic://127.0.0.1:$QPORT" --key "$QKEY" \ |
| 2174 | { printf 'printf "quic-%%s\\n" pre-restart\n'; sleep 3; \ | 2222 | --quic-idle-ms 1500 |
| 2175 | printf 'printf "quic-%%s\\n" post-restart\n'; sleep 3; printf '\034\034'; } | \ | 2223 | pipe_send 'printf "quic-%%s\\n" pre-restart\n' |
| 2176 | timeout 40 "$MUX" "quic://127.0.0.1:$QPORT" --key "$QKEY" \ | ||
| 2177 | --quic-idle-ms 1500 > "$OUT.qk" 2> "$OUT.qk.err" & | ||
| 2178 | QKPID=$! | ||
| 2179 | set -e | ||
| 2180 | wait_for "$OUT.qk" "quic-pre-restart" 20 || { | 2224 | wait_for "$OUT.qk" "quic-pre-restart" 20 || { |
| 2181 | echo "e2e FAIL: quic restart client never got its pre-restart marker" | 2225 | echo "e2e FAIL: quic restart client never got its pre-restart marker" |
| 2182 | cat "$OUT.qk" "$OUT.qk.err" 2>/dev/null; exit 1; | 2226 | cat "$OUT.qk" "$OUT.qk.err" 2>/dev/null; exit 1; |
| 2183 | } | 2227 | } |
| 2184 | 2228 | ||
| 2229 | PAINTS_BEFORE=$(repaints "$OUT.qk") | ||
| 2185 | hardkill "$D4PID" | 2230 | hardkill "$D4PID" |
| 2186 | D4PID="" | 2231 | D4PID="" |
| 2187 | sleep 0.5 | 2232 | sleep 0.5 |
| @@ -2226,18 +2271,10 @@ udp_local_bound "$QHEX" || { | |||
| 2226 | } | 2271 | } |
| 2227 | kill -0 "$D4PID" || { echo "e2e FAIL: restarted --quic daemon died"; cat "$OUT.q"; exit 1; } | 2272 | kill -0 "$D4PID" || { echo "e2e FAIL: restarted --quic daemon died"; cat "$OUT.q"; exit 1; } |
| 2228 | 2273 | ||
| 2229 | set +e | 2274 | await_repaint "$OUT.qk" "$PAINTS_BEFORE" "quic client never resumed into the restarted daemon" |
| 2230 | wait "$QKPID" | 2275 | pipe_send 'printf "quic-%%s\\n" post-restart\n' |
| 2231 | RC=$? | 2276 | await_out "$OUT.qk" "quic-post-restart" "quic client did not resume into the restarted daemon" |
| 2232 | set -e | 2277 | pipe_detach "quic client" |
| 2233 | [ "$RC" -eq 0 ] || { | ||
| 2234 | echo "e2e FAIL: quic client exited $RC across a daemon restart (want 0)" | ||
| 2235 | cat "$OUT.qk" "$OUT.qk.err" 2>/dev/null; exit 1; | ||
| 2236 | } | ||
| 2237 | grep -q "quic-post-restart" "$OUT.qk" || { | ||
| 2238 | echo "e2e FAIL: quic client did not resume into the restarted daemon" | ||
| 2239 | cat "$OUT.qk" "$OUT.qk.err" 2>/dev/null; exit 1; | ||
| 2240 | } | ||
| 2241 | # A new daemon means a new shell, so the old marker cannot be in its grid. | 2278 | # A new daemon means a new shell, so the old marker cannot be in its grid. |
| 2242 | # If it were, we would be looking at a client that resumed off a seq | 2279 | # If it were, we would be looking at a client that resumed off a seq |
| 2243 | # belonging to a session that no longer exists. | 2280 | # belonging to a session that no longer exists. |
| @@ -2270,16 +2307,10 @@ env MUX_KEY_FILE="$QKEY" "$MUXD" run --sock "$SOCK9" --shell /bin/sh \ | |||
| 2270 | D9PID=$! | 2307 | D9PID=$! |
| 2271 | wait_sock "$SOCK9" "$OUT.d9.d" "MUX_KEY_FILE daemon never bound its session socket" | 2308 | wait_sock "$SOCK9" "$OUT.d9.d" "MUX_KEY_FILE daemon never bound its session socket" |
| 2272 | 2309 | ||
| 2273 | set +e | 2310 | pipe_mux "$OUT.env1" "$OUT.env1.err" timeout 30 "$MUX" "quic://127.0.0.1:$QPORT2" --key "$QKEY" --quic-idle-ms 15000 |
| 2274 | { printf 'printf "envkey-%%s\\n" ok\n'; sleep 2; printf '\034\034'; } | \ | 2311 | pipe_send 'printf "envkey-%%s\\n" ok\n' |
| 2275 | timeout 30 "$MUX" "quic://127.0.0.1:$QPORT2" --key "$QKEY" \ | 2312 | await_out "$OUT.env1" "envkey-ok" "envkey-ok never reached the client" |
| 2276 | --quic-idle-ms 15000 > "$OUT.env1" 2> "$OUT.env1.err" | 2313 | pipe_detach "quic attach to a MUX_KEY_FILE daemon" |
| 2277 | RC=$? | ||
| 2278 | set -e | ||
| 2279 | [ "$RC" -eq 0 ] || { | ||
| 2280 | echo "e2e FAIL: quic attach to a MUX_KEY_FILE daemon exited $RC (want 0)" | ||
| 2281 | cat "$OUT.env1" "$OUT.env1.err" 2>/dev/null; exit 1; | ||
| 2282 | } | ||
| 2283 | grep -q "envkey-ok" "$OUT.env1" || { | 2314 | grep -q "envkey-ok" "$OUT.env1" || { |
| 2284 | echo "e2e FAIL: MUX_KEY_FILE daemon served no session" | 2315 | echo "e2e FAIL: MUX_KEY_FILE daemon served no session" |
| 2285 | cat "$OUT.env1" "$OUT.env1.err" 2>/dev/null; exit 1; } | 2316 | cat "$OUT.env1" "$OUT.env1.err" 2>/dev/null; exit 1; } |
| @@ -2297,16 +2328,10 @@ env MUX_KEY_FILE="$QKEY.wrong" "$MUXD" run --sock "$SOCK10" --shell /bin/sh \ | |||
| 2297 | D10PID=$! | 2328 | D10PID=$! |
| 2298 | wait_sock "$SOCK10" "$OUT.d10.d" "--key-beats-env daemon never bound its session socket" | 2329 | wait_sock "$SOCK10" "$OUT.d10.d" "--key-beats-env daemon never bound its session socket" |
| 2299 | 2330 | ||
| 2300 | set +e | 2331 | pipe_mux "$OUT.env2" "$OUT.env2.err" timeout 30 "$MUX" "quic://127.0.0.1:$QPORT3" --key "$QKEY" --quic-idle-ms 15000 |
| 2301 | { printf 'printf "flagwins-%%s\\n" ok\n'; sleep 2; printf '\034\034'; } | \ | 2332 | pipe_send 'printf "flagwins-%%s\\n" ok\n' |
| 2302 | timeout 30 "$MUX" "quic://127.0.0.1:$QPORT3" --key "$QKEY" \ | 2333 | await_out "$OUT.env2" "flagwins-ok" "flagwins-ok never reached the client" |
| 2303 | --quic-idle-ms 15000 > "$OUT.env2" 2> "$OUT.env2.err" | 2334 | pipe_detach "the --key attach (which must beat MUX_KEY_FILE)" |
| 2304 | RC=$? | ||
| 2305 | set -e | ||
| 2306 | [ "$RC" -eq 0 ] || { | ||
| 2307 | echo "e2e FAIL: --key did not beat MUX_KEY_FILE: attach exited $RC (want 0)" | ||
| 2308 | cat "$OUT.env2" "$OUT.env2.err" 2>/dev/null; exit 1; | ||
| 2309 | } | ||
| 2310 | grep -q "flagwins-ok" "$OUT.env2" || { | 2335 | grep -q "flagwins-ok" "$OUT.env2" || { |
| 2311 | echo "e2e FAIL: --key-beats-env daemon served no session" | 2336 | echo "e2e FAIL: --key-beats-env daemon served no session" |
| 2312 | cat "$OUT.env2" "$OUT.env2.err" 2>/dev/null; exit 1; } | 2337 | cat "$OUT.env2" "$OUT.env2.err" 2>/dev/null; exit 1; } |
| @@ -2342,8 +2367,10 @@ kill -0 "$SPID" || { echo "e2e FAIL: started daemon not alive"; exit 1; } | |||
| 2342 | echo "e2e FAIL: non-tty start not exactly two lines:"; cat "$OUT.start"; exit 1; } | 2367 | echo "e2e FAIL: non-tty start not exactly two lines:"; cat "$OUT.start"; exit 1; } |
| 2343 | 2368 | ||
| 2344 | # The daemon it started serves a session (marker in, marker in dump). | 2369 | # The daemon it started serves a session (marker in, marker in dump). |
| 2345 | { printf 'printf "start-%%s\\n" works\n'; sleep 2; printf '\034\034'; } | \ | 2370 | pipe_mux "$OUT.s8" "$OUT.s8.err" "$MUX" --sock "$SOCK8" |
| 2346 | "$MUX" --sock "$SOCK8" > "$OUT.s8" 2> "$OUT.s8.err" | 2371 | pipe_send 'printf "start-%%s\\n" works\n' |
| 2372 | await_out "$OUT.s8" "start-works" "start-works never reached the client" | ||
| 2373 | pipe_detach | ||
| 2347 | "$MUXD" dump --sock "$SOCK8" | grep -q "start-works" || { | 2374 | "$MUXD" dump --sock "$SOCK8" | grep -q "start-works" || { |
| 2348 | echo "e2e FAIL: auto-started daemon lost the marker" | 2375 | echo "e2e FAIL: auto-started daemon lost the marker" |
| 2349 | cat "$OUT.s8" "$OUT.s8.err" 2>/dev/null; exit 1; } | 2376 | cat "$OUT.s8" "$OUT.s8.err" 2>/dev/null; exit 1; } |
| @@ -2389,8 +2416,10 @@ wait "$RB"; RCB=$? | |||
| 2389 | set -e | 2416 | set -e |
| 2390 | { [ "$RCA" = "0" ] && [ "$RCB" = "0" ]; } || { | 2417 | { [ "$RCA" = "0" ] && [ "$RCB" = "0" ]; } || { |
| 2391 | echo "e2e FAIL: race: exits $RCA/$RCB"; cat "$OUT.ra" "$OUT.rb"; exit 1; } | 2418 | echo "e2e FAIL: race: exits $RCA/$RCB"; cat "$OUT.ra" "$OUT.rb"; exit 1; } |
| 2392 | { printf 'printf "race-%%s\\n" one\n'; sleep 2; printf '\034\034'; } | \ | 2419 | pipe_mux "$OUT.race" /dev/null "$MUX" --sock "$SOCK8" |
| 2393 | "$MUX" --sock "$SOCK8" > "$OUT.race" 2> /dev/null | 2420 | pipe_send 'printf "race-%%s\\n" one\n' |
| 2421 | await_out "$OUT.race" "race-one" "race-one never reached the client" | ||
| 2422 | pipe_detach | ||
| 2394 | "$MUXD" dump --sock "$SOCK8" | grep -q "race-one" || { | 2423 | "$MUXD" dump --sock "$SOCK8" | grep -q "race-one" || { |
| 2395 | echo "e2e FAIL: race: session unusable"; exit 1; } | 2424 | echo "e2e FAIL: race: session unusable"; exit 1; } |
| 2396 | SPID=$(cat "$OUT.ra" "$OUT.rb" | sed -n 's/.* pid=\([0-9]*\).*/\1/p' | while read -r p; do | 2425 | SPID=$(cat "$OUT.ra" "$OUT.rb" | sed -n 's/.* pid=\([0-9]*\).*/\1/p' | while read -r p; do |
| @@ -2461,8 +2490,10 @@ ok "a start whose daemon dies young says so, with the log path" | |||
| 2461 | "$MUXD" start --sock "$SOCK11" --quic "127.0.0.1:$QPORT4" 2> "$OUT.goal" | 2490 | "$MUXD" start --sock "$SOCK11" --quic "127.0.0.1:$QPORT4" 2> "$OUT.goal" |
| 2462 | GPID=$(sed -n 's/.* pid=\([0-9]*\).*/\1/p' "$OUT.goal") | 2491 | GPID=$(sed -n 's/.* pid=\([0-9]*\).*/\1/p' "$OUT.goal") |
| 2463 | [ -n "$GPID" ] || { echo "e2e FAIL: goal start reported no pid"; cat "$OUT.goal"; exit 1; } | 2492 | [ -n "$GPID" ] || { echo "e2e FAIL: goal start reported no pid"; cat "$OUT.goal"; exit 1; } |
| 2464 | { printf 'printf "goal-%%s\\n" quic\n'; sleep 2; printf '\034\034'; } | \ | 2493 | pipe_mux "$OUT.g9" "$OUT.g9.err" timeout 30 "$MUX" "quic://127.0.0.1:$QPORT4" |
| 2465 | timeout 30 "$MUX" "quic://127.0.0.1:$QPORT4" > "$OUT.g9" 2> "$OUT.g9.err" | 2494 | pipe_send 'printf "goal-%%s\\n" quic\n' |
| 2495 | await_out "$OUT.g9" "goal-quic" "goal-quic never reached the client" | ||
| 2496 | pipe_detach | ||
| 2466 | "$MUXD" dump --sock "$SOCK11" | grep -q "goal-quic" || { | 2497 | "$MUXD" dump --sock "$SOCK11" | grep -q "goal-quic" || { |
| 2467 | echo "e2e FAIL: no-key-flag QUIC attach did not reach the session" | 2498 | echo "e2e FAIL: no-key-flag QUIC attach did not reach the session" |
| 2468 | cat "$OUT.g9" "$OUT.g9.err" 2>/dev/null; exit 1; } | 2499 | cat "$OUT.g9" "$OUT.g9.err" 2>/dev/null; exit 1; } |
| @@ -3212,14 +3243,10 @@ ok "reconnect while scrolled: view restored, prediction resumed" | |||
| 3212 | # Nothing is serving SOCK14: the attach itself must produce the daemon. | 3243 | # Nothing is serving SOCK14: the attach itself must produce the daemon. |
| 3213 | # SHELL pinned because the auto-started daemon gets no --shell flag and | 3244 | # SHELL pinned because the auto-started daemon gets no --shell flag and |
| 3214 | # resolves $SHELL — the suite must not inherit the developer's. | 3245 | # resolves $SHELL — the suite must not inherit the developer's. |
| 3215 | # | 3246 | pipe_mux "$OUT.as" "$OUT.as.err" env SHELL=/bin/sh timeout 30 "$MUX" --via "$MUXD proxy --sock $SOCK14" |
| 3216 | # `|| true` for the same reason the M6 --via scenario has it: without it | 3247 | pipe_send 'printf "auto-%%s\\n" start\n' |
| 3217 | # `set -e` aborts the run on the client's exit status before the labelled | 3248 | await_out "$OUT.as" "auto-start" "proxy auto-start: marker never reached the client" |
| 3218 | # diagnostics below get to print the stderr that says why. `timeout` is | 3249 | pipe_detach |
| 3219 | # what keeps that from being a licence to hang. | ||
| 3220 | { printf 'printf "auto-%%s\\n" start\n'; sleep 2; printf '\034\034'; } | \ | ||
| 3221 | SHELL=/bin/sh timeout 30 "$MUX" --via "$MUXD proxy --sock $SOCK14" \ | ||
| 3222 | > "$OUT.as" 2> "$OUT.as.err" || true | ||
| 3223 | "$MUXD" dump --sock "$SOCK14" | grep -q "auto-start" || { | 3250 | "$MUXD" dump --sock "$SOCK14" | grep -q "auto-start" || { |
| 3224 | echo "e2e FAIL: proxy auto-start: attached daemon lost the marker" | 3251 | echo "e2e FAIL: proxy auto-start: attached daemon lost the marker" |
| 3225 | cat "$OUT.as" "$OUT.as.err" 2>/dev/null; exit 1; } | 3252 | cat "$OUT.as" "$OUT.as.err" 2>/dev/null; exit 1; } |
| @@ -3239,9 +3266,10 @@ kill -0 "$APID" || { echo "e2e FAIL: auto-started daemon not alive"; exit 1; } | |||
| 3239 | assert_converged "$OUT.as" "$SOCK14" "auto-start via proxy" | 3266 | assert_converged "$OUT.as" "$SOCK14" "auto-start via proxy" |
| 3240 | 3267 | ||
| 3241 | # Silence is the fast path: a warm attach must print NO spawn progress. | 3268 | # Silence is the fast path: a warm attach must print NO spawn progress. |
| 3242 | { printf 'printf "auto-%%s\\n" again\n'; sleep 2; printf '\034\034'; } | \ | 3269 | pipe_mux "$OUT.as2" "$OUT.as2.err" env SHELL=/bin/sh timeout 30 "$MUX" --via "$MUXD proxy --sock $SOCK14" |
| 3243 | SHELL=/bin/sh timeout 30 "$MUX" --via "$MUXD proxy --sock $SOCK14" \ | 3270 | pipe_send 'printf "auto-%%s\\n" again\n' |
| 3244 | > "$OUT.as2" 2> "$OUT.as2.err" || true | 3271 | await_out "$OUT.as2" "auto-again" "warm attach: marker never reached the client" |
| 3272 | pipe_detach | ||
| 3245 | grep -q 'starting' "$OUT.as2.err" && { | 3273 | grep -q 'starting' "$OUT.as2.err" && { |
| 3246 | echo "e2e FAIL: warm attach printed spawn progress" | 3274 | echo "e2e FAIL: warm attach printed spawn progress" |
| 3247 | cat "$OUT.as2.err"; exit 1; } | 3275 | cat "$OUT.as2.err"; exit 1; } |
| @@ -3802,11 +3830,9 @@ HCACHE="$XDG_CACHE_HOME/mux/hosts/$HHOST" | |||
| 3802 | # inference: the ssh the announce arrived on is killed by the client on | 3830 | # inference: the ssh the announce arrived on is killed by the client on |
| 3803 | # QUIC success, so once its pid is OBSERVED gone, a second marker still | 3831 | # QUIC success, so once its pid is OBSERVED gone, a second marker still |
| 3804 | # making the round trip can only be riding QUIC. The pipe's owner is dead. | 3832 | # making the round trip can only be riding QUIC. The pipe's owner is dead. |
| 3805 | { printf 'printf "cold-%%s\\n" one\n'; sleep 6; \ | 3833 | pipe_mux "$OUT.h1" "$OUT.h1.err" env SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN" PATH="$HPATH" timeout 60 \ |
| 3806 | printf 'printf "cold-%%s\\n" two\n'; sleep 2.5; printf '\034\034'; } | \ | 3834 | "$MUX" "$HHOST" |
| 3807 | SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN" PATH="$HPATH" timeout 60 \ | 3835 | pipe_send 'printf "cold-%%s\\n" one\n' |
| 3808 | "$MUX" "$HHOST" > "$OUT.h1" 2> "$OUT.h1.err" & | ||
| 3809 | H1PID=$! | ||
| 3810 | # The bounded wait, with a message of its own, because of what it is FOR: | 3836 | # The bounded wait, with a message of its own, because of what it is FOR: |
| 3811 | # a client blocked on an announce that is never coming has no other | 3837 | # a client blocked on an announce that is never coming has no other |
| 3812 | # symptom. It cannot be left to the suite's timeout or the trap — those | 3838 | # symptom. It cannot be left to the suite's timeout or the trap — those |
| @@ -3823,49 +3849,19 @@ HSHIMS=$(wc -l < "$SSHIM_PIDLOG") | |||
| 3823 | cat "$SSHIM_PIDLOG"; exit 1; } | 3849 | cat "$SSHIM_PIDLOG"; exit 1; } |
| 3824 | HSHIMPID=$(head -1 "$SSHIM_PIDLOG") | 3850 | HSHIMPID=$(head -1 "$SSHIM_PIDLOG") |
| 3825 | wait_pid_gone "$HSHIMPID" "cold handoff: QUIC took over, so ssh must be gone" | 3851 | wait_pid_gone "$HSHIMPID" "cold handoff: QUIC took over, so ssh must be gone" |
| 3826 | # The BASELINE, and it comes AFTER the death rather than before it so that | 3852 | # The second marker is typed only now, after the death was OBSERVED, so its |
| 3827 | # what it establishes is exactly what the next check needs: at the instant | 3853 | # round trip is traffic that moved after the pipe's owner died — by |
| 3828 | # ssh was observed gone, the second marker had not arrived. Its later | 3854 | # construction, not by a clock. What guarantees the ordering on the product |
| 3829 | # arrival is therefore traffic that moved after the pipe's owner died. | 3855 | # side: openHandoff kills the ssh child the moment QUIC is ready, before |
| 3830 | # Taken before the death instead, it would pin absence at some earlier | 3856 | # Transport.open returns, so before the session can emit a single byte. |
| 3831 | # moment and lean on wait_pid_gone's 2s budget staying small against the | 3857 | # Anyone who moves that kill (to after the first frame, into a deferred |
| 3832 | # script's 6s — a coupling nothing states and nobody would maintain. | 3858 | # teardown) takes this scenario's premise with them. |
| 3833 | # | 3859 | pipe_send 'printf "cold-%%s\\n" two\n' |
| 3834 | # What guarantees the ordering in the first place is the PRODUCT, and | ||
| 3835 | # saying so is the other half of this comment's job: openHandoff kills the | ||
| 3836 | # ssh child the moment QUIC is ready, before Transport.open returns, so | ||
| 3837 | # before the session can emit a single byte — before cold-one, never mind | ||
| 3838 | # cold-two. Anyone who moves that kill (to after the first frame, into a | ||
| 3839 | # deferred teardown) takes this scenario's premise with them and should | ||
| 3840 | # expect to rewrite the block rather than nudge a sleep. | ||
| 3841 | # | ||
| 3842 | # The case it catches is real rather than theoretical. Both markers are | ||
| 3843 | # typed by a script on its own clock: if an attach ever outran the 6s | ||
| 3844 | # between them, both would be buffered before the session existed and | ||
| 3845 | # delivered together, and cold-two would already be on screen here. The | ||
| 3846 | # scenario could then no longer WITNESS post-death traffic — not because | ||
| 3847 | # the product misbehaved (the kill still preceded both) but because the | ||
| 3848 | # two events stopped being separable. That is what this reports. | ||
| 3849 | grep -q "cold-two" "$OUT.h1" && { | ||
| 3850 | echo "e2e FAIL: cold handoff: the second marker is already on screen at the" | ||
| 3851 | echo " baseline, so it cannot witness bytes moving after ssh died —" | ||
| 3852 | echo " both markers were delivered together, which is what happens" | ||
| 3853 | echo " when the attach outruns this scenario's 6s script (~300ms" | ||
| 3854 | echo " observed). A timing premise broke, not necessarily the product." | ||
| 3855 | exit 1; } | ||
| 3856 | # ...and the session did not go with it. | ||
| 3857 | wait_for "$OUT.h1" "cold-two" 20 || { | 3860 | wait_for "$OUT.h1" "cold-two" 20 || { |
| 3858 | echo "e2e FAIL: cold handoff: the session stopped converging once ssh was gone," | 3861 | echo "e2e FAIL: cold handoff: the session stopped converging once ssh was gone," |
| 3859 | echo " so the bytes were riding the pipe rather than QUIC" | 3862 | echo " so the bytes were riding the pipe rather than QUIC" |
| 3860 | cat "$OUT.h1" "$OUT.h1.err" 2>/dev/null; exit 1; } | 3863 | cat "$OUT.h1" "$OUT.h1.err" 2>/dev/null; exit 1; } |
| 3861 | set +e | 3864 | pipe_detach "cold handoff client" |
| 3862 | wait "$H1PID" | ||
| 3863 | RC=$? | ||
| 3864 | set -e | ||
| 3865 | H1PID="" | ||
| 3866 | [ "$RC" -eq 0 ] || { | ||
| 3867 | echo "e2e FAIL: cold handoff client exited $RC (want 0; 124 means it hung)" | ||
| 3868 | cat "$OUT.h1" "$OUT.h1.err" 2>/dev/null; exit 1; } | ||
| 3869 | 3865 | ||
| 3870 | # The daemon `muxd endpoint` started, by the pid its own up-line reported — | 3866 | # The daemon `muxd endpoint` started, by the pid its own up-line reported — |
| 3871 | # the only handle this suite has on a process that is nobody's child. Same | 3867 | # the only handle this suite has on a process that is nobody's child. Same |
| @@ -3912,15 +3908,10 @@ ok "cold handoff: ssh fetches the coordinates, QUIC carries the session" | |||
| 3912 | # contract that a warm attach prints no spawn progress, extended to the | 3908 | # contract that a warm attach prints no spawn progress, extended to the |
| 3913 | # handoff's own line, which has nothing to report when nothing fell back. | 3909 | # handoff's own line, which has nothing to report when nothing fell back. |
| 3914 | HSHIMS_B=$(wc -l < "$SSHIM_PIDLOG") | 3910 | HSHIMS_B=$(wc -l < "$SSHIM_PIDLOG") |
| 3915 | set +e | 3911 | pipe_mux "$OUT.h2" "$OUT.h2.err" env SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN" PATH="$HPATH" timeout 40 "$MUX" "$HHOST" |
| 3916 | { printf 'printf "warm-%%s\\n" ok\n'; sleep 2.5; printf '\034\034'; } | \ | 3912 | pipe_send 'printf "warm-%%s\\n" ok\n' |
| 3917 | SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN" PATH="$HPATH" timeout 40 \ | 3913 | await_out "$OUT.h2" "warm-ok" "warm-ok never reached the client" |
| 3918 | "$MUX" "$HHOST" > "$OUT.h2" 2> "$OUT.h2.err" | 3914 | pipe_detach "warm handoff client" |
| 3919 | RC=$? | ||
| 3920 | set -e | ||
| 3921 | [ "$RC" -eq 0 ] || { | ||
| 3922 | echo "e2e FAIL: warm handoff client exited $RC (want 0)" | ||
| 3923 | cat "$OUT.h2" "$OUT.h2.err" 2>/dev/null; exit 1; } | ||
| 3924 | grep -q "warm-ok" "$OUT.h2" || { | 3915 | grep -q "warm-ok" "$OUT.h2" || { |
| 3925 | echo "e2e FAIL: warm handoff served no session" | 3916 | echo "e2e FAIL: warm handoff served no session" |
| 3926 | cat "$OUT.h2" "$OUT.h2.err" 2>/dev/null; exit 1; } | 3917 | cat "$OUT.h2" "$OUT.h2.err" 2>/dev/null; exit 1; } |
| @@ -3956,39 +3947,26 @@ ok "warm handoff: the cache dials QUIC, ssh never runs (pidlog still $HSHIMS_B2) | |||
| 3956 | # loopback round trip and the whole heal measures ~200ms. The bound below | 3947 | # loopback round trip and the whole heal measures ~200ms. The bound below |
| 3957 | # was a floor on that spent budget and is now a ceiling on its absence. | 3948 | # was a floor on that spent budget and is now a ceiling on its absence. |
| 3958 | # | 3949 | # |
| 3959 | # The detach byte stays six seconds out even so. The stdin script runs on | 3950 | # The detach is sent only after the marker has rendered, and that ordering |
| 3960 | # its own clock, in PARALLEL with the attach, and `waitReady` answers | 3951 | # is load-bearing: `waitReady` answers Ctrl-\ DURING a handshake (M8 pins |
| 3961 | # Ctrl-\ DURING a handshake (M8 pins exactly that). A detach landing | 3952 | # exactly that), so a detach landing inside the dial window aborts the |
| 3962 | # inside the dial window aborts the attach: no session, no error, exit 0 — | 3953 | # attach — no session, no error, exit 0 — and a scenario that paced the |
| 3963 | # a scenario that passes its exit check having tested nothing. The window | 3954 | # detach on a clock could pass its exit check having tested nothing. |
| 3964 | # it has to clear shrank from 2172ms to ~200ms; six seconds is now margin | ||
| 3965 | # over the ssh refetch and the session that follows it. | ||
| 3966 | HHEXKEY=$(sed -n 's/^endpoint [0-9][0-9]* \([0-9a-f]*\)$/\1/p' "$HCACHE") | 3955 | HHEXKEY=$(sed -n 's/^endpoint [0-9][0-9]* \([0-9a-f]*\)$/\1/p' "$HCACHE") |
| 3967 | [ -n "$HHEXKEY" ] || { echo "e2e FAIL: could not read the cached key"; exit 1; } | 3956 | [ -n "$HHEXKEY" ] || { echo "e2e FAIL: could not read the cached key"; exit 1; } |
| 3968 | printf 'endpoint %s %s\n' "$HDEADPORT" "$HHEXKEY" > "$HCACHE" | 3957 | printf 'endpoint %s %s\n' "$HDEADPORT" "$HHEXKEY" > "$HCACHE" |
| 3969 | chmod 600 "$HCACHE" | 3958 | chmod 600 "$HCACHE" |
| 3970 | HSHIMS_C=$(wc -l < "$SSHIM_PIDLOG") | 3959 | HSHIMS_C=$(wc -l < "$SSHIM_PIDLOG") |
| 3971 | HT4=$(date +%s%N) | 3960 | HT4=$(date +%s%N) |
| 3972 | { printf 'printf "heal-%%s\\n" ok\n'; sleep 6; printf '\034\034'; } | \ | 3961 | pipe_mux "$OUT.h3" "$OUT.h3.err" env SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN" PATH="$HPATH" timeout 40 \ |
| 3973 | SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN" PATH="$HPATH" timeout 40 \ | 3962 | "$MUX" "$HHOST" |
| 3974 | "$MUX" "$HHOST" > "$OUT.h3" 2> "$OUT.h3.err" & | 3963 | pipe_send 'printf "heal-%%s\\n" ok\n' |
| 3975 | H3PID=$! | ||
| 3976 | wait_for "$OUT.h3" "heal-ok" 30 || { | 3964 | wait_for "$OUT.h3" "heal-ok" 30 || { |
| 3977 | echo "e2e FAIL: stale-cache handoff never served a session" | 3965 | echo "e2e FAIL: stale-cache handoff never served a session" |
| 3978 | cat "$OUT.h3" "$OUT.h3.err" 2>/dev/null; exit 1; } | 3966 | cat "$OUT.h3" "$OUT.h3.err" 2>/dev/null; exit 1; } |
| 3979 | HT5=$(date +%s%N) | 3967 | HT5=$(date +%s%N) |
| 3980 | HMS_C=$(( (HT5 - HT4) / 1000000 )) | 3968 | HMS_C=$(( (HT5 - HT4) / 1000000 )) |
| 3981 | set +e | 3969 | pipe_detach "stale-cache handoff client" |
| 3982 | wait "$H3PID" | ||
| 3983 | RC=$? | ||
| 3984 | set -e | ||
| 3985 | H3PID="" | ||
| 3986 | [ "$RC" -eq 0 ] || { | ||
| 3987 | echo "e2e FAIL: stale-cache handoff client exited $RC (want 0)" | ||
| 3988 | cat "$OUT.h3" "$OUT.h3.err" 2>/dev/null; exit 1; } | ||
| 3989 | grep -q "heal-ok" "$OUT.h3" || { | ||
| 3990 | echo "e2e FAIL: stale-cache handoff served no session" | ||
| 3991 | cat "$OUT.h3" "$OUT.h3.err" 2>/dev/null; exit 1; } | ||
| 3992 | # The absent-grep, and the control that proves it can fire is scenario (d) | 3970 | # The absent-grep, and the control that proves it can fire is scenario (d) |
| 3993 | # below: the same pattern, asserted PRESENT, against a build where the | 3971 | # below: the same pattern, asserted PRESENT, against a build where the |
| 3994 | # fallback really happened. | 3972 | # fallback really happened. |
| @@ -4060,10 +4038,9 @@ HDPID=$! | |||
| 4060 | wait_sock "$SOCK17" "$OUT.d17.d" "key-mismatch daemon never bound" | 4038 | wait_sock "$SOCK17" "$OUT.d17.d" "key-mismatch daemon never bound" |
| 4061 | HSHIMS_D=$(wc -l < "$SSHIM_PIDLOG") | 4039 | HSHIMS_D=$(wc -l < "$SSHIM_PIDLOG") |
| 4062 | HT0=$(date +%s%N) | 4040 | HT0=$(date +%s%N) |
| 4063 | { printf 'printf "fallback-%%s\\n" ok\n'; sleep 6; printf '\034\034'; } | \ | 4041 | pipe_mux "$OUT.h4" "$OUT.h4.err" env SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN2" PATH="$HPATH" timeout 40 \ |
| 4064 | SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN2" PATH="$HPATH" timeout 40 \ | 4042 | "$MUX" "127.0.0.1" |
| 4065 | "$MUX" "127.0.0.1" > "$OUT.h4" 2> "$OUT.h4.err" & | 4043 | pipe_send 'printf "fallback-%%s\\n" ok\n' |
| 4066 | H4PID=$! | ||
| 4067 | # Timed to the LINE rather than to the client's exit, so no session sleeps | 4044 | # Timed to the LINE rather than to the client's exit, so no session sleeps |
| 4068 | # are folded in. The elapsed time is the dial's budget plus launch overhead | 4045 | # are folded in. The elapsed time is the dial's budget plus launch overhead |
| 4069 | # (measured 26-129ms), which only inflates it — the floor is safe. | 4046 | # (measured 26-129ms), which only inflates it — the floor is safe. |
| @@ -4097,13 +4074,8 @@ grep -q "^mux: quic://127.0.0.1:$HQPORT unreachable, attaching over ssh$" "$OUT. | |||
| 4097 | # misses, while making the single scenario that already pays 2s by design | 4074 | # misses, while making the single scenario that already pays 2s by design |
| 4098 | # the most load-sensitive check in the suite. | 4075 | # the most load-sensitive check in the suite. |
| 4099 | # | 4076 | # |
| 4100 | # And it is worth knowing what this bound can actually SEE, which is a | 4077 | # The wait_for above is the backstop beyond it: an overrun past 15s is |
| 4101 | # narrow band. Past about six seconds the script's own detach byte lands | 4078 | # reported there, with its own message, rather than here. |
| 4102 | # inside the dial, `waitReady` answers it as an abort, no fallback line is | ||
| 4103 | # ever printed, and the overrun is reported by the wait_for above — with | ||
| 4104 | # its own message — rather than here. So this check owns the range between | ||
| 4105 | # the budget and that: long enough to be a real overrun, short enough that | ||
| 4106 | # the line still gets printed. The wait_for is the backstop beyond it. | ||
| 4107 | [ "$HMS" -ge 1500 ] || { | 4079 | [ "$HMS" -ge 1500 ] || { |
| 4108 | echo "e2e FAIL: the fallback came after ${HMS}ms, too fast to have spent the" | 4080 | echo "e2e FAIL: the fallback came after ${HMS}ms, too fast to have spent the" |
| 4109 | echo " 2000ms QUIC budget — the dial cannot have happened" | 4081 | echo " 2000ms QUIC budget — the dial cannot have happened" |
| @@ -4111,19 +4083,10 @@ grep -q "^mux: quic://127.0.0.1:$HQPORT unreachable, attaching over ssh$" "$OUT. | |||
| 4111 | [ "$HMS" -lt 10000 ] || { | 4083 | [ "$HMS" -lt 10000 ] || { |
| 4112 | echo "e2e FAIL: the fallback took ${HMS}ms; the deadline is meant to bound it" | 4084 | echo "e2e FAIL: the fallback took ${HMS}ms; the deadline is meant to bound it" |
| 4113 | exit 1; } | 4085 | exit 1; } |
| 4114 | set +e | ||
| 4115 | wait "$H4PID" | ||
| 4116 | RC=$? | ||
| 4117 | set -e | ||
| 4118 | H4PID="" | ||
| 4119 | [ "$RC" -eq 0 ] || { | ||
| 4120 | echo "e2e FAIL: key-mismatch client exited $RC (want 0)" | ||
| 4121 | cat "$OUT.h4" "$OUT.h4.err" 2>/dev/null; exit 1; } | ||
| 4122 | # ...and the session it fell back to is a real one, over the pipe that | 4086 | # ...and the session it fell back to is a real one, over the pipe that |
| 4123 | # carried the announce. | 4087 | # carried the announce. |
| 4124 | grep -q "fallback-ok" "$OUT.h4" || { | 4088 | await_out "$OUT.h4" "fallback-ok" "key-mismatch attach printed the line but served no session" |
| 4125 | echo "e2e FAIL: key-mismatch attach printed the line but served no session" | 4089 | pipe_detach "key-mismatch client" |
| 4126 | cat "$OUT.h4" "$OUT.h4.err" 2>/dev/null; exit 1; } | ||
| 4127 | HSHIMS_D2=$(wc -l < "$SSHIM_PIDLOG") | 4090 | HSHIMS_D2=$(wc -l < "$SSHIM_PIDLOG") |
| 4128 | [ "$((HSHIMS_D2 - HSHIMS_D))" -eq 1 ] || { | 4091 | [ "$((HSHIMS_D2 - HSHIMS_D))" -eq 1 ] || { |
| 4129 | echo "e2e FAIL: the fallback attach ran $((HSHIMS_D2 - HSHIMS_D)) ssh invocations, want 1" | 4092 | echo "e2e FAIL: the fallback attach ran $((HSHIMS_D2 - HSHIMS_D)) ssh invocations, want 1" |
| @@ -4143,24 +4106,16 @@ ok "a key mismatch falls back to the ssh pipe: one deadline (${HMS}ms), one line | |||
| 4143 | : > "$HCFGBAD" | 4106 | : > "$HCFGBAD" |
| 4144 | HSHIMS_E=$(wc -l < "$SSHIM_PIDLOG") | 4107 | HSHIMS_E=$(wc -l < "$SSHIM_PIDLOG") |
| 4145 | HT2=$(date +%s%N) | 4108 | HT2=$(date +%s%N) |
| 4146 | { printf 'printf "none-%%s\\n" ok\n'; sleep 2.5; printf '\034\034'; } | \ | 4109 | pipe_mux "$OUT.h5" "$OUT.h5.err" env SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN" XDG_CONFIG_HOME="$HCFGBAD" \ |
| 4147 | SHELL=/bin/sh XDG_RUNTIME_DIR="$HRUN" XDG_CONFIG_HOME="$HCFGBAD" \ | ||
| 4148 | PATH="$HPATH" timeout 40 \ | 4110 | PATH="$HPATH" timeout 40 \ |
| 4149 | "$MUX" "mux-e2e-none@127.0.0.1" > "$OUT.h5" 2> "$OUT.h5.err" & | 4111 | "$MUX" "mux-e2e-none@127.0.0.1" |
| 4150 | H5PID=$! | 4112 | pipe_send 'printf "none-%%s\\n" ok\n' |
| 4151 | wait_for "$OUT.h5" "none-ok" 20 || { | 4113 | wait_for "$OUT.h5" "none-ok" 20 || { |
| 4152 | echo "e2e FAIL: announce-none handoff never served a session" | 4114 | echo "e2e FAIL: announce-none handoff never served a session" |
| 4153 | cat "$OUT.h5" "$OUT.h5.err" 2>/dev/null; exit 1; } | 4115 | cat "$OUT.h5" "$OUT.h5.err" 2>/dev/null; exit 1; } |
| 4154 | HT3=$(date +%s%N) | 4116 | HT3=$(date +%s%N) |
| 4155 | HMS_E=$(( (HT3 - HT2) / 1000000 )) | 4117 | HMS_E=$(( (HT3 - HT2) / 1000000 )) |
| 4156 | set +e | 4118 | pipe_detach "announce-none client" |
| 4157 | wait "$H5PID" | ||
| 4158 | RC=$? | ||
| 4159 | set -e | ||
| 4160 | H5PID="" | ||
| 4161 | [ "$RC" -eq 0 ] || { | ||
| 4162 | echo "e2e FAIL: announce-none client exited $RC (want 0)" | ||
| 4163 | cat "$OUT.h5" "$OUT.h5.err" 2>/dev/null; exit 1; } | ||
| 4164 | # The remote said why, in one line, on the stderr ssh already carries. | 4119 | # The remote said why, in one line, on the stderr ssh already carries. |
| 4165 | grep -q '^muxd endpoint: .*staying on ssh' "$OUT.h5.err" || { | 4120 | grep -q '^muxd endpoint: .*staying on ssh' "$OUT.h5.err" || { |
| 4166 | echo "e2e FAIL: announce-none said nothing about why it stayed on ssh" | 4121 | echo "e2e FAIL: announce-none said nothing about why it stayed on ssh" |
| @@ -4249,12 +4204,16 @@ wait_sock "$SOCK21" "$OUT.m18.d" "M18 multi-session daemon never bound" | |||
| 4249 | # client leaves (decision 8) — so these greps run against two sessions | 4204 | # client leaves (decision 8) — so these greps run against two sessions |
| 4250 | # with nobody attached, which is also why none of their answers can be | 4205 | # with nobody attached, which is also why none of their answers can be |
| 4251 | # explained by a live client holding something open. | 4206 | # explained by a live client holding something open. |
| 4252 | { printf 'printf "m18a-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 4207 | pipe_mux "$OUT.m18a" "$OUT.m18a.err" timeout 40 "$MUX" --sock "$SOCK21" --session a |
| 4253 | timeout 40 "$MUX" --sock "$SOCK21" --session a > "$OUT.m18a" 2> "$OUT.m18a.err" | 4208 | pipe_send 'printf "m18a-%%s\\n" pin\n' |
| 4209 | await_out "$OUT.m18a" "m18a-pin" "m18a-pin never reached the client" | ||
| 4210 | pipe_detach | ||
| 4254 | wait_grid "$SOCK21" "m18a-pin" "M18: session a's marker" a | 4211 | wait_grid "$SOCK21" "m18a-pin" "M18: session a's marker" a |
| 4255 | 4212 | ||
| 4256 | { printf 'printf "m18b-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 4213 | pipe_mux "$OUT.m18b" "$OUT.m18b.err" timeout 40 "$MUX" --sock "$SOCK21" --session b |
| 4257 | timeout 40 "$MUX" --sock "$SOCK21" --session b > "$OUT.m18b" 2> "$OUT.m18b.err" | 4214 | pipe_send 'printf "m18b-%%s\\n" pin\n' |
| 4215 | await_out "$OUT.m18b" "m18b-pin" "m18b-pin never reached the client" | ||
| 4216 | pipe_detach | ||
| 4258 | wait_grid "$SOCK21" "m18b-pin" "M18: session b's marker" b | 4217 | wait_grid "$SOCK21" "m18b-pin" "M18: session b's marker" b |
| 4259 | 4218 | ||
| 4260 | # Each session's grid holds its own marker and NOT the other's. | 4219 | # Each session's grid holds its own marker and NOT the other's. |
| @@ -4333,14 +4292,9 @@ fi | |||
| 4333 | # every death but the last (decision 8). This client attaches to a session | 4292 | # every death but the last (decision 8). This client attaches to a session |
| 4334 | # that ALREADY EXISTS — attach-or-create's join arm, the other half of the | 4293 | # that ALREADY EXISTS — attach-or-create's join arm, the other half of the |
| 4335 | # two creations above — and types the exit that ends it. | 4294 | # two creations above — and types the exit that ends it. |
| 4336 | set +e | 4295 | pipe_mux "$OUT.m18ax" "$OUT.m18ax.err" timeout 40 "$MUX" --sock "$SOCK21" --session a |
| 4337 | { printf 'exit\n'; sleep 3; } | \ | 4296 | pipe_send 'exit\n' |
| 4338 | timeout 40 "$MUX" --sock "$SOCK21" --session a > "$OUT.m18ax" 2> "$OUT.m18ax.err" | 4297 | pipe_waitexit "M18: the client of an exiting session" |
| 4339 | RC=$? | ||
| 4340 | set -e | ||
| 4341 | [ "$RC" -eq 0 ] || { | ||
| 4342 | echo "e2e FAIL: M18: the client of an exiting session exited $RC, want 0" | ||
| 4343 | cat "$OUT.m18ax.err"; exit 1; } | ||
| 4344 | 4298 | ||
| 4345 | wait_sessions "$SOCK21" 2 "M18: session a's shell exited" | 4299 | wait_sessions "$SOCK21" 2 "M18: session a's shell exited" |
| 4346 | 4300 | ||
| @@ -4375,11 +4329,15 @@ wait_for "$OUT.m18wh" "serving" 10 || { | |||
| 4375 | 4329 | ||
| 4376 | # Content for each session, planted by a CLI client and left behind: the | 4330 | # Content for each session, planted by a CLI client and left behind: the |
| 4377 | # tiles are passive 0x0 wall tiles and can never type anything themselves. | 4331 | # tiles are passive 0x0 wall tiles and can never type anything themselves. |
| 4378 | { printf 'printf "wall-a-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 4332 | pipe_mux "$OUT.m18wa" "$OUT.m18wa.err" timeout 40 "$MUX" --sock "$SOCK22" --session a |
| 4379 | timeout 40 "$MUX" --sock "$SOCK22" --session a > "$OUT.m18wa" 2> "$OUT.m18wa.err" | 4333 | pipe_send 'printf "wall-a-%%s\\n" pin\n' |
| 4334 | await_out "$OUT.m18wa" "wall-a-pin" "M18 wall: session a's marker never reached the client" | ||
| 4335 | pipe_detach | ||
| 4380 | wait_grid "$SOCK22" "wall-a-pin" "M18 wall: session a's marker" a | 4336 | wait_grid "$SOCK22" "wall-a-pin" "M18 wall: session a's marker" a |
| 4381 | { printf 'printf "wall-b-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 4337 | pipe_mux "$OUT.m18wb" "$OUT.m18wb.err" timeout 40 "$MUX" --sock "$SOCK22" --session b |
| 4382 | timeout 40 "$MUX" --sock "$SOCK22" --session b > "$OUT.m18wb" 2> "$OUT.m18wb.err" | 4338 | pipe_send 'printf "wall-b-%%s\\n" pin\n' |
| 4339 | await_out "$OUT.m18wb" "wall-b-pin" "M18 wall: session b's marker never reached the client" | ||
| 4340 | pipe_detach | ||
| 4383 | wait_grid "$SOCK22" "wall-b-pin" "M18 wall: session b's marker" b | 4341 | wait_grid "$SOCK22" "wall-b-pin" "M18 wall: session b's marker" b |
| 4384 | 4342 | ||
| 4385 | # Tile 0 is session a's; tile 1 is session b's. The stand-in spells the | 4343 | # Tile 0 is session a's; tile 1 is session b's. The stand-in spells the |
| @@ -4476,26 +4434,16 @@ while : ; do | |||
| 4476 | QPORT5=$((QPORT5 + 137)) | 4434 | QPORT5=$((QPORT5 + 137)) |
| 4477 | done | 4435 | done |
| 4478 | 4436 | ||
| 4479 | set +e | 4437 | pipe_mux "$OUT.m18qa" "$OUT.m18qa.err" timeout 40 "$MUX" "quic://127.0.0.1:$QPORT5" --key "$M18KEY" --quic-idle-ms 15000 --session a |
| 4480 | { printf 'printf "q18a-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 4438 | pipe_send 'printf "q18a-%%s\\n" pin\n' |
| 4481 | timeout 40 "$MUX" "quic://127.0.0.1:$QPORT5" --key "$M18KEY" \ | 4439 | await_out "$OUT.m18qa" "q18a-pin" "q18a-pin never reached the client" |
| 4482 | --quic-idle-ms 15000 --session a > "$OUT.m18qa" 2> "$OUT.m18qa.err" | 4440 | pipe_detach "M18 quic: the --session a dial" |
| 4483 | RC=$? | ||
| 4484 | set -e | ||
| 4485 | [ "$RC" -eq 0 ] || { | ||
| 4486 | echo "e2e FAIL: M18 quic: the --session a dial exited $RC" | ||
| 4487 | cat "$OUT.m18qa" "$OUT.m18qa.err" 2>/dev/null; exit 1; } | ||
| 4488 | wait_grid "$SOCK23" "q18a-pin" "M18 quic: session a's marker" a | 4441 | wait_grid "$SOCK23" "q18a-pin" "M18 quic: session a's marker" a |
| 4489 | 4442 | ||
| 4490 | set +e | 4443 | pipe_mux "$OUT.m18qb" "$OUT.m18qb.err" timeout 40 "$MUX" "quic://127.0.0.1:$QPORT5" --key "$M18KEY" --quic-idle-ms 15000 --session b |
| 4491 | { printf 'printf "q18b-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 4444 | pipe_send 'printf "q18b-%%s\\n" pin\n' |
| 4492 | timeout 40 "$MUX" "quic://127.0.0.1:$QPORT5" --key "$M18KEY" \ | 4445 | await_out "$OUT.m18qb" "q18b-pin" "q18b-pin never reached the client" |
| 4493 | --quic-idle-ms 15000 --session b > "$OUT.m18qb" 2> "$OUT.m18qb.err" | 4446 | pipe_detach "M18 quic: the --session b dial" |
| 4494 | RC=$? | ||
| 4495 | set -e | ||
| 4496 | [ "$RC" -eq 0 ] || { | ||
| 4497 | echo "e2e FAIL: M18 quic: the --session b dial exited $RC" | ||
| 4498 | cat "$OUT.m18qb" "$OUT.m18qb.err" 2>/dev/null; exit 1; } | ||
| 4499 | wait_grid "$SOCK23" "q18b-pin" "M18 quic: session b's marker" b | 4447 | wait_grid "$SOCK23" "q18b-pin" "M18 quic: session b's marker" b |
| 4500 | 4448 | ||
| 4501 | if dump_session "$SOCK23" a | grep -q "q18b-pin"; then | 4449 | if dump_session "$SOCK23" a | grep -q "q18b-pin"; then |
| @@ -4512,14 +4460,10 @@ fi | |||
| 4512 | 4460 | ||
| 4513 | # The cross-transport join. Same name, different door: this must land in | 4461 | # The cross-transport join. Same name, different door: this must land in |
| 4514 | # the shell the QUIC client left behind, not spawn a second one. | 4462 | # the shell the QUIC client left behind, not spawn a second one. |
| 4515 | set +e | 4463 | pipe_mux "$OUT.m18qx" "$OUT.m18qx.err" timeout 40 "$MUX" --sock "$SOCK23" --session a |
| 4516 | { printf 'printf "x18a-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 4464 | pipe_send 'printf "x18a-%%s\\n" pin\n' |
| 4517 | timeout 40 "$MUX" --sock "$SOCK23" --session a > "$OUT.m18qx" 2> "$OUT.m18qx.err" | 4465 | await_out "$OUT.m18qx" "x18a-pin" "x18a-pin never reached the client" |
| 4518 | RC=$? | 4466 | pipe_detach "M18 quic: the socket client of session a" |
| 4519 | set -e | ||
| 4520 | [ "$RC" -eq 0 ] || { | ||
| 4521 | echo "e2e FAIL: M18 quic: the socket client of session a exited $RC" | ||
| 4522 | cat "$OUT.m18qx" "$OUT.m18qx.err" 2>/dev/null; exit 1; } | ||
| 4523 | wait_grid "$SOCK23" "x18a-pin" "M18 quic: the socket client's marker in a" a | 4467 | wait_grid "$SOCK23" "x18a-pin" "M18 quic: the socket client's marker in a" a |
| 4524 | 4468 | ||
| 4525 | # Both markers on one grid is the whole assertion: the QUIC client's | 4469 | # Both markers on one grid is the whole assertion: the QUIC client's |
| @@ -4556,22 +4500,22 @@ ok "quic: two dials are two sessions, and one name is one session on either tran | |||
| 4556 | D14PID=$! | 4500 | D14PID=$! |
| 4557 | wait_sock "$SOCK18" "$OUT.weba.d" "tiny attach daemon never bound" | 4501 | wait_sock "$SOCK18" "$OUT.weba.d" "tiny attach daemon never bound" |
| 4558 | 4502 | ||
| 4559 | # The 80x24 client: types the first marker, holds the session open long | 4503 | # The 80x24 client: types the first marker, holds the session open while |
| 4560 | # enough for the 1x1 attacher to come and go, types the second marker | 4504 | # the 1x1 attacher comes and goes, types the second marker (the geometry |
| 4561 | # (the geometry probe), detaches. | 4505 | # probe) once the attacher is provably on, detaches. |
| 4562 | { printf 'printf "wall-%%s\\n" pin\n'; sleep 4; printf 'printf "zz-%%s\\n" web\n'; sleep 2; printf '\034\034'; } | \ | 4506 | pipe_mux "$OUT.weba" "$OUT.weba.err" timeout 40 "$MUX" --sock "$SOCK18" |
| 4563 | timeout 40 "$MUX" --sock "$SOCK18" > "$OUT.weba" 2> "$OUT.weba.err" & | 4507 | pipe_send 'printf "wall-%%s\\n" pin\n' |
| 4564 | WCLIPID=$! | ||
| 4565 | wait_grid "$SOCK18" "wall-pin" "tiny attach: the first marker" | 4508 | wait_grid "$SOCK18" "wall-pin" "tiny attach: the first marker" |
| 4566 | 4509 | ||
| 4567 | # The 1x1 attacher, on a real 1x1 pty. Its attach is answered with a | 4510 | # The 1x1 attacher, on a real 1x1 pty. Its attach is answered with a |
| 4568 | # unicast snapshot (the alt-screen enter proves the first frame came), | 4511 | # unicast snapshot (the alt-screen enter proves the first frame came), |
| 4569 | # its keystroke is the claim attempt, and the 'z' it waits for is the | 4512 | # its keystroke is the claim attempt, and the 'z' it waits for is the |
| 4570 | # second marker echoing — proof it was STILL ATTACHED while the marker | 4513 | # second marker echoing — proof it was STILL ATTACHED while the marker |
| 4571 | # landed, so the grid it could have wrecked was live the whole time. | 4514 | # landed, so the grid it could have wrecked was live the whole time. The |
| 4572 | set +e | 4515 | # marker is typed only after the fixture reports its claim sent (`done 2`), |
| 4516 | # so the ordering is witnessed rather than paced. | ||
| 4573 | timeout 40 "$PTYCLIENT" --cols 1 --rows 1 --out "$OUT.web1x1" --err "$OUT.web1x1.err" \ | 4517 | timeout 40 "$PTYCLIENT" --cols 1 --rows 1 --out "$OUT.web1x1" --err "$OUT.web1x1.err" \ |
| 4574 | -- "$MUX" --sock "$SOCK18" > "$OUT.web1x1.log" 2>&1 <<'EOF' | 4518 | -- "$MUX" --sock "$SOCK18" > "$OUT.web1x1.log" 2>&1 <<'EOF' & |
| 4575 | expect \x1b[?1049h 15000 | 4519 | expect \x1b[?1049h 15000 |
| 4576 | send \x20 | 4520 | send \x20 |
| 4577 | expect z 20000 | 4521 | expect z 20000 |
| @@ -4579,6 +4523,13 @@ settle 300 10000 | |||
| 4579 | send \x1c\x1c | 4523 | send \x1c\x1c |
| 4580 | waitexit 10000 | 4524 | waitexit 10000 |
| 4581 | EOF | 4525 | EOF |
| 4526 | W1X1PID=$! | ||
| 4527 | wait_for "$OUT.web1x1.log" "ptyclient: done 2" 20 || { | ||
| 4528 | echo "e2e FAIL: tiny attach: the 1x1 client never got as far as its claim" | ||
| 4529 | cat "$OUT.web1x1.log"; cat -v "$OUT.web1x1.err" 2>/dev/null; exit 1; } | ||
| 4530 | pipe_send 'printf "zz-%%s\\n" web\n' | ||
| 4531 | set +e | ||
| 4532 | wait "$W1X1PID" | ||
| 4582 | RC=$? | 4533 | RC=$? |
| 4583 | set -e | 4534 | set -e |
| 4584 | [ "$RC" -eq 0 ] || { | 4535 | [ "$RC" -eq 0 ] || { |
| @@ -4594,12 +4545,8 @@ set -e | |||
| 4594 | echo "e2e FAIL: tiny attach: the 1x1 attacher moved the grid (marker not contiguous):" | 4545 | echo "e2e FAIL: tiny attach: the 1x1 attacher moved the grid (marker not contiguous):" |
| 4595 | "$MUXD" dump --sock "$SOCK18"; exit 1; } | 4546 | "$MUXD" dump --sock "$SOCK18"; exit 1; } |
| 4596 | 4547 | ||
| 4597 | set +e | 4548 | await_out "$OUT.weba" "zz-web" "tiny attach: the second marker never reached the 80x24 client" |
| 4598 | wait "$WCLIPID" | 4549 | pipe_detach "tiny attach: 80x24 client" |
| 4599 | RC=$? | ||
| 4600 | set -e | ||
| 4601 | WCLIPID="" | ||
| 4602 | [ "$RC" -eq 0 ] || { echo "e2e FAIL: tiny attach: 80x24 client exited $RC"; cat "$OUT.weba.err"; exit 1; } | ||
| 4603 | assert_converged "$OUT.weba" "$SOCK18" "tiny attach: the 80x24 client never glitched" | 4550 | assert_converged "$OUT.weba" "$SOCK18" "tiny attach: the 80x24 client never glitched" |
| 4604 | 4551 | ||
| 4605 | assert_stopped "$SOCK18" "$D14PID" "tiny attach" "$OUT.webstop" | 4552 | assert_stopped "$SOCK18" "$D14PID" "tiny attach" "$OUT.webstop" |
| @@ -4615,9 +4562,10 @@ W1PID=$! | |||
| 4615 | wait_for "$OUT.webh" "serving" 10 || { | 4562 | wait_for "$OUT.webh" "serving" 10 || { |
| 4616 | echo "e2e FAIL: hub never reported serving"; cat "$OUT.webh"; exit 1; } | 4563 | echo "e2e FAIL: hub never reported serving"; cat "$OUT.webh"; exit 1; } |
| 4617 | 4564 | ||
| 4618 | { printf 'printf "web-%%s\\n" b1\n'; sleep 4; printf '\034\034'; } | \ | 4565 | # The typing client stays attached until after the browser leg below, so |
| 4619 | timeout 40 "$MUX" --sock "$SOCK19" > "$OUT.webb" 2> "$OUT.webb.err" & | 4566 | # the hub pumps a session that has a live CLI client on it too. |
| 4620 | WCLIPID=$! | 4567 | pipe_mux "$OUT.webb" "$OUT.webb.err" timeout 40 "$MUX" --sock "$SOCK19" |
| 4568 | pipe_send 'printf "web-%%s\\n" b1\n' | ||
| 4621 | wait_grid "$SOCK19" "web-b1" "web hub: the typing client's marker" | 4569 | wait_grid "$SOCK19" "web-b1" "web hub: the typing client's marker" |
| 4622 | 4570 | ||
| 4623 | # The browser stand-in: a passive 0x0 wall tile through the hub. Its | 4571 | # The browser stand-in: a passive 0x0 wall tile through the hub. Its |
| @@ -4657,12 +4605,7 @@ CLIENTS_AFTER=$("$MUXD" stats --sock "$SOCK19" | sed -n 's/.*clients=\([0-9]*\). | |||
| 4657 | [ "$CLIENTS_BEFORE" = "$CLIENTS_AFTER" ] || { | 4605 | [ "$CLIENTS_BEFORE" = "$CLIENTS_AFTER" ] || { |
| 4658 | echo "e2e FAIL: web hub: evil origin reached the daemon (clients $CLIENTS_BEFORE -> $CLIENTS_AFTER)"; exit 1; } | 4606 | echo "e2e FAIL: web hub: evil origin reached the daemon (clients $CLIENTS_BEFORE -> $CLIENTS_AFTER)"; exit 1; } |
| 4659 | 4607 | ||
| 4660 | set +e | 4608 | pipe_detach "web hub: typing client" |
| 4661 | wait "$WCLIPID" | ||
| 4662 | RC=$? | ||
| 4663 | set -e | ||
| 4664 | WCLIPID="" | ||
| 4665 | [ "$RC" -eq 0 ] || { echo "e2e FAIL: web hub: typing client exited $RC"; cat "$OUT.webb.err"; exit 1; } | ||
| 4666 | assert_converged "$OUT.webb" "$SOCK19" "web hub: the typing client" | 4609 | assert_converged "$OUT.webb" "$SOCK19" "web hub: the typing client" |
| 4667 | 4610 | ||
| 4668 | kill "$W1PID" 2>/dev/null || true | 4611 | kill "$W1PID" 2>/dev/null || true |
| @@ -4686,8 +4629,10 @@ W2PID=$! | |||
| 4686 | wait_for "$OUT.webh2" "serving" 10 || { | 4629 | wait_for "$OUT.webh2" "serving" 10 || { |
| 4687 | echo "e2e FAIL: tear hub never reported serving"; cat "$OUT.webh2"; exit 1; } | 4630 | echo "e2e FAIL: tear hub never reported serving"; cat "$OUT.webh2"; exit 1; } |
| 4688 | 4631 | ||
| 4689 | { printf 'printf "web-%%s\\n" c1\n'; sleep 1.5; printf '\034\034'; } | \ | 4632 | pipe_mux "$OUT.webc" "$OUT.webc.err" timeout 30 "$MUX" --sock "$SOCK20" |
| 4690 | timeout 30 "$MUX" --sock "$SOCK20" > "$OUT.webc" 2> "$OUT.webc.err" | 4633 | pipe_send 'printf "web-%%s\\n" c1\n' |
| 4634 | await_out "$OUT.webc" "web-c1" "web-c1 never reached the client" | ||
| 4635 | pipe_detach | ||
| 4691 | wait_grid "$SOCK20" "web-c1" "web tear: the first session's marker" | 4636 | wait_grid "$SOCK20" "web-c1" "web tear: the first session's marker" |
| 4692 | 4637 | ||
| 4693 | timeout 90 "$WSCLIENT" --port "$WPORT2" --tile 0 --out "$OUT.webws2" --err "$OUT.webws2.err" <<'EOF' & | 4638 | timeout 90 "$WSCLIENT" --port "$WPORT2" --tile 0 --out "$OUT.webws2" --err "$OUT.webws2.err" <<'EOF' & |
| @@ -4713,8 +4658,10 @@ D16PID="" | |||
| 4713 | D17PID=$! | 4658 | D17PID=$! |
| 4714 | wait_sock "$SOCK20" "$OUT.webc2.d" "web tear restart never bound" | 4659 | wait_sock "$SOCK20" "$OUT.webc2.d" "web tear restart never bound" |
| 4715 | 4660 | ||
| 4716 | { printf 'printf "web-%%s\\n" c2\n'; sleep 1.5; printf '\034\034'; } | \ | 4661 | pipe_mux "$OUT.webc2" "$OUT.webc2.err" timeout 30 "$MUX" --sock "$SOCK20" |
| 4717 | timeout 30 "$MUX" --sock "$SOCK20" > "$OUT.webc2" 2> "$OUT.webc2.err" | 4662 | pipe_send 'printf "web-%%s\\n" c2\n' |
| 4663 | await_out "$OUT.webc2" "web-c2" "web-c2 never reached the client" | ||
| 4664 | pipe_detach | ||
| 4718 | 4665 | ||
| 4719 | set +e | 4666 | set +e |
| 4720 | wait "$WCLIPID" | 4667 | wait "$WCLIPID" |
| @@ -4799,13 +4746,10 @@ RC=$(curl -s -o /dev/null -w '%{http_code}' -H "Origin: $DWORIG" -X POST \ | |||
| 4799 | # passivity contract is in play in passing — a tile that claimed no size | 4746 | # passivity contract is in play in passing — a tile that claimed no size |
| 4800 | # never moves the grid, and the 80-wide marker is still one contiguous | 4747 | # never moves the grid, and the 80-wide marker is still one contiguous |
| 4801 | # string to expect. | 4748 | # string to expect. |
| 4802 | set +e | 4749 | pipe_mux "$OUT.dwcli" "$OUT.dwcli.err" timeout 40 "$MUX" --sock "$SOCK25" |
| 4803 | { printf 'printf "dyn-%%s\\n" w1\n'; sleep 4; printf '\034\034'; } | \ | 4750 | pipe_send 'printf "dyn-%%s\\n" w1\n' |
| 4804 | timeout 40 "$MUX" --sock "$SOCK25" > "$OUT.dwcli" 2> "$OUT.dwcli.err" | 4751 | await_out "$OUT.dwcli" "dyn-w1" "dyn-w1 never reached the client" |
| 4805 | RC=$? | 4752 | pipe_detach "dyn wall: CLI client" |
| 4806 | set -e | ||
| 4807 | [ "$RC" -eq 0 ] || { | ||
| 4808 | echo "e2e FAIL: dyn wall: CLI client exited $RC"; cat "$OUT.dwcli.err"; exit 1; } | ||
| 4809 | wait_grid "$SOCK25" "dyn-w1" "dyn wall: CLI marker" | 4753 | wait_grid "$SOCK25" "dyn-w1" "dyn wall: CLI marker" |
| 4810 | set +e | 4754 | set +e |
| 4811 | timeout 40 "$WSCLIENT" --port "$WPORT4" --tile 0 --out "$OUT.dwws" --err "$OUT.dwws.err" <<'EOF' | 4755 | timeout 40 "$WSCLIENT" --port "$WPORT4" --tile 0 --out "$OUT.dwws" --err "$OUT.dwws.err" <<'EOF' |
| @@ -4956,11 +4900,15 @@ ok "the wall is runtime state: add, remove, reorder, restore, argv adds" | |||
| 4956 | D23PID=$! | 4900 | D23PID=$! |
| 4957 | wait_sock "$SOCK26" "$OUT.cwall.d" "CLI wall daemon never bound" | 4901 | wait_sock "$SOCK26" "$OUT.cwall.d" "CLI wall daemon never bound" |
| 4958 | 4902 | ||
| 4959 | { printf 'printf "cwa-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 4903 | pipe_mux "$OUT.cwa" "$OUT.cwa.err" timeout 40 "$MUX" --sock "$SOCK26" --session a |
| 4960 | timeout 40 "$MUX" --sock "$SOCK26" --session a > "$OUT.cwa" 2> "$OUT.cwa.err" | 4904 | pipe_send 'printf "cwa-%%s\\n" pin\n' |
| 4905 | await_out "$OUT.cwa" "cwa-pin" "cwa-pin never reached the client" | ||
| 4906 | pipe_detach | ||
| 4961 | wait_grid "$SOCK26" "cwa-pin" "CLI wall: session a's marker" a | 4907 | wait_grid "$SOCK26" "cwa-pin" "CLI wall: session a's marker" a |
| 4962 | { printf 'printf "cwb-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 4908 | pipe_mux "$OUT.cwb" "$OUT.cwb.err" timeout 40 "$MUX" --sock "$SOCK26" --session b |
| 4963 | timeout 40 "$MUX" --sock "$SOCK26" --session b > "$OUT.cwb" 2> "$OUT.cwb.err" | 4909 | pipe_send 'printf "cwb-%%s\\n" pin\n' |
| 4910 | await_out "$OUT.cwb" "cwb-pin" "cwb-pin never reached the client" | ||
| 4911 | pipe_detach | ||
| 4964 | wait_grid "$SOCK26" "cwb-pin" "CLI wall: session b's marker" b | 4912 | wait_grid "$SOCK26" "cwb-pin" "CLI wall: session b's marker" b |
| 4965 | 4913 | ||
| 4966 | ( sleep 5; "$MUXA" send 'printf "cwlive-%s\n" pin\n' \ | 4914 | ( sleep 5; "$MUXA" send 'printf "cwlive-%s\n" pin\n' \ |
| @@ -5552,11 +5500,15 @@ wait_sock "$SOCK32" "$OUT.wz.d" "wall-zoom daemon never bound" | |||
| 5552 | # Two sessions, each with its own marker, created exactly as scenario 33 | 5500 | # Two sessions, each with its own marker, created exactly as scenario 33 |
| 5553 | # creates them: no tty on either client, so both grids are the default 80 | 5501 | # creates them: no tty on either client, so both grids are the default 80 |
| 5554 | # wide — the number the passivity check reads back later. | 5502 | # wide — the number the passivity check reads back later. |
| 5555 | { printf 'printf "wza-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 5503 | pipe_mux "$OUT.wza" "$OUT.wza.err" timeout 40 "$MUX" --sock "$SOCK32" --session a |
| 5556 | timeout 40 "$MUX" --sock "$SOCK32" --session a > "$OUT.wza" 2> "$OUT.wza.err" | 5504 | pipe_send 'printf "wza-%%s\\n" pin\n' |
| 5505 | await_out "$OUT.wza" "wza-pin" "wza-pin never reached the client" | ||
| 5506 | pipe_detach | ||
| 5557 | wait_grid "$SOCK32" "wza-pin" "wall zoom: session a's marker" a | 5507 | wait_grid "$SOCK32" "wza-pin" "wall zoom: session a's marker" a |
| 5558 | { printf 'printf "wzb-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 5508 | pipe_mux "$OUT.wzb" "$OUT.wzb.err" timeout 40 "$MUX" --sock "$SOCK32" --session b |
| 5559 | timeout 40 "$MUX" --sock "$SOCK32" --session b > "$OUT.wzb" 2> "$OUT.wzb.err" | 5509 | pipe_send 'printf "wzb-%%s\\n" pin\n' |
| 5510 | await_out "$OUT.wzb" "wzb-pin" "wzb-pin never reached the client" | ||
| 5511 | pipe_detach | ||
| 5560 | wait_grid "$SOCK32" "wzb-pin" "wall zoom: session b's marker" b | 5512 | wait_grid "$SOCK32" "wzb-pin" "wall zoom: session b's marker" b |
| 5561 | 5513 | ||
| 5562 | # Brackets the wall and nothing else: every `muxa` and `wait_grid` call in | 5514 | # Brackets the wall and nothing else: every `muxa` and `wait_grid` call in |
| @@ -5928,11 +5880,15 @@ wait_sock "$SOCK37" "$OUT.zs.d" "zoom-skip daemon never bound" | |||
| 5928 | 5880 | ||
| 5929 | # Both sessions exist before the wall does, with a marker each so the wall | 5881 | # Both sessions exist before the wall does, with a marker each so the wall |
| 5930 | # has something to paint and this leg has an anchor to enter on. | 5882 | # has something to paint and this leg has an anchor to enter on. |
| 5931 | { printf 'printf "zsa-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 5883 | pipe_mux "$OUT.zsa" "$OUT.zsa.err" timeout 40 "$MUX" --sock "$SOCK37" --session a |
| 5932 | timeout 40 "$MUX" --sock "$SOCK37" --session a > "$OUT.zsa" 2> "$OUT.zsa.err" | 5884 | pipe_send 'printf "zsa-%%s\\n" pin\n' |
| 5885 | await_out "$OUT.zsa" "zsa-pin" "zsa-pin never reached the client" | ||
| 5886 | pipe_detach | ||
| 5933 | wait_grid "$SOCK37" "zsa-pin" "zoom skip: session a's marker" a | 5887 | wait_grid "$SOCK37" "zsa-pin" "zoom skip: session a's marker" a |
| 5934 | { printf 'printf "zsb-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 5888 | pipe_mux "$OUT.zsb" "$OUT.zsb.err" timeout 40 "$MUX" --sock "$SOCK37" --session b |
| 5935 | timeout 40 "$MUX" --sock "$SOCK37" --session b > "$OUT.zsb" 2> "$OUT.zsb.err" | 5889 | pipe_send 'printf "zsb-%%s\\n" pin\n' |
| 5890 | await_out "$OUT.zsb" "zsb-pin" "zsb-pin never reached the client" | ||
| 5891 | pipe_detach | ||
| 5936 | wait_grid "$SOCK37" "zsb-pin" "zoom skip: session b's marker" b | 5892 | wait_grid "$SOCK37" "zsb-pin" "zoom skip: session b's marker" b |
| 5937 | 5893 | ||
| 5938 | ZSATT_BEFORE=$(attaches_now "$SOCK37") | 5894 | ZSATT_BEFORE=$(attaches_now "$SOCK37") |
| @@ -6084,11 +6040,15 @@ ok "the zoom skips between tiles with Ctrl-\\ n / Ctrl-\\ l, and the daemon sees | |||
| 6084 | "$MUXD" run --sock "$SOCK38" --shell /bin/sh > "$OUT.zm.d" 2>&1 & | 6040 | "$MUXD" run --sock "$SOCK38" --shell /bin/sh > "$OUT.zm.d" 2>&1 & |
| 6085 | D35PID=$! | 6041 | D35PID=$! |
| 6086 | wait_sock "$SOCK38" "$OUT.zm.d" "zoom-mute daemon never bound" | 6042 | wait_sock "$SOCK38" "$OUT.zm.d" "zoom-mute daemon never bound" |
| 6087 | { printf 'printf "zma-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6043 | pipe_mux "$OUT.zma" "$OUT.zma.err" timeout 40 "$MUX" --sock "$SOCK38" --session a |
| 6088 | timeout 40 "$MUX" --sock "$SOCK38" --session a > "$OUT.zma" 2> "$OUT.zma.err" | 6044 | pipe_send 'printf "zma-%%s\\n" pin\n' |
| 6045 | await_out "$OUT.zma" "zma-pin" "zma-pin never reached the client" | ||
| 6046 | pipe_detach | ||
| 6089 | wait_grid "$SOCK38" "zma-pin" "zoom mute: session a's marker" a | 6047 | wait_grid "$SOCK38" "zma-pin" "zoom mute: session a's marker" a |
| 6090 | { printf 'printf "zmb-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6048 | pipe_mux "$OUT.zmb" "$OUT.zmb.err" timeout 40 "$MUX" --sock "$SOCK38" --session b |
| 6091 | timeout 40 "$MUX" --sock "$SOCK38" --session b > "$OUT.zmb" 2> "$OUT.zmb.err" | 6049 | pipe_send 'printf "zmb-%%s\\n" pin\n' |
| 6050 | await_out "$OUT.zmb" "zmb-pin" "zmb-pin never reached the client" | ||
| 6051 | pipe_detach | ||
| 6092 | wait_grid "$SOCK38" "zmb-pin" "zoom mute: session b's marker" b | 6052 | wait_grid "$SOCK38" "zmb-pin" "zoom mute: session b's marker" b |
| 6093 | 6053 | ||
| 6094 | set +e | 6054 | set +e |
| @@ -6486,8 +6446,10 @@ ok "a tile the zoom is not on paints nothing at all, however loud its session ge | |||
| 6486 | "$MUXD" run --sock "$SOCK39" --shell /bin/sh > "$OUT.zd.d" 2>&1 & | 6446 | "$MUXD" run --sock "$SOCK39" --shell /bin/sh > "$OUT.zd.d" 2>&1 & |
| 6487 | D36PID=$! | 6447 | D36PID=$! |
| 6488 | wait_sock "$SOCK39" "$OUT.zd.d" "zoom-dead daemon never bound" | 6448 | wait_sock "$SOCK39" "$OUT.zd.d" "zoom-dead daemon never bound" |
| 6489 | { printf 'printf "zdlive-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6449 | pipe_mux "$OUT.zda" "$OUT.zda.err" timeout 40 "$MUX" --sock "$SOCK39" --session a |
| 6490 | timeout 40 "$MUX" --sock "$SOCK39" --session a > "$OUT.zda" 2> "$OUT.zda.err" | 6450 | pipe_send 'printf "zdlive-%%s\\n" pin\n' |
| 6451 | await_out "$OUT.zda" "zdlive-pin" "zdlive-pin never reached the client" | ||
| 6452 | pipe_detach | ||
| 6491 | wait_grid "$SOCK39" "zdlive-pin" "zoom dead: the live session's marker" a | 6453 | wait_grid "$SOCK39" "zdlive-pin" "zoom dead: the live session's marker" a |
| 6492 | 6454 | ||
| 6493 | set +e | 6455 | set +e |
| @@ -6559,9 +6521,10 @@ ok "a tile whose pump has died narrates its zoom and gets its stripe back" | |||
| 6559 | D37PID=$! | 6521 | D37PID=$! |
| 6560 | wait_sock "$SOCK40" "$OUT.wh.d" "attach-history daemon never bound" | 6522 | wait_sock "$SOCK40" "$OUT.wh.d" "attach-history daemon never bound" |
| 6561 | 6523 | ||
| 6562 | { printf 'printf "wh1-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6524 | pipe_mux "$OUT.wh1" "$OUT.wh1.err" env XDG_STATE_HOME="$WHSTATE" timeout 40 "$MUX" --sock "$SOCK40" |
| 6563 | XDG_STATE_HOME="$WHSTATE" timeout 40 "$MUX" --sock "$SOCK40" \ | 6525 | pipe_send 'printf "wh1-%%s\\n" pin\n' |
| 6564 | > "$OUT.wh1" 2> "$OUT.wh1.err" | 6526 | await_out "$OUT.wh1" "wh1-pin" "wh1-pin never reached the client" |
| 6527 | pipe_detach | ||
| 6565 | wait_grid "$SOCK40" "wh1-pin" "attach history: the default session's marker" | 6528 | wait_grid "$SOCK40" "wh1-pin" "attach history: the default session's marker" |
| 6566 | grep -qx -- "--sock $SOCK40#0" "$WHWALL" || { | 6529 | grep -qx -- "--sock $SOCK40#0" "$WHWALL" || { |
| 6567 | echo "e2e FAIL: attach history: the attach wrote no tile (or not '#0'):" | 6530 | echo "e2e FAIL: attach history: the attach wrote no tile (or not '#0'):" |
| @@ -6571,9 +6534,10 @@ _wh_n=$(wc -l < "$WHWALL") | |||
| 6571 | echo "e2e FAIL: attach history: one attach wrote $_wh_n lines:" | 6534 | echo "e2e FAIL: attach history: one attach wrote $_wh_n lines:" |
| 6572 | cat "$WHWALL"; exit 1; } | 6535 | cat "$WHWALL"; exit 1; } |
| 6573 | 6536 | ||
| 6574 | { printf 'printf "wh2-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6537 | pipe_mux "$OUT.wh2" "$OUT.wh2.err" env XDG_STATE_HOME="$WHSTATE" timeout 40 "$MUX" --sock "$SOCK40" |
| 6575 | XDG_STATE_HOME="$WHSTATE" timeout 40 "$MUX" --sock "$SOCK40" \ | 6538 | pipe_send 'printf "wh2-%%s\\n" pin\n' |
| 6576 | > "$OUT.wh2" 2> "$OUT.wh2.err" | 6539 | await_out "$OUT.wh2" "wh2-pin" "wh2-pin never reached the client" |
| 6540 | pipe_detach | ||
| 6577 | wait_grid "$SOCK40" "wh2-pin" "attach history: the second attach's marker" | 6541 | wait_grid "$SOCK40" "wh2-pin" "attach history: the second attach's marker" |
| 6578 | _wh_n=$(wc -l < "$WHWALL") | 6542 | _wh_n=$(wc -l < "$WHWALL") |
| 6579 | [ "$_wh_n" -eq 1 ] || { | 6543 | [ "$_wh_n" -eq 1 ] || { |
| @@ -6609,9 +6573,10 @@ grep -qx -- "--sock $SOCK40#1" "$WHWALL" || { | |||
| 6609 | # and an attach that happened anyway — best effort means the attach is the | 6573 | # and an attach that happened anyway — best effort means the attach is the |
| 6610 | # act and the tile is only the record. | 6574 | # act and the tile is only the record. |
| 6611 | mkdir -p "$WHBAD/mux/wall" | 6575 | mkdir -p "$WHBAD/mux/wall" |
| 6612 | { printf 'printf "whro-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6576 | pipe_mux "$OUT.whro" "$OUT.whro.err" env XDG_STATE_HOME="$WHBAD" timeout 40 "$MUX" --sock "$SOCK40" |
| 6613 | XDG_STATE_HOME="$WHBAD" timeout 40 "$MUX" --sock "$SOCK40" \ | 6577 | pipe_send 'printf "whro-%%s\\n" pin\n' |
| 6614 | > "$OUT.whro" 2> "$OUT.whro.err" | 6578 | await_out "$OUT.whro" "whro-pin" "whro-pin never reached the client" |
| 6579 | pipe_detach | ||
| 6615 | grep -q "wall not updated" "$OUT.whro.err" || { | 6580 | grep -q "wall not updated" "$OUT.whro.err" || { |
| 6616 | echo "e2e FAIL: attach history: an unwritable wall file said nothing:" | 6581 | echo "e2e FAIL: attach history: an unwritable wall file said nothing:" |
| 6617 | cat "$OUT.whro.err"; exit 1; } | 6582 | cat "$OUT.whro.err"; exit 1; } |
| @@ -6688,13 +6653,15 @@ ok "the wall is attach history: mux adds, muxa never does, add/rm edit it" | |||
| 6688 | # Two ptyclient runs rather than one, because the file is the artifact: | 6653 | # Two ptyclient runs rather than one, because the file is the artifact: |
| 6689 | # what a run did is only readable after it has exited, so the one-tile | 6654 | # what a run did is only readable after it has exited, so the one-tile |
| 6690 | # state between them is the second run's input. | 6655 | # state between them is the second run's input. |
| 6691 | { printf 'printf "whxa-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6656 | pipe_mux "$OUT.whxa" "$OUT.whxa.err" env XDG_STATE_HOME="$WHXSTATE" timeout 40 "$MUX" --sock "$SOCK40" --session xa |
| 6692 | XDG_STATE_HOME="$WHXSTATE" timeout 40 "$MUX" --sock "$SOCK40" --session xa \ | 6657 | pipe_send 'printf "whxa-%%s\\n" pin\n' |
| 6693 | > "$OUT.whxa" 2> "$OUT.whxa.err" | 6658 | await_out "$OUT.whxa" "whxa-pin" "whxa-pin never reached the client" |
| 6659 | pipe_detach | ||
| 6694 | wait_grid "$SOCK40" "whxa-pin" "x forgets: session xa's marker" xa | 6660 | wait_grid "$SOCK40" "whxa-pin" "x forgets: session xa's marker" xa |
| 6695 | { printf 'printf "whxb-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6661 | pipe_mux "$OUT.whxb" "$OUT.whxb.err" env XDG_STATE_HOME="$WHXSTATE" timeout 40 "$MUX" --sock "$SOCK40" --session xb |
| 6696 | XDG_STATE_HOME="$WHXSTATE" timeout 40 "$MUX" --sock "$SOCK40" --session xb \ | 6662 | pipe_send 'printf "whxb-%%s\\n" pin\n' |
| 6697 | > "$OUT.whxb" 2> "$OUT.whxb.err" | 6663 | await_out "$OUT.whxb" "whxb-pin" "whxb-pin never reached the client" |
| 6664 | pipe_detach | ||
| 6698 | wait_grid "$SOCK40" "whxb-pin" "x forgets: session xb's marker" xb | 6665 | wait_grid "$SOCK40" "whxb-pin" "x forgets: session xb's marker" xb |
| 6699 | _whx_n=$(wc -l < "$WHXSTATE/mux/wall") | 6666 | _whx_n=$(wc -l < "$WHXSTATE/mux/wall") |
| 6700 | [ "$_whx_n" -eq 2 ] || { | 6667 | [ "$_whx_n" -eq 2 ] || { |
| @@ -6836,9 +6803,10 @@ wait_sock "$SOCK45" "$OUT.cv.d" "convergence daemon never bound" | |||
| 6836 | # The tile that is already on the wall before this leg's client starts. A | 6803 | # The tile that is already on the wall before this leg's client starts. A |
| 6837 | # piped `mux`, so its attach writes the line and then goes: what the leg | 6804 | # piped `mux`, so its attach writes the line and then goes: what the leg |
| 6838 | # asserts on is the FILE it left behind, not a process still holding it. | 6805 | # asserts on is the FILE it left behind, not a process still holding it. |
| 6839 | { printf 'printf "cvside-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6806 | pipe_mux "$OUT.cvside" "$OUT.cvside.err" env XDG_STATE_HOME="$CVSTATE" timeout 40 "$MUX" --sock "$SOCK45" --session side |
| 6840 | XDG_STATE_HOME="$CVSTATE" timeout 40 "$MUX" --sock "$SOCK45" --session side \ | 6807 | pipe_send 'printf "cvside-%%s\\n" pin\n' |
| 6841 | > "$OUT.cvside" 2> "$OUT.cvside.err" | 6808 | await_out "$OUT.cvside" "cvside-pin" "cvside-pin never reached the client" |
| 6809 | pipe_detach | ||
| 6842 | wait_grid "$SOCK45" "cvside-pin" "convergence: the saved tile's marker" side | 6810 | wait_grid "$SOCK45" "cvside-pin" "convergence: the saved tile's marker" side |
| 6843 | grep -qx -- "--sock $SOCK45#side" "$CVWALL" || { | 6811 | grep -qx -- "--sock $SOCK45#side" "$CVWALL" || { |
| 6844 | echo "e2e FAIL: convergence: the setup attach wrote no tile to unzoom onto:" | 6812 | echo "e2e FAIL: convergence: the setup attach wrote no tile to unzoom onto:" |
| @@ -6940,9 +6908,10 @@ wait_sock "$SOCK46" "$OUT.rg.d" "ring-grow daemon never bound" | |||
| 6940 | # `two` exists on the DAEMON but not in this leg's wall: a separate state | 6908 | # `two` exists on the DAEMON but not in this leg's wall: a separate state |
| 6941 | # home is what makes the setup client's own tile invisible here, so the | 6909 | # home is what makes the setup client's own tile invisible here, so the |
| 6942 | # first `n` meets a sibling with no tile — which is the case under test. | 6910 | # first `n` meets a sibling with no tile — which is the case under test. |
| 6943 | { printf 'printf "rgtwo-%%s\\n" pin\n'; sleep 2; printf '\034\034'; } | \ | 6911 | pipe_mux "$OUT.rgtwo" "$OUT.rgtwo.err" env XDG_STATE_HOME="$RGOTHER" timeout 40 "$MUX" --sock "$SOCK46" --session two |
| 6944 | XDG_STATE_HOME="$RGOTHER" timeout 40 "$MUX" --sock "$SOCK46" --session two \ | 6912 | pipe_send 'printf "rgtwo-%%s\\n" pin\n' |
| 6945 | > "$OUT.rgtwo" 2> "$OUT.rgtwo.err" | 6913 | await_out "$OUT.rgtwo" "rgtwo-pin" "rgtwo-pin never reached the client" |
| 6914 | pipe_detach | ||
| 6946 | wait_grid "$SOCK46" "rgtwo-pin" "ring grow: the untiled sibling's marker" two | 6915 | wait_grid "$SOCK46" "rgtwo-pin" "ring grow: the untiled sibling's marker" two |
| 6947 | grep -qx -- "--sock $SOCK46#two" "$RGSTATE/mux/wall" 2>/dev/null && { | 6916 | grep -qx -- "--sock $SOCK46#two" "$RGSTATE/mux/wall" 2>/dev/null && { |
| 6948 | echo "e2e FAIL: ring grow: the sibling already had a tile, so the ADD is vacuous:" | 6917 | echo "e2e FAIL: ring grow: the sibling already had a tile, so the ADD is vacuous:" |
| @@ -7035,16 +7004,12 @@ ok "Ctrl-\\ n grows the wall for a sibling with no tile, and is free for one tha | |||
| 7035 | D47PID=$! | 7004 | D47PID=$! |
| 7036 | wait_sock "$SOCK47" "$OUT.xe.d" "exit-semantics daemon never bound" | 7005 | wait_sock "$SOCK47" "$OUT.xe.d" "exit-semantics daemon never bound" |
| 7037 | 7006 | ||
| 7038 | set +e | 7007 | # A wall it dropped to instead would read as 124: it never leaves, because |
| 7039 | { printf 'exit 7\n'; sleep 3; } | XDG_STATE_HOME="$XESTATE" timeout 40 \ | 7008 | # nothing closes its stdin under it. |
| 7040 | "$MUX" --sock "$SOCK47" > "$OUT.xe1" 2> "$OUT.xe1.err" | 7009 | pipe_mux "$OUT.xe1" "$OUT.xe1.err" env XDG_STATE_HOME="$XESTATE" timeout 40 \ |
| 7041 | RC=$? | 7010 | "$MUX" --sock "$SOCK47" |
| 7042 | set -e | 7011 | pipe_send 'exit 7\n' |
| 7043 | [ "$RC" -eq 7 ] || { | 7012 | pipe_waitexit "exit semantics: the only tile's shell exited 7, and mux" 7 |
| 7044 | echo "e2e FAIL: exit semantics: the only tile's shell exited 7 and mux exited $RC" | ||
| 7045 | echo " — a wall it dropped to instead reads as 0 once this script's" | ||
| 7046 | echo " stdin closes under it, or 124 if it never gets that far:" | ||
| 7047 | cat "$OUT.xe1.err"; exit 1; } | ||
| 7048 | 7013 | ||
| 7049 | set +e | 7014 | set +e |
| 7050 | XDG_STATE_HOME="$XESTATE" timeout 90 "$PTYCLIENT" --cols 100 --rows 30 \ | 7015 | XDG_STATE_HOME="$XESTATE" timeout 90 "$PTYCLIENT" --cols 100 --rows 30 \ |