Skip to content

Commit b87f9f1

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 b87f9f1

File tree

1 file changed

+100
-20
lines changed

1 file changed

+100
-20
lines changed

crates/virtio-queue/src/lib.rs

Lines changed: 100 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,18 @@ 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>>(mut qstate: QueueGuard<&AddrSpace, S>) {
14221446
qstate.ready = true;
14231447
qstate.reset();
14241448
assert_eq!(qstate.ready, false);
@@ -1427,11 +1451,35 @@ mod tests {
14271451
}
14281452

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

1434-
let mut q: Queue<_> = vq.as_queue(m);
1482+
let mut q: Q = vq.as_queue(m);
14351483
q.with(|mut qstate| {
14361484
qstate.size = 8;
14371485
qstate.ready = true;
@@ -1442,12 +1490,22 @@ mod tests {
14421490
}
14431491

14441492
#[test]
1445-
fn test_needs_notification() {
1493+
fn test_reset_queue() {
14461494
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1495+
do_test_reset_queue::<Queue<&AddrSpace>>(m);
1496+
}
1497+
1498+
#[test]
1499+
fn test_reset_queue_sync() {
1500+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1501+
do_test_reset_queue::<QueueSync<&AddrSpace>>(m);
1502+
}
1503+
1504+
fn do_test_needs_notification<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
14471505
let qsize = 16;
14481506
let vq = MockSplitQueue::new(m, qsize);
14491507

1450-
let mut q: Queue<_> = vq.as_queue(m);
1508+
let mut q: Q = vq.as_queue(m);
14511509
let avail_addr = vq.avail_addr();
14521510

14531511
// It should always return true when EVENT_IDX isn't enabled.
@@ -1491,11 +1549,21 @@ mod tests {
14911549
}
14921550

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

1498-
let mut q: Queue<_> = vq.as_queue(m);
1566+
let mut q: Q = vq.as_queue(m);
14991567
let used_addr = vq.used_addr();
15001568

15011569
q.with(|qstate| assert_eq!(qstate.event_idx_enabled, false));
@@ -1526,4 +1594,16 @@ mod tests {
15261594
q.with(|mut qstate| qstate.next_avail = Wrapping(8));
15271595
assert_eq!(q.enable_notification().unwrap(), false);
15281596
}
1597+
1598+
#[test]
1599+
fn test_enable_disable_notification() {
1600+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1601+
do_test_enable_disable_notification::<Queue<&AddrSpace>>(m);
1602+
}
1603+
1604+
#[test]
1605+
fn test_enable_disable_notification_sync() {
1606+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1607+
do_test_enable_disable_notification::<QueueSync<&AddrSpace>>(m);
1608+
}
15291609
}

0 commit comments

Comments
 (0)