use std::io::{Read, Write};
use std::mem::size_of;
use assert_matches::assert_matches;
use libc::{PROT_READ, PROT_WRITE};
use zerocopy::{FromBytes, Immutable, IntoBytes};
use super::{ArcMemPages, RamBus};
#[derive(Debug, IntoBytes, FromBytes, Immutable, PartialEq, Eq)]
#[repr(C)]
struct MyStruct {
data: [u32; 8],
}
const PAGE_SIZE: u64 = 1 << 12;
#[test]
fn test_ram_bus_read() {
let bus = RamBus::new();
let prot = PROT_READ | PROT_WRITE;
let mem1 = ArcMemPages::from_anonymous(PAGE_SIZE as usize, Some(prot), None).unwrap();
let mem2 = ArcMemPages::from_anonymous(PAGE_SIZE as usize, Some(prot), None).unwrap();
if mem1.addr > mem2.addr {
bus.add(0x0, mem1).unwrap();
bus.add(PAGE_SIZE, mem2).unwrap();
} else {
bus.add(0x0, mem2).unwrap();
bus.add(PAGE_SIZE, mem1).unwrap();
}
let data = MyStruct {
data: [1, 2, 3, 4, 5, 6, 7, 8],
};
let data_size = size_of::<MyStruct>() as u64;
for gpa in (PAGE_SIZE - data_size)..=PAGE_SIZE {
bus.write_t(gpa, &data).unwrap();
let r: MyStruct = bus.read_t(gpa).unwrap();
assert_eq!(r, data)
}
let memory_end = PAGE_SIZE * 2;
for gpa in (memory_end - data_size - 10)..=(memory_end - data_size) {
bus.write_t(gpa, &data).unwrap();
let r: MyStruct = bus.read_t(gpa).unwrap();
assert_eq!(r, data)
}
for gpa in (memory_end - data_size + 1)..memory_end {
assert_matches!(bus.write_t(gpa, &data), Err(_));
assert_matches!(bus.read_t::<MyStruct>(gpa), Err(_));
}
let data: Vec<u8> = (0..64).collect();
for gpa in (PAGE_SIZE - 64)..=PAGE_SIZE {
bus.write_range(gpa, 64, &*data).unwrap();
let mut buf = Vec::new();
bus.read_range(gpa, 64, &mut buf).unwrap();
assert_eq!(data, buf)
}
let guest_iov = [(0, 16), (PAGE_SIZE - 16, 32), (2 * PAGE_SIZE - 16, 16)];
let write_ret = bus.write_vectored(&guest_iov, |iov| {
assert_eq!(iov.len(), 4);
(&*data).read_vectored(iov)
});
assert_matches!(write_ret, Ok(Ok(64)));
let mut buf_read = Vec::new();
let read_ret = bus.read_vectored(&guest_iov, |iov| {
assert_eq!(iov.len(), 4);
buf_read.write_vectored(iov)
});
assert_matches!(read_ret, Ok(Ok(64)));
let locked_bus = bus.lock_layout();
let bufs = locked_bus.translate_iov(&guest_iov).unwrap();
println!("{bufs:?}");
drop(locked_bus);
bus.remove(0x0).unwrap();
}