Crate bach

Crate bach 

Source
Expand description

§Bach

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.

§Key Features

  • 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 or async-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

§Example: Simulating a Networked Ping-Pong

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

§Installation

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!

Re-exports§

pub use task::spawn;
pub use task::spawn;

Modules§

coop
environment
executor
ext
group
metrics
net
queue
rand
runtime
scope
sync
task
time

Macros§

count
debug_span_
info_span_
measure
trace_

Functions§

is_active
Returns true if the caller is being executed in a bach environment
sim
Runs a simulation using the default environment