91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
220 lines
7.4 KiB
Bash
Executable File
220 lines
7.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Start one native, headless Sway session and run the complete Rust E2E matrix.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
|
RUNTIME_DIR="$(mktemp -d)"
|
|
SWAY_CONFIG="$(mktemp)"
|
|
SESSION_KIND="${CUA_E2E_WAYLAND_SESSION:-sway}"
|
|
COMPOSITOR_LOG="${REPO_ROOT}/artifacts/cua-driver/linux/${SESSION_KIND}.log"
|
|
ATSPI_LOG="${REPO_ROOT}/artifacts/cua-driver/linux/at-spi-bus.log"
|
|
COMPOSITOR_PID=""
|
|
DBUS_PID=""
|
|
ATSPI_PID=""
|
|
|
|
cleanup() {
|
|
if [[ -n "${COMPOSITOR_PID}" ]]; then
|
|
kill "${COMPOSITOR_PID}" 2>/dev/null || true
|
|
wait "${COMPOSITOR_PID}" 2>/dev/null || true
|
|
fi
|
|
if [[ -n "${DBUS_PID}" ]]; then
|
|
kill "${DBUS_PID}" 2>/dev/null || true
|
|
fi
|
|
if [[ -n "${ATSPI_PID}" ]]; then
|
|
kill "${ATSPI_PID}" 2>/dev/null || true
|
|
wait "${ATSPI_PID}" 2>/dev/null || true
|
|
fi
|
|
rm -f "${SWAY_CONFIG}"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
mkdir -p "$(dirname "${COMPOSITOR_LOG}")"
|
|
chmod 700 "${RUNTIME_DIR}"
|
|
cat > "${SWAY_CONFIG}" <<'EOF'
|
|
xwayland disable
|
|
output HEADLESS-1 mode 1920x1080
|
|
seat seat0 fallback true
|
|
focus_follows_mouse no
|
|
default_border none
|
|
default_floating_border none
|
|
for_window [title="^CuaTestHarness"] floating enable, resize set 940 780, move position 0 0
|
|
for_window [title="CuaTestHarness Sentinel"] fullscreen enable
|
|
EOF
|
|
|
|
unset DISPLAY
|
|
unset WAYLAND_DISPLAY
|
|
export XDG_RUNTIME_DIR="${RUNTIME_DIR}"
|
|
export XDG_SESSION_TYPE=wayland
|
|
export XDG_CURRENT_DESKTOP=sway
|
|
export XDG_SESSION_DESKTOP=sway
|
|
export WLR_BACKENDS=headless
|
|
export WLR_RENDERER=pixman
|
|
export WLR_RENDERER_ALLOW_SOFTWARE=1
|
|
export WLR_LIBINPUT_NO_DEVICES=1
|
|
export WLR_HEADLESS_OUTPUTS=1
|
|
export CUA_DRIVER_RS_ENABLE_WAYLAND=1
|
|
if [[ "${SESSION_KIND}" == cua-compositor ]]; then
|
|
export CUA_E2E_COMPOSITOR=cua-compositor-nested
|
|
export CUA_E2E_INPUT_BACKENDS=atspi,cua-compositor-inject
|
|
export CUA_E2E_HARNESS_FILTER=electron
|
|
export CUA_INJECT_SOCKET="${XDG_RUNTIME_DIR}/cua-inject.sock"
|
|
else
|
|
export CUA_E2E_COMPOSITOR=sway
|
|
export CUA_E2E_INPUT_BACKENDS=atspi,wlr-virtual-pointer
|
|
fi
|
|
export CUA_WAYLAND_RECORDING_OUTPUT=HEADLESS-1
|
|
export ELECTRON_OZONE_PLATFORM_HINT=wayland
|
|
export GDK_BACKEND=wayland
|
|
export QT_QPA_PLATFORM=wayland
|
|
# WebKitGTK's accelerated compositor requires a DRM render node. The canonical
|
|
# hosted lane has none, so keep its best-effort software settings explicit;
|
|
# native-Wayland WebKit coverage runs on the representative GNOME/KDE VMs.
|
|
export WEBKIT_DISABLE_COMPOSITING_MODE=1
|
|
export WEBKIT_DISABLE_DMABUF_RENDERER=1
|
|
# This isolated CI session uses a private runtime directory and no user home
|
|
# namespaces. Modern WebKitGTK ignores WEBKIT_FORCE_SANDBOX; use its explicit
|
|
# test-only escape hatch so the WebProcess can publish its AT-SPI subtree.
|
|
export WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1
|
|
export NO_AT_BRIDGE=0
|
|
export ACCESSIBILITY_ENABLED=1
|
|
|
|
if [[ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]]; then
|
|
dbus_daemon="$(command -v dbus-daemon)"
|
|
dbus_prefix="$(dirname "$(dirname "$(readlink -f "${dbus_daemon}")")")"
|
|
dbus_config="${dbus_prefix}/share/dbus-1/session.conf"
|
|
if [[ ! -f "${dbus_config}" ]]; then
|
|
echo "DBus session config is missing: ${dbus_config}" >&2
|
|
exit 1
|
|
fi
|
|
dbus_info="$(dbus-daemon --config-file="${dbus_config}" --fork --print-address=1 --print-pid=1)"
|
|
export DBUS_SESSION_BUS_ADDRESS="$(sed -n '1p' <<< "${dbus_info}")"
|
|
DBUS_PID="$(sed -n '2p' <<< "${dbus_info}")"
|
|
fi
|
|
|
|
# A private session bus does not activate the desktop accessibility stack by
|
|
# itself. Start the repo-pinned AT-SPI launcher, then require org.a11y.Bus to
|
|
# answer before any fixture or driver process inherits this session.
|
|
ATSPI_LAUNCHER="${CUA_AT_SPI_BUS_LAUNCHER:-$(command -v at-spi-bus-launcher || true)}"
|
|
if [[ ! -x "${ATSPI_LAUNCHER}" ]]; then
|
|
echo "AT-SPI bus launcher is unavailable: ${ATSPI_LAUNCHER:-<not found>}" >&2
|
|
exit 1
|
|
fi
|
|
"${ATSPI_LAUNCHER}" --launch-immediately > "${ATSPI_LOG}" 2>&1 &
|
|
ATSPI_PID=$!
|
|
deadline=$((SECONDS + 15))
|
|
while ((SECONDS < deadline)); do
|
|
if ! kill -0 "${ATSPI_PID}" 2>/dev/null; then
|
|
echo "AT-SPI bus launcher exited before org.a11y.Bus became ready" >&2
|
|
cat "${ATSPI_LOG}" >&2
|
|
exit 1
|
|
fi
|
|
if gdbus call --session \
|
|
--dest org.a11y.Bus \
|
|
--object-path /org/a11y/bus \
|
|
--method org.a11y.Bus.GetAddress >/dev/null 2>&1; then
|
|
break
|
|
fi
|
|
sleep 0.2
|
|
done
|
|
if ! gdbus call --session \
|
|
--dest org.a11y.Bus \
|
|
--object-path /org/a11y/bus \
|
|
--method org.a11y.Bus.GetAddress >/dev/null 2>&1; then
|
|
echo "org.a11y.Bus did not become ready within 15 seconds" >&2
|
|
cat "${ATSPI_LOG}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# The bus launcher and the registry daemon are separate services. Resolve the
|
|
# private accessibility bus and require the registry to activate on it before
|
|
# any toolkit inherits this session.
|
|
a11y_address="$(
|
|
gdbus call --session \
|
|
--dest org.a11y.Bus \
|
|
--object-path /org/a11y/bus \
|
|
--method org.a11y.Bus.GetAddress \
|
|
| sed -e "s/^('//" -e "s/',)$//"
|
|
)"
|
|
export AT_SPI_BUS_ADDRESS="${a11y_address}"
|
|
if [[ -z "${a11y_address}" ]] || ! gdbus call \
|
|
--address "${a11y_address}" \
|
|
--dest org.a11y.atspi.Registry \
|
|
--object-path /org/a11y/atspi/accessible/root \
|
|
--method org.freedesktop.DBus.Properties.Get \
|
|
org.a11y.atspi.Accessible ChildCount >/dev/null 2>&1; then
|
|
echo "AT-SPI registry did not activate on the accessibility bus" >&2
|
|
cat "${ATSPI_LOG}" >&2
|
|
exit 1
|
|
fi
|
|
if ! gdbus call --session \
|
|
--dest org.a11y.Bus \
|
|
--object-path /org/a11y/bus \
|
|
--method org.freedesktop.DBus.Properties.Set \
|
|
org.a11y.Status IsEnabled '<true>' >/dev/null 2>&1; then
|
|
echo "Could not enable accessibility on org.a11y.Bus" >&2
|
|
cat "${ATSPI_LOG}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${SESSION_KIND}" == cua-compositor ]]; then
|
|
command -v cua-compositor >/dev/null || {
|
|
echo "cua-compositor is required for the nested injection lane" >&2
|
|
exit 1
|
|
}
|
|
cua-compositor > "${COMPOSITOR_LOG}" 2>&1 &
|
|
else
|
|
sway --unsupported-gpu --config "${SWAY_CONFIG}" > "${COMPOSITOR_LOG}" 2>&1 &
|
|
fi
|
|
COMPOSITOR_PID=$!
|
|
|
|
deadline=$((SECONDS + 20))
|
|
while ((SECONDS < deadline)); do
|
|
if ! kill -0 "${COMPOSITOR_PID}" 2>/dev/null; then
|
|
echo "${SESSION_KIND} exited before its Wayland socket became ready" >&2
|
|
cat "${COMPOSITOR_LOG}" >&2
|
|
exit 1
|
|
fi
|
|
socket="$(find "${XDG_RUNTIME_DIR}" -maxdepth 1 -type s -name 'wayland-*' -print -quit)"
|
|
if [[ -n "${socket}" ]]; then
|
|
export WAYLAND_DISPLAY="$(basename "${socket}")"
|
|
break
|
|
fi
|
|
sleep 0.2
|
|
done
|
|
|
|
if [[ -z "${WAYLAND_DISPLAY:-}" ]]; then
|
|
echo "${SESSION_KIND} did not create a Wayland socket within 20 seconds" >&2
|
|
cat "${COMPOSITOR_LOG}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${SESSION_KIND}" == cua-compositor ]]; then
|
|
deadline=$((SECONDS + 10))
|
|
while [[ ! -S "${CUA_INJECT_SOCKET}" ]] && ((SECONDS < deadline)); do
|
|
sleep 0.2
|
|
done
|
|
if [[ ! -S "${CUA_INJECT_SOCKET}" ]]; then
|
|
echo "cua-compositor did not expose its injection socket" >&2
|
|
cat "${COMPOSITOR_LOG}" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
export SWAYSOCK="$(find "${XDG_RUNTIME_DIR}" -maxdepth 1 -type s -name 'sway-ipc.*.sock' -print -quit)"
|
|
if [[ -z "${SWAYSOCK}" ]]; then
|
|
echo "Sway did not expose its IPC socket" >&2
|
|
cat "${COMPOSITOR_LOG}" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "Native Wayland E2E session: ${SESSION_KIND} on ${WAYLAND_DISPLAY}"
|
|
set +e
|
|
"${SCRIPT_DIR}/run-rust-e2e.sh" "$@"
|
|
status=$?
|
|
set -e
|
|
if [[ "${status}" != 0 && "${SESSION_KIND}" == sway ]]; then
|
|
swaymsg -t get_tree > "${REPO_ROOT}/artifacts/cua-driver/linux/sway-tree.json" 2>/dev/null || true
|
|
fi
|
|
exit "${status}"
|