#[path = "../../../os-shared-memory/src/guest_ring.rs"] mod guest_ring; use guest_ring::{Error, SharedRing, CAPACITY}; use std::sync::atomic::Ordering; #[test] fn two_endpoints_exchange_1000_messages_concurrently() { let page = SharedRing::new(); let (mut producer, mut consumer) = page.endpoints(); std::thread::scope(|scope| { let writer = scope.spawn(move || { for value in 0..1000 { loop { match producer.try_push(value) { Ok(()) => break, Err(Error::Full) => std::thread::yield_now(), other => panic!("unexpected producer result: {other:?}"), } } } producer.published() }); let reader = scope.spawn(move || { for expected in 0..1000 { loop { match consumer.try_pop() { Ok(value) => { assert_eq!(value, expected); break; } Err(Error::Empty) => std::thread::yield_now(), other => panic!("unexpected consumer result: {other:?}"), } } } consumer.consumed() }); assert_eq!(writer.join().unwrap(), 1000); assert_eq!(reader.join().unwrap(), 1000); }); assert_eq!(page.producer.load(Ordering::Acquire), 1000); assert_eq!(page.consumer.load(Ordering::Acquire), 1000); assert_eq!(core::mem::size_of::(), 192); assert_eq!(CAPACITY, 16); } #[test] fn corrupt_producer_index_is_rejected_before_slot_access() { #[repr(C)] struct Bounded { page: SharedRing, kernel_canary: [u8; 16] } let bounded = Bounded { page: SharedRing::new(), kernel_canary: *b"RING-KERNEL-SAFE" }; let (mut producer, mut consumer) = bounded.page.endpoints(); producer.try_push(0x71).unwrap(); let prior_slots: [u64; CAPACITY as usize] = core::array::from_fn(|i| bounded.page.slots[i].load(Ordering::Relaxed)); bounded.page.producer.store(100_000, Ordering::Release); assert_eq!(consumer.try_pop(), Err(Error::InvalidHeader)); assert_eq!(consumer.consumed(), 0); assert_eq!(bounded.page.consumer.load(Ordering::Acquire), 0); assert_eq!(core::array::from_fn::<_, { CAPACITY as usize }, _>( |i| bounded.page.slots[i].load(Ordering::Relaxed)), prior_slots); assert_eq!(bounded.kernel_canary, *b"RING-KERNEL-SAFE"); } #[test] fn full_and_peer_header_corruption_leave_state_unchanged() { let page = SharedRing::new(); let (mut producer, mut consumer) = page.endpoints(); for value in 0..CAPACITY { producer.try_push(value).unwrap(); } assert_eq!(producer.try_push(99), Err(Error::Full)); assert_eq!(producer.published(), CAPACITY); assert_eq!(consumer.try_pop(), Ok(0)); page.consumer.store(u64::MAX, Ordering::Release); assert_eq!(producer.try_push(99), Err(Error::InvalidHeader)); assert_eq!(producer.published(), CAPACITY); assert_eq!(page.producer.load(Ordering::Acquire), CAPACITY); }