nx_html5_raw_text_test.nx source
↩ module page · 189 lines · 7284 B
1// nx_html5_raw_text_test.nx -- KAT for Arc B1 HTML5 tokenizer additions:
2// - nx_html_is_raw_text_tag
3// - nx_html_consume_raw_text
4// - nx_html_entity_decode
5//
6// Hand-built fragment exercises all three.
7//
8// expect_exit: 0
9// license_tier: ORIGINAL
10
11import "nx_syscalls.nx"
12import "nx_html_tokenizer.nx"
13
14func _emit_fail(n: i64) -> i64 {
15 let b: *u8 = sys_mmap(8)
16 b[0] = 0x46; b[1] = 0x41; b[2] = 0x49; b[3] = 0x4C // FAIL
17 b[4] = 0x3D // =
18 sys_write(2, b, 5)
19 let d: *u8 = sys_mmap(8)
20 var x: i64 = n
21 if x < 0 { d[0] = 0x2D; sys_write(2, d, 1); x = 0 - x }
22 if x == 0 { d[0] = 0x30; sys_write(2, d, 1) }
23 else {
24 let buf: *u8 = sys_mmap(16)
25 var pos: i64 = 0
26 while x > 0 { buf[pos] = (0x30 + (x % 10)) as u8; x = x / 10; pos = pos + 1 }
27 let out: *u8 = sys_mmap(16)
28 var i: i64 = 0
29 while i < pos { out[i] = buf[pos - 1 - i]; i = i + 1 }
30 sys_write(2, out, pos)
31 }
32 let nl: *u8 = sys_mmap(8); nl[0] = 0x0A; sys_write(2, nl, 1)
33 return 0
34}
35
36func main() -> i64 {
37 // ============================================================
38 // Section A: nx_html_is_raw_text_tag
39 // ============================================================
40 let s_script: *u8 = "script" as *u8
41 if nx_html_is_raw_text_tag(s_script, 0, 6) != 1 { _emit_fail(1); return 1 }
42
43 let s_SCRIPT: *u8 = "SCRIPT" as *u8
44 if nx_html_is_raw_text_tag(s_SCRIPT, 0, 6) != 1 { _emit_fail(2); return 2 }
45
46 let s_style: *u8 = "style" as *u8
47 if nx_html_is_raw_text_tag(s_style, 0, 5) != 1 { _emit_fail(3); return 3 }
48
49 let s_title: *u8 = "title" as *u8
50 if nx_html_is_raw_text_tag(s_title, 0, 5) != 1 { _emit_fail(4); return 4 }
51
52 let s_textarea: *u8 = "textarea" as *u8
53 if nx_html_is_raw_text_tag(s_textarea, 0, 8) != 1 { _emit_fail(5); return 5 }
54
55 let s_div: *u8 = "div" as *u8
56 if nx_html_is_raw_text_tag(s_div, 0, 3) != 0 { _emit_fail(6); return 6 }
57
58 let s_p: *u8 = "p" as *u8
59 if nx_html_is_raw_text_tag(s_p, 0, 1) != 0 { _emit_fail(7); return 7 }
60
61 let s_html: *u8 = "html" as *u8
62 if nx_html_is_raw_text_tag(s_html, 0, 4) != 0 { _emit_fail(8); return 8 }
63
64 // ============================================================
65 // Section B: nx_html_consume_raw_text
66 // ============================================================
67 // <script>if (a < b) { c = "</strong>"; }</script>
68 let html: *u8 = "<script>if (a < b) { c = \"</strong>\"; }</script>"
69 var hlen: i64 = 0
70 while html[hlen] != 0 { hlen = hlen + 1 }
71
72 let c: *HtmlCursor = sys_mmap(24) as *HtmlCursor
73 nx_html_cursor_init(c, html, hlen)
74 let tok: *HtmlToken = sys_mmap(56) as *HtmlToken
75
76 // First token: START_TAG <script>
77 nx_html_next_token(c, tok)
78 if tok.kind != NX_HTML_TOK_START_TAG { _emit_fail(10); return 10 }
79 if nx_html_is_raw_text_tag(html, tok.name_off, tok.name_len) != 1 { _emit_fail(11); return 11 }
80
81 // Consume raw-text body up to (but not including) </script>.
82 let tag_script: *u8 = "script" as *u8
83 nx_html_consume_raw_text(c, tag_script, 6, tok)
84 if tok.kind != NX_HTML_TOK_TEXT { _emit_fail(12); return 12 }
85 // Body should be `if (a < b) { c = "</strong>"; }` -- 31 bytes
86 if tok.body_len != 31 { _emit_fail(13 + tok.body_len); return 13 }
87
88 // Body must contain '<' (the `a < b` `<`) -- proves we did NOT treat it as tag start.
89 var saw_lt: i64 = 0
90 var i: i64 = 0
91 while i < tok.body_len {
92 if html[tok.body_off + i] == 60 { saw_lt = 1; i = tok.body_len }
93 else { i = i + 1 }
94 }
95 if saw_lt != 1 { _emit_fail(14); return 14 }
96
97 // Next token: END_TAG </script>
98 nx_html_next_token(c, tok)
99 if tok.kind != NX_HTML_TOK_END_TAG { _emit_fail(15); return 15 }
100 if tok.name_len != 6 { _emit_fail(16); return 16 }
101
102 // Then EOF.
103 nx_html_next_token(c, tok)
104 if tok.kind != NX_HTML_TOK_EOF { _emit_fail(17); return 17 }
105
106 // ============================================================
107 // Section C: nx_html_entity_decode
108 // ============================================================
109 let dst: *u8 = sys_mmap(256)
110
111 // C1: basic 5
112 let e1: *u8 = "&<>"'"
113 var e1l: i64 = 0
114 while e1[e1l] != 0 { e1l = e1l + 1 }
115 var n: i64 = nx_html_entity_decode(e1, e1l, dst, 256)
116 if n != 5 { _emit_fail(20 + n); return 20 }
117 if dst[0] != 0x26 { _emit_fail(21); return 21 } // &
118 if dst[1] != 0x3C { _emit_fail(22); return 22 } // <
119 if dst[2] != 0x3E { _emit_fail(23); return 23 } // >
120 if dst[3] != 0x22 { _emit_fail(24); return 24 } // "
121 if dst[4] != 0x27 { _emit_fail(25); return 25 } // '
122
123 // C2: numeric decimal A = 'A'
124 let e2: *u8 = "A"
125 n = nx_html_entity_decode(e2, 5, dst, 256)
126 if n != 1 { _emit_fail(30); return 30 }
127 if dst[0] != 0x41 { _emit_fail(31); return 31 }
128
129 // C3: numeric hex A = 'A' (lower x)
130 let e3: *u8 = "A"
131 n = nx_html_entity_decode(e3, 6, dst, 256)
132 if n != 1 { _emit_fail(40); return 40 }
133 if dst[0] != 0x41 { _emit_fail(41); return 41 }
134
135 // C4: numeric hex uppercase X
136 let e4: *u8 = "J" // 'J'
137 n = nx_html_entity_decode(e4, 6, dst, 256)
138 if n != 1 { _emit_fail(50); return 50 }
139 if dst[0] != 0x4A { _emit_fail(51); return 51 }
140
141 // C5: named -- nbsp = U+00A0 = C2 A0 in UTF-8
142 let e5: *u8 = " "
143 n = nx_html_entity_decode(e5, 6, dst, 256)
144 if n != 2 { _emit_fail(60); return 60 }
145 if dst[0] != 0xC2 { _emit_fail(61); return 61 }
146 if dst[1] != 0xA0 { _emit_fail(62); return 62 }
147
148 // C6: named -- mdash = U+2014 = E2 80 94 in UTF-8
149 let e6: *u8 = "—"
150 n = nx_html_entity_decode(e6, 7, dst, 256)
151 if n != 3 { _emit_fail(70); return 70 }
152 if dst[0] != 0xE2 { _emit_fail(71); return 71 }
153 if dst[1] != 0x80 { _emit_fail(72); return 72 }
154 if dst[2] != 0x94 { _emit_fail(73); return 73 }
155
156 // C7: unknown entity passes through verbatim
157 let e7: *u8 = "&zzz;"
158 n = nx_html_entity_decode(e7, 5, dst, 256)
159 if n != 5 { _emit_fail(80); return 80 }
160 if dst[0] != 0x26 { _emit_fail(81); return 81 } // &
161 if dst[4] != 0x3B { _emit_fail(82); return 82 } // ;
162
163 // C8: mixed text + entities
164 let e8: *u8 = "A&B"
165 n = nx_html_entity_decode(e8, 7, dst, 256)
166 if n != 3 { _emit_fail(90); return 90 }
167 if dst[0] != 0x41 { _emit_fail(91); return 91 }
168 if dst[1] != 0x26 { _emit_fail(92); return 92 }
169 if dst[2] != 0x42 { _emit_fail(93); return 93 }
170
171 // C9: '&' with no terminator passes through
172 let e9: *u8 = "&"
173 n = nx_html_entity_decode(e9, 1, dst, 256)
174 if n != 1 { _emit_fail(100); return 100 }
175 if dst[0] != 0x26 { _emit_fail(101); return 101 }
176
177 // C10: '&' followed by long-no-semicolon passes through
178 let e10: *u8 = "a&unfinished_entity_name_here"
179 var e10l: i64 = 0
180 while e10[e10l] != 0 { e10l = e10l + 1 }
181 n = nx_html_entity_decode(e10, e10l, dst, 256)
182 // Expected: 'a' + '&' + the long body verbatim = same as input length
183 if n != e10l { _emit_fail(110); return 110 }
184
185 let pass: *u8 = sys_mmap(16)
186 pass[0]=0x50; pass[1]=0x41; pass[2]=0x53; pass[3]=0x53; pass[4]=0x0A
187 sys_write(1, pass, 5)
188 return 0
189}