code wiki / (root) / nx_lib_http_test.nx

nx_lib_http_test.nx source

↩ module page · 105 lines · 5020 B

1// nx_lib_http_test.nx -- gate for the sovereign library HTTP router. 2// Proves GET routing + HTTP response building straight from nx_lib_store 3// (no socket needed, no python/sqlite). Exit = failed assertion #. 4import "nx_syscalls.nx" 5import "nx_lib_http.nx" 6 7func lht_has(hay: *u8, hayn: i64, needle: *u8) -> i64 { 8 let nn: i64 = ls_strlen(needle) 9 if nn == 0 { return 1 } 10 if hayn < nn { return 0 } 11 let last: i64 = hayn - nn 12 var i: i64 = 0 13 while i <= last { 14 var j: i64 = 0 15 var st: i64 = 0 16 while st == 0 { 17 if j >= nn { st = 2 } 18 if st == 0 { if hay[i+j] != needle[j] { st = 1 } if st == 0 { j = j + 1 } } 19 } 20 if st == 2 { return 1 } 21 i = i + 1 22 } 23 return 0 24} 25 26func main() -> i64 { 27 let rec: *u8 = "HTTPD Work\t10.7/h\t2026\tcc0" as *u8 28 nx_lib_store_put_work("HTTPDT1" as *u8, rec, ls_strlen(rec)) 29 30 let out: *u8 = sys_mmap(1200000) 31 32 // GET /api/work/<hk> -> 200 + JSON with the title, from the sovereign store 33 let p1: *u8 = "/api/work/HTTPDT1" as *u8 34 let n1: i64 = lhd_response(p1, ls_strlen(p1), out) 35 if n1 <= 0 { return 1 } 36 if lht_has(out, n1, "HTTP/1.1 200 OK" as *u8) != 1 { return 2 } 37 if lht_has(out, n1, "Content-Type: application/json" as *u8) != 1 { return 3 } 38 if lht_has(out, n1, "Content-Length: " as *u8) != 1 { return 4 } 39 if lht_has(out, n1, "\"title\":\"HTTPD Work\"" as *u8) != 1 { return 5 } 40 41 // missing work -> 404 42 let p2: *u8 = "/api/work/NOPE_XX" as *u8 43 let n2: i64 = lhd_response(p2, ls_strlen(p2), out) 44 if lht_has(out, n2, "404 Not Found" as *u8) != 1 { return 6 } 45 46 // GET /api/works -> 200 + JSON array containing the hk 47 let p3: *u8 = "/api/works" as *u8 48 let n3: i64 = lhd_response(p3, ls_strlen(p3), out) 49 if lht_has(out, n3, "HTTP/1.1 200 OK" as *u8) != 1 { return 7 } 50 if lht_has(out, n3, "\"HTTPDT1\"" as *u8) != 1 { return 8 } 51 52 // unknown path -> 404 53 let p4: *u8 = "/nope" as *u8 54 let n4: i64 = lhd_response(p4, ls_strlen(p4), out) 55 if lht_has(out, n4, "404 Not Found" as *u8) != 1 { return 9 } 56 57 // LONG-PATH COVERAGE for the three buffers that lhd_response sizes from path_n (was a fixed 58 // 2048/2048/1024 with an UNBOUNDED copy; LHD_REQ_CAP lets a client send 131072). 59 // πŸ”΄THIS IS NOT A BITE PROOF, AND I MEASURED THAT RATHER THAN ASSUMING IT. Reverting hqbuf to 60 // sys_mmap(2048) and re-running gives 12/12 PASS, run-exit=0 -- THE MUTANT SURVIVES. An ~9000-byte 61 // copy into a 4096-byte mapping lands in the allocator's slack instead of faulting, exactly as the 62 // estate already banked: AN OVERFLOW LANDS ON WHATEVER mmap PUT NEXT -- IT WORKS UNTIL THE NEIGHBOUR 63 // IS UNMAPPED. β˜…β˜…β˜…β˜…β˜…β˜…A TEST THAT READS ONLY THE RESPONSE CANNOT SEE A CORRUPTED NEIGHBOUR, SO IT 64 // CANNOT DISTINGUISH THE FIXED CODE FROM THE BROKEN CODE. 65 // β‡’ What these assertions DO prove is NEUTRALITY: deriving the sizes did not change any route. 66 // β‡’ What makes the fix correct is CONSTRUCTION, not this test: the copy loops are bounded by path_n 67 // and the buffers are path_n+1, so no input can overrun them. 68 // β‡’ OWED, NAMED: a real detector needs a CANARY allocated immediately after the buffer and checked 69 // after the copy (or the runtime's ARENA-OVERRUN guard extended to mmap-sized allocations). Left 70 // undone rather than left implied. 71 let LHT_QN: i64 = 9000 72 let qp: *u8 = sys_mmap(LHT_QN + 8) 73 var qi: i64 = 0 74 qi = 0; qp[qi] = 47 as u8; qi = 1 // '/' 75 qp[qi] = 63 as u8; qi = qi + 1 // '?' 76 qp[qi] = 113 as u8; qi = qi + 1 // 'q' 77 qp[qi] = 61 as u8; qi = qi + 1 // '=' 78 while qi < LHT_QN { qp[qi] = 65 as u8; qi = qi + 1 } // 'A' filler 79 let n5: i64 = lhd_response(qp, qi, out) 80 if n5 <= 0 { return 10 } 81 if lht_has(out, n5, "HTTP/1.1 200 OK" as *u8) != 1 { return 11 } 82 83 // Same shape on the /api/search route, which owns the second of the three resized buffers. 84 let sp: *u8 = sys_mmap(LHT_QN + 32) 85 var si2: i64 = 0 86 let spre: *u8 = "/api/search?q=" as *u8 87 while spre[si2] != (0 as u8) { sp[si2] = spre[si2]; si2 = si2 + 1 } 88 while si2 < LHT_QN { sp[si2] = 66 as u8; si2 = si2 + 1 } 89 let n6: i64 = lhd_response(sp, si2, out) 90 if n6 <= 0 { return 12 } 91 if lht_has(out, n6, "HTTP/1.1 200 OK" as *u8) != 1 { return 13 } 92 93 // And the /api/work/<hk> route, which owns the third (was sys_mmap(1024)). 94 let wp: *u8 = sys_mmap(LHT_QN + 32) 95 var wi: i64 = 0 96 let wpre: *u8 = "/api/work/" as *u8 97 while wpre[wi] != (0 as u8) { wp[wi] = wpre[wi]; wi = wi + 1 } 98 while wi < LHT_QN { wp[wi] = 67 as u8; wi = wi + 1 } 99 let n7: i64 = lhd_response(wp, wi, out) 100 if lht_has(out, n7, "404 Not Found" as *u8) != 1 { return 14 } 101 102 let msg: *u8 = "nx_lib_http: 12/12 sovereign HTTP-route assertions PASS (GET /api/work,/api/works from nx_lib_store; no python/sqlite)\n" as *u8 103 sys_write(1, msg, ls_strlen(msg)) 104 return 0 105}