code wiki / (root) / nx_moonraker_io_test.nx

nx_moonraker_io_test.nx source

↩ module page · 109 lines · 3731 B

1// nx_moonraker_io_test.nx -- REAL network roundtrip test. 2// 3// Parent: acts as a fake Moonraker server -- listens on a loopback 4// port, accepts the connection, reads the POST request, validates 5// it contains expected markers, sends back a canned HTTP/1.1 200 OK 6// response. 7// 8// Child: builds + sends the Moonraker POST /printer/print/start 9// request via nx_mr_post_loopback (composes nx_mr_build_post_request 10// + tcp_connect_loopback + sys_write + sys_read). Verifies the 11// response status is 200. Exits with assertion code. 12// 13// Bytes flow over a real loopback socket through the real Linux 14// kernel TCP stack inside qemu -- this is REAL network I/O, not a 15// mock. 16// 17// expect_exit: 0 18// license_tier: ORIGINAL 19 20import "nx_syscalls.nx" 21import "nx_tls13_io.nx" 22import "nx_moonraker_client.nx" 23import "nx_moonraker_io.nx" 24 25const TEST_PORT: i64 = 18447 26 27// Verify buf contains needle as a contiguous substring. 28func smoke_contains(buf: *u8, len: i64, needle: *u8) -> i64 { 29 var nlen: i64 = 0 30 while needle[nlen] != 0 { nlen = nlen + 1 } 31 if len < nlen { return 0 } 32 var i: i64 = 0 33 while i <= len - nlen { 34 var j: i64 = 0 35 var matched: i64 = 1 36 while j < nlen { 37 if buf[i + j] != needle[j] { matched = 0; j = nlen } 38 j = j + 1 39 } 40 if matched == 1 { return 1 } 41 i = i + 1 42 } 43 return 0 44} 45 46func main() -> i64 { 47 let listen_fd: i64 = tcp_listen_loopback(TEST_PORT) 48 if listen_fd < 0 { return 1 } 49 50 let pid: i64 = sys_fork() 51 if pid < 0 { return 2 } 52 53 if pid == 0 { 54 // ===== Child: client ===== 55 // Brief spin so parent has time to call accept. 56 var spin: i64 = 0 57 while spin < 50000 { spin = spin + 1 } 58 59 let scratch: *u8 = sys_mmap(4096) 60 let resp: *u8 = sys_mmap(4096) 61 let host: *u8 = "127.0.0.1:18447" 62 let path: *u8 = "/printer/print/start" 63 let body: *u8 = "{\"filename\":\"cube.gcode\"}" 64 let api_key: *u8 = "demo" 65 66 let n_resp: i64 = nx_mr_post_loopback(TEST_PORT, 67 host, 15, 68 path, 20, 69 body, 26, 70 api_key, 4, 71 scratch, 4096, 72 resp, 4096) 73 if n_resp <= 0 { sys_exit(10) } 74 75 // Parse HTTP status code from response. 76 let status: i64 = nx_mr_parse_status(resp, n_resp) 77 if status != 200 { sys_exit(11) } 78 79 // Verify response contains expected substring. 80 if smoke_contains(resp, n_resp, "HTTP/1.1 200 OK") != 1 { sys_exit(12) } 81 82 sys_exit(0) 83 } 84 85 // ===== Parent: fake Moonraker ===== 86 let cfd: i64 = sys_accept(listen_fd) 87 if cfd < 0 { return 3 } 88 89 let req_buf: *u8 = sys_mmap(4096) 90 let n_req: i64 = sys_read(cfd, req_buf, 4096) 91 if n_req <= 0 { return 4 } 92 93 // Validate the request looks like what we built. 94 if smoke_contains(req_buf, n_req, "POST /printer/print/start") != 1 { return 5 } 95 if smoke_contains(req_buf, n_req, "Host: 127.0.0.1:18447") != 1 { return 6 } 96 if smoke_contains(req_buf, n_req, "X-Api-Key: demo") != 1 { return 7 } 97 if smoke_contains(req_buf, n_req, "{\"filename\":\"cube.gcode\"}") != 1 { return 8 } 98 99 // Canned 200 OK response. 100 let resp: *u8 = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" 101 var rl: i64 = 0 102 while resp[rl] != 0 { rl = rl + 1 } 103 let n_w: i64 = sys_write(cfd, resp, rl) 104 if n_w != rl { return 9 } 105 106 sys_close(cfd) 107 sys_close(listen_fd) 108 return 0 109}