439d9e14
test: e2e through the real client/daemon loop
a73x 2026-08-08 14:08
Commit message
src/client.zig
| Old | New | ||
|---|---|---|---|
| @@ -111,6 +111,9 @@ fn ttySize(fd: std.posix.fd_t) ?proto.Size { | |||
| 111 | if (!std.posix.isatty(fd)) return null; | 111 | if (!std.posix.isatty(fd)) return null; |
| 112 | var ws: std.posix.winsize = undefined; | 112 | var ws: std.posix.winsize = undefined; |
| 113 | if (std.os.linux.ioctl(fd, std.os.linux.T.IOCGWINSZ, @intFromPtr(&ws)) != 0) return null; | 113 | if (std.os.linux.ioctl(fd, std.os.linux.T.IOCGWINSZ, @intFromPtr(&ws)) != 0) return null; |
| 114 | // A pty can report 0x0 (e.g. `script` with piped stdin); a zero-sized | ||
| 115 | // grid is invalid for the engine. Treat it as "unknown". | ||
| 116 | if (ws.col < 2 or ws.row < 2) return null; | ||
| 114 | return .{ .cols = ws.col, .rows = ws.row }; | 117 | return .{ .cols = ws.col, .rows = ws.row }; |
| 115 | } | 118 | } |
| 116 | 119 | ||
src/server.zig
| Old | New | ||
|---|---|---|---|
| @@ -225,6 +225,9 @@ pub const Server = struct { | |||
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | fn applySize(self: *Server, cols: u16, rows: u16) void { | 227 | fn applySize(self: *Server, cols: u16, rows: u16) void { |
| 228 | // A degenerate size (0x0 pty, buggy client) would trip engine | ||
| 229 | // asserts; keep the current grid instead. | ||
| 230 | if (cols < 2 or rows < 2) return; | ||
| 228 | self.eng.resize(cols, rows) catch return; | 231 | self.eng.resize(cols, rows) catch return; |
| 229 | self.pty.resize(cols, rows) catch {}; | 232 | self.pty.resize(cols, rows) catch {}; |
| 230 | } | 233 | } |
test/e2e.sh
| Old | New | ||
|---|---|---|---|
| @@ -1,25 +1,37 @@ | |||
| 1 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | # End-to-end: run muxd headless with piped stdin, dump the grid from a | 2 | # End-to-end: muxd daemon + mux client. Input flows client -> daemon -> pty; |
| 3 | # second process, verify shell output landed in the ghostty-vt grid. | 3 | # output flows pty -> engine -> snapshot -> client replica -> client stdout. |
| 4 | set -eu | 4 | set -eu |
| 5 | MUXD="$1" | 5 | MUXD="$1" |
| 6 | MUX="$2" | ||
| 6 | SOCK="${TMPDIR:-/tmp}/muxd-e2e-$$.sock" | 7 | SOCK="${TMPDIR:-/tmp}/muxd-e2e-$$.sock" |
| 8 | OUT="${TMPDIR:-/tmp}/mux-e2e-out-$$" | ||
| 7 | 9 | ||
| 8 | cleanup() { kill "$DPID" 2>/dev/null || true; rm -f "$SOCK"; } | 10 | cleanup() { kill "$DPID" 2>/dev/null || true; rm -f "$SOCK" "$OUT"; } |
| 9 | trap cleanup EXIT INT TERM | 11 | trap cleanup EXIT INT TERM |
| 10 | 12 | ||
| 11 | { printf 'printf "e2e-%%s\\n" works\n'; sleep 3; } | \ | 13 | "$MUXD" run --sock "$SOCK" --shell /bin/sh & |
| 12 | "$MUXD" run --sock "$SOCK" --shell /bin/sh & | ||
| 13 | DPID=$! | 14 | DPID=$! |
| 14 | 15 | ||
| 15 | # Wait for the socket, then give the shell a moment to run the command. | ||
| 16 | i=0 | 16 | i=0 |
| 17 | while [ ! -S "$SOCK" ] && [ "$i" -lt 50 ]; do sleep 0.1; i=$((i+1)); done | 17 | while [ ! -S "$SOCK" ] && [ "$i" -lt 50 ]; do sleep 0.1; i=$((i+1)); done |
| 18 | [ -S "$SOCK" ] || { echo "e2e FAIL: socket never appeared"; exit 1; } | 18 | [ -S "$SOCK" ] || { echo "e2e FAIL: socket never appeared"; exit 1; } |
| 19 | sleep 1 | ||
| 20 | 19 | ||
| 21 | OUT="$("$MUXD" dump --sock "$SOCK")" | 20 | # Client with piped stdio: types a command, waits, detaches with Ctrl-\ (034). |
| 22 | case "$OUT" in | 21 | { printf 'printf "e2e-%%s\\n" works\n'; sleep 2; printf '\034'; } | \ |
| 23 | *e2e-works*) echo "e2e OK" ;; | 22 | "$MUX" --sock "$SOCK" > "$OUT" |
| 24 | *) echo "e2e FAIL: grid was:"; echo "$OUT"; exit 1 ;; | 23 | |
| 25 | esac | 24 | # 1. The client's rendered output must contain the command's result. |
| 25 | grep -q "e2e-works" "$OUT" || { | ||
| 26 | echo "e2e FAIL: client render missing output; got:"; cat "$OUT"; exit 1; | ||
| 27 | } | ||
| 28 | |||
| 29 | # 2. The daemon kept the session; its grid must match. | ||
| 30 | "$MUXD" dump --sock "$SOCK" | grep -q "e2e-works" || { | ||
| 31 | echo "e2e FAIL: daemon grid missing output"; exit 1; | ||
| 32 | } | ||
| 33 | |||
| 34 | # 3. Detach left the daemon running. | ||
| 35 | kill -0 "$DPID" || { echo "e2e FAIL: daemon died on detach"; exit 1; } | ||
| 36 | |||
| 37 | echo "e2e OK" | ||