code wiki / (root) / nx_blob_store_mcu_test.nx

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}