nx_moonraker_ready_check_test.nx source
↩ module page · 92 lines · 3926 B
1// nx_moonraker_ready_check_test.nx -- ready-state classifier tests
2// (offline; classify_body verified against canned response bodies)
3// + loopback fork test against fake Moonraker returning ready JSON.
4//
5// Closed-form invariants:
6// (a) "{\"result\":{\"state\":\"ready\"}}" -> NX_READY_OK
7// (b) "{\"result\":{\"state\":\"shutdown\"}}" -> NX_READY_NOT_READY
8// (c) "{\"result\":{\"state\":\"error\"}}" -> NX_READY_NOT_READY
9// (d) Body with no "state" field -> NX_READY_BAD_RESPONSE
10// (e) Loose form with space: "\"state\": \"ready\"" -> NX_READY_OK
11// (f) Loopback fork: fake Moonraker returns 200 + ready JSON ->
12// ready check returns NX_READY_OK
13// (g) Verdict names non-NULL for all verdicts.
14//
15// expect_exit: 0
16// license_tier: ORIGINAL
17
18import "nx_syscalls.nx"
19import "nx_tls13_io.nx"
20import "nx_moonraker_client.nx"
21import "nx_moonraker_io.nx"
22import "nx_moonraker_ready_check.nx"
23
24const TEST_PORT: i64 = 18449
25
26func body_len(s: *u8) -> i64 {
27 var i: i64 = 0
28 while s[i] != 0 { i = i + 1 }
29 return i
30}
31
32func main() -> i64 {
33 // --- (a)(b)(c)(d)(e) Offline body classification ---
34 let b_ready: *u8 = "{\"result\":{\"state\":\"ready\",\"hostname\":\"qidi\"}}"
35 let b_shutdown: *u8 = "{\"result\":{\"state\":\"shutdown\",\"reason\":\"err\"}}"
36 let b_error: *u8 = "{\"result\":{\"state\":\"error\"}}"
37 let b_nostate: *u8 = "{\"result\":{\"hostname\":\"qidi\"}}"
38 let b_loose: *u8 = "{\"result\": {\"state\": \"ready\"}}"
39
40 if nx_ready_classify_body(b_ready, body_len(b_ready)) != NX_READY_OK { return 10 }
41 if nx_ready_classify_body(b_shutdown, body_len(b_shutdown)) != NX_READY_NOT_READY { return 11 }
42 if nx_ready_classify_body(b_error, body_len(b_error)) != NX_READY_NOT_READY { return 12 }
43 if nx_ready_classify_body(b_nostate, body_len(b_nostate)) != NX_READY_BAD_RESPONSE { return 13 }
44 if nx_ready_classify_body(b_loose, body_len(b_loose)) != NX_READY_OK { return 14 }
45
46 // --- (f) Loopback fork test ---
47 let listen_fd: i64 = tcp_listen_loopback(TEST_PORT)
48 if listen_fd < 0 { return 20 }
49 let pid: i64 = sys_fork()
50 if pid < 0 { return 21 }
51
52 if pid == 0 {
53 // Child: query loopback
54 var spin: i64 = 0
55 while spin < 50000 { spin = spin + 1 }
56 let scratch: *u8 = sys_mmap(4096)
57 let resp: *u8 = sys_mmap(4096)
58 let host: *u8 = "127.0.0.1:18449"
59 let v: i64 = nx_moonraker_ready_check_loopback(TEST_PORT,
60 host, 15,
61 0 as *u8, 0,
62 scratch, 4096,
63 resp, 4096)
64 if v != NX_READY_OK { sys_exit(30 + v) }
65 sys_exit(0)
66 }
67
68 // Parent: serve canned 200 OK with ready state
69 let cfd: i64 = sys_accept(listen_fd)
70 if cfd < 0 { return 22 }
71 let req_buf: *u8 = sys_mmap(4096)
72 let n_req: i64 = sys_read(cfd, req_buf, 4096)
73 if n_req <= 0 { return 23 }
74
75 // Canned response: HTTP 200 with ready-state JSON body.
76 // Body: {"result":{"state":"ready"}} (29 bytes)
77 let resp: *u8 = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 29\r\nConnection: close\r\n\r\n{\"result\":{\"state\":\"ready\"}}"
78 var rl: i64 = 0
79 while resp[rl] != 0 { rl = rl + 1 }
80 let n_w: i64 = sys_write(cfd, resp, rl)
81 if n_w != rl { return 24 }
82 sys_close(cfd)
83 sys_close(listen_fd)
84
85 // --- (g) Verdict names ---
86 if (nx_ready_verdict_name(NX_READY_OK) as i64) == 0 { return 80 }
87 if (nx_ready_verdict_name(NX_READY_NOT_READY) as i64) == 0 { return 81 }
88 if (nx_ready_verdict_name(NX_READY_BAD_RESPONSE) as i64) == 0 { return 82 }
89 if (nx_ready_verdict_name(NX_READY_NETWORK_ERR) as i64) == 0 { return 83 }
90
91 return 0
92}