Writing Tests
Tests are Rust functions annotated with #[ktstr_test]. Each test
boots a KVM VM, runs the scenario inside it, and evaluates results
on the host.
use ktstr::prelude::*;
#[ktstr_test(llcs = 1, cores = 2, threads = 1)]
fn my_test(ctx: &Ctx) -> Result<AssertResult> {
execute_defs(ctx, vec![
ctx.cgroup_def("cg_0"),
ctx.cgroup_def("cg_1"),
])
}
ctx.cgroup_def("name") is shorthand for
CgroupDef::named("name").workers(ctx.workers_per_cgroup) — the
common case. Use CgroupDef::named(...).workers(N).work_type(...)
directly when the test needs to customize worker count or work type.
Run with cargo ktstr test --kernel 7.0 (see
Getting Started for setup). A passing run is
one nextest line per test; the VM boot, scenario, and teardown all
happen inside the reported duration:
cargo ktstr: resolved kernel "7.0"
...
Nextest run ID 24c18577-... with nextest profile: default
Starting 1 test across 121 binaries (12531 tests skipped)
PASS [ 34.451s] (1/1) ktstr::failure_dump_e2e ktstr/failure_dump_renders_bss_fields
...
Summary [ 34.490s] 1 test run: 1 passed, 12531 skipped
Every test gets the same machinery for free: a fresh VM per test (no state shared between tests), a failure dump with BTF-rendered scheduler BPF state if the scheduler crashes (see Reading Failure Output), and an automatic second-VM reproduction run with probes attached (Auto-Repro). Each test also expands into gauntlet variants across topology presets — see Gauntlet.
Warning
No worker checks run by default. The example above passes as long as nothing crashes — it does not assert fairness, starvation, or gaps. Opt in with
not_starved = trueand the threshold attributes; see Checking for the model.
Where to go next
- The #[ktstr_test] Attribute — the full attribute reference: topology, timing, checking thresholds, execution knobs.
- Scheduler Definitions —
declare_scheduler!: how the scheduler under test is named, found, configured, and launched. - Payloads and Included Files — run
benchmark binaries (
schbench,fio, …) alongside workers and extract their metrics. - Custom Scenarios — scenario logic the ops system cannot express, written directly in the test body.
- Snapshots — capture scheduler BPF state on demand mid-scenario and assert on it.
- Watch Snapshots — capture at the exact instant the kernel writes a chosen symbol.
- Periodic Capture — cadenced BPF-state sampling across the workload window, no scenario code required.
- Temporal Assertions — assert on trajectories: counters that only advance, metrics that hold steady, systems that converge.