moonpool_sim/lib.rs
1//! # Moonpool Simulation Framework
2//!
3//! Deterministic simulation for testing distributed systems, inspired by
4//! [FoundationDB's simulation testing](https://apple.github.io/foundationdb/testing.html).
5//!
6//! ## Why Deterministic Simulation?
7//!
8//! `FoundationDB`'s insight: **bugs hide in error paths**. Production code rarely
9//! exercises timeout handlers, retry logic, or failure recovery. Deterministic
10//! simulation with fault injection finds these bugs before production does.
11//!
12//! Key properties:
13//! - **Reproducible**: Same seed produces identical execution
14//! - **Comprehensive**: Tests all failure modes (network, timing, corruption)
15//! - **Fast**: Logical time skips idle periods
16//!
17//! ## Core Components
18//!
19//! - [`SimWorld`]: The simulation runtime managing events and time
20//! - [`SimulationBuilder`]: Configure and run simulations
21//! - [`chaos`]: Fault injection (buggify, 14 assertion macros, invariants)
22//! - [`storage`]: Storage simulation with fault injection
23//! - Multiverse exploration via `moonpool-explorer` (re-exported as [`ExplorationConfig`], [`AdaptiveConfig`])
24//!
25//! ## Fault Injection Overview
26//!
27//! See [`chaos`] module for detailed documentation.
28//!
29//! | Mechanism | Default | What it tests |
30//! |-----------|---------|---------------|
31//! | TCP latencies | 1-11ms connect | Async scheduling |
32//! | Random connection close | 0.001% | Reconnection, redelivery |
33//! | Bit flip corruption | 0.01% | Checksum validation |
34//! | Connect failure | 50% probabilistic | Timeout handling, retries |
35//! | Clock drift | 100ms max | Leases, heartbeats |
36//! | Buggified delays | 25% | Race conditions |
37//! | Partial writes | 1000 bytes max | Message fragmentation |
38//! | Packet loss | disabled | At-least-once delivery |
39//! | Network partitions | disabled | Split-brain handling |
40//! | Storage corruption | configurable | Checksum validation, recovery |
41//! | Torn writes | configurable | Write atomicity, journaling |
42//! | Sync failures | configurable | Durability guarantees |
43//!
44//! ## Coverage-Preserving Multi-Seed Exploration
45//!
46//! When exploration is enabled, multiple seeds share coverage context. The
47//! explored map (coverage bitmap union) and assertion watermarks are preserved
48//! between seeds so each subsequent seed focuses energy on genuinely new
49//! branches rather than re-treading already-discovered paths.
50//!
51//! A **warm start** mechanism reduces wasted forks: on seeds after the first,
52//! marks whose first probe batch finds zero new coverage bits stop after
53//! `warm_min_timelines` forks instead of the full `min_timelines`.
54//!
55//! ```text
56//! Seed 1 (cold start) Seed 2 (warm start) Seed 3 (warm start)
57//! energy: 400K energy: 400K energy: 400K
58//!
59//! root ─┬─ mark A ──> 400 root ─┬─ mark A ──> 30 root ─┬─ mark A ──> 30
60//! │ (new bits!) forks │ (barren!) skip │ (barren!) skip
61//! │ │ │
62//! ├─ mark B ──> 400 ├─ mark B ──> 30 ├─ mark B ──> 30
63//! │ (new bits!) forks │ (barren!) skip │ (barren!) skip
64//! │ │ │
65//! └─ mark C ──> 400 ├─ mark C ──> 30 ├─ mark C ──> 30
66//! (new bits!) forks │ (barren!) skip │ (barren!) skip
67//! │ │
68//! └─ mark D ──> 400 └─ mark E ──> 400
69//! (NEW bits!) forks (NEW bits!) forks
70//! │ │ │
71//! ┌────────────────┘ ┌────────────────┘ ┌────────────────┘
72//! v v v
73//! ┌──────────┐ ──preserved──> ┌──────────┐ ──preserved──> ┌──────────┐
74//! │ explored │ coverage map │ explored │ coverage map │ explored │
75//! │ map: │ + watermarks │ map: │ + watermarks │ map: │
76//! │ A,B,C │ │ A,B,C,D │ │ A,B,C,D,E│
77//! └──────────┘ └──────────┘ └──────────┘
78//!
79//! Total: each seed spends most energy on NEW discoveries.
80//! Warm marks (A,B,C on seed 2) exit after warm_min_timelines (30)
81//! instead of min_timelines (400), saving ~95% energy per barren mark.
82//! ```
83//!
84//! ```ignore
85//! SimulationBuilder::new()
86//! .set_iterations(3) // 3 root seeds with coverage forwarding
87//! .enable_exploration(ExplorationConfig {
88//! max_depth: 120,
89//! timelines_per_split: 4,
90//! global_energy: 400_000, // per-seed energy budget
91//! adaptive: Some(AdaptiveConfig {
92//! batch_size: 30,
93//! min_timelines: 400,
94//! max_timelines: 1_000,
95//! per_mark_energy: 10_000,
96//! warm_min_timelines: Some(30), // quick skip for barren warm marks
97//! }),
98//! parallelism: Some(Parallelism::HalfCores),
99//! })
100//! .workload(my_workload);
101//! ```
102
103#![deny(missing_docs)]
104#![deny(clippy::unwrap_used)]
105
106// Re-export core types for convenience
107pub use moonpool_core::{
108 CodecError, Endpoint, JsonCodec, MessageCodec, NetworkAddress, NetworkAddressParseError,
109 NetworkProvider, Providers, RandomProvider, SimulationError, SimulationResult, TaskProvider,
110 TcpListenerTrait, TimeError, TimeProvider, UID, WELL_KNOWN_RESERVED_COUNT, WellKnownToken,
111};
112// The deterministic select! (moonpool-sim always enables core's
113// deterministic-select, so this is tokio's expansion with a seeded start
114// offset). Process and
115// workload code must use this instead of tokio::select!, whose branch offset is
116// entropy-drawn outside a seeded tokio runtime.
117pub use moonpool_core::select;
118// Production provider bundle — only when the tokio-providers feature pulls core's
119// net/fs/time. A wasm-able sim (`--no-default-features`) omits these.
120#[cfg(feature = "tokio-providers")]
121pub use moonpool_core::{
122 TokioNetworkProvider, TokioProviders, TokioTaskProvider, TokioTimeProvider,
123};
124
125// =============================================================================
126// Core Modules
127// =============================================================================
128
129/// Core simulation engine for deterministic testing.
130pub mod sim;
131
132/// The deterministic single-threaded executor (seeded-random scheduling).
133pub mod executor;
134
135/// Simulation runner and orchestration framework.
136pub mod runner;
137
138/// Chaos testing infrastructure for deterministic fault injection.
139pub mod chaos;
140
141/// Provider implementations for simulation.
142pub mod providers;
143
144/// Network simulation and configuration.
145pub mod network;
146
147/// Production-friendly observability layer (replaces legacy Timeline + Invariant).
148pub mod observability;
149
150/// Storage simulation and configuration.
151pub mod storage;
152
153/// Simulation workloads and binary targets.
154pub mod simulations;
155
156// =============================================================================
157// Public API Re-exports
158// =============================================================================
159
160// Sim module re-exports
161pub use sim::{
162 ConnectionStateChange, Event, EventQueue, NetworkOperation, ScheduledEvent, SimFaultRecord,
163 SimWorld, SleepFuture, StorageOperation, WeakSimWorld, clear_rng_breakpoints, current_sim_seed,
164 reset_rng_call_count, reset_sim_rng, rng_call_count, set_rng_breakpoints, set_sim_seed,
165 set_swarm_op_seed, sim_random, sim_random_range, sim_random_range_or_default, swarm_op_enabled,
166};
167
168// Runner module re-exports
169pub use runner::{
170 Attrition, AttritionScope, Chaos, ChaosMode, ClientId, DomainLevel, FaultContext,
171 FaultInjector, IterationControl, LocalityConfig, LocalityInfo, MachineRegistry, Process,
172 ProcessTags, RebootKind, SimContext, SimulationBuilder, SimulationMetrics, SimulationReport,
173 TagRegistry, Workload, WorkloadCount, WorkloadTopology,
174};
175
176// Chaos module re-exports
177pub use chaos::{
178 AssertionStats, SIM_FAULT_EVENT_NAME, SimFaultEvent, StateHandle, assertion_results,
179 buggify_init, buggify_reset, has_always_violations, reset_always_violations,
180 reset_assertion_results, validate_assertion_contracts,
181};
182
183// Observability module re-exports (plain-tracing capture + invariants)
184pub use observability::{
185 Clock, FieldValue, InstallGuard, Invariant, SimTime, SimulationLayer, SimulationLayerHandle,
186 TraceEvent, TraceQuery, init_sim_tracing, invariant_fn,
187};
188
189// Network exports
190pub use network::{
191 ChaosConfiguration, ConnectFailureMode, LatencyDistribution, NetworkConfiguration,
192 SimNetworkProvider, sample_duration, sample_latency,
193};
194
195// Storage exports
196pub use storage::{
197 InMemoryStorage, SECTOR_SIZE, SectorBitSet, SimStorageProvider, StorageConfiguration,
198 StorageError,
199};
200
201// Provider exports
202pub use providers::{SimProviders, SimRandomProvider, SimTaskProvider, SimTimeProvider};
203
204// Assertion vocabulary — always available (dependency-free accounting layer).
205pub use moonpool_assertions::{AssertCmp, AssertKind};
206// Exploration-only re-exports (fork-based multiverse engine).
207#[cfg(feature = "exploration")]
208pub use moonpool_explorer::{
209 AdaptiveConfig, ExplorationConfig, Parallelism, format_timeline, parse_timeline,
210};
211pub use runner::report::{BugRecipe, ExplorationReport};
212
213// Macros are automatically available at crate root when defined with #[macro_export]