# SQ-003: Simulation I/O Traits **Status:** `[x] DONE` **Blocked by:** SQ-000 **Priority:** High ## Description Define the trait abstractions for Clock and FileSystem that allow swapping real I/O for deterministic simulated I/O. This is the foundation of TigerBeetle-style testing. ## Files to Create/Modify - `crates/sq-sim/src/lib.rs` - re-exports - `crates/sq-sim/src/clock.rs` - Clock trait + RealClock + SimClock - `crates/sq-sim/src/fs.rs` - FileSystem trait + FileHandle trait + RealFileSystem + InMemoryFileSystem ## Key Traits ```rust pub trait Clock: Send + Sync { fn now(&self) -> std::time::Instant; async fn sleep(&self, duration: Duration); } pub trait FileSystem: Send + Sync { async fn create_dir_all(&self, path: &Path) -> Result<()>; async fn open_read(&self, path: &Path) -> Result>; async fn open_write(&self, path: &Path) -> Result>; async fn open_append(&self, path: &Path) -> Result>; async fn remove_file(&self, path: &Path) -> Result<()>; async fn list_dir(&self, path: &Path) -> Result>; async fn exists(&self, path: &Path) -> bool; } pub trait FileHandle: Send + Sync { async fn write_all(&mut self, buf: &[u8]) -> Result; async fn read_exact(&mut self, buf: &mut [u8]) -> Result; async fn read_to_end(&mut self, buf: &mut Vec) -> Result; async fn fsync(&mut self) -> Result<()>; fn position(&self) -> u64; async fn seek(&mut self, pos: u64) -> Result<()>; } ``` ## Fault Injection (InMemoryFileSystem) ```rust impl InMemoryFileSystem { pub fn fail_next_fsync(&self, error: io::Error); pub fn simulate_disk_full(&self); pub fn corrupt_bytes(&self, path: &Path, offset: u64, len: usize); pub fn clear_faults(&self); } ``` ## Acceptance Criteria - [ ] InMemoryFileSystem: write, read back, verify content - [ ] InMemoryFileSystem: create_dir_all, list_dir - [ ] InMemoryFileSystem: fsync succeeds normally - [ ] InMemoryFileSystem: fail_next_fsync causes next fsync to error - [ ] InMemoryFileSystem: simulate_disk_full causes writes to fail - [ ] SimClock: starts at time 0, advance(Duration) changes now() - [ ] SimClock: sleep returns immediately when time is advanced - [ ] RealClock: delegates to std::time - [ ] RealFileSystem: delegates to tokio::fs (basic smoke test)