code wiki / (root) / nx_html5_raw_text_test.nx

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 = "&amp;&lt;&gt;&quot;&apos;" 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 &#65; = 'A' 124 let e2: *u8 = "&#65;" 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 &#x41; = 'A' (lower x) 130 let e3: *u8 = "&#x41;" 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 = "&#X4A;" // '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 = "&nbsp;" 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 = "&mdash;" 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&amp;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}