@@ -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+ }
0 commit comments