nx_websocket_stream_test.nx source
↩ module page · 169 lines · 6562 B
1// nx_websocket_stream_test.nx -- KAT for the streaming WebSocket framer.
2//
3// Uses sys_pipe2 to create a loopback fd pair (write end = "client",
4// read end = our nx_ws_read_frame_from_fd reader). Drives canonical
5// RFC 6455 frame bytes through and asserts the parsed result.
6//
7// Tests:
8// T1: short unmasked text frame (server -> client direction simulated)
9// T2: client-masked "Hello" frame (RFC 6455 §5.7 wire vector) gets
10// unmasked in place during read
11// T3: extended 16-bit length (1000 bytes payload)
12// T4: send-to-fd round-trip: nx_ws_send_text -> read back through
13// a fresh pipe -> parse and verify
14// T5: nx_ws_send_close round-trip
15//
16// expect_exit: 0
17// license_tier: ORIGINAL
18
19import "nx_syscalls.nx"
20import "nx_websocket_frame.nx"
21import "nx_websocket_stream.nx"
22
23func main() -> i64 {
24 // ---- T1: unmasked text frame ----
25 let fds1: *i32 = sys_mmap(16) as *i32
26 if sys_pipe2(fds1 as *i64, 0) < 0 { return 1 }
27 let rfd1: i64 = fds1[0] as i64
28 let wfd1: i64 = fds1[1] as i64
29
30 let f1bytes: *u8 = sys_mmap(16)
31 f1bytes[0] = 0x81; f1bytes[1] = 0x05
32 f1bytes[2] = 0x48; f1bytes[3] = 0x65; f1bytes[4] = 0x6C
33 f1bytes[5] = 0x6C; f1bytes[6] = 0x6F
34 if sys_write(wfd1, f1bytes, 7) != 7 { return 2 }
35 sys_close(wfd1) // EOF after frame so read can settle
36
37 let buf1: *u8 = sys_mmap(64)
38 let f1_raw: *u8 = sys_mmap(128)
39 let f1: *WsFrame = f1_raw as *WsFrame
40 let v1: i64 = nx_ws_read_frame_from_fd(rfd1, buf1, 64, f1)
41 sys_close(rfd1)
42 if v1 != NX_WSS_OK { return 3 }
43 if f1.opcode != WS_OP_TEXT { return 4 }
44 if f1.payload_len != 5 { return 5 }
45 if buf1[f1.payload_off] != 0x48 as u8 { return 6 } // 'H'
46 if buf1[f1.payload_off + 4] != 0x6F as u8 { return 7 } // 'o'
47
48 // ---- T2: masked client "Hello" (RFC 6455 §5.7) -- unmasked in place ----
49 let fds2: *i32 = sys_mmap(16) as *i32
50 if sys_pipe2(fds2 as *i64, 0) < 0 { return 10 }
51 let rfd2: i64 = fds2[0] as i64
52 let wfd2: i64 = fds2[1] as i64
53
54 let f2bytes: *u8 = sys_mmap(16)
55 f2bytes[0] = 0x81; f2bytes[1] = 0x85
56 f2bytes[2] = 0x37; f2bytes[3] = 0xFA; f2bytes[4] = 0x21; f2bytes[5] = 0x3D
57 f2bytes[6] = 0x7F; f2bytes[7] = 0x9F; f2bytes[8] = 0x4D
58 f2bytes[9] = 0x51; f2bytes[10] = 0x58
59 if sys_write(wfd2, f2bytes, 11) != 11 { return 11 }
60 sys_close(wfd2)
61
62 let buf2: *u8 = sys_mmap(64)
63 let f2_raw: *u8 = sys_mmap(128)
64 let f2: *WsFrame = f2_raw as *WsFrame
65 let v2: i64 = nx_ws_read_frame_from_fd(rfd2, buf2, 64, f2)
66 sys_close(rfd2)
67 if v2 != NX_WSS_OK { return 12 }
68 if f2.masked != 1 { return 13 }
69 if f2.payload_len != 5 { return 14 }
70 // Read-from-fd unmasks in place -- buf2 should now show "Hello"
71 if buf2[f2.payload_off] != 0x48 as u8 { return 15 }
72 if buf2[f2.payload_off + 1] != 0x65 as u8 { return 16 }
73 if buf2[f2.payload_off + 2] != 0x6C as u8 { return 17 }
74 if buf2[f2.payload_off + 3] != 0x6C as u8 { return 18 }
75 if buf2[f2.payload_off + 4] != 0x6F as u8 { return 19 }
76
77 // ---- T3: extended 16-bit length frame (1000 bytes) ----
78 let fds3: *i32 = sys_mmap(16) as *i32
79 if sys_pipe2(fds3 as *i64, 0) < 0 { return 20 }
80 let rfd3: i64 = fds3[0] as i64
81 let wfd3: i64 = fds3[1] as i64
82
83 let f3bytes: *u8 = sys_mmap(2048)
84 f3bytes[0] = 0x82; f3bytes[1] = 126 // binary FIN + extlen sentinel
85 f3bytes[2] = 0x03; f3bytes[3] = 0xE8 // 1000 in BE
86 var i: i64 = 0
87 while i < 1000 {
88 f3bytes[4 + i] = (i & 0xFF) as u8
89 i = i + 1
90 }
91 if sys_write(wfd3, f3bytes, 1004) != 1004 { return 21 }
92 sys_close(wfd3)
93
94 let buf3: *u8 = sys_mmap(2048)
95 let f3_raw: *u8 = sys_mmap(128)
96 let f3: *WsFrame = f3_raw as *WsFrame
97 let v3: i64 = nx_ws_read_frame_from_fd(rfd3, buf3, 2048, f3)
98 sys_close(rfd3)
99 if v3 != NX_WSS_OK { return 22 }
100 if f3.opcode != WS_OP_BINARY { return 23 }
101 if f3.payload_len != 1000 { return 24 }
102 if buf3[f3.payload_off] != 0x00 as u8 { return 25 }
103 if buf3[f3.payload_off + 999] != 0xE7 as u8 { return 26 } // (999 & 0xFF)
104
105 // ---- T4: send-to-fd round-trip -- send_text writes a parseable frame ----
106 let fds4: *i32 = sys_mmap(16) as *i32
107 if sys_pipe2(fds4 as *i64, 0) < 0 { return 30 }
108 let rfd4: i64 = fds4[0] as i64
109 let wfd4: i64 = fds4[1] as i64
110
111 let txt: *u8 = "ping" as *u8
112 let sv: i64 = nx_ws_send_text(wfd4, txt, 4)
113 sys_close(wfd4)
114 if sv != NX_WSS_OK { return 31 }
115
116 let buf4: *u8 = sys_mmap(64)
117 let f4_raw: *u8 = sys_mmap(128)
118 let f4: *WsFrame = f4_raw as *WsFrame
119 let v4: i64 = nx_ws_read_frame_from_fd(rfd4, buf4, 64, f4)
120 sys_close(rfd4)
121 if v4 != NX_WSS_OK { return 32 }
122 if f4.opcode != WS_OP_TEXT { return 33 }
123 if f4.fin != 1 { return 34 }
124 if f4.masked != 0 { return 35 } // server frames MUST NOT be masked
125 if f4.payload_len != 4 { return 36 }
126 if buf4[f4.payload_off] != 0x70 as u8 { return 37 } // 'p'
127 if buf4[f4.payload_off + 3] != 0x67 as u8 { return 38 } // 'g'
128
129 // ---- T5: send_close with status code 1000 (normal closure) ----
130 let fds5: *i32 = sys_mmap(16) as *i32
131 if sys_pipe2(fds5 as *i64, 0) < 0 { return 40 }
132 let rfd5: i64 = fds5[0] as i64
133 let wfd5: i64 = fds5[1] as i64
134
135 let svc: i64 = nx_ws_send_close(wfd5, 1000)
136 sys_close(wfd5)
137 if svc != NX_WSS_OK { return 41 }
138
139 let buf5: *u8 = sys_mmap(64)
140 let f5_raw: *u8 = sys_mmap(128)
141 let f5: *WsFrame = f5_raw as *WsFrame
142 let v5: i64 = nx_ws_read_frame_from_fd(rfd5, buf5, 64, f5)
143 sys_close(rfd5)
144 if v5 != NX_WSS_OK { return 42 }
145 if f5.opcode != WS_OP_CLOSE { return 43 }
146 if f5.payload_len != 2 { return 44 }
147 // status code 1000 = 0x03E8 big-endian
148 if buf5[f5.payload_off] != 0x03 as u8 { return 45 }
149 if buf5[f5.payload_off + 1] != 0xE8 as u8 { return 46 }
150
151 // ---- T6: EOF before any bytes returns NX_WSS_EOF (clean close) ----
152 let fds6: *i32 = sys_mmap(16) as *i32
153 if sys_pipe2(fds6 as *i64, 0) < 0 { return 50 }
154 let rfd6: i64 = fds6[0] as i64
155 sys_close(fds6[1] as i64) // close write end immediately
156
157 let buf6: *u8 = sys_mmap(64)
158 let f6_raw: *u8 = sys_mmap(128)
159 let f6: *WsFrame = f6_raw as *WsFrame
160 let v6: i64 = nx_ws_read_frame_from_fd(rfd6, buf6, 64, f6)
161 sys_close(rfd6)
162 if v6 != NX_WSS_EOF { return 51 }
163
164 // "PASS\n"
165 let ok: *u8 = sys_mmap(8)
166 ok[0]=80; ok[1]=65; ok[2]=83; ok[3]=83; ok[4]=10
167 sys_write(1, ok, 5)
168 return 0
169}