@@ -19,3 +19,95 @@ generate_fam_struct_impl!(vfio_irq_set, u8, data, u32, count, MSIX_MAX_VECTORS);
1919/// elements, this type is implemented using
2020/// [FamStructWrapper](../vmm_sys_util/fam/struct.FamStructWrapper.html).
2121pub type IrqSet = FamStructWrapper < vfio_irq_set > ;
22+
23+ #[ cfg( test) ]
24+ mod tests {
25+ extern crate byteorder;
26+
27+ use super :: * ;
28+ use byteorder:: { ByteOrder , LittleEndian } ;
29+ use std:: mem;
30+
31+ fn vec_with_size_in_bytes < T : Default > ( size_in_bytes : usize ) -> Vec < T > {
32+ let rounded_size = ( size_in_bytes + mem:: size_of :: < T > ( ) - 1 ) / mem:: size_of :: < T > ( ) ;
33+ let mut v = Vec :: with_capacity ( rounded_size) ;
34+ for _ in 0 ..rounded_size {
35+ v. push ( T :: default ( ) )
36+ }
37+ v
38+ }
39+
40+ fn vec_with_array_field < T : Default , F > ( count : usize ) -> Vec < T > {
41+ let element_space = count * mem:: size_of :: < F > ( ) ;
42+ let vec_size_bytes = mem:: size_of :: < T > ( ) + element_space;
43+ vec_with_size_in_bytes ( vec_size_bytes)
44+ }
45+
46+ // Opinionated PartialEq implementation for vfio_irq_set.
47+ impl PartialEq for vfio_irq_set {
48+ fn eq ( & self , other : & Self ) -> bool {
49+ if self . argsz != other. argsz
50+ || self . flags != other. flags
51+ || self . index != other. index
52+ || self . start != other. start
53+ || self . count != other. count
54+ {
55+ return false ;
56+ }
57+ true
58+ }
59+ }
60+
61+ #[ test]
62+ fn irqset_fam_test ( ) {
63+ let event_fds: Vec < u32 > = vec ! [ 0 , 1 , 2 , 3 , 4 , 5 ] ;
64+
65+ // Build a FAM wrapper for this vfio_irq_set.
66+ let mut irq_set_wrapper = IrqSet :: new ( event_fds. len ( ) * mem:: size_of :: < u32 > ( ) ) ;
67+ let mut irq_set_fam = irq_set_wrapper. as_mut_fam_struct ( ) ;
68+
69+ let fds_fam = irq_set_fam. as_mut_slice ( ) ;
70+ for ( index, event_fd) in event_fds. iter ( ) . enumerate ( ) {
71+ let fds_offset = index * mem:: size_of :: < u32 > ( ) ;
72+ let fd = & mut fds_fam[ fds_offset..fds_offset + mem:: size_of :: < u32 > ( ) ] ;
73+ LittleEndian :: write_u32 ( fd, * event_fd) ;
74+ }
75+
76+ irq_set_fam. argsz = mem:: size_of :: < vfio_irq_set > ( ) as u32
77+ + ( event_fds. len ( ) * mem:: size_of :: < u32 > ( ) ) as u32 ;
78+ irq_set_fam. flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER ;
79+ irq_set_fam. index = 1 ;
80+ irq_set_fam. start = 0 ;
81+ irq_set_fam. count = event_fds. len ( ) as u32 ;
82+
83+ // Build the same vfio_irq_set structure with the vec_with_array routines
84+ let mut irq_set_vec = vec_with_array_field :: < vfio_irq_set , u32 > ( event_fds. len ( ) ) ;
85+ irq_set_vec[ 0 ] . argsz = mem:: size_of :: < vfio_irq_set > ( ) as u32
86+ + ( event_fds. len ( ) * mem:: size_of :: < u32 > ( ) ) as u32 ;
87+ irq_set_vec[ 0 ] . flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER ;
88+ irq_set_vec[ 0 ] . index = 1 ;
89+ irq_set_vec[ 0 ] . start = 0 ;
90+ irq_set_vec[ 0 ] . count = event_fds. len ( ) as u32 ;
91+
92+ let fds_vec = unsafe {
93+ irq_set_vec[ 0 ]
94+ . data
95+ . as_mut_slice ( event_fds. len ( ) * mem:: size_of :: < u32 > ( ) )
96+ } ;
97+ for ( index, event_fd) in event_fds. iter ( ) . enumerate ( ) {
98+ let fds_offset = index * mem:: size_of :: < u32 > ( ) ;
99+ let fd = & mut fds_vec[ fds_offset..fds_offset + mem:: size_of :: < u32 > ( ) ] ;
100+ LittleEndian :: write_u32 ( fd, * event_fd) ;
101+ }
102+
103+ // Both sets should be identical.
104+ assert_eq ! (
105+ irq_set_vec
106+ . iter( )
107+ . zip( irq_set_wrapper. into_raw( ) . iter( ) )
108+ . filter( |& ( a, b) | a == b)
109+ . count( ) ,
110+ irq_set_vec. len( )
111+ ) ;
112+ }
113+ }
0 commit comments