#![allow(dead_code)] #[path = "../../../os-handles/transfer/handles.rs"] mod handles; use handles::{Error, Object, Rights, TransferTable}; #[test] fn message_moves_handle_after_sender_exit() { let mut table = TransferTable::::new(); let sender = table.open_kernel(10, Object::File(55), Rights::READ_WRITE) .unwrap(); assert_eq!(table.send(10, sender, 20, Rights::READ, b"DATA"), Ok(1)); assert_eq!(table.owned(10), 0); assert_eq!(table.query(10, sender), Err(Error::BadFd)); // The sender has exited; the escrow still holds its object and bytes. let before = table.snapshot(); assert_eq!(table.receive(30), Err(Error::Access)); assert_eq!(table.peek(30), Err(Error::Access)); assert_eq!(table.snapshot(), before); let preview = table.peek(20).unwrap().unwrap(); assert_eq!(preview.ticket, 1); assert_eq!(preview.message.as_slice(), b"DATA"); assert_eq!(table.snapshot(), before); let transfer = table.receive(20).unwrap().unwrap(); assert_eq!(transfer.ticket, 1); assert_eq!(transfer.message.as_slice(), b"DATA"); assert_eq!(transfer.sender_object, Object::File(55)); assert_eq!(transfer.rights, Rights::READ); assert_eq!(transfer.recipient, 20); assert_ne!(transfer.handle, sender); assert_eq!(table.query(20, transfer.handle), Ok((Object::File(55), Rights::READ))); assert_eq!(table.queued(), 0); assert_eq!(table.close(20, transfer.handle), Ok(())); assert_eq!(table.owned(20), 0); assert_eq!(table.snapshot().generations, [2, 0]); } #[test] fn transfer_capacity_and_overflow_leave_escrow_intact() { let mut table = TransferTable::::new(); let source = table.open_kernel(10, Object::File(56), Rights::READ_WRITE) .unwrap(); assert_eq!(table.send(10, source, 20, Rights::READ, b"A"), Ok(1)); let blocker = table.open_kernel(30, Object::Task(1), Rights::READ).unwrap(); let before = table.snapshot(); assert_eq!(table.receive(20), Err(Error::Full)); assert_eq!(table.snapshot(), before); assert_eq!(table.close(30, blocker), Ok(())); let received = table.receive(20).unwrap().unwrap(); assert_eq!(received.message.as_slice(), b"A"); assert_eq!(table.close(20, received.handle), Ok(())); let mut ticket_overflow = TransferTable::::with_seeds([0], u64::MAX); let handle = ticket_overflow.open_kernel(10, Object::File(57), Rights::READ_WRITE).unwrap(); let before = ticket_overflow.snapshot(); assert_eq!(ticket_overflow.send(10, handle, 20, Rights::READ, b"A"), Err(Error::IdExhausted)); assert_eq!(ticket_overflow.snapshot(), before); let mut generation_overflow = TransferTable:: ::with_seeds([u32::MAX - 1], 1); let handle = generation_overflow.open_kernel(10, Object::File(58), Rights::READ_WRITE).unwrap(); generation_overflow.send(10, handle, 20, Rights::READ, b"A").unwrap(); let before = generation_overflow.snapshot(); assert_eq!(generation_overflow.receive(20), Err(Error::IdExhausted)); assert_eq!(generation_overflow.snapshot(), before); } #[test] fn failed_copy_and_rights_denial_keep_sender_handle() { let mut table = TransferTable::::new(); let source = table.open_kernel(10, Object::File(59), Rights::READ).unwrap(); let before = table.snapshot(); assert_eq!(table.send(10, source, 20, Rights::READ_WRITE, b"A"), Err(Error::Access)); assert_eq!(table.send(10, source, 20, Rights::READ, b"ABCDE"), Err(Error::MessageTooLarge)); assert_eq!(table.send(11, source, 20, Rights::READ, b"A"), Err(Error::BadFd)); assert_eq!(table.snapshot(), before); let result = table.send_from(10, source, 20, Rights::READ, 4, |destination| { destination[..2].copy_from_slice(b"AB"); Err(Error::Fault) }); assert_eq!(result, Err(Error::Fault)); assert_eq!(table.snapshot(), before); assert_eq!(table.query(10, source), Ok((Object::File(59), Rights::READ))); }