code wiki / (root) / nx_arena_scope_test.nx

nx_arena_scope_test.nx source

↩ module page · 111 lines · 4271 B

1// nx_arena_scope_test.nx -- smoke for mark/reset-to-mark + ceiling. 2// 3// Verifies the SSS-class behaviour that closes the arena issue from 4// NISHI_HONEST_TRADE_OFFS.md: nested workloads can scope their 5// allocations without accumulating across loop iterations. 6// 7// Construct the NxArena manually from a caller-provided buffer 8// (per user directive "user owns every bit") rather than calling 9// nx_arena_new which mmaps internally. This keeps the smoke 10// cross-target portable -- the test doesn't depend on a particular 11// syscall set. 12// 13// expect_exit: 0 14// 15// license_tier: ORIGINAL 16 17// Caller-chosen syscall layer (x86_64 native exec). Composes against 18// nx_arena_types.nx which carries NO syscall import. This is the 19// four-pillar FIX 2026-05-16 for the F-meta-4 cross-target gap: types 20// + alloc/reset/inspect live in nx_arena_types.nx (no deps), the 21// caller picks whichever syscall layer matches its target ABI. 22import "nx_syscalls_x86_64.nx" 23import "nx_arena_types.nx" 24import "nx_arena_scope.nx" 25 26func main() -> i64 { 27 // ---- Sealed-enum gate ----------------------------------------- 28 if nx_arena_verdict_is_valid(NX_ARENA_OK) != 1 { return 1 } 29 if nx_arena_verdict_is_valid(NX_ARENA_OOM_CEILING) != 1 { return 2 } 30 if nx_arena_verdict_is_valid(NX_ARENA_OOM_CAP) != 1 { return 3 } 31 if nx_arena_verdict_is_valid(NX_ARENA_BAD_MARK) != 1 { return 4 } 32 if nx_arena_verdict_is_valid(NX_ARENA_BAD_ARG) != 1 { return 5 } 33 if nx_arena_verdict_is_valid(NX_ARENA_N) != 0 { return 6 } 34 if nx_arena_verdict_is_valid(-1) != 0 { return 7 } 35 36 // ---- Construct arena from user-owned buffer ------------------- 37 // User-controlled allocation: 64 KB backing buffer via x86_64 38 // sys_mmap. The substrate doesn't reserve; the user requests. 39 let backing: *u8 = sys_mmap(65536) 40 let arena_raw: *u8 = sys_mmap(NX_ARENA_BYTES) 41 let a: *NxArena = arena_raw as *NxArena 42 a.base = backing 43 a.cap = 65536 44 a.off = 0 45 a.n_alloc = 0 46 a.n_oom = 0 47 48 if nx_arena_used(a) != 0 { return 11 } 49 if nx_arena_headroom_bytes(a) != 65536 { return 12 } 50 51 // ---- Mark + reset-to-mark cycle ------------------------------ 52 let mark0: i64 = nx_arena_mark(a) 53 if mark0 != 0 { return 20 } 54 55 // Bump the offset manually (simulating an allocation) 56 a.off = 1024 57 58 let mark1: i64 = nx_arena_mark(a) 59 if mark1 != 1024 { return 21 } 60 61 let v: *i64 = sys_mmap(8) as *i64 62 63 // Reset to mark0: rewinds to 0 64 nx_arena_reset_to_mark(a, mark0, v) 65 if v[0] != NX_ARENA_OK { return 22 } 66 if nx_arena_used(a) != 0 { return 23 } 67 68 // ---- Daemon-style nested-scope simulation -------------------- 69 // "Daemon startup" -- allocate 1 KB of long-lived state. 70 a.off = 1024 71 let after_startup: i64 = nx_arena_used(a) 72 73 // Tick loop: 100 iterations, each does +4 KB then resets to mark 74 var tick: i64 = 0 75 while tick < 100 { 76 let mark: i64 = nx_arena_mark(a) 77 if mark != after_startup { return 30 + tick } 78 // simulate tick-scoped 4 KB scratch 79 a.off = a.off + 4096 80 // reset to mark 81 nx_arena_reset_to_mark(a, mark, v) 82 if v[0] != NX_ARENA_OK { return 400 + tick } 83 if nx_arena_used(a) != mark { return 600 + tick } 84 tick = tick + 1 85 } 86 87 // After 100 ticks: arena offset still equals after_startup 88 if nx_arena_used(a) != after_startup { return 800 } 89 90 // ---- BAD_MARK paths ------------------------------------------- 91 // mark > current off (would expose stale): refuse 92 let bad_mark: i64 = nx_arena_used(a) + 1000 93 nx_arena_reset_to_mark(a, bad_mark, v) 94 if v[0] != NX_ARENA_BAD_MARK { return 930 } 95 96 // negative mark: refuse 97 nx_arena_reset_to_mark(a, -1, v) 98 if v[0] != NX_ARENA_BAD_MARK { return 931 } 99 100 // ---- Ceiling check (would_fit observer) ---------------------- 101 if nx_arena_would_fit(a, 1024, 8, 8192) != 1 { return 940 } 102 if nx_arena_would_fit(a, 8192, 8, 1024) != 0 { return 941 } 103 // observer didn't mutate 104 if nx_arena_used(a) != after_startup { return 942 } 105 106 // ---- Headroom observer --------------------------------------- 107 let head: i64 = nx_arena_headroom_bytes(a) 108 if head != 65536 - after_startup { return 950 } 109 110 return 0 111}