nx_monitor_html_test.nx source
↩ module page · 107 lines · 4439 B
1// nx_monitor_html_test.nx -- verify sovereign browser-monitor HTML
2// emit produces a structurally valid page with all required markers
3// + correct host/port substitution.
4//
5// Closed-form invariants:
6// (a) Emit returns positive byte count > 2000 (substantial page).
7// (b) Contains DOCTYPE + <html> + <body> + </html> tags.
8// (c) Contains all 6 tile IDs (state, progress, hotend, bed, zpos, eta).
9// (d) Contains WebSocket URL with substituted host + port.
10// (e) Contains camera MJPEG URL with host + camera port.
11// (f) Contains all 4 buttons (pause, resume, cancel, estop).
12// (g) Contains API_KEY constant in JS (with operator value).
13// (h) Half-print detection (setInterval + Z stall check).
14// (i) Refused-overflow capacity: small buffer (256) returns error.
15//
16// expect_exit: 0
17// license_tier: ORIGINAL
18
19import "nx_syscalls.nx"
20import "nx_moonraker_client.nx"
21import "nx_monitor_html.nx"
22
23func contains(buf: *u8, len: i64, needle: *u8) -> i64 {
24 var nlen: i64 = 0
25 while needle[nlen] != 0 { nlen = nlen + 1 }
26 if len < nlen { return 0 }
27 var i: i64 = 0
28 while i <= len - nlen {
29 var j: i64 = 0
30 var matched: i64 = 1
31 while j < nlen {
32 if buf[i + j] != needle[j] { matched = 0; j = nlen }
33 j = j + 1
34 }
35 if matched == 1 { return 1 }
36 i = i + 1
37 }
38 return 0
39}
40
41func main() -> i64 {
42 let cfg: *NxMonitorConfig = (sys_mmap(NX_MONITOR_CONFIG_BYTES)) as *NxMonitorConfig
43 cfg.printer_host = "192.168.1.42"
44 cfg.printer_host_len = 12
45 cfg.printer_port = 7125
46 cfg.camera_port = 8080
47 cfg.api_key = "demo-key"
48 cfg.api_key_len = 8
49
50 let buf: *u8 = sys_mmap(16384)
51 let n: i64 = nx_monitor_html_emit(cfg, buf, 16384)
52
53 // --- (a) Reasonable byte count ---
54 if n <= 2000 { return 10 }
55
56 // --- (b) HTML structure ---
57 if contains(buf, n, "<!DOCTYPE html>") != 1 { return 20 }
58 if contains(buf, n, "<html") != 1 { return 21 }
59 if contains(buf, n, "<body>") != 1 { return 22 }
60 if contains(buf, n, "</html>") != 1 { return 23 }
61
62 // --- (c) 6 telemetry tile IDs ---
63 if contains(buf, n, "id=\"state\"") != 1 { return 30 }
64 if contains(buf, n, "id=\"progress\"") != 1 { return 31 }
65 if contains(buf, n, "id=\"hotend\"") != 1 { return 32 }
66 if contains(buf, n, "id=\"bed\"") != 1 { return 33 }
67 if contains(buf, n, "id=\"zpos\"") != 1 { return 34 }
68 if contains(buf, n, "id=\"eta\"") != 1 { return 35 }
69
70 // --- (d) WebSocket URL with host + port substitution ---
71 if contains(buf, n, "ws://") != 1 { return 40 }
72 if contains(buf, n, "192.168.1.42") != 1 { return 41 }
73 if contains(buf, n, "7125") != 1 { return 42 }
74 if contains(buf, n, "/websocket") != 1 { return 43 }
75
76 // --- (e) Camera MJPEG URL ---
77 if contains(buf, n, "8080") != 1 { return 50 }
78 if contains(buf, n, "/?action=stream") != 1 { return 51 }
79
80 // --- (f) All 4 buttons ---
81 if contains(buf, n, "onclick=\"pause()\"") != 1 { return 60 }
82 if contains(buf, n, "onclick=\"resume()\"") != 1 { return 61 }
83 if contains(buf, n, "onclick=\"cancelPrint()\"") != 1 { return 62 }
84 if contains(buf, n, "onclick=\"estop()\"") != 1 { return 63 }
85
86 // --- (g) API_KEY embedded in JS ---
87 if contains(buf, n, "API_KEY=\"demo-key\"") != 1 { return 70 }
88
89 // --- (h) Multi-mode half-print detection ---
90 if contains(buf, n, "setInterval") != 1 { return 80 }
91 if contains(buf, n, "lastZAt") != 1 { return 81 }
92 if contains(buf, n, "lastHotendDriftAt") != 1 { return 82 }
93 if contains(buf, n, "lastBedDriftAt") != 1 { return 83 }
94 if contains(buf, n, "lastProgressAt") != 1 { return 84 }
95 if contains(buf, n, "lastEAt") != 1 { return 85 }
96 if contains(buf, n, "Hotend drift") != 1 { return 86 }
97 if contains(buf, n, "Bed drift") != 1 { return 87 }
98 if contains(buf, n, "Progress stalled") != 1 { return 88 }
99 if contains(buf, n, "Extruder E stalled") != 1 { return 89 }
100
101 // --- (i) Overflow defense (now larger; use 512 to test) ---
102 let tiny: *u8 = sys_mmap(512)
103 let n_overflow: i64 = nx_monitor_html_emit(cfg, tiny, 512)
104 if n_overflow >= 0 { return 90 } // must return negative verdict
105
106 return 0
107}