Skip to content

Commit f9fe527

Browse files
author
Dorinda Bassey
committed
Add unit tests for vhost-user device
Adds unit tests for VhostUserDevice and VhostUserRng Signed-off-by: Dorinda Bassey <dbassey@redhat.com>
1 parent 7d18fa0 commit f9fe527

2 files changed

Lines changed: 125 additions & 0 deletions

File tree

src/devices/src/virtio/vhost_user/device.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,3 +424,109 @@ impl VirtioDevice for VhostUserDevice {
424424
true
425425
}
426426
}
427+
428+
#[cfg(test)]
429+
mod tests {
430+
use std::io::{self, ErrorKind, Result as IoResult};
431+
432+
use vhost::vhost_user::VhostUserProtocolFeatures;
433+
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion};
434+
435+
use crate::virtio::Queue as VirtQueue;
436+
437+
const VHOST_USER_F_PROTOCOL_FEATURES: u64 = 1 << 30;
438+
439+
fn test_gpa_to_vmm_va(mem: &GuestMemoryMmap, gpa: u64) -> IoResult<u64> {
440+
for region in mem.iter() {
441+
let region_start = region.start_addr().raw_value();
442+
let region_end = region_start + region.len();
443+
444+
if gpa >= region_start && gpa < region_end {
445+
let offset = gpa - region_start;
446+
let vmm_va = region.as_ptr() as u64 + offset;
447+
return Ok(vmm_va);
448+
}
449+
}
450+
451+
Err(io::Error::new(
452+
ErrorKind::InvalidInput,
453+
format!("GPA 0x{:x} not found in any memory region", gpa),
454+
))
455+
}
456+
457+
#[test]
458+
fn test_feature_separation() {
459+
let backend_features = 0x1234_5678 | VHOST_USER_F_PROTOCOL_FEATURES;
460+
let virtio_features = backend_features & !VHOST_USER_F_PROTOCOL_FEATURES;
461+
let backend_only = backend_features & VHOST_USER_F_PROTOCOL_FEATURES;
462+
463+
assert_eq!(virtio_features, 0x1234_5678);
464+
assert_eq!(backend_only, VHOST_USER_F_PROTOCOL_FEATURES);
465+
assert_eq!(virtio_features & (1 << 30), 0);
466+
assert_eq!(backend_only & (1 << 30), 1 << 30);
467+
}
468+
469+
#[test]
470+
fn test_gpa_to_vmm_va_translation() {
471+
let regions = vec![
472+
(GuestAddress(0x0), 0x1000),
473+
(GuestAddress(0x10000), 0x2000),
474+
(GuestAddress(0x100000), 0x10000),
475+
];
476+
let mem = GuestMemoryMmap::from_ranges(&regions).unwrap();
477+
478+
// Test valid translations and offset arithmetic
479+
let va_0 = test_gpa_to_vmm_va(&mem, 0x0).unwrap();
480+
let va_100 = test_gpa_to_vmm_va(&mem, 0x100).unwrap();
481+
assert_eq!(va_100, va_0 + 0x100);
482+
483+
// Test boundaries
484+
assert!(test_gpa_to_vmm_va(&mem, 0xfff).is_ok());
485+
assert!(test_gpa_to_vmm_va(&mem, 0x1000).is_err());
486+
assert!(test_gpa_to_vmm_va(&mem, 0x10000).is_ok());
487+
assert!(test_gpa_to_vmm_va(&mem, 0x11fff).is_ok());
488+
assert!(test_gpa_to_vmm_va(&mem, 0x12000).is_err());
489+
490+
// Test gaps and invalid addresses
491+
assert!(test_gpa_to_vmm_va(&mem, 0x5000).is_err());
492+
assert!(test_gpa_to_vmm_va(&mem, 0x200000).is_err());
493+
}
494+
495+
#[test]
496+
fn test_queue_configuration() {
497+
let queue_sizes = vec![64, 128, 256, 512];
498+
let queues: Vec<VirtQueue> = queue_sizes
499+
.iter()
500+
.map(|&size| VirtQueue::new(size))
501+
.collect();
502+
503+
assert_eq!(queues.len(), 4);
504+
assert_eq!(queues[0].get_max_size(), 64);
505+
assert_eq!(queues[3].get_max_size(), 512);
506+
}
507+
508+
#[test]
509+
fn test_protocol_feature_flags() {
510+
let mut features = VhostUserProtocolFeatures::empty();
511+
features |= VhostUserProtocolFeatures::CONFIG;
512+
features |= VhostUserProtocolFeatures::MQ;
513+
514+
assert!(features.contains(VhostUserProtocolFeatures::CONFIG));
515+
assert!(features.contains(VhostUserProtocolFeatures::MQ));
516+
}
517+
518+
#[test]
519+
fn test_feature_negotiation() {
520+
let guest_acked: u64 = 0x1234;
521+
522+
// Without protocol features
523+
let backend_no_proto: u64 = 0x1234_5678;
524+
let bits = guest_acked | (backend_no_proto & VHOST_USER_F_PROTOCOL_FEATURES);
525+
assert_eq!(bits, guest_acked);
526+
527+
// With protocol features
528+
let backend_with_proto = 0x1234_5678 | VHOST_USER_F_PROTOCOL_FEATURES;
529+
let bits = guest_acked | (backend_with_proto & VHOST_USER_F_PROTOCOL_FEATURES);
530+
assert_eq!(bits, guest_acked | VHOST_USER_F_PROTOCOL_FEATURES);
531+
}
532+
}

src/devices/src/virtio/vhost_user/rng.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,22 @@ impl VirtioDevice for VhostUserRng {
9595
self.inner.reset()
9696
}
9797
}
98+
99+
#[cfg(test)]
100+
mod tests {
101+
use super::{VhostUserRng, NUM_QUEUES, QUEUE_SIZES, RNG_DEV_ID, VIRTIO_ID_RNG};
102+
103+
#[test]
104+
fn test_rng_constants() {
105+
assert_eq!(RNG_DEV_ID, "vhost_user_rng");
106+
assert_eq!(NUM_QUEUES, 1);
107+
assert_eq!(QUEUE_SIZES[0], 256);
108+
assert_eq!(VIRTIO_ID_RNG, 4);
109+
}
110+
111+
#[test]
112+
fn test_rng_new_fails_without_backend() {
113+
let result = VhostUserRng::new("/tmp/nonexistent-socket");
114+
assert!(result.is_err());
115+
}
116+
}

0 commit comments

Comments
 (0)