#[path = "../../../os-turkfs-journal/src/replay.rs"] mod replay; use replay::{Block, Device, Error, Outcome, Recovery, HOMES}; struct Disk { homes: [Block;3], durable: [Block;3], calls: Vec, fail: Option } impl Device for Disk { fn write(&mut self, lba: u64, bytes: &Block) -> Result<(), ()> { self.calls.push(lba); if self.fail == Some(self.calls.len()) { return Err(()); } self.homes[HOMES.iter().position(|v| *v==lba).unwrap()] = *bytes; Ok(()) } fn flush(&mut self) -> Result<(), ()> { self.calls.push(0); if self.fail == Some(self.calls.len()) { return Err(()); } self.durable = self.homes; Ok(()) } } fn setup() -> (Block, Block, Disk) { let mut log = [0;512]; log[..128].copy_from_slice(include_bytes!("fixtures/turkfs-journal-v1.bin")); let mut commit = [0;512]; commit[..8].copy_from_slice(b"TKCOMMIT"); commit[8..16].copy_from_slice(&7u64.to_le_bytes()); commit[16..20].copy_from_slice(&log[28..32]); let homes = [[0x44;512],[0x66;512],[0x77;512]]; (log,commit,Disk {homes,durable:homes,calls:Vec::new(),fail:None}) } #[test] fn os_turkfs_recovery_replay_positive() { // All eight old/new home combinations represent completed writes that can // survive before a final flush. Replay changes only the remaining homes. for mask in 0u8..8 { let (log,commit,mut disk) = setup(); let mut recovery = Recovery::new(&log,&commit).unwrap(); for i in 0..3 { if mask & (1<