9b87751ab8
План 5 ч.2: поднял Lima-VM и довёл сквозной E2E до зелёного из чистого yaml (just vm-reset && just e2e — exit 0). Приёмка §9.4 (v0.1 + v0.6 + шагающий скелет). Shell (lib+bin split): - режим --screenshot <path>: headless software-render первого кадра в PNG (Slint software-renderer, без дисплея/композитора, §6); TDD-тест «кадр не пустой + тема отражена», зелёный и на dev-Mac, и в VM (Linux). - shturman-shell.service → oneshot software-render → /run/shturman/frame.png (RemainAfterExit → is-active детерминированно, без хрупкого weston; живой weston-shell — v0.5). just shell-frame — инспекция кадра. E2E (tests/e2e/run.sh, двухфазно pre→reboot→post): - /data+power-safe опции, volatile-tmpfs, first-boot идемпотентность, per-unit active, имена на шине + GetPowerState, fake-ACC SetAcc→AccChanged, первый кадр PNG, base-бюджеты (journald volatile / zram / oomd / fake-hwclock→/data / eMMC-прокси), персист Settings + machine-id every-boot bind после reboot. Провижининг (lima/shturman.yaml) — правки по реальным ошибкам Lima: - build-deps Slint/winit на Linux (libfontconfig1-dev/libxkbcommon-dev/libwayland-dev); - linux-modules-extra (zram/vcan не в vz-ядре); systemd-oomd; rm стокового /etc/fake-hwclock.data (A11); VM-локальный CARGO_TARGET_DIR. Док-синхронизация (спека §13/§8.1/§7.5 + CLAUDE.md): швы реализации, eMMC-порог T=4096 сект, fake-hwclock masked-в-Lima, dev-mock policy не нужен. Перф-вердикт — на RK3588 (в VM — функционально, performance §2). just ci зелёный. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Alexander <akotenev2003@gmail.com>
72 lines
2.9 KiB
Rust
72 lines
2.9 KiB
Rust
//! Headless software-render первого кадра в PNG (спека §6 / §9.3 п.6 / §9.4 «шагающий скелет»).
|
||
//! Работает без дисплея (и на dev-Mac, и в Lima): Slint software-renderer → PNG.
|
||
//!
|
||
//! Один тест намеренно: Slint-платформа процесс-глобальна и ставится один раз, а `render_screenshot`
|
||
//! в проде зовётся ровно раз на процесс (oneshot-сервис / `just shell-frame`) — параллельный прогон
|
||
//! нескольких рендер-тестов в одном бинаре ушёл бы в дефолтный winit-бэкенд (на macOS — только main-thread).
|
||
|
||
use shturman_shell::{render_screenshot, Initial};
|
||
use std::path::Path;
|
||
|
||
/// Декодировать PNG → (ширина, высота, RGB-байты).
|
||
fn decode(path: &Path) -> (u32, u32, Vec<u8>) {
|
||
let dec = png::Decoder::new(std::fs::File::open(path).unwrap());
|
||
let mut reader = dec.read_info().unwrap();
|
||
let (w, h) = (reader.info().width, reader.info().height);
|
||
let mut buf = vec![0u8; reader.output_buffer_size()];
|
||
let info = reader.next_frame(&mut buf).unwrap();
|
||
buf.truncate(info.buffer_size());
|
||
(w, h, buf)
|
||
}
|
||
|
||
#[test]
|
||
fn renders_first_frame_reflecting_theme() {
|
||
let dir = tempfile::tempdir().unwrap();
|
||
|
||
// --- ночь: кадр не пустой, верный размер, тёмный фон ---
|
||
let night = dir.path().join("night.png");
|
||
render_screenshot(
|
||
&Initial {
|
||
theme: "night".into(),
|
||
ignition: "running".into(),
|
||
network: "unknown".into(),
|
||
},
|
||
12,
|
||
&night,
|
||
)
|
||
.expect("render ночь");
|
||
|
||
let (w, h, npx) = decode(&night);
|
||
assert_eq!((w, h), (1024, 600), "размер кадра");
|
||
// «не пустой» содержательно: кадр не одноцветный (нарисованы тайлы/текст, не только фон).
|
||
let first = npx[0];
|
||
assert!(
|
||
npx.iter().any(|&b| b != first),
|
||
"кадр одноцветный — рендер пустой"
|
||
);
|
||
// угол (0,0) = фон окна — ночью тёмный (#0e1014).
|
||
let (nr, ng, nb) = (npx[0], npx[1], npx[2]);
|
||
assert!(
|
||
nr < 64 && ng < 64 && nb < 64,
|
||
"ночной фон не тёмный: {nr},{ng},{nb}"
|
||
);
|
||
|
||
// --- день: тот же угол — светлый (#f4f5f7) — тема отражена ---
|
||
let day = dir.path().join("day.png");
|
||
render_screenshot(
|
||
&Initial {
|
||
theme: "day".into(),
|
||
..Default::default()
|
||
},
|
||
12,
|
||
&day,
|
||
)
|
||
.expect("render день");
|
||
let (_, _, dpx) = decode(&day);
|
||
let (dr, dg, db) = (dpx[0], dpx[1], dpx[2]);
|
||
assert!(
|
||
dr > 192 && dg > 192 && db > 192,
|
||
"дневной фон не светлый: {dr},{dg},{db}"
|
||
);
|
||
}
|