Skip to content

Commit 6ae196d

Browse files
committed
add tests for QueueSync
The tests simply invoke the same code twice, once with a Queue and once with a QueueSync. test_queue_guard/test_queue_guard_sync are different, because one uses lock() and one uses acquire(). Suggested-by: Laura Loghin <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent e1d0679 commit 6ae196d

File tree

1 file changed

+102
-20
lines changed

1 file changed

+102
-20
lines changed

crates/virtio-queue/src/lib.rs

Lines changed: 102 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,12 +1211,10 @@ mod tests {
12111211
}
12121212
}
12131213

1214-
#[test]
1215-
fn test_queue_and_iterator() {
1216-
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1214+
fn do_test_queue_and_iterator<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
12171215
let vq = MockSplitQueue::new(m, 16);
12181216

1219-
let mut q: Queue<_> = vq.as_queue(m);
1217+
let mut q: Q = vq.as_queue(m);
12201218

12211219
// q is currently valid
12221220
assert!(q.is_valid());
@@ -1326,11 +1324,21 @@ mod tests {
13261324
}
13271325

13281326
#[test]
1329-
fn test_descriptor_and_iterator() {
1327+
fn test_queue_and_iterator() {
1328+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1329+
do_test_queue_and_iterator::<Queue<&AddrSpace>>(m);
1330+
}
1331+
1332+
#[test]
1333+
fn test_queue_and_iterator_sync() {
13301334
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1335+
do_test_queue_and_iterator::<QueueSync<&AddrSpace>>(m);
1336+
}
1337+
1338+
fn do_test_descriptor_and_iterator<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
13311339
let vq = MockSplitQueue::new(m, 16);
13321340

1333-
let mut q: Queue<_> = vq.as_queue(m);
1341+
let mut q: Q = vq.as_queue(m);
13341342

13351343
// q is currently valid
13361344
assert!(q.is_valid());
@@ -1390,11 +1398,21 @@ mod tests {
13901398
}
13911399

13921400
#[test]
1393-
fn test_add_used() {
1401+
fn test_descriptor_and_iterator() {
13941402
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1403+
do_test_descriptor_and_iterator::<Queue<&AddrSpace>>(m);
1404+
}
1405+
1406+
#[test]
1407+
fn test_descriptor_and_iterator_sync() {
1408+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1409+
do_test_descriptor_and_iterator::<QueueSync<&AddrSpace>>(m);
1410+
}
1411+
1412+
fn do_test_add_used<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
13951413
let vq = MockSplitQueue::new(m, 16);
13961414

1397-
let mut q: Queue<_> = vq.as_queue(m);
1415+
let mut q: Q = vq.as_queue(m);
13981416

13991417
assert_eq!(vq.used().idx().load(), 0);
14001418

@@ -1413,12 +1431,20 @@ mod tests {
14131431
}
14141432

14151433
#[test]
1416-
fn test_queue_guard() {
1417-
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1418-
let vq = MockSplitQueue::new(m, 16);
1434+
fn test_add_used() {
1435+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1436+
do_test_add_used::<Queue<&AddrSpace>>(m);
1437+
}
14191438

1420-
let mut q = vq.create_queue(m);
1421-
let mut qstate = q.acquire();
1439+
#[test]
1440+
fn test_add_used_sync() {
1441+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1442+
do_test_add_used::<QueueSync<&AddrSpace>>(m);
1443+
}
1444+
1445+
fn do_test_queue_guard<S: DerefMut<Target = QueueState>>(
1446+
mut qstate: QueueGuard<&AddrSpace, S>,
1447+
) {
14221448
qstate.ready = true;
14231449
qstate.reset();
14241450
assert_eq!(qstate.ready, false);
@@ -1427,11 +1453,35 @@ mod tests {
14271453
}
14281454

14291455
#[test]
1430-
fn test_reset_queue() {
1431-
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1456+
fn test_queue_guard() {
1457+
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1458+
let vq = MockSplitQueue::new(m, 16);
1459+
1460+
let mut q = vq.create_queue(m);
1461+
do_test_queue_guard(q.acquire());
1462+
}
1463+
1464+
#[test]
1465+
fn test_queue_guard_sync() {
1466+
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1467+
let vq = MockSplitQueue::new(m, 16);
1468+
1469+
// Note how the test_queue_guard above has "let mut" here. A singlethreaded
1470+
// queue can only be accessed by one thread, and that one needs to have an
1471+
// exclusive reference; a multithreaded queue can be accessed by many thread
1472+
// and therefore it has to support interior mutability (via Mutex). On the
1473+
// other hand, a multithreaded queue is reference counted and therefore it
1474+
// cannot be accessed via an exclusive reference *at all*. This is the
1475+
// the reason why only Queue has the acquire() method, and only QueueSync
1476+
// has a lock() method.
1477+
let q: QueueSync<_> = vq.as_queue(m);
1478+
do_test_queue_guard(q.lock());
1479+
}
1480+
1481+
fn do_test_reset_queue<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
14321482
let vq = MockSplitQueue::new(m, 16);
14331483

1434-
let mut q: Queue<_> = vq.as_queue(m);
1484+
let mut q: Q = vq.as_queue(m);
14351485
q.with(|mut qstate| {
14361486
qstate.size = 8;
14371487
qstate.ready = true;
@@ -1442,12 +1492,22 @@ mod tests {
14421492
}
14431493

14441494
#[test]
1445-
fn test_needs_notification() {
1495+
fn test_reset_queue() {
14461496
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1497+
do_test_reset_queue::<Queue<&AddrSpace>>(m);
1498+
}
1499+
1500+
#[test]
1501+
fn test_reset_queue_sync() {
1502+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1503+
do_test_reset_queue::<QueueSync<&AddrSpace>>(m);
1504+
}
1505+
1506+
fn do_test_needs_notification<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
14471507
let qsize = 16;
14481508
let vq = MockSplitQueue::new(m, qsize);
14491509

1450-
let mut q: Queue<_> = vq.as_queue(m);
1510+
let mut q: Q = vq.as_queue(m);
14511511
let avail_addr = vq.avail_addr();
14521512

14531513
// It should always return true when EVENT_IDX isn't enabled.
@@ -1491,11 +1551,21 @@ mod tests {
14911551
}
14921552

14931553
#[test]
1494-
fn test_enable_disable_notification() {
1554+
fn test_needs_notification() {
14951555
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1556+
do_test_needs_notification::<Queue<&AddrSpace>>(m);
1557+
}
1558+
1559+
#[test]
1560+
fn test_needs_notification_sync() {
1561+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1562+
do_test_needs_notification::<QueueSync<&AddrSpace>>(m);
1563+
}
1564+
1565+
fn do_test_enable_disable_notification<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
14961566
let vq = MockSplitQueue::new(m, 16);
14971567

1498-
let mut q: Queue<_> = vq.as_queue(m);
1568+
let mut q: Q = vq.as_queue(m);
14991569
let used_addr = vq.used_addr();
15001570

15011571
q.with(|qstate| assert_eq!(qstate.event_idx_enabled, false));
@@ -1526,4 +1596,16 @@ mod tests {
15261596
q.with(|mut qstate| qstate.next_avail = Wrapping(8));
15271597
assert_eq!(q.enable_notification().unwrap(), false);
15281598
}
1599+
1600+
#[test]
1601+
fn test_enable_disable_notification() {
1602+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1603+
do_test_enable_disable_notification::<Queue<&AddrSpace>>(m);
1604+
}
1605+
1606+
#[test]
1607+
fn test_enable_disable_notification_sync() {
1608+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1609+
do_test_enable_disable_notification::<QueueSync<&AddrSpace>>(m);
1610+
}
15291611
}

0 commit comments

Comments
 (0)