#!/usr/bin/env bash # Запускает Lark DE на виртуальном X-сервере и проверяет, что клиентское # окно появилось: поднимает Xvfb, стартует `lark`, запускает клиента и # делает снимок экрана. # # Переменные окружения: # LARK_TEST_DISPLAY дисплей Xvfb (по умолчанию :78) # LARK_TEST_RUNTIME каталог для сокета (по умолчанию /tmp/lark-test-run) # LARK_TEST_SHOT путь к снимку (по умолчанию /tmp/lark-shot.png) # LARK_TEST_CLIENT клиент (по умолчанию eglgears_wayland) # LARK_TEST_WAIT секунд до снимка (по умолчанию 6) # RUST_LOG уровень журналирования set -uo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DISPLAY_NUM="${LARK_TEST_DISPLAY:-:78}" RUNTIME_DIR="${LARK_TEST_RUNTIME:-/tmp/lark-test-run}" SCREENSHOT="${LARK_TEST_SHOT:-/tmp/lark-shot.png}" CLIENT="${LARK_TEST_CLIENT:-eglgears_wayland}" WAIT_SECONDS="${LARK_TEST_WAIT:-6}" LOG="${LARK_TEST_LOG:-/tmp/lark-dev-run.log}" BIN="$ROOT/target/debug/lark" if [[ ! -x "$BIN" ]]; then echo "Сборка не найдена, выполните: cargo build" >&2 exit 1 fi cleanup() { [[ -n "${CLIENT_PID:-}" ]] && kill "$CLIENT_PID" 2>/dev/null [[ -n "${LARK_PID:-}" ]] && kill "$LARK_PID" 2>/dev/null wait 2>/dev/null return 0 } trap cleanup EXIT # --- Виртуальный дисплей ----------------------------------------------------- if [[ ! -S "/tmp/.X11-unix/X${DISPLAY_NUM#:}" ]]; then if ! command -v Xvfb >/dev/null 2>&1; then echo "Xvfb не установлен: apt install xvfb" >&2 exit 1 fi rm -f "/tmp/.X${DISPLAY_NUM#:}-lock" Xvfb "$DISPLAY_NUM" -screen 0 1280x800x24 -nolisten tcp >/tmp/lark-xvfb.log 2>&1 & for _ in $(seq 1 40); do [[ -S "/tmp/.X11-unix/X${DISPLAY_NUM#:}" ]] && break sleep 0.25 done fi # --- Каталог для сокета ------------------------------------------------------ mkdir -p "$RUNTIME_DIR" chmod 700 "$RUNTIME_DIR" rm -f "$RUNTIME_DIR"/wayland-* # --- Композитор -------------------------------------------------------------- : >"$LOG" DISPLAY="$DISPLAY_NUM" \ WAYLAND_DISPLAY= \ XDG_RUNTIME_DIR="$RUNTIME_DIR" \ RUST_LOG="${RUST_LOG:-lark=info}" \ "$BIN" >"$LOG" 2>&1 & LARK_PID=$! SOCKET="" for _ in $(seq 1 60); do SOCKET=$(ls "$RUNTIME_DIR" 2>/dev/null | grep -E '^wayland-[0-9]+$' | head -1) [[ -n "$SOCKET" ]] && break sleep 0.25 done if [[ -z "$SOCKET" ]]; then echo "Lark DE не создал сокет. Журнал:" >&2 cat "$LOG" >&2 exit 1 fi echo "Lark DE слушает: $RUNTIME_DIR/$SOCKET" # --- Клиент ------------------------------------------------------------------ CLIENT_LOG=/tmp/lark-client.log : >"$CLIENT_LOG" if ! command -v "$CLIENT" >/dev/null 2>&1; then echo "Клиент $CLIENT не найден, снимок будет без окна" >&2 else XDG_RUNTIME_DIR="$RUNTIME_DIR" WAYLAND_DISPLAY="$SOCKET" \ "$CLIENT" >"$CLIENT_LOG" 2>&1 & CLIENT_PID=$! # Клиент может завершиться сразу, если не смог инициализировать # графику. Это стоит сообщить явно, иначе пустой снимок выглядит как # ошибка композитора. sleep "$WAIT_SECONDS" if kill -0 "$CLIENT_PID" 2>/dev/null; then echo "Клиент $CLIENT работает" else echo "ВНИМАНИЕ: клиент $CLIENT завершился, окно на снимке может отсутствовать" >&2 fi fi # --- Снимок ------------------------------------------------------------------ if command -v import >/dev/null 2>&1; then if DISPLAY="$DISPLAY_NUM" import -window root "png:$SCREENSHOT" 2>/dev/null; then echo "Снимок: $SCREENSHOT" else echo "Не удалось сделать снимок экрана" >&2 fi fi echo "Журнал Lark: $LOG" if grep -qE '^Error' "$LOG"; then echo "--- Журнал Lark ---" >&2 tail -20 "$LOG" >&2 fi if [[ -s "$CLIENT_LOG" ]]; then echo "--- Журнал клиента ---" >&2 tail -10 "$CLIENT_LOG" >&2 fi