diff --git a/lima/shturman.yaml b/lima/shturman.yaml index ea2ee37..e196329 100644 --- a/lima/shturman.yaml +++ b/lima/shturman.yaml @@ -63,6 +63,10 @@ provision: install -d /etc/tmpfiles.d install -m644 /shturman/systemd/tmpfiles-shturman.conf /etc/tmpfiles.d/shturman.conf systemd-tmpfiles --create /etc/tmpfiles.d/shturman.conf || true + # watchdog (B05/A14, system.conf.d) + save-time .timer (B07; .service ловит *.service glob выше) + install -d /etc/systemd/system.conf.d + install -m644 /shturman/systemd/watchdog-shturman.conf /etc/systemd/system.conf.d/shturman-watchdog.conf + install -m644 /shturman/systemd/shturman-savetime.timer /etc/systemd/system/ # fake-hwclock → /data (не на rootfs; A07/A11). Сервис в Lima masked (Lima сам синхронит время) — # на HW он размаскирован и читает FILE из /etc/default/fake-hwclock через EnvironmentFile. diff --git a/tests/e2e/run.sh b/tests/e2e/run.sh index eda06ad..48d6301 100644 --- a/tests/e2e/run.sh +++ b/tests/e2e/run.sh @@ -81,7 +81,8 @@ sudo install -m644 systemd/shturman.target systemd/data.mount \ sudo install -m644 systemd/shturman-firstboot.service systemd/shturman-machineid.service \ systemd/shturman-power.service systemd/shturman-settings.service \ systemd/shturman-shell.service systemd/shturman-splash.service \ - systemd/shturman-stage2-warmup.service /etc/systemd/system/ + systemd/shturman-stage2-warmup.service systemd/shturman-savetime.service \ + /etc/systemd/system/ sudo install -d /etc/dbus-1/system.d sudo install -m644 systemd/dbus/ru.shturman.conf /etc/dbus-1/system.d/ sudo install -d /etc/systemd/journald.conf.d /etc/systemd/oomd.conf.d @@ -91,6 +92,10 @@ sudo install -m644 systemd/zram-generator.conf /etc/systemd/zram-generator.conf sudo install -d /etc/tmpfiles.d sudo install -m644 systemd/tmpfiles-shturman.conf /etc/tmpfiles.d/shturman.conf sudo systemd-tmpfiles --create /etc/tmpfiles.d/shturman.conf || true +# watchdog (B05/A14) + save-time .timer (B07) +sudo install -d /etc/systemd/system.conf.d +sudo install -m644 systemd/watchdog-shturman.conf /etc/systemd/system.conf.d/shturman-watchdog.conf +sudo install -m644 systemd/shturman-savetime.timer /etc/systemd/system/ sudo systemctl daemon-reload # применить конфиги детерминированно (на свежем boot drop-in’ы появились после старта демонов) sudo systemctl reload dbus 2>/dev/null || true @@ -185,6 +190,67 @@ pass "порядок фаз: splash($sp) ≤ frame($fr) ≤ stage2($w2)" # boot-тайминг (функц., НЕ гейт; вердикт — RK3588, performance §2) echo " $(systemd-analyze time 2>/dev/null | head -1 || echo 'systemd-analyze н/д')" +# ---- power-safe (v0.3): FSM ShutdownImminent + N циклов зажигания + abort + power-cut ---- +info "power-safe: ShutdownImminent + N=3 цикла зажигания + abort + power-cut" +P_CALL() { busctl --system call "$P_NAME" "$P_PATH" "$P_MOCK" "$@"; } +busctl --system call "$S_NAME" "$S_PATH" "$S_IFACE" Set sv ui.theme s night >/dev/null +echo 0 | sudo tee /data/state/power-cycles >/dev/null + +observe_imminent() { # SetAcc(false) → ждём ShutdownImminent на шине + local mon; mon=$(mktemp) + # shellcheck disable=SC2024 + sudo busctl --system monitor "$P_NAME" >"$mon" 2>&1 & local M=$! + sleep 0.7; P_CALL SetAcc b false >/dev/null; sleep 0.7 + sudo kill "$M" 2>/dev/null; wait "$M" 2>/dev/null + grep -q ShutdownImminent "$mon" || { echo "--- mon ---"; cat "$mon"; rm -f "$mon"; return 1; } + rm -f "$mon" +} + +for i in 1 2 3; do + observe_imminent || fail "цикл $i: ShutdownImminent не наблюдаем" + n=$(($(sudo cat /data/state/power-cycles) + 1)) + sudo systemctl stop shturman-stage1.target # освобождает /data + sync; sudo umount /data || fail "цикл $i: umount /data" + sudo mount /data || fail "цикл $i: mount /data" + echo "$n" | sudo tee /data/state/power-cycles >/dev/null + sudo systemctl start shturman.target + for _ in $(seq 1 15); do systemctl is-active --quiet shturman-settings && break; sleep 1; done + pass "цикл зажигания $i: stop→umount→remount→restart" +done +got=$(busctl --system call "$S_NAME" "$S_PATH" "$S_IFACE" Get s ui.theme 2>/dev/null) +echo "$got" | grep -q '"night"' || fail "ui.theme потерян после циклов" +[ "$(sudo cat /data/state/power-cycles)" = 3 ] || fail "счётчик циклов != 3" +pass "N=3 цикла: /data + счётчик целы (нет потери)" + +# abort до PONR +mon=$(mktemp) +# shellcheck disable=SC2024 +sudo busctl --system monitor "$P_NAME" >"$mon" 2>&1 & M=$! +sleep 0.7; P_CALL SetAcc b false >/dev/null; sleep 0.3; P_CALL SetAcc b true >/dev/null; sleep 0.7 +sudo kill "$M" 2>/dev/null; wait "$M" 2>/dev/null +grep -q ShutdownAborted "$mon" || { cat "$mon"; rm -f "$mon"; fail "ShutdownAborted не наблюдаем"; } +rm -f "$mon" +findmnt /data >/dev/null || fail "/data не смонтирован после abort" +busctl --system call "$P_NAME" "$P_PATH" "$P_IFACE" GetPowerState | grep -q running || fail "не running после abort" +pass "abort до PONR: ShutdownAborted + /data RW + running" + +# power-cut-сим: SIGKILL во время shutdown → /data консистентен +P_CALL SetAcc b false >/dev/null; sleep 0.3 +sudo systemctl kill -s KILL shturman-power.service shturman-settings.service 2>/dev/null || true +sudo systemctl stop shturman-stage1.target 2>/dev/null || true +sudo umount /data 2>/dev/null || true +sudo fsck.ext4 -n /var/lib/shturman/data.img >/dev/null 2>&1 || fail "fsck /data не clean после power-cut" +sudo mount /data +sudo grep -q night /data/settings/settings.json || fail "last durable value потерян после power-cut" +pass "power-cut-сим: /data консистентен (fsck clean, night present)" +sudo systemctl start shturman.target +for _ in $(seq 1 15); do systemctl is-active --quiet shturman-settings && break; sleep 1; done + +# watchdog/save-time конфиг +test -f /etc/systemd/system.conf.d/shturman-watchdog.conf || fail "нет watchdog-конфига" +systemctl is-active --quiet shturman-savetime.timer && pass "savetime.timer активен" || echo " WARN: savetime.timer не активен" +pass "watchdog-конфиг на месте" + # ---- 8. base-бюджеты: journald / zram / fake-hwclock / eMMC-прокси (§9.3.7) ---- info "8. base-бюджеты (функц.)" # journald volatile: активный журнал в /run/log/journal, persistent /var/log/journal отсутствует (A10)