crates/nornir-build-thing/tests/kernel_probe_live.rs
//! **HEAVY, LIVE probe boot — the built kernel actually runs, `#[ignore]`d.**
//!
//! Boots a `bzImage` that `kernel_build_live` (or the forge) already produced,
//! in QEMU **inside the toolchain container**, and reads the serial console.
//!
//! This is the step the canary cannot do. The canary checks that every option
//! the FRAGMENT NAMES survived `olddefconfig`; it can say nothing about an
//! option nobody wrote down — and `CONFIG_BINFMT_ELF` is exactly that option: a
//! `tinyconfig` build without it is canary-clean and cannot execute PID 1.
//!
//! ```bash
//! export KERNEL_PROBE_ROOT=/path/holding/.kernel-out # the repo_root used to build
//! export KERNEL_PROBE_NAME=e2e-slim
//! export KERNEL_PROBE_TOOLCHAIN=localhost/nordisk-kernel-toolchain:latest
//! cargo test -p nornir-build-thing --features kernel-build \
//! --test kernel_probe_live -- --ignored --nocapture
//! ```
#![cfg(feature = "kernel-build")]
use nornir_build_thing::kernel::{probe_kernel_with, DraupnirKernelRunner, KernelBuild};
#[test]
#[ignore = "HEAVY: boots a real kernel under QEMU (TCG) inside a container. Needs \
KERNEL_PROBE_ROOT + KERNEL_PROBE_NAME and a podman/Docker socket."]
fn a_built_kernel_boots_and_executes_pid1() {
let (Ok(root), Ok(name)) = (
std::env::var("KERNEL_PROBE_ROOT"),
std::env::var("KERNEL_PROBE_NAME"),
) else {
eprintln!(
"SKIP (not a pass): set KERNEL_PROBE_ROOT to the repo_root a kernel was built \
under (it holds `.kernel-out/`) and KERNEL_PROBE_NAME to the variant name."
);
return;
};
let mut k = KernelBuild {
name,
version: "0.0.0".into(),
// The probe never fetches — it boots what is on disk — but the
// declaration is validated all the same, and an unpinned one is refused.
tarball_sha256: "0".repeat(64),
..KernelBuild::default()
};
if let Ok(img) = std::env::var("KERNEL_PROBE_TOOLCHAIN") {
k.toolchain_image = img;
k.toolchain_packages = Vec::new();
}
if let Ok(d) = std::env::var("KERNEL_PROBE_TOOLCHAIN_SHA256") {
k.toolchain_image_sha256 = d;
}
k.validate().expect("the probe declaration");
let probe = probe_kernel_with(&DraupnirKernelRunner::new(), &k, std::path::Path::new(&root))
.expect("the probe boot");
eprintln!("kernel_probe_live: {} → {:?}", k.name, probe);
assert!(probe.booted, "PID 1 never printed its marker");
assert!(probe.reported_devices, "PID 1 died between booting and reporting");
// The console is the one device EVERY preset must have: without it the
// machine cannot tell anyone anything, and the boot contract names it.
assert!(probe.has("console"), "no /dev/console: {:?}", probe.devices);
}