Skip to content

Commit 031715e

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 bc7569d commit 031715e

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
@@ -1213,12 +1213,10 @@ mod tests {
12131213
}
12141214
}
12151215

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

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

12231221
// q is currently valid
12241222
assert!(q.is_valid());
@@ -1352,11 +1350,21 @@ mod tests {
13521350
}
13531351

13541352
#[test]
1355-
fn test_descriptor_and_iterator() {
1353+
fn test_queue_and_iterator() {
1354+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1355+
do_test_queue_and_iterator::<Queue<&AddrSpace>>(m);
1356+
}
1357+
1358+
#[test]
1359+
fn test_queue_and_iterator_sync() {
13561360
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1361+
do_test_queue_and_iterator::<QueueSync<&AddrSpace>>(m);
1362+
}
1363+
1364+
fn do_test_descriptor_and_iterator<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
13571365
let vq = MockSplitQueue::new(m, 16);
13581366

1359-
let mut q: Queue<_> = vq.as_queue(m);
1367+
let mut q: Q = vq.as_queue(m);
13601368

13611369
// q is currently valid
13621370
assert!(q.is_valid());
@@ -1416,11 +1424,21 @@ mod tests {
14161424
}
14171425

14181426
#[test]
1419-
fn test_add_used() {
1427+
fn test_descriptor_and_iterator() {
14201428
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1429+
do_test_descriptor_and_iterator::<Queue<&AddrSpace>>(m);
1430+
}
1431+
1432+
#[test]
1433+
fn test_descriptor_and_iterator_sync() {
1434+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1435+
do_test_descriptor_and_iterator::<QueueSync<&AddrSpace>>(m);
1436+
}
1437+
1438+
fn do_test_add_used<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
14211439
let vq = MockSplitQueue::new(m, 16);
14221440

1423-
let mut q: Queue<_> = vq.as_queue(m);
1441+
let mut q: Q = vq.as_queue(m);
14241442

14251443
assert_eq!(vq.used().idx().load(), 0);
14261444

@@ -1439,12 +1457,20 @@ mod tests {
14391457
}
14401458

14411459
#[test]
1442-
fn test_queue_guard() {
1443-
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1444-
let vq = MockSplitQueue::new(m, 16);
1460+
fn test_add_used() {
1461+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1462+
do_test_add_used::<Queue<&AddrSpace>>(m);
1463+
}
14451464

1446-
let mut q = vq.create_queue(m);
1447-
let mut qstate = q.acquire();
1465+
#[test]
1466+
fn test_add_used_sync() {
1467+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1468+
do_test_add_used::<QueueSync<&AddrSpace>>(m);
1469+
}
1470+
1471+
fn do_test_queue_guard<S: DerefMut<Target = QueueState>>(
1472+
mut qstate: QueueGuard<&AddrSpace, S>,
1473+
) {
14481474
qstate.ready = true;
14491475
qstate.reset();
14501476
assert_eq!(qstate.ready, false);
@@ -1453,11 +1479,35 @@ mod tests {
14531479
}
14541480

14551481
#[test]
1456-
fn test_reset_queue() {
1457-
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1482+
fn test_queue_guard() {
1483+
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1484+
let vq = MockSplitQueue::new(m, 16);
1485+
1486+
let mut q = vq.create_queue(m);
1487+
do_test_queue_guard(q.acquire());
1488+
}
1489+
1490+
#[test]
1491+
fn test_queue_guard_sync() {
1492+
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1493+
let vq = MockSplitQueue::new(m, 16);
1494+
1495+
// Note how the test_queue_guard above has "let mut" here. A singlethreaded
1496+
// queue can only be accessed by one thread, and that one needs to have an
1497+
// exclusive reference; a multithreaded queue can be accessed by many thread
1498+
// and therefore it has to support interior mutability (via Mutex). On the
1499+
// other hand, a multithreaded queue is reference counted and therefore it
1500+
// cannot be accessed via an exclusive reference *at all*. This is the
1501+
// the reason why only Queue has the acquire() method, and only QueueSync
1502+
// has a lock() method.
1503+
let q: QueueSync<_> = vq.as_queue(m);
1504+
do_test_queue_guard(q.lock());
1505+
}
1506+
1507+
fn do_test_reset_queue<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
14581508
let vq = MockSplitQueue::new(m, 16);
14591509

1460-
let mut q: Queue<_> = vq.as_queue(m);
1510+
let mut q: Q = vq.as_queue(m);
14611511
q.with(|mut qstate| {
14621512
qstate.size = 8;
14631513
qstate.ready = true;
@@ -1468,12 +1518,22 @@ mod tests {
14681518
}
14691519

14701520
#[test]
1471-
fn test_needs_notification() {
1521+
fn test_reset_queue() {
14721522
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1523+
do_test_reset_queue::<Queue<&AddrSpace>>(m);
1524+
}
1525+
1526+
#[test]
1527+
fn test_reset_queue_sync() {
1528+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1529+
do_test_reset_queue::<QueueSync<&AddrSpace>>(m);
1530+
}
1531+
1532+
fn do_test_needs_notification<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
14731533
let qsize = 16;
14741534
let vq = MockSplitQueue::new(m, qsize);
14751535

1476-
let mut q: Queue<_> = vq.as_queue(m);
1536+
let mut q: Q = vq.as_queue(m);
14771537
let avail_addr = vq.avail_addr();
14781538

14791539
// It should always return true when EVENT_IDX isn't enabled.
@@ -1517,11 +1577,21 @@ mod tests {
15171577
}
15181578

15191579
#[test]
1520-
fn test_enable_disable_notification() {
1580+
fn test_needs_notification() {
15211581
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1582+
do_test_needs_notification::<Queue<&AddrSpace>>(m);
1583+
}
1584+
1585+
#[test]
1586+
fn test_needs_notification_sync() {
1587+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1588+
do_test_needs_notification::<QueueSync<&AddrSpace>>(m);
1589+
}
1590+
1591+
fn do_test_enable_disable_notification<'a, Q: QueueT<&'a AddrSpace>>(m: &'a AddrSpace) {
15221592
let vq = MockSplitQueue::new(m, 16);
15231593

1524-
let mut q: Queue<_> = vq.as_queue(m);
1594+
let mut q: Q = vq.as_queue(m);
15251595
let used_addr = vq.used_addr();
15261596

15271597
q.with(|qstate| assert_eq!(qstate.event_idx_enabled, false));
@@ -1552,4 +1622,16 @@ mod tests {
15521622
q.with(|mut qstate| qstate.next_avail = Wrapping(8));
15531623
assert_eq!(q.enable_notification().unwrap(), false);
15541624
}
1625+
1626+
#[test]
1627+
fn test_enable_disable_notification() {
1628+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1629+
do_test_enable_disable_notification::<Queue<&AddrSpace>>(m);
1630+
}
1631+
1632+
#[test]
1633+
fn test_enable_disable_notification_sync() {
1634+
let m = &AddrSpace::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1635+
do_test_enable_disable_notification::<QueueSync<&AddrSpace>>(m);
1636+
}
15551637
}

0 commit comments

Comments
 (0)