-
Notifications
You must be signed in to change notification settings - Fork 0
Development and Testing
Ordinary development and CI never write to the real /sys. Everything
runs against fixture trees via --sysfs-root plus a scriptable MockSmc;
real hardware is a final, explicit, supervised gate. Cargo.toml deps are
exactly the allowlist (serde, toml, serde_json, thiserror, tracing,
tracing-subscriber, libc); unsafe lives only in safety.rs (grep-gated);
unwrap/expect/panic are clippy-denied outside tests, main.rs wiring,
and safety.rs's sanctioned arm_test_panic.
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
cargo test --features hw # must SKIP cleanly (no applesmc here) — proves the guard worksPlus an expanded gate 2b denying clippy::unwrap_used / expect_used /
panic explicitly (the §8 lints sit at warn in Cargo.toml [lints.clippy]).
| Suite | Tests | What each proves |
|---|---|---|
tests/policy_traces.rs (7) |
plateau 80 °C × 50 → f(80); hot-core {92,60,88} acts on 92; descending approach, no ratchet; hysteresis no-flap; sensor-loss streak → ReturnToAuto; overshoot guard; hold-with-hot-core escalates |
The debate's traces: H1/H2 dead, guards live |
tests/integration.rs (13) |
once decision + AUTO restore (incl. from pre-existing Manual); doctor honors --sysfs-root/--config; hold→cmd→daemon applies within one poll; selftest-panic → fixture fan1_manual == 0; L1 re-assert on induced drift; hw guard skips; F14 reconcile (observe + curve); F18 monitor_only in JSON + human; F24 mode-change journal |
End-to-end binary behavior on fixtures |
tests/schema.rs (4) |
status --json vs afanctl.status.v1; hold/observe/curve cmd files vs afanctl.cmd.v1; once state file vs afanctl.state.v1
|
Versioned schemas hold |
tests/pin_constants.rs (7) |
echo tolerance boundary (49 passes / 51 fails); stall fires at exactly STALL_POLLS; F19/F20/F21 constants pinned; interval_s 12 legal / 14 rejected; sub/super-epsilon jitter behavior |
Frozen constants cannot drift silently |
tests/settle_window.rs (2) |
300 ms echo latency accepted, curve converges failure-free; never-adopted echo → VerifyFailed → fallback restores AUTO |
Settle-window verify on both backends |
co-located #[cfg(test)] units |
per-module (config rejections with key+fix, smc round-trip/verify/drift/mode-flip/outliers, supervisor transitions, doctor checks, notify socket) | Every testable PRD claim has a test |
Integration tests spawn the real binary against a tempdir copy of
tests/fixtures/sysfs/ via --sysfs-root, with AFANCTL_RUNTIME_DIR
pointed at a tempdir; the repo fixture is never mutated.
Healthy baseline devices/ mirrors the live machine exactly: applesmc.768
(fan1_label Exhaust, fan1_min 1200, fan1_max 7200, fan1_manual 0,
fan1_input/fan1_output 1200, empty fan1_safe, attribute-less husk
hwmon/hwmon3) + coretemp.0/hwmon/hwmon4 (Package id 0 45 °C, Core 0
44 °C, Core 1 43 °C, all crit 100 °C; milli-°C on disk). Fault variants
(each a full independent tree): outlier_hi (> 120 °C), outlier_neg
(< 0 °C), empty_temp, garbage_temp, garbage_fan, missing_fan,
no_coretemp, layout_changed (fan files moved into hwmon3, fan1_input
3400 — exercises the layout hook).
The full fault-injection surface the defect map demands: drift,
write-not-taking (set_write_stuck), sensor outliers, mode flips, tach lag
(set_tach_lag), tach frozen (set_tach_frozen), echo latency
(set_echo_latency). The hardware gate's three fixture-uncatchable defects
(no reconcile; tach-vs-echo confusion; ~1 s SMC tick) are now modeled here.
The only path that may touch real /sys, and only with all three:
--features hw and AFANCTL_HWTEST=1 and real applesmc present —
otherwise skipped. Never in CI. The supervised hardware gate (§9.3) is the
only real-sysfs session; the orchestrator never ran it.
R11: poll loop < 0.1 % CPU at 1 Hz (sleep with timer slack, no busy waits),
RSS < 5 MB, binary < 2 MB release (strip, lto). Measured: 0.05 % CPU /
2.4 MB peak over a 1 h 10 min observe soak. Shipped product is ~4.2k non-test
LOC against the early ~1.4k sketch — the delta is mandated surface (fault
face, doctor checks + --compare, key+reason+fix errors), ledgered per file
in QUESTIONS.md/DEVIATIONS.md; the "LOC within ±20 %" criterion is
therefore not met as written — re-baseline the sketch, don't carve up
gate-tested code.
- Home
- Installation
- CLI Reference
- Configuration
- Control Policy
- Supervisor and Run Modes
- Safety Model
- Hardware Interface
- Diagnostics (doctor)
- Plugin Surface (omafan)
- JSON Schemas
- systemd and Packaging
- Development and Testing
- Architecture and Internals
- Troubleshooting and FAQ
- Background and Verification
- afanctl-vs-mbpfan