code wiki / (root) / nx_dom_query_test.nx

nx_dom_query_test.nx source

↩ module page · 164 lines · 7624 B

1// nx_dom_query_test.nx -- smoke test for nx_dom_query.nx. 2// 3// Tests against a representative bits-up game-emitted HTML buffer (the 4// kind nx_checkers_render.nx writes to fd 99). Covers all four queries 5// plus the underlying attribute scanner. 6 7// Syscalls come transitively via nx_dom_query.nx -> nx_html_tokenizer.nx -> 8// nx_syscalls_x86_64.nx. This file builds + runs natively on x86_64 Linux. 9import "nx_dom_query.nx" 10 11func _dqt_strlen(s: *u8) -> i64 { 12 var n: i64 = 0 13 while s[n] != 0 { n = n + 1 } 14 return n 15} 16 17func _dqt_w(s: *u8) -> i64 { 18 return sys_write(1 as i64, s, _dqt_strlen(s)) 19} 20 21func _dqt_wln(s: *u8) -> i64 { 22 _dqt_w(s) 23 let nl: *u8 = sys_mmap(2) as *u8 24 nl[0] = 10 as u8 25 return sys_write(1 as i64, nl, 1 as i64) 26} 27 28func _dqt_assert_int(label: *u8, got: i64, want: i64, 29 passes: *i64, fails: *i64) -> i64 { 30 if got == want { 31 _dqt_w(" [PASS] " as *u8) 32 _dqt_wln(label) 33 passes[0] = passes[0] + 1 34 return 1 35 } 36 _dqt_w(" [FAIL] " as *u8) 37 _dqt_w(label) 38 _dqt_wln(" (int mismatch)" as *u8) 39 fails[0] = fails[0] + 1 40 return 0 41} 42 43func nx_dom_query_test() -> i64 { 44 let passes: *i64 = sys_mmap(8) as *i64 45 let fails: *i64 = sys_mmap(8) as *i64 46 passes[0] = 0 47 fails[0] = 0 48 49 _dqt_wln("nx_dom_query_test:" as *u8) 50 51 // A representative slice of a /checkers bits-up render. Mixes: 52 // - status div with class 53 // - 32 dark sqs (button.sq.dark) -- only show 4 here 54 // - light sqs (div.sq.light) 55 // - selected square (button with class "sq dark sel") 56 // - controls (button[data-action="2"] for reset) 57 // - select[data-action="3"] for opponent 58 let html: *u8 = "<div class=\"chk-shell\"><div class=\"chk-status\">Your move (Red).</div><div class=\"chk-board\"><button type=\"button\" class=\"sq dark\" data-sq=\"1\" data-action=\"1\" data-arg0=\"1\"></button><div class=\"sq light\"></div><button type=\"button\" class=\"sq dark sel\" data-sq=\"40\" data-action=\"1\" data-arg0=\"40\"><div class=\"piece red\"></div></button><div class=\"sq light\"></div></div><div class=\"controls\"><button type=\"button\" data-action=\"2\">New game</button><select data-action=\"3\"><option value=\"-1\">Another human</option><option value=\"0\" selected>AI - easy (random)</option></select></div></div>" as *u8 59 let n: i64 = _dqt_strlen(html) 60 61 // Test 1: count all dark squares -> 2 (we have 2 in the fixture). 62 let n_dark: i64 = nx_dom_count_class(html, n, "dark" as *u8) 63 _dqt_assert_int("count dark class = 2" as *u8, n_dark, 2 as i64, passes, fails) 64 65 // Test 2: count all light squares -> 2. 66 let n_light: i64 = nx_dom_count_class(html, n, "light" as *u8) 67 _dqt_assert_int("count light class = 2" as *u8, n_light, 2 as i64, passes, fails) 68 69 // Test 3: count "sel" class -> 1 (one selected). 70 let n_sel: i64 = nx_dom_count_class(html, n, "sel" as *u8) 71 _dqt_assert_int("count sel class = 1" as *u8, n_sel, 1 as i64, passes, fails) 72 73 // Test 4: count all <button> tags -> 3 (2 squares + reset). 74 let n_btn: i64 = nx_dom_count_tag(html, n, "button" as *u8) 75 _dqt_assert_int("count button tags = 3" as *u8, n_btn, 3 as i64, passes, fails) 76 77 // Test 5: count all <div> tags -> 6 (chk-shell + chk-status + chk-board + 78 // 2 light squares + piece red + controls = actually 7). Recount fixture: 79 // <div class="chk-shell"> 1 80 // <div class="chk-status"> 2 81 // <div class="chk-board"> 3 82 // <div class="sq light"> 4 83 // <div class="sq light"> 5 84 // <div class="piece red"> 6 85 // <div class="controls"> 7 86 let n_div: i64 = nx_dom_count_tag(html, n, "div" as *u8) 87 _dqt_assert_int("count div tags = 7" as *u8, n_div, 7 as i64, passes, fails) 88 89 // Test 6: find class "chk-shell" -> found, name should be "div". 90 let r1: *NxDomQueryResult = nx_dom_find_class(html, n, "chk-shell" as *u8) 91 _dqt_assert_int("find chk-shell.found = 1" as *u8, r1.found, 1 as i64, passes, fails) 92 _dqt_assert_int("find chk-shell.name_len = 3 (div)" as *u8, r1.name_len, 3 as i64, passes, fails) 93 94 // Test 7: find class "sel" -> found (the selected square). 95 let r2: *NxDomQueryResult = nx_dom_find_class(html, n, "sel" as *u8) 96 _dqt_assert_int("find sel.found = 1" as *u8, r2.found, 1 as i64, passes, fails) 97 _dqt_assert_int("find sel.name_len = 6 (button)" as *u8, r2.name_len, 6 as i64, passes, fails) 98 99 // Test 8: find data-sq="40" exact value -> the selected square. 100 let r3: *NxDomQueryResult = nx_dom_find_attr_eq(html, n, "data-sq" as *u8, "40" as *u8) 101 _dqt_assert_int("find data-sq=40.found = 1" as *u8, r3.found, 1 as i64, passes, fails) 102 103 // Test 9: find data-action="2" -> the reset button. 104 let r4: *NxDomQueryResult = nx_dom_find_attr_eq(html, n, "data-action" as *u8, "2" as *u8) 105 _dqt_assert_int("find data-action=2.found = 1" as *u8, r4.found, 1 as i64, passes, fails) 106 _dqt_assert_int("find data-action=2.name_len = 6 (button)" as *u8, r4.name_len, 6 as i64, passes, fails) 107 108 // Test 10: find class "ghost" -> NOT found. 109 let r5: *NxDomQueryResult = nx_dom_find_class(html, n, "ghost" as *u8) 110 _dqt_assert_int("find ghost.found = 0" as *u8, r5.found, 0 as i64, passes, fails) 111 112 // Test 11: find data-action="999" -> NOT found. 113 let r6: *NxDomQueryResult = nx_dom_find_attr_eq(html, n, "data-action" as *u8, "999" as *u8) 114 _dqt_assert_int("find data-action=999.found = 0" as *u8, r6.found, 0 as i64, passes, fails) 115 116 // Test 12: word-boundary correctness -- "dark" should NOT match "darkness". 117 // No "darkness" class in our fixture, but verify the matcher is strict. 118 let html2: *u8 = "<div class=\"darkness\"></div>" as *u8 119 let n2: i64 = _dqt_strlen(html2) 120 let r7: i64 = nx_dom_count_class(html2, n2, "dark" as *u8) 121 _dqt_assert_int("dark must not match darkness" as *u8, r7, 0 as i64, passes, fails) 122 123 // Test 13: substring-attr-name correctness -- query "action" should 124 // NOT spuriously match "data-action". 125 let r8: *NxDomQueryResult = nx_dom_find_attr_eq(html, n, "action" as *u8, "2" as *u8) 126 _dqt_assert_int("action != data-action (no false match)" as *u8, r8.found, 0 as i64, passes, fails) 127 128 _dqt_w("nx_dom_query_test: " as *u8) 129 // Print "X pass, Y fail" via two simple counts (just write digit chars). 130 let buf: *u8 = sys_mmap(64) as *u8 131 var off: i64 = 0 132 let p: i64 = passes[0] 133 let f: i64 = fails[0] 134 // Tens + ones for both counts (we have <100 tests). 135 let pt: i64 = p / 10 136 let po: i64 = p - pt * 10 137 if pt > 0 { buf[off] = (48 + pt) as u8; off = off + 1 } 138 buf[off] = (48 + po) as u8; off = off + 1 139 buf[off] = 32 as u8; off = off + 1 140 buf[off] = 112 as u8; off = off + 1 // p 141 buf[off] = 97 as u8; off = off + 1 // a 142 buf[off] = 115 as u8; off = off + 1 // s 143 buf[off] = 115 as u8; off = off + 1 // s 144 buf[off] = 44 as u8; off = off + 1 // , 145 buf[off] = 32 as u8; off = off + 1 // space 146 let ft: i64 = f / 10 147 let fo: i64 = f - ft * 10 148 if ft > 0 { buf[off] = (48 + ft) as u8; off = off + 1 } 149 buf[off] = (48 + fo) as u8; off = off + 1 150 buf[off] = 32 as u8; off = off + 1 151 buf[off] = 102 as u8; off = off + 1 // f 152 buf[off] = 97 as u8; off = off + 1 // a 153 buf[off] = 105 as u8; off = off + 1 // i 154 buf[off] = 108 as u8; off = off + 1 // l 155 buf[off] = 10 as u8; off = off + 1 // \n 156 sys_write(1 as i64, buf, off) 157 158 if fails[0] > 0 { return 1 } 159 return 0 160} 161 162func main() -> i64 { 163 return nx_dom_query_test() 164}