Skip to content

Commit 9c3e6aa

Browse files
roypatJonathanWoollett-Light
authored andcommitted
test: Add tests for VolatileRead/Write
Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
1 parent 0173112 commit 9c3e6aa

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed

src/io.rs

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)