@@ -270,3 +270,175 @@ impl ReadVolatile for &[u8] {
270270 self . read_volatile ( buf) . map ( |_| ( ) )
271271 }
272272}
273+
274+ #[ cfg( test) ]
275+ mod tests {
276+ use crate :: io:: { ReadVolatile , WriteVolatile } ;
277+ use crate :: { VolatileMemoryError , VolatileSlice } ;
278+ use std:: io:: { ErrorKind , Read , Seek , Write } ;
279+ use vmm_sys_util:: tempfile:: TempFile ;
280+
281+ // ---- Test ReadVolatile for &[u8] ----
282+ fn read_4_bytes_to_5_byte_memory ( source : Vec < u8 > , expected_output : [ u8 ; 5 ] ) {
283+ // Test read_volatile for &[u8] works
284+ let mut memory = vec ! [ 0u8 ; 5 ] ;
285+
286+ assert_eq ! (
287+ ( & source[ ..] )
288+ . read_volatile( & mut VolatileSlice :: from( & mut memory[ ..4 ] ) )
289+ . unwrap( ) ,
290+ source. len( ) . min( 4 )
291+ ) ;
292+ assert_eq ! ( & memory, & expected_output) ;
293+
294+ // Test read_exact_volatile for &[u8] works
295+ let mut memory = vec ! [ 0u8 ; 5 ] ;
296+ let result = ( & source[ ..] ) . read_exact_volatile ( & mut VolatileSlice :: from ( & mut memory[ ..4 ] ) ) ;
297+
298+ // read_exact fails if there are not enough bytes in input to completely fill
299+ // memory[..4]
300+ if source. len ( ) < 4 {
301+ match result. unwrap_err ( ) {
302+ VolatileMemoryError :: IOError ( ioe) => {
303+ assert_eq ! ( ioe. kind( ) , ErrorKind :: UnexpectedEof )
304+ }
305+ err => panic ! ( "{:?}" , err) ,
306+ }
307+ assert_eq ! ( memory, vec![ 0u8 ; 5 ] ) ;
308+ } else {
309+ result. unwrap ( ) ;
310+ assert_eq ! ( & memory, & expected_output) ;
311+ }
312+ }
313+
314+ // ---- Test ReadVolatile for File ----
315+ fn read_4_bytes_from_file ( source : Vec < u8 > , expected_output : [ u8 ; 5 ] ) {
316+ let mut temp_file = TempFile :: new ( ) . unwrap ( ) . into_file ( ) ;
317+ temp_file. write_all ( source. as_ref ( ) ) . unwrap ( ) ;
318+ temp_file. rewind ( ) . unwrap ( ) ;
319+
320+ // Test read_volatile for File works
321+ let mut memory = vec ! [ 0u8 ; 5 ] ;
322+
323+ assert_eq ! (
324+ temp_file
325+ . read_volatile( & mut VolatileSlice :: from( & mut memory[ ..4 ] ) )
326+ . unwrap( ) ,
327+ source. len( ) . min( 4 )
328+ ) ;
329+ assert_eq ! ( & memory, & expected_output) ;
330+
331+ temp_file. rewind ( ) . unwrap ( ) ;
332+
333+ // Test read_exact_volatile for File works
334+ let mut memory = vec ! [ 0u8 ; 5 ] ;
335+
336+ let read_exact_result =
337+ temp_file. read_exact_volatile ( & mut VolatileSlice :: from ( & mut memory[ ..4 ] ) ) ;
338+
339+ if source. len ( ) < 4 {
340+ read_exact_result. unwrap_err ( ) ;
341+ } else {
342+ read_exact_result. unwrap ( ) ;
343+ }
344+ assert_eq ! ( & memory, & expected_output) ;
345+ }
346+
347+ #[ test]
348+ fn test_read_volatile ( ) {
349+ let test_cases = [
350+ ( vec ! [ 1u8 , 2 ] , [ 1u8 , 2 , 0 , 0 , 0 ] ) ,
351+ ( vec ! [ 1 , 2 , 3 , 4 ] , [ 1 , 2 , 3 , 4 , 0 ] ) ,
352+ // ensure we don't have a buffer overrun
353+ ( vec ! [ 5 , 6 , 7 , 8 , 9 ] , [ 5 , 6 , 7 , 8 , 0 ] ) ,
354+ ] ;
355+
356+ for ( input, output) in test_cases {
357+ read_4_bytes_to_5_byte_memory ( input. clone ( ) , output) ;
358+ read_4_bytes_from_file ( input, output) ;
359+ }
360+ }
361+
362+ // ---- Test WriteVolatile for &mut [u8] ----
363+ fn write_4_bytes_to_5_byte_vec ( mut source : Vec < u8 > , expected_result : [ u8 ; 5 ] ) {
364+ let mut memory = vec ! [ 0u8 ; 5 ] ;
365+
366+ // Test write_volatile for &mut [u8] works
367+ assert_eq ! (
368+ ( & mut memory[ ..4 ] )
369+ . write_volatile( & VolatileSlice :: from( source. as_mut_slice( ) ) )
370+ . unwrap( ) ,
371+ source. len( ) . min( 4 )
372+ ) ;
373+ assert_eq ! ( & memory, & expected_result) ;
374+
375+ // Test write_all_volatile for &mut [u8] works
376+ let mut memory = vec ! [ 0u8 ; 5 ] ;
377+
378+ let result =
379+ ( & mut memory[ ..4 ] ) . write_all_volatile ( & VolatileSlice :: from ( source. as_mut_slice ( ) ) ) ;
380+
381+ if source. len ( ) > 4 {
382+ match result. unwrap_err ( ) {
383+ VolatileMemoryError :: IOError ( ioe) => {
384+ assert_eq ! ( ioe. kind( ) , ErrorKind :: WriteZero )
385+ }
386+ err => panic ! ( "{:?}" , err) ,
387+ }
388+ // This quirky behavior of writing to the slice even in the case of failure is also
389+ // exhibited by the stdlib
390+ assert_eq ! ( & memory, & expected_result) ;
391+ } else {
392+ result. unwrap ( ) ;
393+ assert_eq ! ( & memory, & expected_result) ;
394+ }
395+ }
396+
397+ // ---- Test ẂriteVolatile for File works ----
398+ fn write_5_bytes_to_file ( mut source : Vec < u8 > ) {
399+ // Test write_volatile for File works
400+ let mut temp_file = TempFile :: new ( ) . unwrap ( ) . into_file ( ) ;
401+
402+ temp_file
403+ . write_volatile ( & VolatileSlice :: from ( source. as_mut_slice ( ) ) )
404+ . unwrap ( ) ;
405+ temp_file. rewind ( ) . unwrap ( ) ;
406+
407+ let mut written = vec ! [ 0u8 ; source. len( ) ] ;
408+ temp_file. read_exact ( written. as_mut_slice ( ) ) . unwrap ( ) ;
409+
410+ assert_eq ! ( source, written) ;
411+ // check no excess bytes were written to the file
412+ assert_eq ! ( temp_file. read( & mut [ 0u8 ] ) . unwrap( ) , 0 ) ;
413+
414+ // Test write_all_volatile for File works
415+ let mut temp_file = TempFile :: new ( ) . unwrap ( ) . into_file ( ) ;
416+
417+ temp_file
418+ . write_all_volatile ( & VolatileSlice :: from ( source. as_mut_slice ( ) ) )
419+ . unwrap ( ) ;
420+ temp_file. rewind ( ) . unwrap ( ) ;
421+
422+ let mut written = vec ! [ 0u8 ; source. len( ) ] ;
423+ temp_file. read_exact ( written. as_mut_slice ( ) ) . unwrap ( ) ;
424+
425+ assert_eq ! ( source, written) ;
426+ // check no excess bytes were written to the file
427+ assert_eq ! ( temp_file. read( & mut [ 0u8 ] ) . unwrap( ) , 0 ) ;
428+ }
429+
430+ #[ test]
431+ fn test_write_volatile ( ) {
432+ let test_cases = [
433+ ( vec ! [ 1u8 , 2 ] , [ 1u8 , 2 , 0 , 0 , 0 ] ) ,
434+ ( vec ! [ 1 , 2 , 3 , 4 ] , [ 1 , 2 , 3 , 4 , 0 ] ) ,
435+ // ensure we don't have a buffer overrun
436+ ( vec ! [ 5 , 6 , 7 , 8 , 9 ] , [ 5 , 6 , 7 , 8 , 0 ] ) ,
437+ ] ;
438+
439+ for ( input, output) in test_cases {
440+ write_4_bytes_to_5_byte_vec ( input. clone ( ) , output) ;
441+ write_5_bytes_to_file ( input) ;
442+ }
443+ }
444+ }
0 commit comments