code wiki / _hdl_build / nx_apistack_configpush_gate.nx
nx_apistack_configpush_gate.nx source
↩ module page · 45 lines · 3234 B
1// nx_apistack_configpush_gate.nx -- hermetic gate for CAP-API-CONFIGPUSH. Proves apply writes + returns a gen,
2// current-gen tracks the on-disk content, a changed config changes the gen (hot-reload trigger), and same content
3// gives the same gen. expect_exit: 0
4import "nx_syscalls.nx"
5import "nx_apistack_configpush.nx"
6import "nx_gate_verdict.nx"
7
8func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
9func gn(v: i64) -> i64 { var t: i64=v; if t<0{sys_write(1,"-" as *u8,1);t=0-t} let tm:*u8=sys_mmap(24); var k:i64=0; if t==0{tm[0]=48 as u8;k=1} while t>0{tm[k]=(48+(t%10)) as u8;t=t/10;k=k+1} let b:*u8=sys_mmap(24); var j:i64=0; while j<k{b[j]=tm[k-1-j];j=j+1} sys_write(1,b,k); return 0 }
10func g_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
11func g_eq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 }
12
13func main(argc: i64, argv: *i64) -> i64 {
14 gp("=== nx_apistack_configpush_gate (declarative config hot-reload) ===\n" as *u8)
15 let P: *u8 = "/tmp/cp_conf.tsv" as *u8
16 let c1: *u8 = "quota-limit=100\nlog-level=info\n" as *u8; let c1n: i64 = g_slen(c1)
17 let c2: *u8 = "quota-limit=250\nlog-level=debug\n" as *u8; let c2n: i64 = g_slen(c2)
18 var pass: i64 = 0; var fail: i64 = 0
19
20 // T1 apply -> gen matches on-disk current gen
21 let g1: i64 = cp_apply(P, c1, c1n)
22 if cp_current_gen(P) == g1 { pass=pass+1; gp(" T1 apply -> current-gen matches PASS\n" as *u8) } else { fail=fail+1; gp(" T1 FAIL\n" as *u8) }
23
24 // T2 changed config -> changed gen (hot-reload trigger)
25 let g2: i64 = cp_apply(P, c2, c2n)
26 if g2 != g1 { if cp_current_gen(P) == g2 { pass=pass+1; gp(" T2 changed config -> new gen (hot-reload) PASS\n" as *u8) } else { fail=fail+1; gp(" T2 FAIL current\n" as *u8) } } else { fail=fail+1; gp(" T2 FAIL gen unchanged\n" as *u8) }
27
28 // T3 on-disk content is the new config
29 let rb: *u8 = sys_mmap(4096); let rn: i64 = cp_read_file(P, rb, 4096)
30 if rn == c2n { if g_eq(rb, c2, c2n) == 1 { pass=pass+1; gp(" T3 on-disk content == pushed config PASS\n" as *u8) } else { fail=fail+1; gp(" T3 FAIL content\n" as *u8) } } else { fail=fail+1; gp(" T3 FAIL len\n" as *u8) }
31
32 // T4 same content -> same gen (idempotent reload detection)
33 if cp_fnv(c1, c1n) == cp_fnv(c1, c1n) { if cp_fnv(c1, c1n) == g1 { pass=pass+1; gp(" T4 same content -> same gen PASS\n" as *u8) } else { fail=fail+1; gp(" T4 FAIL gen mismatch\n" as *u8) } } else { fail=fail+1; gp(" T4 FAIL nondeterministic\n" as *u8) }
34
35 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail)
36 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
37 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
38 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
39 let ctr__dry: *i64 = gv_ctr()
40 ctr__dry[0] = pass
41 ctr__dry[1] = pass + fail
42 let rc__dry: i64 = gv_verdict("APISTACK-CONFIGPUSH-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
43 sys_exit(rc__dry)
44 return rc__dry
45}