nx_blob_store_mcu_test.nx source
↩ module page · 158 lines · 7074 B
1// nx_blob_store_mcu_test.nx -- smoke for MCU-tier blob_store variant.
2//
3// Exercises:
4// 1. Allocation + canary + initial state
5// 2. Put + get roundtrip on a known sequence
6// 3. DEDUP: same bytes twice -> same hash + count unchanged
7// 4. Distinct bytes -> distinct hashes
8// 5. has_blob positive + negative
9// 6. SHA-256 determinism across two MCU stores
10// 7. Bad-input gates (null bytes with len>0, negative len, null
11// out_hash, null hash on get, null out_buf, undersized buffer)
12// 8. MCU-specific OVERSIZED GATE: blob > 256 bytes -> NX_BLOB_MCU_TOO_BIG
13// 9. CAPACITY GATE: put 4 distinct + try 5th -> NX_BLOB_MCU_FULL
14// 10. TAMPER detection: canary stomp -> ops refuse
15// 11. Empty-blob roundtrip + dedup
16// 12. Sealed-enum verdict gate
17
18import "nx_syscalls.nx"
19import "nx_blob_store.nx" // NxBlobHash + nx_blob_hash_new + nx_blob_hash_eq
20import "nx_blob_store_mcu.nx"
21
22func _fill(buf: *u8, len: i64, seed: i64) -> i64 {
23 var i: i64 = 0
24 while i < len {
25 buf[i] = (((i * 23) + seed) & 255) as u8
26 i = i + 1
27 }
28 return 0
29}
30
31func main() -> i64 {
32 let store: *NxBlobStoreMcu = nx_blob_store_mcu_new()
33
34 // ----- 1. Initial state -----
35 if nx_blob_store_mcu_is_valid(store) != 1 { return 1 }
36 if nx_blob_store_mcu_count(store) != 0 { return 2 }
37 if store.max_entries != NX_BLOB_STORE_MCU_CAPACITY { return 3 }
38
39 // ----- 2. Put + get roundtrip -----
40 let p1: *u8 = sys_mmap(64)
41 _fill(p1, 32, 1)
42 let h1: *NxBlobHash = nx_blob_hash_new()
43 if nx_blob_store_mcu_put(store, p1, 32, h1) != NX_BLOB_MCU_OK { return 4 }
44 if nx_blob_store_mcu_count(store) != 1 { return 5 }
45 let o1: *u8 = sys_mmap(64)
46 let n1: i64 = nx_blob_store_mcu_get(store, h1, o1, 64)
47 if n1 != 32 { return 6 }
48 var k: i64 = 0
49 while k < 32 {
50 if (o1[k] as i64) != (p1[k] as i64) { return 7 }
51 k = k + 1
52 }
53
54 // ----- 3. DEDUP -----
55 let h1_dup: *NxBlobHash = nx_blob_hash_new()
56 if nx_blob_store_mcu_put(store, p1, 32, h1_dup) != NX_BLOB_MCU_OK { return 8 }
57 if nx_blob_store_mcu_count(store) != 1 { return 9 }
58 if nx_blob_hash_eq(h1, h1_dup) != 1 { return 10 }
59
60 // ----- 4. Distinct -----
61 let p2: *u8 = sys_mmap(64)
62 _fill(p2, 32, 2)
63 let h2: *NxBlobHash = nx_blob_hash_new()
64 if nx_blob_store_mcu_put(store, p2, 32, h2) != NX_BLOB_MCU_OK { return 11 }
65 if nx_blob_store_mcu_count(store) != 2 { return 12 }
66 if nx_blob_hash_eq(h1, h2) != 0 { return 13 }
67
68 // ----- 5. has_blob -----
69 if nx_blob_store_mcu_has(store, h1) != 1 { return 14 }
70 if nx_blob_store_mcu_has(store, h2) != 1 { return 15 }
71 let h_missing: *NxBlobHash = nx_blob_hash_new()
72 h_missing.w0 = 0xCAFE
73 if nx_blob_store_mcu_has(store, h_missing) != 0 { return 16 }
74
75 // ----- 6. Determinism across stores -----
76 let store_b: *NxBlobStoreMcu = nx_blob_store_mcu_new()
77 let h1_b: *NxBlobHash = nx_blob_hash_new()
78 if nx_blob_store_mcu_put(store_b, p1, 32, h1_b) != NX_BLOB_MCU_OK { return 17 }
79 if nx_blob_hash_eq(h1, h1_b) != 1 { return 18 }
80
81 // ----- 7. Bad-input gates -----
82 let null_bytes: *u8 = (0 as i64) as *u8
83 let scratch_h: *NxBlobHash = nx_blob_hash_new()
84 if nx_blob_store_mcu_put(store, null_bytes, 1, scratch_h) != NX_BLOB_MCU_BAD_INPUT { return 19 }
85 if nx_blob_store_mcu_put(store, p1, -1, scratch_h) != NX_BLOB_MCU_BAD_INPUT { return 20 }
86 let null_h: *NxBlobHash = (0 as i64) as *NxBlobHash
87 if nx_blob_store_mcu_put(store, p1, 32, null_h) != NX_BLOB_MCU_BAD_INPUT { return 21 }
88 let scratch_out: *u8 = sys_mmap(64)
89 if nx_blob_store_mcu_get(store, null_h, scratch_out, 64) != -1 { return 22 }
90 if nx_blob_store_mcu_get(store, h1, null_bytes, 64) != -1 { return 23 }
91 let tiny_out: *u8 = sys_mmap(16)
92 if nx_blob_store_mcu_get(store, h1, tiny_out, 16) != -1 { return 24 }
93
94 // ----- 8. MCU-specific OVERSIZED GATE -----
95 let huge: *u8 = sys_mmap(1024)
96 _fill(huge, 512, 7)
97 let huge_h: *NxBlobHash = nx_blob_hash_new()
98 if nx_blob_store_mcu_put(store, huge, 257, huge_h) != NX_BLOB_MCU_TOO_BIG { return 25 }
99 if nx_blob_store_mcu_put(store, huge, 512, huge_h) != NX_BLOB_MCU_TOO_BIG { return 26 }
100 // Exactly 256 bytes is permitted.
101 if nx_blob_store_mcu_put(store, huge, 256, huge_h) != NX_BLOB_MCU_OK { return 27 }
102 if nx_blob_store_mcu_count(store) != 3 { return 28 }
103
104 // ----- 9. CAPACITY GATE -----
105 // Store currently has 3 entries (h1 + h2 + 256-byte huge).
106 // Add 1 more distinct -> count = 4 (capacity). Try 5th -> FULL.
107 let p4: *u8 = sys_mmap(64)
108 _fill(p4, 32, 4)
109 let h4: *NxBlobHash = nx_blob_hash_new()
110 if nx_blob_store_mcu_put(store, p4, 32, h4) != NX_BLOB_MCU_OK { return 29 }
111 if nx_blob_store_mcu_count(store) != 4 { return 30 }
112
113 let p5: *u8 = sys_mmap(64)
114 _fill(p5, 32, 5)
115 let h5: *NxBlobHash = nx_blob_hash_new()
116 if nx_blob_store_mcu_put(store, p5, 32, h5) != NX_BLOB_MCU_FULL { return 31 }
117 if nx_blob_store_mcu_count(store) != 4 { return 32 } // unchanged on FULL
118
119 // Dedup of existing entry still works at capacity (no new slot
120 // consumed).
121 let h1_again: *NxBlobHash = nx_blob_hash_new()
122 if nx_blob_store_mcu_put(store, p1, 32, h1_again) != NX_BLOB_MCU_OK { return 33 }
123 if nx_blob_store_mcu_count(store) != 4 { return 34 }
124
125 // ----- 10. TAMPER -----
126 let tamper_store: *NxBlobStoreMcu = nx_blob_store_mcu_new()
127 let tp: *u8 = sys_mmap(32)
128 _fill(tp, 16, 8)
129 let th: *NxBlobHash = nx_blob_hash_new()
130 nx_blob_store_mcu_put(tamper_store, tp, 16, th)
131 tamper_store.canary_post = 0xDEADBEEF
132 if nx_blob_store_mcu_is_valid(tamper_store) != 0 { return 35 }
133 let scratch_h2: *NxBlobHash = nx_blob_hash_new()
134 if nx_blob_store_mcu_put(tamper_store, tp, 16, scratch_h2) != NX_BLOB_MCU_TAMPER { return 36 }
135 if nx_blob_store_mcu_get(tamper_store, th, scratch_out, 64) != -1 { return 37 }
136 if nx_blob_store_mcu_has(tamper_store, th) != 0 { return 38 }
137 if nx_blob_store_mcu_count(tamper_store) != -1 { return 39 }
138
139 // ----- 11. Empty-blob -----
140 let empty_store: *NxBlobStoreMcu = nx_blob_store_mcu_new()
141 let empty_buf: *u8 = sys_mmap(8)
142 let empty_h: *NxBlobHash = nx_blob_hash_new()
143 if nx_blob_store_mcu_put(empty_store, empty_buf, 0, empty_h) != NX_BLOB_MCU_OK { return 40 }
144 if nx_blob_store_mcu_count(empty_store) != 1 { return 41 }
145 let empty_out: *u8 = sys_mmap(8)
146 if nx_blob_store_mcu_get(empty_store, empty_h, empty_out, 8) != 0 { return 42 }
147 let empty_h_dup: *NxBlobHash = nx_blob_hash_new()
148 if nx_blob_store_mcu_put(empty_store, empty_buf, 0, empty_h_dup) != NX_BLOB_MCU_OK { return 43 }
149 if nx_blob_store_mcu_count(empty_store) != 1 { return 44 }
150 if nx_blob_hash_eq(empty_h, empty_h_dup) != 1 { return 45 }
151
152 // ----- 12. Sealed-enum verdict gate -----
153 if nx_blob_mcu_verdict_is_valid(NX_BLOB_MCU_OK) != 1 { return 46 }
154 if nx_blob_mcu_verdict_is_valid(-1) != 0 { return 47 }
155 if nx_blob_mcu_verdict_is_valid(NX_BLOB_MCU_N_VERDICTS) != 0 { return 48 }
156
157 return 0
158}