kick/test-headless.sh
Andrew Hamilton 7db91f9d60 make test scripts build first; keep build.sh incremental
Running pytest against a stale build/ binary silently proved nothing:
test.sh and test-headless.sh now run build.sh first, and build.sh
skips meson setup/compile when both binaries are newer than their
sources (tracked per program: kick.c feeds kick, tests/wltest.c feeds
wltest, meson.build and subprojects feed both).
2026-08-19 16:02:20 +10:00

106 lines
No EOL
3.3 KiB
Bash
Executable file

#!/bin/sh
# Run the pytest suite with no window appearing on the desktop.
#
# The nested tests open the compositor's single host window on the ambient
# Wayland session. This wrapper re-hosts that window inside an invisible
# headless compositor: a second, standalone instance of the same binary
# (KICK_MODE=standalone WLR_BACKENDS=headless) whose output is shown
# nowhere. WAYLAND_DISPLAY is pointed at that headless host for the pytest
# run, so every nested session maps its window inside the headless scene
# instead of flashing on the real desktop.
#
# The headless host exposes wlr-data-control and wl_data_device, so the
# clipboard tests exercise the (preferred) data-control bridge rather than
# the focus-based one; the focus bridge is keyed to your real compositor
# granting the window focus, which no headless host does.
set -e
cd "$(dirname "$0")"
./build.sh
BIN=build/kick
WL=build/wltest
HOST_LOG=/tmp/kick-headless-host.log
for p in "$BIN" "$WL"; do
if [ ! -x "$p" ]; then
echo "test-headless.sh: build first: $p" >&2
exit 1
fi
done
rm -f "$HOST_LOG"
# One invisible tab so the host never exits on its own; the quotes make it a
# single CLI tab ("wltest '#112233'"), not a bare command plus a stray arg.
host_tab="$WL '#112233'"
# A real font, mirroring _pick_font() in tests/test_smoke.py.
font="${KICK_FONT:-}"
if [ -z "$font" ]; then
for f in \
/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf \
/usr/share/fonts/dejavu/DejaVuSans.ttf \
/usr/share/fonts/TTF/DejaVuSans.ttf \
/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf \
/usr/share/fonts/liberation/LiberationSans-Regular.ttf \
/usr/share/fonts/noto/NotoSans-Regular.ttf; do
if [ -f "$f" ]; then
font="$f"
break
fi
done
fi
# env -i so the host never sees the desktop WAYLAND_DISPLAY: inheriting it
# would make the "standalone" host go nested instead and open its own visible
# window. This mirrors the standalone_session fixture's environment. The
# subshell keeps "$@" (the pytest args) untouched.
(
export PATH="$PATH" \
HOME="${HOME:-/}" \
XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/tmp}" \
XDG_DATA_HOME="${XDG_DATA_HOME:-}" \
XDG_DATA_DIRS="${XDG_DATA_DIRS:-}" \
KICK_LOG=2 \
KICK_MODE=standalone \
WLR_BACKENDS=headless \
KICK_FONT="$font" \
XCURSOR_THEME=Adwaita
unset WAYLAND_DISPLAY
exec stdbuf -oL "$BIN" "$host_tab"
) >"$HOST_LOG" 2>&1 &
host_pid=$!
cleanup() {
kill -TERM "$host_pid" 2>/dev/null || true
wait "$host_pid" 2>/dev/null || true
}
trap cleanup EXIT INT TERM
socket=
deadline=$(( $(date +%s) + 60 ))
while [ -z "$socket" ]; do
if ! kill -0 "$host_pid" 2>/dev/null; then
echo "test-headless.sh: headless host died:" >&2
cat "$HOST_LOG" >&2
exit 1
fi
socket=$(sed -n 's/.*Wayland socket: \(kick-[0-9][0-9]*\).*/\1/p' \
"$HOST_LOG" | tail -n 1)
if [ -z "$socket" ] && [ "$(date +%s)" -ge "$deadline" ]; then
echo "test-headless.sh: timed out waiting for the headless host socket:" >&2
cat "$HOST_LOG" >&2
exit 1
fi
[ -z "$socket" ] && sleep 0.2
done
export WAYLAND_DISPLAY="$socket"
pytest -v "$@"
status=$?
exit $status