#[path = "../../../os-handles/src/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 FOREIGN: ProcessId = ProcessId { slot: 3, generation: 1 }; #[test] fn os_handles_types_positive() { let mut table = Table::::new(); let file = table.open(OWNER, Object::File(41)).unwrap(); let channel = table.open(OWNER, Object::Channel(52)).unwrap(); let task = table.open(OWNER, Object::Task(63)).unwrap(); assert_eq!([file.raw(), channel.raw(), task.raw()], [1, 2, 3]); assert_eq!(table.len(), 3); assert_eq!(table.owned(OWNER), 3); assert_eq!(table.owned(FOREIGN), 0); assert_eq!(table.file_read(OWNER, file), Ok(41)); assert_eq!(table.channel_send(OWNER, channel), Ok(52)); assert_eq!(table.task_inspect(OWNER, task), Ok(63)); let snapshot = table.snapshot(); assert_eq!(snapshot.next, 4); assert_eq!(snapshot.entries, [ Some((1, OWNER, Object::File(41))), Some((2, OWNER, Object::Channel(52))), Some((3, OWNER, Object::Task(63))), ]); assert_eq!(table.open(OWNER, Object::File(99)), Err(Error::Full)); assert_eq!(table.snapshot(), snapshot); assert_eq!(table.close_owner(OWNER), 3); assert_eq!(table.len(), 0); assert_eq!(table.snapshot().next, 4); } #[test] fn os_handles_types_negative() { let mut table = Table::::new(); let file = table.open(OWNER, Object::File(41)).unwrap(); let channel = table.open(OWNER, Object::Channel(52)).unwrap(); let task = table.open(OWNER, Object::Task(63)).unwrap(); let before = table.snapshot(); let resources = table.len(); assert_eq!(table.channel_send(OWNER, file), Err(Error::BadFd)); assert_eq!(Error::BadFd.errno(), 9); assert_eq!(table.snapshot(), before); assert_eq!(table.len(), resources); assert_eq!(table.owned(OWNER), 3); assert_eq!(table.channel_send(OWNER, channel), Ok(52)); assert_eq!(table.file_read(OWNER, file), Ok(41)); assert_eq!(table.task_inspect(OWNER, task), Ok(63)); assert_eq!(table.snapshot(), before); } #[test] fn invalid_stale_and_foreign_handles_leave_inventory_unchanged() { let mut table = Table::::new(); assert_eq!(table.open(OWNER, Object::File(0)), Err(Error::InvalidObject)); assert_eq!(table.len(), 0); let file = table.open(OWNER, Object::File(17)).unwrap(); let before = table.snapshot(); let recycled = ProcessId { slot: OWNER.slot, generation: OWNER.generation + 1 }; for wrong in [FOREIGN, recycled] { assert_eq!(table.file_read(wrong, file), Err(Error::BadFd)); assert_eq!(table.close(wrong, file), Err(Error::BadFd)); } assert_eq!(table.channel_send(OWNER, Handle::from_raw(0)), Err(Error::BadFd)); assert_eq!(table.task_inspect(OWNER, Handle::from_raw(900)), Err(Error::BadFd)); assert_eq!(table.snapshot(), before); assert_eq!(table.close(OWNER, file), Ok(())); let newer = table.open(OWNER, Object::Channel(18)).unwrap(); assert_ne!(newer, file); assert_eq!(table.file_read(OWNER, file), Err(Error::BadFd)); assert_eq!(table.channel_send(OWNER, newer), Ok(18)); assert_eq!(table.close_owner(OWNER), 1); assert_eq!(table.len(), 0); }