code wiki / _hdl_build / nx_site_search_gate.nx
nx_site_search_gate.nx source
↩ module page · 105 lines · 7222 B
1// nx_site_search_gate.nx -- MEASURED gate for the live /search endpoint handler (nx_site_search). Self-contained:
2// builds a small PERSISTED onsite index + manifest (the 4 andelinwest practice areas) in-process, then drives the
3// pure handler sr_handle with crafted GET /search?q=... requests and asserts the rendered results page:
4// T1 q=divorce -> 200, links /practice/family-law ("Family Law"), 1 result
5// T2 q=will -> Estate Planning (/practice/estate-planning)
6// T3 q=zzznomatch-> 0 results (graceful)
7// T4 q=divorce+injury -> 2 results (family-law + personal-injury), multi-term union
8// T5 the search form echoes the query back (sticky input)
9// GREEN iff 5/5. Appends knowledge/status/site_search_gate.log. license_tier: ORIGINAL
10import "nx_site_search.nx"
11
12func g_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
13func g_num(v: i64) -> i64 {
14 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) }
15 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 }
16 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
17 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0
18}
19func g_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
20func g_wn(fd: i64, v: i64) -> i64 {
21 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m }
22 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 }
23 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
24 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(fd, bb, k); return 0
25}
26func g_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
27func g_contains(hay: *u8, n: i64, ndl: *u8) -> i64 {
28 let nl: i64 = g_slen(ndl); if nl == 0 { return 0 }
29 var i: i64 = 0
30 while i + nl <= n { var j: i64 = 0; var hit: i64 = 1; while j < nl { if hay[i + j] != ndl[j] { hit = 0; j = nl } else { j = j + 1 } } if hit == 1 { return 1 } i = i + 1 }
31 return 0
32}
33func g_mkreq(out: *u8, s: *u8) -> i64 { var o: i64 = 0; while s[o] != (0 as u8) { out[o] = s[o]; o = o + 1 } return o }
34
35func main() -> i64 {
36 g_puts("=== SITE SEARCH GATE (live /search endpoint: query -> branded results over the real index) ===\n" as *u8)
37 let idxp: *u8 = "knowledge/index/srtest.idx" as *u8
38 let manp: *u8 = "knowledge/index/srtest.manifest" as *u8
39
40 // build the 4-practice index (docid = line) + the aligned manifest
41 let t0: *u8 = "divorce custody support family law" as *u8
42 let t1: *u8 = "will testament probate trust estate" as *u8
43 let t2: *u8 = "contract formation dispute business" as *u8
44 let t3: *u8 = "injury accident insurance personal" as *u8
45 let idx: *NxInvIndex = nx_inv_new_sized(2048)
46 nx_inv_index_row(idx, t0, g_slen(t0), 0); nx_inv_index_row(idx, t1, g_slen(t1), 1); nx_inv_index_row(idx, t2, g_slen(t2), 2); nx_inv_index_row(idx, t3, g_slen(t3), 3)
47 idx.n_rows = 4
48 nx_inv_finalize_offsets(idx)
49 nx_inv_emit_row(idx, t0, g_slen(t0), 0); nx_inv_emit_row(idx, t1, g_slen(t1), 1); nx_inv_emit_row(idx, t2, g_slen(t2), 2); nx_inv_emit_row(idx, t3, g_slen(t3), 3)
50 if nx_inv_save(idx, idxp) != NX_INV_OK { g_puts("GATE-FAIL: index save\n" as *u8); sys_exit(1); return 1 }
51 let mfd: i64 = sys_openat_wr(manp, 0x1a4)
52 if mfd < 0 { g_puts("GATE-FAIL: manifest open\n" as *u8); sys_exit(1); return 1 }
53 g_w(mfd, "/practice/family-law\tFamily Law\t" as *u8); g_w(mfd, t0); g_w(mfd, "\n" as *u8)
54 g_w(mfd, "/practice/estate-planning\tEstate Planning\t" as *u8); g_w(mfd, t1); g_w(mfd, "\n" as *u8)
55 g_w(mfd, "/practice/business-law\tBusiness Law\t" as *u8); g_w(mfd, t2); g_w(mfd, "\n" as *u8)
56 g_w(mfd, "/practice/personal-injury\tPersonal Injury\t" as *u8); g_w(mfd, t3); g_w(mfd, "\n" as *u8)
57 sys_close(mfd)
58
59 let base: *u8 = "https://andelinwest.com" as *u8
60 let firm: *u8 = "Andelin West" as *u8
61 let req: *u8 = sys_mmap(4096)
62 let out: *u8 = sys_mmap(262144)
63 var pass: i64 = 0
64
65 let n1: i64 = g_mkreq(req, "GET /search?q=divorce HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
66 let o1: i64 = sr_handle(req, n1, idxp, manp, base, firm, out)
67 var c1: i64 = 0
68 if g_contains(out, o1, "200 OK" as *u8) == 1 { if g_contains(out, o1, "/practice/family-law" as *u8) == 1 { if g_contains(out, o1, "1 result" as *u8) == 1 { c1 = 1 } } }
69 pass = pass + c1; g_puts(" T1 q=divorce -> family-law, 1 result: "); if c1 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
70
71 let n2: i64 = g_mkreq(req, "GET /search?q=will HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
72 let o2: i64 = sr_handle(req, n2, idxp, manp, base, firm, out)
73 var c2: i64 = 0
74 if g_contains(out, o2, "/practice/estate-planning" as *u8) == 1 { if g_contains(out, o2, "Estate Planning" as *u8) == 1 { c2 = 1 } }
75 pass = pass + c2; g_puts(" T2 q=will -> estate-planning: "); if c2 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
76
77 let n3: i64 = g_mkreq(req, "GET /search?q=zzznomatch HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
78 let o3: i64 = sr_handle(req, n3, idxp, manp, base, firm, out)
79 var c3: i64 = 0
80 if g_contains(out, o3, "0 results" as *u8) == 1 { c3 = 1 }
81 pass = pass + c3; g_puts(" T3 q=zzznomatch -> 0 results (graceful): "); if c3 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
82
83 let n4: i64 = g_mkreq(req, "GET /search?q=divorce+injury HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
84 let o4: i64 = sr_handle(req, n4, idxp, manp, base, firm, out)
85 var c4: i64 = 0
86 if g_contains(out, o4, "2 results" as *u8) == 1 { if g_contains(out, o4, "family-law" as *u8) == 1 { if g_contains(out, o4, "personal-injury" as *u8) == 1 { c4 = 1 } } }
87 pass = pass + c4; g_puts(" T4 q=divorce+injury -> 2 results (multi-term): "); if c4 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
88
89 let n5: i64 = g_mkreq(req, "GET /search?q=divorce HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
90 let o5: i64 = sr_handle(req, n5, idxp, manp, base, firm, out)
91 var c5: i64 = 0
92 if g_contains(out, o5, "value=\"divorce\"" as *u8) == 1 { c5 = 1 }
93 pass = pass + c5; g_puts(" T5 search form echoes the query (sticky): "); if c5 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) }
94
95 g_puts("----\nSITE-SEARCH rows=5 pass="); g_num(pass); g_puts("\n" as *u8)
96 let lg: i64 = sys_openat_append("knowledge/status/site_search_gate.log" as *u8, 0x1a4)
97 if lg >= 0 {
98 g_w(lg, "SITE-SEARCH q_divorce="); g_wn(lg, c1); g_w(lg, " q_will="); g_wn(lg, c2); g_w(lg, " no_match="); g_wn(lg, c3)
99 g_w(lg, " multi_term="); g_wn(lg, c4); g_w(lg, " sticky="); g_wn(lg, c5); g_w(lg, " rows=5 pass="); g_wn(lg, pass)
100 if pass == 5 { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) }
101 sys_close(lg)
102 }
103 if pass == 5 { g_puts("SITE-SEARCH GREEN (live /search: query->branded results over the real onsite index -- measured)\n" as *u8); sys_exit(0); return 0 }
104 g_puts("SITE-SEARCH RED\n" as *u8); sys_exit(1); return 1
105}