code wiki / _hdl_build / nx_synth_serve_gate.nx
nx_synth_serve_gate.nx source
↩ module page · 105 lines · 7532 B
1// nx_synth_serve_gate.nx -- prove the Synth Studio is LIVE over real loopback HTTP: forks the server, then acts
2// as the browser. T1 GET /synth -> the studio page · T2 GET /synth/api/move?id=1 -> a real APNG · T3 POST
3// /synth/api/text2motion "say hello with a wave" -> a real APNG (neural chain runs in the request) · T4 POST
4// /synth/api/variant?sp=1&tv=1 -> a real PNG · T5 GET /synth/health -> ok. All served by sv_serve_conn.
5// license_tier: ORIGINAL expect_exit: 0
6import "nx_synth_serve.nx"
7import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
8import "nx_syscalls.nx"
9
10func g(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
11func glen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
12func gcat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){d[o+i]=s[i]; i=i+1} return o+i }
13func gcatb(d: *u8, o: i64, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n {d[o+i]=s[i]; i=i+1} return o+n }
14func gitoa(d: *u8, o: i64, v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var q: i64=k-1; while q>=0{d[o]=t[q];o=o+1;q=q-1} return o }
15func gfind(buf: *u8, n: i64, needle: *u8) -> i64 {
16 let nl: i64 = glen(needle); if nl==0 {return 0}
17 var i: i64=0
18 while i+nl<=n { var j: i64=0; var ok: i64=1; while j<nl { if (buf[i+j]&0xff)!=(needle[j]&0xff){ok=0;j=nl} else {j=j+1} } if ok==1{return i} i=i+1 }
19 return 0-1
20}
21// PNG signature 137 80 78 71 appears in the BODY (after the header)
22func gpng(buf: *u8, n: i64) -> i64 {
23 var i: i64=0
24 while i+4<=n { if (buf[i]&0xff)==137 { if (buf[i+1]&0xff)==80 { if (buf[i+2]&0xff)==78 { if (buf[i+3]&0xff)==71 { return i } } } } i=i+1 }
25 return 0-1
26}
27func glisten(port: i64) -> i64 {
28 let lfd: i64 = sys_socket(2,1,0); if lfd<0 {return 0-1}
29 let optv: *u8 = sys_mmap(4); optv[0]=1 as u8; sys_setsockopt(lfd,1,2,optv,4)
30 let addr: *u8 = sys_mmap(16)
31 addr[0]=2 as u8; addr[1]=0 as u8; addr[2]=((port>>8)&0xff) as u8; addr[3]=(port&0xff) as u8
32 addr[4]=127 as u8; addr[5]=0 as u8; addr[6]=0 as u8; addr[7]=1 as u8
33 var zi: i64=8; while zi<16 {addr[zi]=0 as u8; zi=zi+1}
34 if sys_bind(lfd, addr, 16) < 0 { return 0-1 }
35 if sys_listen(lfd, 16) < 0 { return 0-1 }
36 return lfd
37}
38func gconnect(port: i64) -> i64 {
39 let fd: i64 = sys_socket(2,1,0); if fd<0 {return 0-1}
40 sys_set_socket_timeout(fd, 120)
41 let a: *u8 = sys_mmap(16)
42 a[0]=2 as u8; a[1]=0 as u8; a[2]=((port>>8)&0xff) as u8; a[3]=(port&0xff) as u8
43 a[4]=127 as u8; a[5]=0 as u8; a[6]=0 as u8; a[7]=1 as u8
44 var zi: i64=8; while zi<16 {a[zi]=0 as u8; zi=zi+1}
45 if nx_connect_bounded(fd, a, 16, NX_CONN_DEFAULT_MS) != 0 { sys_close(fd); return 0-1 }
46 return fd
47}
48func gread(fd: i64, resp: *u8, cap: i64) -> i64 { var rn: i64=0; var go: i64=1; while go==1 { let r: i64=sys_read(fd,(resp as i64+rn) as *u8,cap-rn); if r<=0 {go=0} else {rn=rn+r; if rn>=cap {go=0}} } return rn }
49func greq_get(port: i64, path: *u8, resp: *u8, cap: i64) -> i64 {
50 let fd: i64 = gconnect(port); if fd<0 { return 0-1 }
51 let rq: *u8 = sys_mmap(2048); var o: i64 = gcat(rq, 0, "GET " as *u8); o = gcat(rq, o, path); o = gcat(rq, o, " HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n" as *u8)
52 sys_write(fd, rq, o); let rn: i64 = gread(fd, resp, cap); sys_close(fd); return rn
53}
54func greq_post(port: i64, path: *u8, body: *u8, resp: *u8, cap: i64) -> i64 {
55 let fd: i64 = gconnect(port); if fd<0 { return 0-1 }
56 let bl: i64 = glen(body)
57 let rq: *u8 = sys_mmap(2048); var o: i64 = gcat(rq, 0, "POST " as *u8); o = gcat(rq, o, path)
58 o = gcat(rq, o, " HTTP/1.1\r\nHost: x\r\nConnection: close\r\nContent-Length: " as *u8); o = gitoa(rq, o, bl); o = gcat(rq, o, "\r\n\r\n" as *u8); o = gcatb(rq, o, body, bl)
59 sys_write(fd, rq, o); let rn: i64 = gread(fd, resp, cap); sys_close(fd); return rn
60}
61
62func main() -> i64 {
63 g("=== nx_synth_serve_gate -- the Synth Studio LIVE over loopback ===\n" as *u8)
64 let PORT: i64 = 39351
65 let lfd: i64 = glisten(PORT); if lfd<0 { g("GATE FAIL: listen\n" as *u8); sys_exit(1); return 1 }
66 let pid: i64 = sys_fork()
67 if pid == 0 {
68 var i: i64 = 0
69 while i < 8 { let c: i64 = sys_accept(lfd); if c>=0 { sv_serve_conn(c); sys_close(c) } i=i+1 }
70 sys_exit(0)
71 }
72 sys_close(lfd)
73 let resp: *u8 = sys_mmap(12 * 1024 * 1024)
74 var fails: i64 = 0
75
76 let n1: i64 = greq_get(PORT, "/synth" as *u8, resp, 12*1024*1024)
77 if gfind(resp, n1, "200 OK" as *u8) >= 0 { if gfind(resp, n1, "Synth Studio" as *u8) >= 0 { g("T1 PASS GET /synth -> studio page\n" as *u8) } else { fails=fails+1; g("T1 FAIL no studio marker\n" as *u8) } } else { fails=fails+1; g("T1 FAIL not 200\n" as *u8) }
78
79 let n2: i64 = greq_get(PORT, "/synth/api/move?id=1" as *u8, resp, 12*1024*1024)
80 if gfind(resp, n2, "200 OK" as *u8) >= 0 { if gpng(resp, n2) >= 0 { g("T2 PASS /api/move?id=1 -> APNG (" as *u8); let nb: *u8=sys_mmap(16); let k: i64=gitoa(nb,0,n2); sys_write(1,nb,k); g(" bytes)\n" as *u8) } else { fails=fails+1; g("T2 FAIL no PNG body\n" as *u8) } } else { fails=fails+1; g("T2 FAIL not 200\n" as *u8) }
81
82 let n3: i64 = greq_post(PORT, "/synth/api/text2motion" as *u8, "say hello with a wave" as *u8, resp, 12*1024*1024)
83 if gfind(resp, n3, "200 OK" as *u8) >= 0 { if gpng(resp, n3) >= 0 { g("T3 PASS POST /api/text2motion 'say hello with a wave' -> neural motion APNG (" as *u8); let nb2: *u8=sys_mmap(16); let k2: i64=gitoa(nb2,0,n3); sys_write(1,nb2,k2); g(" bytes)\n" as *u8) } else { fails=fails+1; g("T3 FAIL no PNG body\n" as *u8) } } else { fails=fails+1; g("T3 FAIL not 200\n" as *u8) }
84
85 let n4: i64 = greq_post(PORT, "/synth/api/variant?sp=1&hv=0&ev=1&tv=1&build=110" as *u8, "" as *u8, resp, 12*1024*1024)
86 if gfind(resp, n4, "200 OK" as *u8) >= 0 { if gpng(resp, n4) >= 0 { g("T4 PASS POST /api/variant (wolf+tail) -> PNG (" as *u8); let nb3: *u8=sys_mmap(16); let k3: i64=gitoa(nb3,0,n4); sys_write(1,nb3,k3); g(" bytes)\n" as *u8) } else { fails=fails+1; g("T4 FAIL no PNG body\n" as *u8) } } else { fails=fails+1; g("T4 FAIL not 200\n" as *u8) }
87
88 let n5: i64 = greq_get(PORT, "/synth/health" as *u8, resp, 12*1024*1024)
89 if gfind(resp, n5, "\"ok\":1" as *u8) >= 0 { g("T5 PASS /synth/health ok\n" as *u8) } else { fails=fails+1; g("T5 FAIL health\n" as *u8) }
90
91 let n6: i64 = greq_get(PORT, "/synth/api/coach?err=0" as *u8, resp, 12*1024*1024)
92 if gfind(resp, n6, "\"form\":1000" as *u8) >= 0 { g("T6 PASS /api/coach?err=0 -> perfect form 1000/1000\n" as *u8) } else { fails=fails+1; g("T6 FAIL clean form not 1000\n" as *u8) }
93
94 let n7: i64 = greq_get(PORT, "/synth/api/coach?err=65" as *u8, resp, 12*1024*1024)
95 if gfind(resp, n7, "wrist" as *u8) >= 0 { g("T7 PASS /api/coach?err=65 -> coach flags the wrist (form scored down)\n" as *u8) } else { fails=fails+1; g("T7 FAIL coach did not flag wrist\n" as *u8) }
96
97 // let the server loop finish + reap
98 greq_get(PORT, "/synth/health" as *u8, resp, 4096)
99 let stx: *i64 = sys_mmap(16) as *i64
100 sys_wait4(pid, stx, 0)
101
102 if fails == 0 { g("SYNTH-STUDIO-GATE 7/7 GREEN -- studio page + text2motion + move + variant + COACH (form score + names the off-joint) all LIVE over HTTP\n" as *u8); sys_exit(0); return 0 }
103 g("SYNTH-STUDIO-GATE RED fails=" as *u8); let fb: *u8=sys_mmap(16); let kk: i64=gitoa(fb,0,fails); sys_write(1,fb,kk); g("\n" as *u8)
104 sys_exit(1); return 1
105}