Bach is a Rust-based framework for simulating and testing complex async/await-based systems in a non-real-time environment. It's capable of modeling network protocols, queueing systems, and concurrent task interactions with testing and visualization tools.
- Discrete Event Simulation: Schedules events in simulated time for deterministic testing.
- Async/Await Integration: Supports any async that doesn't require a specific runtime, like
tokio
orasync-std
. - Composable Queues: Build flexible queues with latency, packet loss, mutexes, and sojourn tracking.
- Network Simulation: Simulates UDP sockets with configurable latency, loss, reordering, and duplication; TCP support planned for the near future.
- Partial Order Reduction: Optimizes task interleaving testing using a disjoint set, reducing the search space for conflicting resource accesses.
- PCAP Exporting: Captures simulated network traffic as PCAP files for analysis with Wireshark.
- Bolero Integration: Enables exhaustive and non-exhaustive (fuzzing-based) interleaving testing using engines like libFuzzer, with corpus replay and basic RNG input generation for
cargo test
. - Monitoring: Tracks packet sends, socket reads/writes, and supports fault injection.
- WASM Support: Can compile to WebAssembly and run in the browser for interactive simulations
This example simulates two clients sending "ping" to a server over UDP, which responds with "pong".
use bach::{ext::*, net::UdpSocket};
#[test]
fn ping_pong() {
bach::sim(|| {
for i in 0..2 {
async move {
let socket = UdpSocket::bind("0.0.0.0:0").await.unwrap();
socket.send_to(b"ping", "server:8080").await.unwrap();
let mut data = [0; 4];
let (len, _) = socket.recv_from(&mut data).await.unwrap();
assert_eq!(&data[..len], b"pong");
}
.group(format!("client_{i}"))
.primary()
.spawn();
}
async {
let socket = UdpSocket::bind("server:8080").await.unwrap();
loop {
let mut data = [0; 4];
let (len, addr) = socket.recv_from(&mut data).await.unwrap();
assert_eq!(&data[..len], b"ping");
socket.send_to(b"pong", addr).await.unwrap();
}
}
.group("server")
.spawn();
});
}
This test can be executed with the following command, while also exporting pcaps showing the interaction between the tasks:
$ BACH_PCAP_DIR=target/bach/pcaps cargo test
Add to Cargo.toml
:
[dependencies]
bach = "0.1"
- aws/s2n-quic: A QUIC protocol implementation. Employs Bach’s UDP-based network simulation to test high-level protocol behaviors, such as correctness, using PCAP exporting, fault injection, and monte-carlo simulations.
- camshaft/kew: A book about queueing theory. Utilizes Bach to simulate and visualize queue behaviors (e.g., FIFO, priority queues) in a browser via WebAssembly.
- camshaft/euphony-rs: A music composition environment. Uses Bach to schedule musical events (e.g., notes, rhythms) in non-real-time simulations for algorithmic composition.
Explore the Bach repository for more details or to contribute!