a73x

a7704310

test: e2e — one no_saved_tree helper replaces five copies of the same rm and comment

a73x   2026-08-28 19:53

Commit message
test: e2e — one no_saved_tree helper replaces five copies of the same rm and comment

test/e2e_07_wallcli.sh
Old New
@@ -77,11 +77,7 @@ wait_grid "$SOCK26" "cwb-pin" "CLI wall: session b's marker" b
77 CWINJPID=$! 77 CWINJPID=$!
78 defer_kill "$CWINJPID" 78 defer_kill "$CWINJPID"
79 set +e 79 set +e
80 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 80 no_saved_tree "$CWSTATE"
81 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
82 # state home has already left one. The aspect rule applies only when
83 # nothing is saved.
84 rm -f "$CWSTATE/mux/layout"
85 XDG_STATE_HOME="$CWSTATE" timeout 40 "$PTYCLIENT" --cols 40 --rows 30 \ 81 XDG_STATE_HOME="$CWSTATE" timeout 40 "$PTYCLIENT" --cols 40 --rows 30 \
86 --out "$OUT.cwcap" --err "$OUT.cwcap.err" -- \ 82 --out "$OUT.cwcap" --err "$OUT.cwcap.err" -- \
87 "$MUX" --sock "$SOCK26" --session a > "$OUT.cwpc" 2>&1 <<'EOF' 83 "$MUX" --sock "$SOCK26" --session a > "$OUT.cwpc" 2>&1 <<'EOF'
@@ -133,11 +129,7 @@ start_daemon "$SOCK27" "$OUT.pfx.d" "prefix daemon never bound" --shell /bin/sh
133 D24PID=$DPID 129 D24PID=$DPID
134 130
135 set +e 131 set +e
136 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 132 no_saved_tree "$PFXSTATE"
137 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
138 # state home has already left one. The aspect rule applies only when
139 # nothing is saved.
140 rm -f "$PFXSTATE/mux/layout"
141 XDG_STATE_HOME="$PFXSTATE" timeout 40 "$PTYCLIENT" --cols 80 --rows 24 \ 133 XDG_STATE_HOME="$PFXSTATE" timeout 40 "$PTYCLIENT" --cols 80 --rows 24 \
142 --out "$OUT.pfx" --err "$OUT.pfx.err" \ 134 --out "$OUT.pfx" --err "$OUT.pfx.err" \
143 -- "$MUX" --sock "$SOCK27" > "$OUT.pfx.log" 2>&1 <<'EOF' 135 -- "$MUX" --sock "$SOCK27" > "$OUT.pfx.log" 2>&1 <<'EOF'
@@ -204,11 +196,7 @@ start_daemon "$SOCK28" "$OUT.nsw.d" "new-session daemon never bound" --shell /bi
204 D25PID=$DPID 196 D25PID=$DPID
205 197
206 set +e 198 set +e
207 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 199 no_saved_tree "$NSWSTATE"
208 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
209 # state home has already left one. The aspect rule applies only when
210 # nothing is saved.
211 rm -f "$NSWSTATE/mux/layout"
212 XDG_STATE_HOME="$NSWSTATE" timeout 40 "$PTYCLIENT" --cols 40 --rows 24 \ 200 XDG_STATE_HOME="$NSWSTATE" timeout 40 "$PTYCLIENT" --cols 40 --rows 24 \
213 --out "$OUT.nsw" --err "$OUT.nsw.err" \ 201 --out "$OUT.nsw" --err "$OUT.nsw.err" \
214 -- "$MUX" --sock "$SOCK28" > "$OUT.nsw.log" 2>&1 <<'EOF' 202 -- "$MUX" --sock "$SOCK28" > "$OUT.nsw.log" 2>&1 <<'EOF'
@@ -256,11 +244,7 @@ fill_sessions "$SOCK28" "$OUT.nswfill" fill 2 7
256 wait_sessions "$SOCK28" 8 "new session: the wall's terminal should be exactly full" 244 wait_sessions "$SOCK28" 8 "new session: the wall's terminal should be exactly full"
257 245
258 set +e 246 set +e
259 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 247 no_saved_tree "$NSWSTATE"
260 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
261 # state home has already left one. The aspect rule applies only when
262 # nothing is saved.
263 rm -f "$NSWSTATE/mux/layout"
264 XDG_STATE_HOME="$NSWSTATE" timeout 60 "$PTYCLIENT" --cols 40 --rows 24 \ 248 XDG_STATE_HOME="$NSWSTATE" timeout 60 "$PTYCLIENT" --cols 40 --rows 24 \
265 --out "$OUT.nsw2" --err "$OUT.nsw2.err" \ 249 --out "$OUT.nsw2" --err "$OUT.nsw2.err" \
266 -- "$MUX" --sock "$SOCK28" > "$OUT.nsw2.log" 2>&1 <<'EOF' 250 -- "$MUX" --sock "$SOCK28" > "$OUT.nsw2.log" 2>&1 <<'EOF'
@@ -355,11 +339,7 @@ D26PID=$DPID
355 339
356 set +e 340 set +e
357 # tall: Ctrl-\ c adds tiles at 80x24 (80 >= 48) 341 # tall: Ctrl-\ c adds tiles at 80x24 (80 >= 48)
358 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 342 no_saved_tree "$RINGSTATE"
359 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
360 # state home has already left one. The aspect rule applies only when
361 # nothing is saved.
362 rm -f "$RINGSTATE/mux/layout"
363 XDG_STATE_HOME="$RINGSTATE" timeout 60 "$PTYCLIENT" --cols 40 --rows 24 \ 343 XDG_STATE_HOME="$RINGSTATE" timeout 60 "$PTYCLIENT" --cols 40 --rows 24 \
364 --out "$OUT.ring" --err "$OUT.ring.err" \ 344 --out "$OUT.ring" --err "$OUT.ring.err" \
365 -- "$MUX" --sock "$SOCK29" > "$OUT.ring.log" 2>&1 <<'EOF' 345 -- "$MUX" --sock "$SOCK29" > "$OUT.ring.log" 2>&1 <<'EOF'
test/e2e_08_mouse.sh
Old New
@@ -364,11 +364,7 @@ ZSATT_BEFORE=$(attaches_now "$SOCK37")
364 watch_clients "$SOCK37" "$OUT.zswatch" 364 watch_clients "$SOCK37" "$OUT.zswatch"
365 set +e 365 set +e
366 # tall: the aspect rule would cut columns at 92x30 (92 >= 60) 366 # tall: the aspect rule would cut columns at 92x30 (92 >= 60)
367 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 367 no_saved_tree "$ZSSTATE"
368 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
369 # state home has already left one. The aspect rule applies only when
370 # nothing is saved.
371 rm -f "$ZSSTATE/mux/layout"
372 XDG_STATE_HOME="$ZSSTATE" timeout 90 "$PTYCLIENT" --cols 40 --rows 30 \ 368 XDG_STATE_HOME="$ZSSTATE" timeout 90 "$PTYCLIENT" --cols 40 --rows 30 \
373 --out "$OUT.zscap" --err "$OUT.zscap.err" -- \ 369 --out "$OUT.zscap" --err "$OUT.zscap.err" -- \
374 "$MUX" --sock "$SOCK37" > "$OUT.zspc" 2>&1 <<'EOF' 370 "$MUX" --sock "$SOCK37" > "$OUT.zspc" 2>&1 <<'EOF'
@@ -481,11 +477,7 @@ until "$MUXD" dump --sock "$SOCK41" | grep -q "wln100"; do
481 sleep 0.1 477 sleep 0.1
482 done 478 done
483 set +e 479 set +e
484 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 480 no_saved_tree "$ZWSTATE"
485 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
486 # state home has already left one. The aspect rule applies only when
487 # nothing is saved.
488 rm -f "$ZWSTATE/mux/layout"
489 XDG_STATE_HOME="$ZWSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 \ 481 XDG_STATE_HOME="$ZWSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 \
490 --out "$OUT.zwcap" --err "$OUT.zwcap.err" -- \ 482 --out "$OUT.zwcap" --err "$OUT.zwcap.err" -- \
491 "$MUX" --sock "$SOCK41" > "$OUT.zwpc" 2>&1 <<'EOF' 483 "$MUX" --sock "$SOCK41" > "$OUT.zwpc" 2>&1 <<'EOF'
@@ -559,11 +551,7 @@ done
559 # not. The tile claims the terminal on its first pass, so the modes are 551 # not. The tile claims the terminal on its first pass, so the modes are
560 # level-set before the wheel is sent. 552 # level-set before the wheel is sent.
561 set +e 553 set +e
562 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 554 no_saved_tree "$ZM2STATE"
563 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
564 # state home has already left one. The aspect rule applies only when
565 # nothing is saved.
566 rm -f "$ZM2STATE/mux/layout"
567 XDG_STATE_HOME="$ZM2STATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 \ 555 XDG_STATE_HOME="$ZM2STATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 \
568 --out "$OUT.zm2cap" --err "$OUT.zm2cap.err" -- \ 556 --out "$OUT.zm2cap" --err "$OUT.zm2cap.err" -- \
569 "$MUX" --sock "$SOCK42" > "$OUT.zm2pc" 2>&1 <<'EOF' 557 "$MUX" --sock "$SOCK42" > "$OUT.zm2pc" 2>&1 <<'EOF'
test/e2e_11_select.sh
Old New
@@ -56,11 +56,7 @@ wait_grid "$SOCK50" "wmb-pin" "wall cluster: session b's marker" b
56 # other way. A negative that cannot fail is not a test, so each carries the 56 # other way. A negative that cannot fail is not a test, so each carries the
57 # marker that MUST land in the focused session. 57 # marker that MUST land in the focused session.
58 set +e 58 set +e
59 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 59 no_saved_tree "$WMSTATE"
60 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
61 # state home has already left one. The aspect rule applies only when
62 # nothing is saved.
63 rm -f "$WMSTATE/mux/layout"
64 XDG_STATE_HOME="$WMSTATE" timeout 60 "$PTYCLIENT" --cols 40 --rows 30 \ 60 XDG_STATE_HOME="$WMSTATE" timeout 60 "$PTYCLIENT" --cols 40 --rows 30 \
65 --out "$OUT.wmcap3" --err "$OUT.wmcap3.err" -- \ 61 --out "$OUT.wmcap3" --err "$OUT.wmcap3.err" -- \
66 "$MUX" --sock "$SOCK50" > "$OUT.wmpc3" 2>&1 <<'EOF' 62 "$MUX" --sock "$SOCK50" > "$OUT.wmpc3" 2>&1 <<'EOF'
@@ -91,11 +87,7 @@ grep -q "wm-three" "$OUT.wmfa" && {
91 # The other direction: focus b explicitly, then click a's content and watch 87 # The other direction: focus b explicitly, then click a's content and watch
92 # the focus come back to a. 88 # the focus come back to a.
93 set +e 89 set +e
94 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 90 no_saved_tree "$WMSTATE"
95 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
96 # state home has already left one. The aspect rule applies only when
97 # nothing is saved.
98 rm -f "$WMSTATE/mux/layout"
99 XDG_STATE_HOME="$WMSTATE" timeout 60 "$PTYCLIENT" --cols 40 --rows 30 \ 91 XDG_STATE_HOME="$WMSTATE" timeout 60 "$PTYCLIENT" --cols 40 --rows 30 \
100 --out "$OUT.wmcap4" --err "$OUT.wmcap4.err" -- \ 92 --out "$OUT.wmcap4" --err "$OUT.wmcap4.err" -- \
101 "$MUX" --sock "$SOCK50" > "$OUT.wmpc4" 2>&1 <<'EOF' 93 "$MUX" --sock "$SOCK50" > "$OUT.wmpc4" 2>&1 <<'EOF'
@@ -132,11 +124,7 @@ ok "a click in a tile's rect focuses it, from wherever the focus was"
132 # test in rectHit earns its keep: focus starts on a (the left pane) and 124 # test in rectHit earns its keep: focus starts on a (the left pane) and
133 # the click must move it to b (the right pane). 125 # the click must move it to b (the right pane).
134 set +e 126 set +e
135 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 127 no_saved_tree "$WMSTATE"
136 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
137 # state home has already left one. The aspect rule applies only when
138 # nothing is saved.
139 rm -f "$WMSTATE/mux/layout"
140 XDG_STATE_HOME="$WMSTATE" timeout 60 "$PTYCLIENT" --cols 100 --rows 30 \ 128 XDG_STATE_HOME="$WMSTATE" timeout 60 "$PTYCLIENT" --cols 100 --rows 30 \
141 --out "$OUT.wmcap5" --err "$OUT.wmcap5.err" -- \ 129 --out "$OUT.wmcap5" --err "$OUT.wmcap5.err" -- \
142 "$MUX" --sock "$SOCK50" > "$OUT.wmpc5" 2>&1 <<'EOF' 130 "$MUX" --sock "$SOCK50" > "$OUT.wmpc5" 2>&1 <<'EOF'
test/e2e_12_panes.sh
Old New
@@ -80,11 +80,7 @@ pipe_detach
80 wait_grid "$SOCK52" "mc-pin" "cursor: session c's marker" c 80 wait_grid "$SOCK52" "mc-pin" "cursor: session c's marker" c
81 81
82 set +e 82 set +e
83 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 83 no_saved_tree "$CUSTATE"
84 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
85 # state home has already left one. The aspect rule applies only when
86 # nothing is saved.
87 rm -f "$CUSTATE/mux/layout"
88 XDG_STATE_HOME="$CUSTATE" timeout 40 "$PTYCLIENT" --cols 40 --rows 30 --out "$OUT.cucap" --err "$OUT.cucap.err" -- \ 84 XDG_STATE_HOME="$CUSTATE" timeout 40 "$PTYCLIENT" --cols 40 --rows 30 --out "$OUT.cucap" --err "$OUT.cucap.err" -- \
89 "$MUX" --sock "$SOCK52" > "$OUT.cupc" 2>&1 <<'EOF' 85 "$MUX" --sock "$SOCK52" > "$OUT.cupc" 2>&1 <<'EOF'
90 expect mc-pin 20000 86 expect mc-pin 20000
@@ -173,11 +169,7 @@ pipe_detach
173 wait_grid "$SOCK53" "sb2nbr" "scrollback-rect: session b's pin" b 169 wait_grid "$SOCK53" "sb2nbr" "scrollback-rect: session b's pin" b
174 170
175 set +e 171 set +e
176 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 172 no_saved_tree "$SB2STATE"
177 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
178 # state home has already left one. The aspect rule applies only when
179 # nothing is saved.
180 rm -f "$SB2STATE/mux/layout"
181 XDG_STATE_HOME="$SB2STATE" timeout 90 "$PTYCLIENT" --cols 40 --rows 30 --out "$OUT.sb2cap" --err "$OUT.sb2cap.err" -- \ 173 XDG_STATE_HOME="$SB2STATE" timeout 90 "$PTYCLIENT" --cols 40 --rows 30 --out "$OUT.sb2cap" --err "$OUT.sb2cap.err" -- \
182 "$MUX" --sock "$SOCK53" > "$OUT.sb2pc" 2>&1 <<'EOF' 174 "$MUX" --sock "$SOCK53" > "$OUT.sb2pc" 2>&1 <<'EOF'
183 expect sb2nbr 20000 175 expect sb2nbr 20000
@@ -236,11 +228,7 @@ wait_grid "$SOCK54" "fs-init-b" "fullscreen: session b's marker" b
236 228
237 set +e 229 set +e
238 # wide: 80x24 trips the aspect rule (80 >= 48 → beside) 230 # wide: 80x24 trips the aspect rule (80 >= 48 → beside)
239 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 231 no_saved_tree "$FSSTATE"
240 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
241 # state home has already left one. The aspect rule applies only when
242 # nothing is saved.
243 rm -f "$FSSTATE/mux/layout"
244 XDG_STATE_HOME="$FSSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.fscap" --err "$OUT.fscap.err" -- \ 232 XDG_STATE_HOME="$FSSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.fscap" --err "$OUT.fscap.err" -- \
245 "$MUX" --sock "$SOCK54" > "$OUT.fspc" 2>&1 <<'EOF' 233 "$MUX" --sock "$SOCK54" > "$OUT.fspc" 2>&1 <<'EOF'
246 expect fs-init-b 20000 234 expect fs-init-b 20000
@@ -328,11 +316,7 @@ set +e
328 # 80x24: aspect rule makes beside; two panes split 39/40 with the rail 316 # 80x24: aspect rule makes beside; two panes split 39/40 with the rail
329 # at column 40 (1-indexed). Three l presses grow the left pane by 3, 317 # at column 40 (1-indexed). Three l presses grow the left pane by 3,
330 # moving the rail to column 43. 318 # moving the rail to column 43.
331 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 319 no_saved_tree "$RSZSTATE"
332 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
333 # state home has already left one. The aspect rule applies only when
334 # nothing is saved.
335 rm -f "$RSZSTATE/mux/layout"
336 XDG_STATE_HOME="$RSZSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.rszcap" --err "$OUT.rszcap.err" -- \ 320 XDG_STATE_HOME="$RSZSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.rszcap" --err "$OUT.rszcap.err" -- \
337 "$MUX" --sock "$SOCK55" > "$OUT.rszpc" 2>&1 <<'EOF' 321 "$MUX" --sock "$SOCK55" > "$OUT.rszpc" 2>&1 <<'EOF'
338 expect rsz-init-b 20000 322 expect rsz-init-b 20000
@@ -361,12 +345,9 @@ set -e
361 # The rail paints as ESC[row;colH followed by ESC[7m (reverse video). 345 # The rail paints as ESC[row;colH followed by ESC[7m (reverse video).
362 # Extract the column from every CUP that precedes a reverse-video 346 # Extract the column from every CUP that precedes a reverse-video
363 # space — the rail's column — and verify it moved right by 3. 347 # space — the rail's column — and verify it moved right by 3.
364 _rail_re=$'\x1b\\[[0-9][0-9]*;[0-9][0-9]*H\x1b\\[7m'
365 # Before resize: rail at column 40 (1-indexed). After lll: column 43. 348 # Before resize: rail at column 40 (1-indexed). After lll: column 43.
366 # Grab all rail CUP columns; the last one is the post-resize position. 349 # All rail columns; the last one is the post-resize position.
367 _rail_cols=$(grep -ao "$_rail_re" "$OUT.rszcap" | \ 350 _last_rail=$(rail_cols "$OUT.rszcap" | tail -1)
368 sed 's/.*\x1b\[[0-9]*;\([0-9]*\)H\x1b\[7m/\1/' | sort -n)
369 _last_rail=$(echo "$_rail_cols" | tail -1)
370 [ -n "$_last_rail" ] || { 351 [ -n "$_last_rail" ] || {
371 echo "e2e FAIL: resize: no rail glyph found in the capture:" 352 echo "e2e FAIL: resize: no rail glyph found in the capture:"
372 cat "$OUT.rszcap"; exit 1; } 353 cat "$OUT.rszcap"; exit 1; }
@@ -411,11 +392,7 @@ wait_grid "$SOCK56" "spc-right-survivor" "span-clear: right session's marker" b
411 set +e 392 set +e
412 # 80x24: aspect rule → beside. The wall client is a tty session: its 393 # 80x24: aspect rule → beside. The wall client is a tty session: its
413 # stdout is the terminal's full byte stream, captured by ptyclient. 394 # stdout is the terminal's full byte stream, captured by ptyclient.
414 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 395 no_saved_tree "$SPCSTATE"
415 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
416 # state home has already left one. The aspect rule applies only when
417 # nothing is saved.
418 rm -f "$SPCSTATE/mux/layout"
419 XDG_STATE_HOME="$SPCSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.spccap" --err "$OUT.spccap.err" -- \ 396 XDG_STATE_HOME="$SPCSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.spccap" --err "$OUT.spccap.err" -- \
420 "$MUX" --sock "$SOCK56" > "$OUT.spcpc" 2>&1 <<'EOF' 397 "$MUX" --sock "$SOCK56" > "$OUT.spcpc" 2>&1 <<'EOF'
421 expect spc-right-survivor 20000 398 expect spc-right-survivor 20000
@@ -468,11 +445,7 @@ wait_grid "$SOCK57" "hjk-origin" "hjkl: origin marker"
468 set +e 445 set +e
469 # 80x24: aspect rule → beside for the first split; the second split goes 446 # 80x24: aspect rule → beside for the first split; the second split goes
470 # below, producing a 1 | (2 over 3) tree. 447 # below, producing a 1 | (2 over 3) tree.
471 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 448 no_saved_tree "$HJKSTATE"
472 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
473 # state home has already left one. The aspect rule applies only when
474 # nothing is saved.
475 rm -f "$HJKSTATE/mux/layout"
476 XDG_STATE_HOME="$HJKSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.hjkcap" --err "$OUT.hjkcap.err" -- \ 449 XDG_STATE_HOME="$HJKSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.hjkcap" --err "$OUT.hjkcap.err" -- \
477 "$MUX" --sock "$SOCK57" > "$OUT.hjkpc" 2>&1 <<'EOF' 450 "$MUX" --sock "$SOCK57" > "$OUT.hjkpc" 2>&1 <<'EOF'
478 expect hjk-origin 20000 451 expect hjk-origin 20000
@@ -543,11 +516,7 @@ wait_grid "$SOCK58" "spl-origin" "split-birth: origin marker"
543 set +e 516 set +e
544 # 80x24: aspect rule → beside. One tile starts, then Ctrl-\ | births a 517 # 80x24: aspect rule → beside. One tile starts, then Ctrl-\ | births a
545 # second session to the right. 518 # second session to the right.
546 # No saved tree: this leg asserts the DEFAULT cut, and a wall ON A 519 no_saved_tree "$SPLSTATE"
547 # TERMINAL saves its tree on the way out — so a ptyclient leg sharing this
548 # state home has already left one. The aspect rule applies only when
549 # nothing is saved.
550 rm -f "$SPLSTATE/mux/layout"
551 XDG_STATE_HOME="$SPLSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.splcap" --err "$OUT.splcap.err" -- \ 520 XDG_STATE_HOME="$SPLSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.splcap" --err "$OUT.splcap.err" -- \
552 "$MUX" --sock "$SOCK58" > "$OUT.splpc" 2>&1 <<'EOF' 521 "$MUX" --sock "$SOCK58" > "$OUT.splpc" 2>&1 <<'EOF'
553 expect spl-origin 20000 522 expect spl-origin 20000
@@ -568,9 +537,7 @@ wait_sessions "$SOCK58" 2 "split-birth: split did not birth a new session"
568 # The rail paints as ESC[row;colH ESC[7m (reverse video). The new pane's 537 # The rail paints as ESC[row;colH ESC[7m (reverse video). The new pane's
569 # label bar is at a column greater than the rail's column — it sits to 538 # label bar is at a column greater than the rail's column — it sits to
570 # the right of the separator, which is the whole point of beside. 539 # the right of the separator, which is the whole point of beside.
571 _rail_re=$'\x1b\\[[0-9][0-9]*;[0-9][0-9]*H\x1b\\[7m' 540 _rail_col=$(rail_cols "$OUT.splcap" | head -1)
572 _rail_col=$(grep -ao "$_rail_re" "$OUT.splcap" | \
573 sed 's/.*\x1b\[[0-9]*;\([0-9]*\)H\x1b\[7m/\1/' | sort -n | head -1)
574 [ -n "$_rail_col" ] || { 541 [ -n "$_rail_col" ] || {
575 echo "e2e FAIL: split-birth: no rail glyph found in the capture:" 542 echo "e2e FAIL: split-birth: no rail glyph found in the capture:"
576 cat "$OUT.splcap"; exit 1; } 543 cat "$OUT.splcap"; exit 1; }
@@ -619,7 +586,7 @@ mkdir -p "$LPSTATE/mux"
619 printf -- '--sock %s\n' "$SOCK59" > "$LPHOSTS" 586 printf -- '--sock %s\n' "$SOCK59" > "$LPHOSTS"
620 # ...and no saved tree yet: what this leg saves and restores has to be the 587 # ...and no saved tree yet: what this leg saves and restores has to be the
621 # tree the FIRST ptyclient builds, not one an earlier terminal left here. 588 # tree the FIRST ptyclient builds, not one an earlier terminal left here.
622 rm -f "$LPLAYOUT" 589 no_saved_tree "$LPSTATE"
623 590
624 set +e 591 set +e
625 # First ptyclient: hydrate, resize three right, detach. The detach saves 592 # First ptyclient: hydrate, resize three right, detach. The detach saves
@@ -690,11 +657,8 @@ set -e
690 echo "e2e FAIL: layout-restore: second ptyclient exited $RC:" 657 echo "e2e FAIL: layout-restore: second ptyclient exited $RC:"
691 cat "$OUT.lprpc2" "$OUT.lprcap2.err"; exit 1; } 658 cat "$OUT.lprpc2" "$OUT.lprcap2.err"; exit 1; }
692 # The rail's CUP column in the second capture must be >= 43 — three 659 # The rail's CUP column in the second capture must be >= 43 — three
693 # right-resizes moved the boundary from 41 to 44. The _rail_re idiom 660 # right-resizes moved the boundary from 41 to 44.
694 # (from the split-birth leg) matches ESC[row;colH ESC[7m. 661 _max_rail=$(rail_cols "$OUT.lprcap2" | tail -1)
695 _rail_re=$'\x1b\\[[0-9][0-9]*;[0-9][0-9]*H\x1b\\[7m'
696 _max_rail=$(grep -ao "$_rail_re" "$OUT.lprcap2" | \
697 sed 's/.*\x1b\[[0-9]*;\([0-9]*\)H\x1b\[7m/\1/' | sort -n | tail -1)
698 [ -n "$_max_rail" ] || { 662 [ -n "$_max_rail" ] || {
699 echo "e2e FAIL: layout-restore: no rail glyph in the second capture:" 663 echo "e2e FAIL: layout-restore: no rail glyph in the second capture:"
700 cat "$OUT.lprcap2"; exit 1; } 664 cat "$OUT.lprcap2"; exit 1; }
@@ -747,7 +711,7 @@ wait_grid "$SOCK60" "lph-doomed-b" "layout-heal: session b marker" b
747 mkdir -p "$LPHSTATE/mux" 711 mkdir -p "$LPHSTATE/mux"
748 printf -- '--sock %s\n' "$SOCK60" > "$LPHHOSTS" 712 printf -- '--sock %s\n' "$SOCK60" > "$LPHHOSTS"
749 # No saved tree yet, for the restore leg's reason. 713 # No saved tree yet, for the restore leg's reason.
750 rm -f "$LPHLAYOUT" 714 no_saved_tree "$LPHSTATE"
751 715
752 set +e 716 set +e
753 XDG_STATE_HOME="$LPHSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 \ 717 XDG_STATE_HOME="$LPHSTATE" timeout 90 "$PTYCLIENT" --cols 80 --rows 24 \
@@ -845,18 +809,12 @@ grep -qi "layout" "$OUT.lphcap2.err" && {
845 # Two tiles: the survivor and the newcomer. The daemon has 0 and c, and 809 # Two tiles: the survivor and the newcomer. The daemon has 0 and c, and
846 # the tile the sidecar's surviving leaf carries is the one the marker 810 # the tile the sidecar's surviving leaf carries is the one the marker
847 # landed in. 811 # landed in.
848 # A rail is a CUP followed by reverse video; a BESIDE cut puts one in a 812 # A BESIDE cut puts a rail in a column of its own; a stacked cut has one
849 # column of its own, a stacked cut only ever at column 1 (the label bars). 813 # only at column 1, which is a label bar and what `rail_cols`' callers
850 # Spelled here rather than leaning on the earlier legs' copy: a variable 814 # filter out.
851 # an unrelated block happens to have left set is not an input.
852 _lph_re=$'\x1b\\[[0-9][0-9]*;[0-9][0-9]*H\x1b\\[7m'
853 _lph_cols() {
854 grep -ao "$_lph_re" "$1" | \
855 sed 's/.*\x1b\[[0-9]*;\([0-9]*\)H\x1b\[7m/\1/' | sort -n | uniq
856 }
857 # Run 1 is the anchor: it really was cut beside and `lll` really moved the 815 # Run 1 is the anchor: it really was cut beside and `lll` really moved the
858 # rail, so run 2's silence below is a difference and not an empty capture. 816 # rail, so run 2's silence below is a difference and not an empty capture.
859 _lph_r1=$(_lph_cols "$OUT.lphcap1" | awk '$1 > 1' | tail -1) 817 _lph_r1=$(rail_cols "$OUT.lphcap1" | awk '$1 > 1' | tail -1)
860 [ -n "$_lph_r1" ] && [ "$_lph_r1" -ge 43 ] || { 818 [ -n "$_lph_r1" ] && [ "$_lph_r1" -ge 43 ] || {
861 echo "e2e FAIL: layout-heal: run 1's rail ended at column ${_lph_r1:-none}, want >= 43" 819 echo "e2e FAIL: layout-heal: run 1's rail ended at column ${_lph_r1:-none}, want >= 43"
862 echo " — the resize this leg saves a tree for did not happen" 820 echo " — the resize this leg saves a tree for did not happen"
@@ -874,7 +832,7 @@ _lph_r1=$(_lph_cols "$OUT.lphcap1" | awk '$1 > 1' | tail -1)
874 # and that is the one answer neither of those can produce. Asserting "no 832 # and that is the one answer neither of those can produce. Asserting "no
875 # rail at all" instead would fail the improvement and blame the restore for 833 # rail at all" instead would fail the improvement and blame the restore for
876 # not having run, which is the opposite of what would have happened. 834 # not having run, which is the opposite of what would have happened.
877 _lph_r2=$(_lph_cols "$OUT.lphcap2" | awk '$1 > 1' | tail -1) 835 _lph_r2=$(rail_cols "$OUT.lphcap2" | awk '$1 > 1' | tail -1)
878 [ -z "$_lph_r2" ] || [ "$_lph_r2" -ge 43 ] || { 836 [ -z "$_lph_r2" ] || [ "$_lph_r2" -ge 43 ] || {
879 echo "e2e FAIL: layout-heal: run 2's vertical rail is at column $_lph_r2 — neither" 837 echo "e2e FAIL: layout-heal: run 2's vertical rail is at column $_lph_r2 — neither"
880 echo " the sidecar's own cut (>= 43, where run 1 left it) nor the bare" 838 echo " the sidecar's own cut (>= 43, where run 1 left it) nor the bare"
test/e2e_13_birth.sh
Old New
@@ -95,9 +95,7 @@ wait_grid "$SOCK63" "pr-bmark" "prompt: daemon B's marker"
95 95
96 mkdir -p "$PRSTATE/mux" 96 mkdir -p "$PRSTATE/mux"
97 printf -- '--sock %s\n' "$SOCK62" > "$PRHOSTS" 97 printf -- '--sock %s\n' "$SOCK62" > "$PRHOSTS"
98 # No saved tree: a wall on a terminal saves its tree on the way out, and 98 no_saved_tree "$PRSTATE"
99 # this leg asserts the default cut.
100 rm -f "$PRSTATE/mux/layout"
101 99
102 # The spelling goes in TWO sends with a settle between: the prompt paints 100 # The spelling goes in TWO sends with a settle between: the prompt paints
103 # its echo when a read ENDS with the prompt still open, so a spelling that 101 # its echo when a read ENDS with the prompt still open, so a spelling that
test/e2e_lib.sh
Old New
@@ -464,6 +464,32 @@ repaints() {
464 grep -a -F -o "$_clr" "$1" 2>/dev/null | wc -l 464 grep -a -F -o "$_clr" "$1" 2>/dev/null | wc -l
465 } 465 }
466 466
467 # rail_cols FILE — the column of every vertical rail in a capture,
468 # ascending and deduplicated. A rail paints as a CUP followed by reverse
469 # video, which is how a label bar starts too, so column 1 is a bar and
470 # never a rail; a caller that cares filters it (`awk '$1 > 1'`).
471 #
472 # Here rather than in the four legs that had spelled it out: an escape
473 # sequence copied per leg is four places a terminal change has to be found,
474 # and a function is hermetic in the way the `_rail_re` variable those
475 # copies shared a name for was not.
476 rail_cols() {
477 grep -ao $'\x1b\\[[0-9][0-9]*;[0-9][0-9]*H\x1b\\[7m' "$1" |
478 sed 's/.*\x1b\[[0-9]*;\([0-9]*\)H\x1b\[7m/\1/' | sort -n | uniq
479 }
480
481 # no_saved_tree STATE — forget the layout sidecar under STATE.
482 #
483 # A wall on a TERMINAL saves its pane tree on the way out and restore is
484 # VERBATIM, so a leg that asserts the default cut must not inherit the tree
485 # an earlier ptyclient run left behind. Whether any run has actually shared
486 # this home is not the caller's to know: legs move, homes get reused, and
487 # the failure — a wall cut by somebody else's resize — reads as this leg's
488 # geometry assertion being wrong.
489 no_saved_tree() {
490 rm -f "$1/mux/layout"
491 }
492
467 # await_repaint FILE BASELINE LABEL — wait until repaints FILE exceeds 493 # await_repaint FILE BASELINE LABEL — wait until repaints FILE exceeds
468 # BASELINE (5s, scaled), FAIL with the capture otherwise. 494 # BASELINE (5s, scaled), FAIL with the capture otherwise.
469 await_repaint() { 495 await_repaint() {