@@ -270,3 +270,175 @@ impl ReadVolatile for &[u8] {
270
270
self . read_volatile ( buf) . map ( |_| ( ) )
271
271
}
272
272
}
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