#[path = "../../../os-handles/rights/handles.rs"] mod handles; use handles::{Error, Object, Rights, 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: 2, generation: 8 }; #[test] fn os_handles_rights_positive() { let mut table = Table::::new(); let original = table.open(OWNER, Object::File(41)).unwrap(); let copy = table.duplicate(OWNER, original, Rights::READ).unwrap(); assert_eq!((original.slot(), original.generation()), (1, 1)); assert_eq!((copy.slot(), copy.generation()), (2, 1)); assert_eq!(table.len(), 2); assert_eq!(table.owned(OWNER), 2); assert_eq!(table.file_read(OWNER, original), Ok(41)); assert_eq!(table.file_read(OWNER, copy), Ok(41)); assert_eq!(table.file_write(OWNER, original), Ok(41)); assert_eq!(table.file_write(OWNER, copy), Err(Error::Access)); assert_eq!(Error::Access.errno(), 13); assert_eq!(table.snapshot().entries, [ Some((original.raw(), OWNER, Object::File(41), Rights::READ_WRITE)), Some((copy.raw(), OWNER, Object::File(41), Rights::READ)), None, ]); assert_eq!(table.snapshot().generations, [1, 1, 0]); assert_eq!(table.close(OWNER, original), Ok(())); assert_eq!(table.file_read(OWNER, copy), Ok(41)); assert_eq!(table.close_owner(OWNER), 1); assert_eq!(table.len(), 0); } #[test] fn os_handles_rights_negative() { let mut table = Table::::new(); let original = table.open(OWNER, Object::File(41)).unwrap(); let copy = table.duplicate(OWNER, original, Rights::READ).unwrap(); let before = table.snapshot(); assert_eq!(table.duplicate(OWNER, copy, Rights::READ_WRITE), Err(Error::Access)); assert_eq!(table.snapshot(), before); assert_eq!(table.len(), 2); assert_eq!(table.owned(OWNER), 2); assert_eq!(table.duplicate(FOREIGN, original, Rights::READ), Err(Error::BadFd)); assert_eq!(table.duplicate(OWNER, original, Rights::READ), Err(Error::Full)); assert_eq!(table.snapshot(), before); assert_eq!(table.file_read(OWNER, copy), Ok(41)); assert_eq!(table.file_write(OWNER, copy), Err(Error::Access)); assert_eq!(table.file_write(OWNER, original), Ok(41)); assert_eq!(table.snapshot(), before); assert_eq!(table.close_owner(OWNER), 2); assert_eq!(table.len(), 0); } #[test] fn kind_rights_and_generation_remain_separate() { let mut table = Table::::new(); let channel = table.open(OWNER, Object::Channel(52)).unwrap(); let task = table.open(OWNER, Object::Task(63)).unwrap(); assert_eq!(table.channel_send(OWNER, channel), Ok(52)); assert_eq!(table.task_inspect(OWNER, task), Ok(63)); assert_eq!(table.file_read(OWNER, channel), Err(Error::BadFd)); assert_eq!(table.file_write(OWNER, task), Err(Error::BadFd)); assert_eq!(table.duplicate(OWNER, channel, Rights::READ), Err(Error::Access)); let before = table.snapshot(); assert_eq!(table.close(OWNER, channel), Ok(())); let recycled = table.open(OWNER, Object::Channel(53)).unwrap(); assert_eq!(recycled.slot(), channel.slot()); assert_eq!(recycled.generation(), channel.generation() + 1); assert_eq!(table.channel_send(OWNER, channel), Err(Error::BadFd)); assert_eq!(table.channel_send(OWNER, recycled), Ok(53)); assert_eq!(before.entries[1], table.snapshot().entries[1]); }