612b2f27111c | atagen | 2026-10-17 05:03 UTC | 1 | # Runs monolith nested on the host session with real clients and checks what |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 2 | # they see. Run from the repo root inside `nix develop`, after |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 3 | # `cargo build -p monolith && cargo build -p monolith-protocols --example workspaces`. |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 4 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 5 | const TOOLS = [foot xterm xwayland lswt grim swaybg swaylock wlrctl] |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 6 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 7 | def main [--log: path = /tmp/monolith-smoke.log] { |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 8 | let tools = $TOOLS | each {|t| $"nixpkgs#($t)" } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 9 | let results = mktemp -t monolith-smoke.XXXXXX |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 10 | let script = $env.CURRENT_FILE |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 11 | let inner = $"nu -n ($script) inner ($results) ($log)" |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 12 | # Some parent shells hand down SIGTERM blocked, so only SIGKILL reliably ends a hung run. |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 13 | do -i { ^nix shell ...$tools -c sh -c $"unset VK_DRIVER_FILES; RUST_LOG=monolith=debug timeout -s KILL 60 target/debug/monolith run --backend nested ($inner) > ($log) 2>&1" } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 14 | let rows = open --raw $results | lines | where $it != "" | each {|l| $l | from json } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 15 | rm $results |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 16 | if ($rows | is-empty) { |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 17 | print $"no results, see ($log)" |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 18 | exit 1 |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 19 | } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 20 | print ($rows | table) |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 21 | if ($rows | any {|r| not $r.ok }) { exit 1 } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 22 | } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 23 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 24 | def "main inner" [results: path, log: path] { |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 25 | try { scenarios $results $log } catch {|e| {name: "harness", ok: false, detail: $e.msg} | to json -r | $"($in)\n" | save -a $results } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 26 | target/debug/monolith msg quit |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 27 | } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 28 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 29 | def scenarios [results: path, log: path] { |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 30 | let check = {|name: string, ok: bool, detail: any| |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 31 | {name: $name, ok: $ok, detail: ($detail | to text | str trim)} | to json -r | $"($in)\n" | save -a $results |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 32 | } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 33 | let windows = {|| target/debug/monolith get state | from json | get windows | length } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 34 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 35 | job spawn { foot } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 36 | job spawn { foot } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 37 | job spawn { xterm -e sleep 60 } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 38 | let n = wait-until 10sec {|| (do $windows) == 3 } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 39 | do $check "three windows over ipc" ($n) (do $windows) |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 40 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 41 | let listed = lswt | lines | skip 1 | length |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 42 | do $check "toplevel list shows them" ($listed == 3) $listed |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 43 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 44 | let ws = do { timeout 1 target/debug/examples/workspaces } | complete | get stdout |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 45 | do $check "ext-workspace sends a snapshot" ($ws | str contains "workspace") ($ws | lines | length) |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 46 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 47 | let shot = mktemp -t smoke-XXXXXX.png |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 48 | let full = grim $shot | complete |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 49 | do $check "output capture" ($full.exit_code == 0 and (ls $shot | get 0.size) > 0b) $full.stderr |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 50 | let id = lswt -j | from json | get toplevels.0.identifier |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 51 | let one = grim -T $id $shot | complete |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 52 | do $check "toplevel capture" ($one.exit_code == 0) $one.stderr |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 53 | rm $shot |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 54 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 55 | wlrctl toplevel close app_id:XTerm |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 56 | let closed = wait-until 5sec {|| (do $windows) == 2 } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 57 | do $check "wlr-foreign-toplevel close" $closed (do $windows) |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 58 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 59 | job spawn { swaybg -c "#336699" } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 60 | let layer = wait-until 5sec {|| open --raw $log | str contains 'namespace="wallpaper"' } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 61 | do $check "layer surface mapped" $layer "" |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 62 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 63 | job spawn { swaylock -c 000000 } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 64 | let locked = wait-until 5sec {|| open --raw $log | str contains "session locked" } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 65 | do $check "session lock" $locked "" |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 66 | } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 67 | |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 68 | def wait-until [limit: duration, cond: closure] { |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 69 | let until = (date now) + $limit |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 70 | loop { |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 71 | if (do $cond) { return true } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 72 | if (date now) > $until { return false } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 73 | sleep 100ms |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 74 | } |
612b2f27111c | atagen | 2026-10-17 05:03 UTC | 75 | } |