Skip to content

Commit 838f06e

Browse files
committed
add tests for QueueStateSync
For tests that do not use iter(), we can simply replace direct access to the QueueState with lock() in order to retrieve the guard. Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 51fe49b commit 838f06e

File tree

1 file changed

+92
-52
lines changed

1 file changed

+92
-52
lines changed

crates/virtio-queue/src/lib.rs

Lines changed: 92 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,7 @@ mod tests {
11931193
use vm_memory::{GuestAddress, GuestMemoryMmap};
11941194

11951195
#[test]
1196-
pub fn test_offset() {
1196+
fn test_offset() {
11971197
assert_eq!(offset_of!(Descriptor, addr), 0);
11981198
assert_eq!(offset_of!(Descriptor, len), 8);
11991199
assert_eq!(offset_of!(Descriptor, flags), 12);
@@ -1340,64 +1340,66 @@ mod tests {
13401340
}
13411341
}
13421342

1343-
#[test]
1344-
fn test_queue_and_iterator() {
1343+
fn do_test_queue_and_iterator<QS: QueueStateT>() {
13451344
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
13461345
let vq = MockSplitQueue::new(m, 16);
13471346

1348-
let mut q: Queue<_, QueueState> = vq.as_queue(m);
1347+
let mut q: Queue<_, QS> = vq.as_queue(m);
13491348

13501349
// q is currently valid
13511350
assert!(q.is_valid());
13521351

13531352
// shouldn't be valid when not marked as ready
1354-
q.state.ready = false;
1353+
q.lock().ready = false;
13551354
assert!(!q.is_valid());
1356-
q.state.ready = true;
1355+
q.lock().ready = true;
1356+
1357+
let max_size = q.lock().max_size;
13571358

13581359
// or when size > max_size
1359-
q.state.size = q.state.max_size << 1;
1360+
q.lock().size = max_size << 1;
13601361
assert!(!q.is_valid());
1361-
q.state.size = q.state.max_size;
1362+
q.lock().size = max_size;
13621363

13631364
// or when size is 0
1364-
q.state.size = 0;
1365+
q.lock().size = 0;
13651366
assert!(!q.is_valid());
1366-
q.state.size = q.state.max_size;
1367+
q.lock().size = max_size;
13671368

13681369
// or when size is not a power of 2
1369-
q.state.size = 11;
1370+
q.lock().size = 11;
13701371
assert!(!q.is_valid());
1371-
q.state.size = q.state.max_size;
1372+
q.lock().size = max_size;
13721373

13731374
// or if the various addresses are off
13741375

1375-
q.state.desc_table = GuestAddress(0xffff_ffff);
1376+
q.lock().desc_table = GuestAddress(0xffff_ffff);
13761377
assert!(!q.is_valid());
1377-
q.state.desc_table = GuestAddress(0x1001);
1378+
q.lock().desc_table = GuestAddress(0x1001);
13781379
assert!(!q.is_valid());
1379-
q.state.desc_table = vq.desc_table_addr();
1380+
q.lock().desc_table = vq.desc_table_addr();
13801381

1381-
q.state.avail_ring = GuestAddress(0xffff_ffff);
1382+
q.lock().avail_ring = GuestAddress(0xffff_ffff);
13821383
assert!(!q.is_valid());
1383-
q.state.avail_ring = GuestAddress(0x1001);
1384+
q.lock().avail_ring = GuestAddress(0x1001);
13841385
assert!(!q.is_valid());
1385-
q.state.avail_ring = vq.avail_addr();
1386+
q.lock().avail_ring = vq.avail_addr();
13861387

1387-
q.state.used_ring = GuestAddress(0xffff_ffff);
1388+
q.lock().used_ring = GuestAddress(0xffff_ffff);
13881389
assert!(!q.is_valid());
1389-
q.state.used_ring = GuestAddress(0x1001);
1390+
q.lock().used_ring = GuestAddress(0x1001);
13901391
assert!(!q.is_valid());
1391-
q.state.used_ring = vq.used_addr();
1392+
q.lock().used_ring = vq.used_addr();
13921393

13931394
{
1395+
let mut qstate = q.lock();
13941396
// an invalid queue should return an iterator with no next
1395-
q.state.ready = false;
1396-
let mut i = q.iter().unwrap();
1397+
qstate.ready = false;
1398+
let mut i = qstate.iter().unwrap();
13971399
assert!(i.next().is_none());
13981400
}
13991401

1400-
q.state.ready = true;
1402+
q.lock().ready = true;
14011403

14021404
// now let's create two simple descriptor chains
14031405
// the chains are (0, 1) and (2, 3, 4)
@@ -1416,7 +1418,8 @@ mod tests {
14161418
vq.avail().ring().ref_at(1).store(2);
14171419
vq.avail().idx().store(2);
14181420

1419-
let mut i = q.iter().unwrap();
1421+
let mut qstate = q.lock();
1422+
let mut i = qstate.iter().unwrap();
14201423

14211424
{
14221425
let mut c = i.next().unwrap();
@@ -1443,7 +1446,7 @@ mod tests {
14431446
{
14441447
assert!(i.next().is_none());
14451448
i.go_to_previous_position();
1446-
let mut c = q.iter().unwrap().next().unwrap();
1449+
let mut c = qstate.iter().unwrap().next().unwrap();
14471450
c.next().unwrap();
14481451
c.next().unwrap();
14491452
c.next().unwrap();
@@ -1453,11 +1456,16 @@ mod tests {
14531456
}
14541457

14551458
#[test]
1456-
fn test_descriptor_and_iterator() {
1459+
fn test_queue_and_iterator() {
1460+
do_test_queue_and_iterator::<QueueState>();
1461+
do_test_queue_and_iterator::<QueueStateSync>();
1462+
}
1463+
1464+
fn do_test_descriptor_and_iterator<QS: QueueStateT>() {
14571465
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
14581466
let vq = MockSplitQueue::new(m, 16);
14591467

1460-
let mut q: Queue<_, QueueState> = vq.as_queue(m);
1468+
let mut q: Queue<_, QS> = vq.as_queue(m);
14611469

14621470
// q is currently valid
14631471
assert!(q.is_valid());
@@ -1479,7 +1487,8 @@ mod tests {
14791487
vq.avail().ring().ref_at(2).store(5);
14801488
vq.avail().idx().store(3);
14811489

1482-
let mut i = q.iter().unwrap();
1490+
let mut qstate = q.lock();
1491+
let mut i = qstate.iter().unwrap();
14831492

14841493
{
14851494
let c = i.next().unwrap();
@@ -1515,11 +1524,16 @@ mod tests {
15151524
}
15161525

15171526
#[test]
1518-
fn test_add_used() {
1527+
fn test_descriptor_and_iterator() {
1528+
do_test_descriptor_and_iterator::<QueueState>();
1529+
do_test_descriptor_and_iterator::<QueueStateSync>();
1530+
}
1531+
1532+
fn do_test_add_used<QS: QueueStateT>() {
15191533
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
15201534
let vq = MockSplitQueue::new(m, 16);
15211535

1522-
let mut q: Queue<_, QueueState> = vq.as_queue(m);
1536+
let mut q: Queue<_, QS> = vq.as_queue(m);
15231537

15241538
assert_eq!(vq.used().idx().load(), 0);
15251539

@@ -1529,7 +1543,7 @@ mod tests {
15291543

15301544
// should be ok
15311545
q.add_used(1, 0x1000).unwrap();
1532-
assert_eq!(q.state.next_used, Wrapping(1));
1546+
assert_eq!(q.lock().next_used, Wrapping(1));
15331547
assert_eq!(vq.used().idx().load(), 1);
15341548

15351549
let x = vq.used().ring().ref_at(0).load();
@@ -1538,44 +1552,59 @@ mod tests {
15381552
}
15391553

15401554
#[test]
1541-
fn test_reset_queue() {
1555+
fn test_add_used() {
1556+
do_test_add_used::<QueueState>();
1557+
do_test_add_used::<QueueStateSync>();
1558+
}
1559+
1560+
fn do_test_reset_queue<QS: QueueStateT>() {
15421561
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
15431562
let vq = MockSplitQueue::new(m, 16);
15441563

1545-
let mut q: Queue<_, QueueState> = vq.as_queue(m);
1546-
q.state.size = 8;
1547-
q.state.ready = true;
1548-
q.state.reset();
1549-
assert_eq!(q.state.size, 16);
1550-
assert_eq!(q.state.ready, false);
1564+
let mut q: Queue<_, QS> = vq.as_queue(m);
1565+
let mut qstate = q.lock();
1566+
qstate.size = 8;
1567+
qstate.ready = true;
1568+
qstate.reset();
1569+
assert_eq!(qstate.size, 16);
1570+
assert_eq!(qstate.ready, false);
15511571
}
15521572

15531573
#[test]
1554-
fn test_needs_notification() {
1574+
fn test_reset_queue() {
1575+
do_test_reset_queue::<QueueState>();
1576+
do_test_reset_queue::<QueueStateSync>();
1577+
}
1578+
1579+
fn do_test_needs_notification<QS: QueueStateT>() {
15551580
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
15561581
let qsize = 16;
15571582
let vq = MockSplitQueue::new(m, qsize);
15581583

1559-
let mut q: Queue<_, QueueState> = vq.as_queue(m);
1584+
let mut q: Queue<_, QS> = vq.as_queue(m);
1585+
15601586
let avail_addr = vq.avail_addr();
15611587

15621588
// It should always return true when EVENT_IDX isn't enabled.
15631589
for i in 0..qsize {
1564-
q.state.next_used = Wrapping(i);
1590+
q.lock().next_used = Wrapping(i);
15651591
assert_eq!(q.needs_notification().unwrap(), true);
15661592
}
15671593

15681594
m.write_obj::<u16>(4, avail_addr.unchecked_add(4 + qsize as u64 * 2))
15691595
.unwrap();
1570-
q.state.set_event_idx(true);
1596+
q.lock().set_event_idx(true);
15711597

15721598
// Incrementing up to this value causes an `u16` to wrap back to 0.
15731599
let wrap = u32::from(u16::MAX) + 1;
15741600

15751601
for i in 0..wrap + 12 {
1576-
q.state.next_used = Wrapping(i as u16);
1602+
let mut qstate = q.lock();
1603+
qstate.next_used = Wrapping(i as u16);
15771604
// Let's test wrapping around the maximum index value as well.
1578-
let expected = i == 5 || i == (5 + wrap) || q.state.signalled_used.is_none();
1605+
let expected = i == 5 || i == (5 + wrap) || qstate.signalled_used.is_none();
1606+
drop(qstate);
1607+
15791608
assert_eq!(q.needs_notification().unwrap(), expected);
15801609
}
15811610

@@ -1589,22 +1618,27 @@ mod tests {
15891618
.unwrap();
15901619

15911620
assert_eq!(q.needs_notification().unwrap(), false);
1592-
q.state.next_used = Wrapping(15);
1621+
q.lock().next_used = Wrapping(15);
15931622
assert_eq!(q.needs_notification().unwrap(), false);
1594-
q.state.next_used = Wrapping(0);
1623+
q.lock().next_used = Wrapping(0);
15951624
assert_eq!(q.needs_notification().unwrap(), true);
15961625
assert_eq!(q.needs_notification().unwrap(), false);
15971626
}
15981627

15991628
#[test]
1600-
fn test_enable_disable_notification() {
1629+
fn test_needs_notification() {
1630+
do_test_needs_notification::<QueueState>();
1631+
do_test_needs_notification::<QueueStateSync>();
1632+
}
1633+
1634+
fn do_test_enable_disable_notification<QS: QueueStateT>() {
16011635
let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
16021636
let vq = MockSplitQueue::new(m, 16);
16031637

1604-
let mut q: Queue<_, QueueState> = vq.as_queue(m);
1638+
let mut q: Queue<_, QS> = vq.as_queue(m);
16051639
let used_addr = vq.used_addr();
16061640

1607-
assert_eq!(q.state.event_idx_enabled, false);
1641+
assert_eq!(q.lock().event_idx_enabled, false);
16081642

16091643
q.enable_notification().unwrap();
16101644
let v = m.read_obj::<u16>(used_addr).unwrap();
@@ -1623,13 +1657,19 @@ mod tests {
16231657
m.write_obj::<u16>(2, avail_addr.unchecked_add(2)).unwrap();
16241658

16251659
assert_eq!(q.enable_notification().unwrap(), true);
1626-
q.state.next_avail = Wrapping(2);
1660+
q.lock().next_avail = Wrapping(2);
16271661
assert_eq!(q.enable_notification().unwrap(), false);
16281662

16291663
m.write_obj::<u16>(8, avail_addr.unchecked_add(2)).unwrap();
16301664

16311665
assert_eq!(q.enable_notification().unwrap(), true);
1632-
q.state.next_avail = Wrapping(8);
1666+
q.lock().next_avail = Wrapping(8);
16331667
assert_eq!(q.enable_notification().unwrap(), false);
16341668
}
1669+
1670+
#[test]
1671+
fn test_enable_disable_notification() {
1672+
do_test_enable_disable_notification::<QueueState>();
1673+
do_test_enable_disable_notification::<QueueStateSync>();
1674+
}
16351675
}

0 commit comments

Comments
 (0)