#[path = "../../../os-virtio-descriptors/src/lib.rs"] mod virtio_descriptors; use virtio_descriptors::{Descriptor, Error, Phase, Pool, NEXT, WRITE}; fn read(address: u64, length: u32, next: u16) -> Descriptor { Descriptor {address, length, flags: NEXT, next} } fn write(address: u64, length: u32) -> Descriptor { Descriptor {address, length, flags: WRITE, next: 0} } #[test] fn os_virtio_descriptors_positive() { let mut pool = Pool::<8, 2>::new(8).unwrap(); let first = pool.claim(3, &[(3, read(0x4000, 16, 1)), (1, write(0x5000, 32))]).unwrap(); let second = pool.claim(0, &[(0, write(0x6000, 64))]).unwrap(); assert_eq!(pool.count(), 2); assert_eq!(pool.phase(first), Ok(Phase::Prepared)); pool.expose(first).unwrap(); pool.expose(second).unwrap(); pool.complete(first, 3, 24).unwrap(); pool.complete(second, 0, 64).unwrap(); pool.reclaim_used(first).unwrap(); pool.reclaim_used(second).unwrap(); assert_eq!(pool.count(), 0); let reused = pool.claim(3, &[(3, write(0x7000, 8))]).unwrap(); assert!(reused.generation > first.generation); assert_eq!(pool.phase(first), Err(Error::StaleHandle)); pool.cancel_prepared(reused).unwrap(); } #[test] fn os_virtio_descriptors_negative_and_reset() { assert!(matches!(Pool::<8, 2>::new(3), Err(Error::InvalidQueue))); let mut pool = Pool::<8, 2>::new(8).unwrap(); let initial = pool.snapshot(); assert_eq!(pool.claim(1, &[(1, read(0x4000, 8, 1)), (1, write(0x5000, 8))]), Err(Error::InvalidChain)); assert_eq!(pool.claim(1, &[(1, read(0x4000, 8, 9)), (2, write(0x5000, 8))]), Err(Error::InvalidChain)); assert_eq!(pool.claim(1, &[(1, Descriptor {flags: 4, ..write(0x5000, 8)})]), Err(Error::UnsupportedFlags)); assert_eq!(pool.claim(1, &[(1, write(u64::MAX, 2))]), Err(Error::InvalidDescriptor)); assert_eq!(pool.claim(1, &[(1, read(0x4000, u32::MAX, 2)), (2, write(0x5000, 2))]), Err(Error::InvalidChain)); assert_eq!(pool.claim(1, &[(1, Descriptor {flags: WRITE | NEXT, ..read(0x4000, 8, 2)}), (2, Descriptor {flags: 0, ..write(0x5000, 8)})]), Err(Error::InvalidChain)); assert_eq!(pool.snapshot(), initial); let first = pool.claim(1, &[(1, write(0x5000, 8))]).unwrap(); let prepared = pool.snapshot(); assert_eq!(pool.claim(1, &[(1, write(0x6000, 8))]), Err(Error::Overlap)); assert_eq!(pool.snapshot(), prepared); pool.expose(first).unwrap(); let exposed = pool.snapshot(); assert_eq!(pool.cancel_prepared(first), Err(Error::WrongPhase)); assert_eq!(pool.reclaim_used(first), Err(Error::WrongPhase)); assert_eq!(pool.complete(first, 2, 8), Err(Error::MismatchedCompletion)); assert_eq!(pool.complete(first, 1, 9), Err(Error::MismatchedCompletion)); assert_eq!(pool.observe_reset(0, 1), Err(Error::NotReset)); assert_eq!(pool.snapshot(), exposed); pool.complete(first, 1, 8).unwrap(); pool.reclaim_used(first).unwrap(); let later = pool.claim(1, &[(1, write(0x5000, 8))]).unwrap(); pool.expose(later).unwrap(); assert_eq!(pool.observe_reset(1, 0), Err(Error::NotReset)); pool.observe_reset(0, 0).unwrap(); assert_eq!(pool.count(), 0); }