code wiki / _hdl_build / nx_apm_collect_gate.nx

nx_apm_collect_gate.nx source

↩ module page · 103 lines · 6271 B

1// nx_apm_collect_gate.nx -- SOVEREIGN gate for the internal-HTTP APM collector. 2// 3// Spawns real mock daemons (nx_apm_mock, self-terminating) on loopback and proves ac_burst's four verdicts 4// against ground truth -- each test prints its MEASURED numbers (no overclaim: the operator reads the raw 5// stats, not a curated "GREEN"): 6// T1 NEGATIVE CONTROL -- a healthy fast daemon must be GREEN, fully served, nothing flagged. 7// T2 DETECTION -- a daemon that SERIALIZES (300ms/req) must, under 8 concurrent probes, show a 8// stall and max >= ~2400ms = the "tabs don't load" wedge, caught. 9// T3 LIAR-KILL -- an ABSENT daemon (no listener) must be DOWN with oks=0, never GREEN. 10// T4 GRACEFUL DEGRADE -- a daemon slower than the probe timeout must time out (~1s) not hang forever. 11// T5 ARTIFACT-IMMUNITY -- a daemon that sends FAST then HOLDS the socket open (keep-alive/idle) must be 12// GREEN (ttfb fast) with slowclose>0 -- NOT a false wedge. This is THE fix: the 13// live :8791/vroom "20s" was exactly this (ttfb~0, total~20-25s), an artifact. 14// 15// Requires /tmp/nx_apm_mock.sov.elf built first. Per-test reap; no kill primitive needed. license_tier: ORIGINAL 16import "nx_syscalls.nx" 17import "nx_apm_collect.nx" // ac_burst + AC_R_* + ac_n 18 19const GE_MOCK: *u8 = "_offc/nx_apm_mock.elf" 20 21func ge_uw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 22func ge_wn(v: i64) -> i64 { let b: *u8 = sys_mmap(24); let e: i64 = ac_n(b, 0, v); sys_write(1, b, e); return 0 } 23func ge_itoa(v: i64) -> *u8 { let b: *u8 = sys_mmap(24); let e: i64 = ac_n(b, 0, v); b[e] = 0 as u8; return b } 24 25// fork + execve the mock with (port, delay_ms, hold_ms, max_reqs) as string args; returns pid. 26func ge_spawn_mock(port: i64, delay: i64, hold: i64, maxr: i64) -> i64 { 27 let pid: i64 = sys_fork() 28 if pid == 0 { 29 let av: *i64 = sys_mmap(8 * 6) as *i64 30 av[0] = GE_MOCK as i64 31 av[1] = ge_itoa(port) as i64 32 av[2] = ge_itoa(delay) as i64 33 av[3] = ge_itoa(hold) as i64 34 av[4] = ge_itoa(maxr) as i64 35 av[5] = 0 36 let ev: *i64 = sys_mmap(8) as *i64; ev[0] = 0 37 sys_execve(GE_MOCK, av, ev); sys_exit(127) 38 } 39 return pid 40} 41 42func main(argc: i64, argv: *i64) -> i64 { 43 var pass: i64 = 0; var total: i64 = 0 44 let out: *i64 = sys_mmap(8 * 12) as *i64 45 let rp: *i64 = sys_mmap(16) as *i64 46 let epoch: i64 = sys_now_realtime_sec() 47 48 // ---- T1: healthy fast daemon (NEGATIVE CONTROL) ---- 49 let pA: i64 = ge_spawn_mock(18091, 0, 0, 8) 50 sys_sleep_ms(300) 51 let cA: i64 = ac_burst(18091, "/" as *u8, "mock-fast" as *u8, 8, 22, epoch, 0x7f000001, out) 52 total = total + 1 53 var okA: i64 = 0 54 if cA == AC_R_GREEN { if out[3] == 8 { if out[4] == 0 { okA = 1 } } } 55 if okA == 1 { pass = pass + 1; ge_uw("[PASS] " as *u8) } else { ge_uw("[FAIL] " as *u8) } 56 ge_uw("T1 healthy(neg-control): code=" as *u8); ge_wn(cA); ge_uw(" oks=" as *u8); ge_wn(out[3]); ge_uw(" p50=" as *u8); ge_wn(out[0]); ge_uw(" max=" as *u8); ge_wn(out[2]); ge_uw("ms stalls=" as *u8); ge_wn(out[4]); ge_uw(" (want GREEN, oks=8, stalls=0)\n" as *u8) 57 sys_wait4(pA, rp, 0) 58 59 // ---- T2: serializing daemon under 8 concurrent probes (DETECTION) ---- 60 let pB: i64 = ge_spawn_mock(18092, 300, 0, 8) 61 sys_sleep_ms(300) 62 let cB: i64 = ac_burst(18092, "/library" as *u8, "mock-wedge" as *u8, 8, 22, epoch, 0x7f000001, out) 63 total = total + 1 64 var okB: i64 = 0 65 if cB >= AC_R_AMBER { if out[4] > 0 { if out[2] >= 2000 { okB = 1 } } } 66 if okB == 1 { pass = pass + 1; ge_uw("[PASS] " as *u8) } else { ge_uw("[FAIL] " as *u8) } 67 ge_uw("T2 serial-wedge(detect): code=" as *u8); ge_wn(cB); ge_uw(" p50=" as *u8); ge_wn(out[0]); ge_uw(" max=" as *u8); ge_wn(out[2]); ge_uw("ms stalls=" as *u8); ge_wn(out[4]); ge_uw(" (want >=AMBER, stalls>0, max>=2000ms)\n" as *u8) 68 sys_wait4(pB, rp, 0) 69 70 // ---- T3: absent daemon, no listener (LIAR-KILL) ---- 71 let cC: i64 = ac_burst(18094, "/" as *u8, "mock-absent" as *u8, 4, 22, epoch, 0x7f000001, out) 72 total = total + 1 73 var okC: i64 = 0 74 if cC == AC_R_DOWN { if out[3] == 0 { okC = 1 } } 75 if okC == 1 { pass = pass + 1; ge_uw("[PASS] " as *u8) } else { ge_uw("[FAIL] " as *u8) } 76 ge_uw("T3 absent(liar-kill): code=" as *u8); ge_wn(cC); ge_uw(" oks=" as *u8); ge_wn(out[3]); ge_uw(" down=" as *u8); ge_wn(out[6]); ge_uw(" (want DOWN, oks=0)\n" as *u8) 77 78 // ---- T4: daemon slower than the probe timeout (GRACEFUL DEGRADATION) ---- 79 let pD: i64 = ge_spawn_mock(18093, 3000, 0, 1) 80 sys_sleep_ms(300) 81 let cD: i64 = ac_burst(18093, "/" as *u8, "mock-hang" as *u8, 1, 1, epoch, 0x7f000001, out) 82 total = total + 1 83 var okD: i64 = 0 84 if cD == AC_R_RED { if out[5] >= 1 { if out[2] < 3000 { okD = 1 } } } 85 if okD == 1 { pass = pass + 1; ge_uw("[PASS] " as *u8) } else { ge_uw("[FAIL] " as *u8) } 86 ge_uw("T4 hang(timeout/grace): code=" as *u8); ge_wn(cD); ge_uw(" timeouts=" as *u8); ge_wn(out[5]); ge_uw(" max=" as *u8); ge_wn(out[2]); ge_uw("ms (want RED, timeouts>=1, max<3000ms i.e. it gave up at ~1s)\n" as *u8) 87 sys_wait4(pD, rp, 0) 88 89 // ---- T5: fast-then-HOLD daemon = keep-alive/idle-close ARTIFACT (the live :8791 + vroom :8446 case) ---- 90 let pE: i64 = ge_spawn_mock(18095, 0, 4000, 1) 91 sys_sleep_ms(300) 92 let cE: i64 = ac_burst(18095, "/" as *u8, "mock-artifact" as *u8, 1, 22, epoch, 0x7f000001, out) 93 total = total + 1 94 var okE: i64 = 0 95 if cE == AC_R_GREEN { if out[9] >= 1 { if out[2] < 2000 { if out[8] >= 3000 { okE = 1 } } } } 96 if okE == 1 { pass = pass + 1; ge_uw("[PASS] " as *u8) } else { ge_uw("[FAIL] " as *u8) } 97 ge_uw("T5 fast-then-hold(artifact-immune): code=" as *u8); ge_wn(cE); ge_uw(" ttfb_max=" as *u8); ge_wn(out[2]); ge_uw("ms total_max=" as *u8); ge_wn(out[8]); ge_uw("ms slowclose=" as *u8); ge_wn(out[9]); ge_uw(" (want GREEN, ttfb<2000, total>=3000, slowclose>=1)\n" as *u8) 98 sys_wait4(pE, rp, 0) 99 100 ge_uw("=== nx_apm_collect_gate " as *u8); ge_wn(pass); ge_uw("/" as *u8); ge_wn(total) 101 if pass == total { ge_uw(" GREEN\n" as *u8); return 0 } 102 ge_uw(" RED\n" as *u8); return 1 103}