153 lines
7.1 KiB
Bash
Executable File
153 lines
7.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Linux canvas smoke under Xvfb — run on a machine with NO WebKitGTK dev
|
|
# package, which makes the build itself the native-only link test.
|
|
#
|
|
# Exercises the Linux gpu_surface software path without a display server:
|
|
# builds examples/ui-inbox (a native-only app, so its GTK host compiles
|
|
# with the WebKitGTK stub seam and never links webkitgtk-6.0) with
|
|
# -Dplatform=linux -Dweb-engine=system -Dautomation=true, runs it under
|
|
# Xvfb, and asserts against the automation snapshot:
|
|
#
|
|
# 1. the built ELF carries no WebKitGTK reference (no libwebkitgtk
|
|
# DT_NEEDED entry, no webkit_/jsc_ dynamic symbol), audited on the
|
|
# real binary by tools/audit_web_layer.zig
|
|
# 2. snapshot ready=true (app booted, automation server live)
|
|
# 3. gpu_backend=software (the software present path is active)
|
|
# 4. gpu_nonblank=true (real pixels were presented)
|
|
# 5. widget-click "Add task" -> '4 open' (automation input mutates state)
|
|
# 6. automate screenshot renders a non-empty PNG
|
|
# 7. ZERO WebKit helper processes for the whole run (a native-only app
|
|
# has no web layer to boot WebKit with)
|
|
#
|
|
# Deliberately NOT `set -e` (same as windows-canvas-smoke.sh): grep exits 1
|
|
# on zero matches, and under `set -e` an assignment like `x=$(grep ...)` or
|
|
# a swallowed `$(cli 2>&1)` capture dies with NO output — this job failed
|
|
# three times with nothing in the log but the exit code. Every assertion
|
|
# goes through fail(), which dumps the snapshot and the app log.
|
|
set -u
|
|
|
|
# No WebKit sandbox workaround: a native-only app's host is compiled
|
|
# without the web layer entirely (and even in web builds the main
|
|
# WebView is lazy), so no WebKit helper processes start and the runner's
|
|
# user-namespace restrictions never come into play. The zero-WebKit
|
|
# assertion below keeps it that way.
|
|
|
|
# GTK_A11Y=none: under Xvfb there is no session bus providing org.a11y.Bus,
|
|
# and GTK4's a11y init blocks ~25 s on the GDBus name lookup before warning
|
|
# and continuing — the app's first runtime event landed after the readiness
|
|
# window had already expired (reproduced in a local container: without this
|
|
# the wait times out at startup; with it the full smoke passes).
|
|
# Accessibility is not what this smoke tests.
|
|
export GTK_A11Y="${GTK_A11Y:-none}"
|
|
|
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
app_dir="$repo_root/examples/ui-inbox"
|
|
snap="$app_dir/.zig-cache/native-sdk-automation/snapshot.txt"
|
|
cli="$repo_root/zig-out/bin/native"
|
|
app_log="${TMPDIR:-/tmp}/linux-canvas-smoke-app.log"
|
|
|
|
# Readiness budget. Even with GTK_A11Y=none, shared ubuntu-24.04 runners
|
|
# show a consistent ~27 s stall between EGL init and the app's first
|
|
# runtime event (measured in runs 28690855597 pass / 28691951139 fail —
|
|
# the SAME stall in both; the old hard 30 s `automate wait` window flipped
|
|
# green/red on one or two seconds of runner noise). Local containers show
|
|
# no stall at all. Widen the budget here instead of weakening the CLI
|
|
# default; every correctness assertion stays strict.
|
|
ready_timeout_ms=90000
|
|
|
|
app_pid=""
|
|
cleanup() {
|
|
[ -n "$app_pid" ] && kill "$app_pid" >/dev/null 2>&1
|
|
# xvfb-run does not forward signals to an already-detached app; reap the
|
|
# app and its Xvfb directly so local runs exit clean (CI would otherwise
|
|
# rely on the runner's orphan sweep).
|
|
pkill -f "$app_dir/zig-out/bin/ui-inbox" >/dev/null 2>&1
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
diagnostics() {
|
|
echo "---- diagnostics ----"
|
|
echo "-- snapshot ($snap):"
|
|
if [ -f "$snap" ]; then tr '|' '\n' < "$snap" | sed 's/^/ /'; else echo " (missing)"; fi
|
|
echo "-- app log head ($app_log):"
|
|
head -20 "$app_log" 2>/dev/null | sed 's/^/ /'
|
|
echo "-- app log tail ($app_log):"
|
|
tail -40 "$app_log" 2>/dev/null | sed 's/^/ /'
|
|
echo "---------------------"
|
|
}
|
|
|
|
fail() {
|
|
echo "FAIL: $1"
|
|
diagnostics
|
|
exit 1
|
|
}
|
|
|
|
# Canvas apps must never spawn WebKit: the window's main WebView is
|
|
# created lazily and nothing in this app materializes it, so any
|
|
# WebKitWebProcess/WebKitNetworkProcess during the run means an eager
|
|
# creation regressed (and with it launch latency, resident helper
|
|
# processes, and the sandbox trouble this smoke used to work around).
|
|
assert_no_webkit() {
|
|
local helpers
|
|
helpers=$(pgrep -af 'WebKit(Web|Network)Process' 2>/dev/null)
|
|
if [ -n "$helpers" ]; then
|
|
echo "-- WebKit helper processes found ($1):"
|
|
echo "$helpers" | sed 's/^/ /'
|
|
fail "canvas app spawned WebKit processes ($1)"
|
|
fi
|
|
}
|
|
|
|
# ---- build ----------------------------------------------------------------
|
|
(cd "$repo_root" && zig build) || fail "root zig build (CLI) failed"
|
|
(cd "$app_dir" && zig build -Dplatform=linux -Dweb-engine=system -Dautomation=true) \
|
|
|| fail "ui-inbox Linux build failed (a native-only app must build without the WebKitGTK dev package)"
|
|
|
|
# ---- 1: the native-only ELF carries no WebKitGTK reference -----------------
|
|
(cd "$repo_root" && zig run tools/audit_web_layer.zig -- "$app_dir/zig-out/bin/ui-inbox" absent) \
|
|
|| fail "native-only ELF audit failed (the binary references WebKitGTK)"
|
|
echo "== native-only ELF audit ok"
|
|
|
|
# ---- launch ---------------------------------------------------------------
|
|
cd "$app_dir" || fail "missing $app_dir"
|
|
rm -rf .zig-cache/native-sdk-automation
|
|
xvfb-run -a "$app_dir/zig-out/bin/ui-inbox" > "$app_log" 2>&1 &
|
|
app_pid=$!
|
|
|
|
# ---- 2: automation snapshot becomes ready ---------------------------------
|
|
# `automate assert` self-reports on timeout (missing patterns + snapshot
|
|
# tail) and prints the measured latency on success, so green logs carry
|
|
# the readiness margin.
|
|
"$cli" automate assert --timeout-ms "$ready_timeout_ms" 'ready=true' \
|
|
|| fail "snapshot never became ready"
|
|
|
|
# ---- 3 + 4: software backend presented non-blank pixels --------------------
|
|
"$cli" automate assert --timeout-ms 30000 'gpu_nonblank=true' \
|
|
|| fail "gpu_nonblank never became true"
|
|
grep -q 'gpu_backend=software' "$snap" || fail "gpu_backend is not software"
|
|
echo "== canvas: $(grep -o 'gpu_backend=[a-z]*' "$snap" | head -1)" \
|
|
"$(grep -o 'gpu_nonblank=[a-z]*' "$snap" | head -1)"
|
|
assert_no_webkit "after first presented frame"
|
|
echo "== zero WebKit processes after first presented frame"
|
|
|
|
# ---- 5: automation widget-click mutates the model --------------------------
|
|
echo "== open before click: $(grep -oE '[0-9]+ open' "$snap" | head -1)"
|
|
add_id=$(grep -o 'widget @w1/inbox-canvas#[0-9]* role=button name="Add task"' "$snap" \
|
|
| grep -o '#[0-9]*' | tr -d '#')
|
|
[ -n "$add_id" ] || fail "Add task button not found in snapshot"
|
|
"$cli" automate widget-click inbox-canvas "$add_id" || fail "CLI widget-click failed"
|
|
"$cli" automate assert --timeout-ms 30000 '4 open' \
|
|
|| fail "widget-click did not reach '4 open'"
|
|
echo "== open after click: $(grep -oE '[0-9]+ open' "$snap" | head -1)"
|
|
|
|
# ---- 6: screenshot renders a non-empty PNG ---------------------------------
|
|
"$cli" automate screenshot inbox-canvas || fail "CLI screenshot failed"
|
|
test -s .zig-cache/native-sdk-automation/screenshot-inbox-canvas.png \
|
|
|| fail "screenshot PNG missing or empty"
|
|
|
|
# ---- 7: still zero WebKit processes at the end of the run -------------------
|
|
assert_no_webkit "at end of run"
|
|
echo "== zero WebKit processes at end of run"
|
|
|
|
echo "PASS: linux canvas smoke"
|
|
exit 0
|