#!/usr/bin/env bash # Дымовая проверка установленного дерева (результат cmake --install) на Linux и macOS. # # tests/scripts/smoke_installed.sh # # Linux: /bin/BiLauncher (+ lib/BiLauncher/libz.so.1, плагины Qt рядом) # macOS: /BiLauncher.app # # Проверяет, что деплой Qt положил всё нужное: бинарник не ссылается на # библиотеки вне дерева (ldd/otool), запускается без окна и через 10 секунд # ещё жив, а в логе нет «module is not installed», «Cannot load library» и т. п. # Запуск идёт с подменённым HOME — настоящие данные лаунчера на машине не трогаются. set -euo pipefail PREFIX="$(cd "${1:?нужен путь к установленному дереву}" && pwd)" RUN_SECONDS="${RUN_SECONDS:-10}" fail() { echo "SMOKE FAIL: $*" >&2; exit 1; } case "$(uname -s)" in Darwin) APP="$PREFIX/BiLauncher.app" BIN="$APP/Contents/MacOS/BiLauncher" [ -x "$BIN" ] || fail "нет $BIN" [ -f "$APP/Contents/Resources/icon.icns" ] || fail "нет иконки в бандле" /usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$APP/Contents/Info.plist" >/dev/null \ || fail "в Info.plist нет версии" # Ссылки на Qt должны вести внутрь бандла, а не в папку Qt сборочной машины. if otool -L "$BIN" | tail -n +2 | grep -E '/Qt/|/Users/|/home/' ; then fail "бинарник ссылается на библиотеки вне бандла" fi [ -d "$APP/Contents/Frameworks/QtQuick.framework" ] || fail "нет QtQuick.framework в бандле" [ -d "$APP/Contents/PlugIns/platforms" ] || fail "нет плагинов платформ" # Деплой идёт с -hardened-runtime: без подписи dyld откажется грузить фреймворки # («different Team IDs»). Подписываем ad-hoc ровно как release.yml перед упаковкой. codesign --force --deep --sign - "$APP" >/dev/null 2>&1 || fail "ad-hoc подпись не удалась" codesign --verify --deep --strict "$APP" || fail "подпись бандла не проходит проверку" ;; Linux) BIN="$PREFIX/bin/BiLauncher" [ -x "$BIN" ] || fail "нет $BIN" [ -f "$PREFIX/lib/BiLauncher/libz.so.1" ] || fail "нет эталонного zlib (lib/BiLauncher/libz.so.1)" [ -f "$PREFIX/share/applications/bilauncher.desktop" ] || fail "нет .desktop-файла" [ -f "$PREFIX/share/icons/hicolor/256x256/apps/bilauncher.png" ] || fail "нет иконки hicolor" [ -f "$PREFIX/share/doc/BiLauncher/LICENSE" ] || fail "нет LICENSE в share/doc" # Все разделяемые библиотеки — бинарника, Qt и плагинов — должны находиться. missing=0 while IFS= read -r -d '' file; do if ldd "$file" 2>/dev/null | grep -q 'not found'; then echo "не хватает библиотек для $file:" >&2 ldd "$file" | grep 'not found' >&2 missing=1 fi done < <(find "$PREFIX" \( -name '*.so*' -o -path '*/bin/BiLauncher' \) -type f -print0) [ "$missing" = 0 ] || fail "ldd: есть ненайденные зависимости" ;; *) fail "неизвестная система $(uname -s)" ;; esac # Платформа Qt. Проверяем то, что реально задеплоено: macdeployqt кладёт только # cocoa — на macOS окно на 10 секунд действительно откроется (раннеру нужна # GUI-сессия). На Linux берём offscreen, если деплой его положил, иначе xcb # под xvfb-run (пакет xvfb, см. ci/setup-runner-linux.sh). LAUNCH=() PLATFORM="" if [ "$(uname -s)" = Linux ]; then if find "$PREFIX" -name 'libqoffscreen.so' | grep -q .; then PLATFORM=offscreen elif command -v xvfb-run >/dev/null; then LAUNCH=(xvfb-run -a) elif [ -z "${DISPLAY:-}" ]; then fail "нет ни плагина offscreen в деплое, ни xvfb-run, ни DISPLAY" fi fi SANDBOX="$(mktemp -d)" LOG="$SANDBOX/stderr.log" trap 'rm -rf "$SANDBOX"' EXIT env HOME="$SANDBOX" \ ${PLATFORM:+QT_QPA_PLATFORM=$PLATFORM} \ QT_FORCE_STDERR_LOGGING=1 \ QTWEBENGINE_DISABLE_SANDBOX=1 \ QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox --disable-gpu" \ ${LAUNCH[@]+"${LAUNCH[@]}"} "$BIN" >"$LOG" 2>&1 & PID=$! sleep "$RUN_SECONDS" if ! kill -0 "$PID" 2>/dev/null; then wait "$PID" || true echo "----- лог -----" >&2; cat "$LOG" >&2 fail "лаунчер завершился раньше чем через ${RUN_SECONDS} с" fi kill "$PID" 2>/dev/null || true wait "$PID" 2>/dev/null || true echo "----- лог запуска -----"; cat "$LOG" if grep -E 'is not installed|Cannot load library|could not find the Qt platform plugin|QQmlApplicationEngine failed|module ".*" plugin ".*" not found|Каталог переводов' "$LOG"; then fail "в логе ошибки загрузки модулей" fi # Лаунчер создал свою папку в подменённом HOME, а не где-то ещё. if [ "$(uname -s)" = Darwin ]; then ROOT="$SANDBOX/Library/Application Support/BiLauncher"; else ROOT="$SANDBOX/BiLauncher"; fi [ -f "$ROOT/settings.json" ] || fail "лаунчер не создал $ROOT/settings.json" echo "SMOKE OK: $BIN"