What it does
Most code is tested only on the happy path. Real systems fail through:
- Partial writes
- Disk full mid-flush
- Connection resets
- Corrupted reads
- Permission denied
- Process crashes
dev-chaos injects these failures on purpose so you can verify that
your recovery logic works.
Quick start
[]
= "0.9.2"
Opt-in features:
[]
= { = "0.9.2", = ["async-io"] }
use ;
// Fail on the 3rd, 7th, and 10th attempt of some operation.
let schedule = on_attempts;
let mut observed_failures = 0;
for attempt in 1..=12
let final_state_ok = true; // your invariant check
let _check = assert_recovered;
The returned CheckResult carries chaos + recovery tags and
numeric Evidence for expected_failures, actual_failures,
final_state_ok.
IO wrappers
Inject failures into a real Read/Write without touching the
system under test:
use ;
use Write;
let sink: = Vecnew;
let schedule = on_attempts;
let mut w = new;
w.write_all.unwrap; // attempt 1: ok
let _ = w.write; // attempt 2: 1 byte then PartialWrite
let inner = w.into_inner;
assert_eq!;
ChaosFile, ChaosReader, and ChaosWriter cover sync IO. With the
async-io feature, AsyncChaosReader and AsyncChaosWriter cover
tokio::io.
Crash-restart helpers
Model "process crashed mid-write" without crashing the process:
use CrashPoint;
use Write;
let sink: = Vecnew;
let mut w = after_byte.wrap;
let _ = w.write_all; // truncated at 3 bytes
let inner = w.into_inner;
assert_eq!;
Latency injection
Simulate slow but successful operations:
use ;
use Duration;
let inj = new;
for attempt in 1..=5
Seeded random schedules
When you need probabilistic exploration but reproducible results:
use ;
// Same seed produces the same sequence on every run, on every machine.
let schedule = seeded_random;
Producer trait
use ;
use Producer;
let producer = new;
let report = producer.produce;
Design choices
- Deterministic by default. Schedules are explicit. You know which attempt fails before the test runs.
- Random failures are opt-in and seeded.
seeded_randomis reproducible from the seed; no clock, no thread, no real RNG state. - Recovery is the verdict, not the failure. A test passes when the system recovers, not when the failure was injected.
Status
v0.9.x is the pre-1.0 stabilization line. APIs are expected to be
near-final; minor adjustments may still happen ahead of 1.0.
Determinism is the contract: the same (schedule, attempt) pair
always produces the same outcome.
Minimum supported Rust version
1.85 — pinned in Cargo.toml via rust-version and verified by
the MSRV job in CI. (Bumped from 1.75 to align with the suite's
shared MSRV after sibling crates picked up dependencies that require
edition2024.)
License
Apache-2.0. See LICENSE.