unc_vm_runner/logic/
test_utils.rs

1use super::{MemSlice, MemoryLike};
2
3/// Tests for implementation of MemoryLike interface.
4///
5/// The `factory` returns a [`MemoryLike`] implementation to be tested.  The
6/// memory must be configured with 64 KiB (i.e. single WASM page) of memory
7/// available.
8///
9/// Panics if any of the tests fails.
10pub fn test_memory_like(factory: impl FnOnce() -> Box<dyn MemoryLike>) {
11    const PAGE: u64 = 0x10000;
12
13    struct TestContext {
14        mem: Box<dyn MemoryLike>,
15        buf: [u8; PAGE as usize + 1],
16    }
17
18    impl TestContext {
19        fn test_read(&mut self, ptr: u64, len: u64, value: u8) {
20            self.buf.fill(!value);
21            self.mem.fits_memory(MemSlice { ptr, len }).unwrap();
22            self.mem.read_memory(ptr, &mut self.buf[..(len as usize)]).unwrap();
23            assert!(self.buf[..(len as usize)].iter().all(|&v| v == value));
24        }
25
26        fn test_write(&mut self, ptr: u64, len: u64, value: u8) {
27            self.buf.fill(value);
28            self.mem.fits_memory(MemSlice { ptr, len }).unwrap();
29            self.mem.write_memory(ptr, &self.buf[..(len as usize)]).unwrap();
30        }
31
32        fn test_oob(&mut self, ptr: u64, len: u64) {
33            self.buf.fill(42);
34            self.mem.fits_memory(MemSlice { ptr, len }).unwrap_err();
35            self.mem.read_memory(ptr, &mut self.buf[..(len as usize)]).unwrap_err();
36            assert!(self.buf[..(len as usize)].iter().all(|&v| v == 42));
37            self.mem.write_memory(ptr, &self.buf[..(len as usize)]).unwrap_err();
38        }
39    }
40
41    let mut ctx = TestContext { mem: factory(), buf: [0; PAGE as usize + 1] };
42
43    // Test memory is initialised to zero.
44    ctx.test_read(0, PAGE, 0);
45    ctx.test_read(PAGE, 0, 0);
46    ctx.test_read(0, PAGE / 2, 0);
47    ctx.test_read(PAGE / 2, PAGE / 2, 0);
48
49    // Test writing works.
50    ctx.test_write(0, PAGE / 2, 42);
51    ctx.test_read(0, PAGE / 2, 42);
52    ctx.test_read(PAGE / 2, PAGE / 2, 0);
53
54    ctx.test_write(PAGE / 4, PAGE / 4, 24);
55    ctx.test_read(0, PAGE / 4, 42);
56    ctx.test_read(PAGE / 4, PAGE / 4, 24);
57    ctx.test_read(PAGE / 2, PAGE / 2, 0);
58
59    // Zero memory.
60    ctx.test_write(0, PAGE, 0);
61    ctx.test_read(0, PAGE, 0);
62
63    // Test out-of-bounds checks.
64    ctx.test_oob(0, PAGE + 1);
65    ctx.test_oob(1, PAGE);
66    ctx.test_oob(PAGE - 1, 2);
67    ctx.test_oob(PAGE, 1);
68
69    // None of the writes in OOB should have any effect.
70    ctx.test_read(0, PAGE, 0);
71}