Testing holger — guide
Class:
guide· Function:testing(spans every function). How to run holger's test matrix, the mannequin test-dummy, and the functional-status emitters. The design-level conformance plan (real client ⇄ real holger in containers) isend-to-end-conformance-testing.md(reasoning); the shipped records aretest-matrix.md,testmatrix-functional-emitters.md,proto-codegen-xtask.md(history).
The test matrix (the green/red grid)
Driven by the published nornir-testmatrix engine — the same engine behind nornir test.
# light: workspace unit/integration grid + the real mannequin-GUI robot-UI cell
cargo test -p xtask --test holger_matrix
# + heavy: actually build + boot the mannequin daemon
cargo test -p xtask --test holger_matrix -- --ignored
Output is one row per component (workspace crate) × aspect, printed with nornir_testmatrix::render_matrix and persisted append-only to target/holger-testmatrix.jsonl. xtask hosts the harness because holger's root Cargo.toml is [workspace]-only and can't own a tests/ dir.
| file | role |
xtask/tests/holger_matrix.rs |
the harness — drives the engine, pivots rows into the component grid, adds mannequin cells |
mannequin/tests/gui_robot.rs |
the real headless robot-UI cell (facett harness render + state_json observe) |
mannequin/tests/smoke_serve.rs |
the heavy #[ignore]'d mannequin boot cell |
Cell colours follow nornir_testmatrix::model::status: pass green, fail/stalled red (a hung test is made visible, never silently eats the clock), ignored/skip amber.
mannequin — the test-dummy daemon
mannequin (binary holger-mannequin, in mannequin/) stands up the environment holger expects — a PKI (CA + server certs), an OIDC provider, and mock upstream registries — so you can develop holger without real infrastructure:
cd mannequin
cargo run --bin holger-mannequin -- serve --port 9999 # all services
cargo run --bin holger-mannequin -- serve --port 9999 --gui # + egui system map (facett)
# standalone PKI, no daemon:
holger-mannequin pki generate --output ./certs --cn localhost --sans a,b
No --config → it generates fresh certs on the fly (zero setup). The dev loop is: holger-mannequin serve → start holger pointed at it → run your UI/client. See mannequin-for-idiots for the click-by-click version.
Functional-status emitters (feed nornir test)
Every meaningful holger test emits one functional-status row per real check into the nornir-testmatrix engine (nornir_testmatrix::functional_status(component, check, ok, detail)), so a nornir test run sees the individual assertions and the value each measured — not just "the binary exited 0". ~97 functional rows across 25 components at full feature-on.
Compiled OUT for release — gated twice: nornir-testmatrix is an optional dep enabled only by each crate's testmatrix passthrough feature, and every call site is #[cfg(feature = "testmatrix")]. With the feature off (the default, every release build) the dep isn't compiled and the calls are stripped.
# release path — nothing compiled, nothing emitted:
cargo build --workspace && cargo test --workspace
# emit rows for the matrix (per crate that has the feature):
NORNIR_TESTMATRIX_OUT=target/holger-functional.json NORNIR_TESTMATRIX_REPO=holger \
cargo test -p repository-znippy-rust --features testmatrix --lib
To make the --features gui/testmatrix cells visible to nornir test run holger without forking the matrix, add one line under the repo entry in the nordisk release/nornir.toml:
[repo.holger]
test_features = "gui,testmatrix" # compile + run the gui robot-UI + testmatrix cells
Regenerating the proto (no protoc)
Only after editing proto/holger.proto:
cargo xtask gen-proto # rewrites server/lib/src/generated/holger.v1.rs, idempotent
A normal cargo build/cargo test --workspace needs no protoc and runs no subprocess — the generated Rust is committed and include!d. Guarded by server/lib/tests/unit_tests.rs::generated_proto_types_roundtrip.
The LAW
Every cell and every functional row injects real input and asserts real output — the ok is the same boolean the test's assert! checks; the detail is the measured count/hash/route, not a constant. No "didn't panic" rows.