#[path = "../../../os-handles/generation/handles.rs"] mod handles; use handles::{Error, Handle, Object, Table}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] struct ProcessId { slot: u32, generation: u64 } const OWNER: ProcessId = ProcessId { slot: 2, generation: 7 }; const NEW_OWNER_GENERATION: ProcessId = ProcessId { slot: 2, generation: 8 }; #[test] fn os_handles_generation_positive() { let mut table = Table::::new(); let mut old = [Handle::from_raw(0); 3]; for generation in 1..=3u32 { let handle = table.open(OWNER, Object::Channel(u64::from(generation))) .unwrap(); assert_eq!(handle.slot(), 1); assert_eq!(handle.generation(), generation); assert_eq!(handle.raw(), (u64::from(generation) << 32) | 1); assert_eq!(table.len(), 1); assert_eq!(table.owned(OWNER), 1); assert_eq!(table.channel_send(OWNER, handle), Ok(u64::from(generation))); for stale in old.iter().take((generation - 1) as usize) { let before = table.snapshot(); assert_eq!(table.channel_send(OWNER, *stale), Err(Error::BadFd)); assert_eq!(table.close(OWNER, *stale), Err(Error::BadFd)); assert_eq!(table.snapshot(), before); } old[(generation - 1) as usize] = handle; assert_eq!(table.close(OWNER, handle), Ok(())); assert_eq!(table.len(), 0); assert_eq!(table.snapshot().generations, [generation]); assert_eq!(table.snapshot().entries, [None]); } assert_eq!(old.map(Handle::generation), [1, 2, 3]); } #[test] fn os_handles_generation_negative() { let mut exhausted = Table::::with_generation_seed([u32::MAX]); let before = exhausted.snapshot(); assert_eq!(exhausted.open(OWNER, Object::File(41)), Err(Error::IdExhausted)); assert_eq!(exhausted.snapshot(), before); assert_eq!(exhausted.len(), 0); assert_eq!(exhausted.owned(OWNER), 0); assert_eq!(exhausted.open(OWNER, Object::File(0)), Err(Error::InvalidObject)); assert_eq!(exhausted.snapshot(), before); let mut healthy = Table::::new(); let live = healthy.open(OWNER, Object::File(42)).unwrap(); let before = healthy.snapshot(); assert_eq!(healthy.file_read(NEW_OWNER_GENERATION, live), Err(Error::BadFd)); assert_eq!(healthy.close(NEW_OWNER_GENERATION, live), Err(Error::BadFd)); assert_eq!(healthy.snapshot(), before); assert_eq!(healthy.file_read(OWNER, live), Ok(42)); assert_eq!(healthy.close_owner(OWNER), 1); assert_eq!(healthy.len(), 0); assert_eq!(healthy.file_read(OWNER, live), Err(Error::BadFd)); }