Skip to main content

javm_guest_tests/tests/
memory.rs

1//! Memory and control-flow test vectors.
2//!
3//! `memcpy_test` and `sort_u32` produce variable-length byte output;
4//! `fib` returns a single u64. The `_suite()` fns XOR-fold each
5//! op's output bytes (interpreted as u64 stride where appropriate)
6//! into a single fingerprint.
7
8use crate::{fold_bytes_to_u64, read_u32, write_u64};
9
10const MEMCPY_INPUTS: &[&[u8]] = &[
11    &[],
12    &[0xAA],
13    &[0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04],
14    b"abcdefghijklmnopqrstuvwxyz",
15];
16
17const SORT_INPUTS: &[&[u32]] = &[
18    &[],
19    &[42],
20    &[3, 1, 2],
21    &[u32::MAX, 0, 100_000, 7, 7, 0],
22    &[5, 4, 3, 2, 1, 0, u32::MAX / 2, u32::MAX],
23];
24
25const FIB_INDICES: &[u32] = &[0, 1, 2, 3, 10, 20, 50, 90];
26
27// -- Byte-level helpers --------------------------------------------------------
28
29/// Copy input bytes to output (exercises load/store patterns).
30pub fn memcpy_test(input: &[u8], output: &mut [u8]) -> usize {
31    let len = input.len();
32    let mut i = 0;
33    while i < len {
34        output[i] = input[i];
35        i += 1;
36    }
37    len
38}
39
40/// Sort an array of u32 LE values via insertion sort.
41pub fn sort_u32(input: &[u8], output: &mut [u8]) -> usize {
42    let n = input.len() / 4;
43    output[..input.len()].copy_from_slice(input);
44
45    let mut i = 1;
46    while i < n {
47        let key = u32::from_le_bytes(output[i * 4..(i + 1) * 4].try_into().unwrap());
48        let mut j = i;
49        while j > 0 {
50            let prev = u32::from_le_bytes(output[(j - 1) * 4..j * 4].try_into().unwrap());
51            if prev <= key {
52                break;
53            }
54            output[j * 4..(j + 1) * 4].copy_from_slice(&prev.to_le_bytes());
55            j -= 1;
56        }
57        output[j * 4..(j + 1) * 4].copy_from_slice(&key.to_le_bytes());
58        i += 1;
59    }
60    n * 4
61}
62
63/// Iterative Fibonacci. Input: n as u32 LE; output: fib(n) as u64 LE.
64pub fn fib(input: &[u8], output: &mut [u8]) -> usize {
65    let mut off = 0;
66    let n = read_u32(input, &mut off);
67
68    let result = if n == 0 {
69        0u64
70    } else {
71        let mut a: u64 = 0;
72        let mut b: u64 = 1;
73        let mut i = 1u32;
74        while i < n {
75            let next = a.wrapping_add(b);
76            a = b;
77            b = next;
78            i += 1;
79        }
80        b
81    };
82    let mut out = 0;
83    write_u64(output, &mut out, result);
84    out
85}
86
87// -- Suites --------------------------------------------------------------------
88
89pub fn memcpy_test_suite() -> u64 {
90    let mut acc = 0u64;
91    let mut buf = [0u8; 64];
92    for input in MEMCPY_INPUTS {
93        let len = memcpy_test(input, &mut buf);
94        acc ^= fold_bytes_to_u64(&buf[..len]);
95        acc = acc.wrapping_add(len as u64); // cardinality fold
96    }
97    acc
98}
99
100pub fn sort_u32_suite() -> u64 {
101    let mut acc = 0u64;
102    let mut input_bytes = [0u8; 64];
103    let mut output_bytes = [0u8; 64];
104    for vals in SORT_INPUTS {
105        let in_len = vals.len() * 4;
106        for (i, v) in vals.iter().enumerate() {
107            input_bytes[i * 4..(i + 1) * 4].copy_from_slice(&v.to_le_bytes());
108        }
109        let out_len = sort_u32(&input_bytes[..in_len], &mut output_bytes);
110        debug_assert_eq!(out_len, in_len);
111        acc ^= fold_bytes_to_u64(&output_bytes[..out_len]);
112        acc = acc.wrapping_add(out_len as u64);
113    }
114    acc
115}
116
117pub fn fib_suite() -> u64 {
118    let mut acc = 0u64;
119    let mut input = [0u8; 4];
120    let mut output = [0u8; 8];
121    for n in FIB_INDICES {
122        input.copy_from_slice(&n.to_le_bytes());
123        let len = fib(&input, &mut output);
124        debug_assert!(len == 8);
125        acc ^= u64::from_le_bytes(output);
126    }
127    acc
128}