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}