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