code wiki / (root) / nx_test_driver_e2e.nx

nx_test_driver_e2e.nx source

↩ module page · 136 lines · 5649 B

1// nx_test_driver_e2e.nx -- end-to-end smoke for the bits-up test driver. 2// Composes all 5 primitives (nx_dom_query + nx_dom_click + nx_url_params 3// + nx_test_harness + nx_game_harness) against an inline "fake game" that 4// emits the same HTML shape as nx_tictactoe_render.nx. 5// 6// Why a fake game instead of importing nx_tictactoe.nx directly: the real 7// game's render imports nx_syscalls.nx (RV64); the harness imports 8// nx_syscalls_x86_64.nx; combining them creates duplicate-symbol errors. 9// Cross-arch cleanup of the substrate's syscall layer is the queued 10// follow-up; this smoke validates the *primitives* end-to-end and 11// produces the same test-output format the .mjs harnesses do, proving the 12// architecture works. 13// 14// The fake game models a 3x3 grid like tic-tac-toe. State is 9 cells + 15// last-move indicator. Render emits buttons with class="cell" and 16// data-cell-idx="N". Action 1 with arg0=N places an X at cell N. 17 18import "nx_test_harness.nx" 19import "nx_game_harness.nx" 20import "nx_dom_query.nx" 21import "nx_dom_click.nx" 22import "nx_url_params.nx" 23const K_MAGIC_65536: i64 = 65536 24 25const _FAKE_RENDER_FD: i64 = 99 26 27static FAKE_CELLS: i64 // bitmask of cells where X was played (real impl 28 // would be a 9-i64 array; bitmask suffices) 29 30func _fake_w(s: *u8) -> i64 { 31 var n: i64 = 0 32 while s[n] != 0 { n = n + 1 } 33 return sys_write(_FAKE_RENDER_FD, s, n) 34} 35 36func _fake_wi(n: i64) -> i64 { 37 if n == 0 { return _fake_w("0" as *u8) } 38 if n == 1 { return _fake_w("1" as *u8) } 39 if n == 2 { return _fake_w("2" as *u8) } 40 if n == 3 { return _fake_w("3" as *u8) } 41 if n == 4 { return _fake_w("4" as *u8) } 42 if n == 5 { return _fake_w("5" as *u8) } 43 if n == 6 { return _fake_w("6" as *u8) } 44 if n == 7 { return _fake_w("7" as *u8) } 45 if n == 8 { return _fake_w("8" as *u8) } 46 return _fake_w("?" as *u8) 47} 48 49func fake_render() -> i64 { 50 _fake_w("<div class=\"board\">" as *u8) 51 var i: i64 = 0 52 while i < 9 { 53 _fake_w("<button class=\"cell\" data-cell-idx=\"" as *u8) 54 _fake_wi(i) 55 _fake_w("\" data-action=\"1\" data-arg0=\"" as *u8) 56 _fake_wi(i) 57 _fake_w("\">" as *u8) 58 // Check the bit for cell i. 59 let mask: i64 = 1 60 var bit: i64 = 0 61 if i == 0 { bit = FAKE_CELLS - (FAKE_CELLS / 2) * 2 } 62 if i == 1 { bit = (FAKE_CELLS / 2) - (FAKE_CELLS / 4) * 2 } 63 if i == 2 { bit = (FAKE_CELLS / 4) - (FAKE_CELLS / 8) * 2 } 64 if i == 3 { bit = (FAKE_CELLS / 8) - (FAKE_CELLS / 16) * 2 } 65 if i == 4 { bit = (FAKE_CELLS / 16) - (FAKE_CELLS / 32) * 2 } 66 if i == 5 { bit = (FAKE_CELLS / 32) - (FAKE_CELLS / 64) * 2 } 67 if i == 6 { bit = (FAKE_CELLS / 64) - (FAKE_CELLS / 128) * 2 } 68 if i == 7 { bit = (FAKE_CELLS / 128) - (FAKE_CELLS / 256) * 2 } 69 if i == 8 { bit = (FAKE_CELLS / 256) - (FAKE_CELLS / 512) * 2 } 70 if bit == 1 { _fake_w("X" as *u8) } 71 _fake_w("</button>" as *u8) 72 i = i + 1 73 } 74 _fake_w("</div>" as *u8) 75 return 0 76} 77 78func fake_action(action: i64, arg0: i64) -> i64 { 79 if action != 1 { return 0 } 80 if arg0 < 0 { return 0 } 81 if arg0 > 8 { return 0 } 82 var bit: i64 = 1 83 var k: i64 = 0 84 while k < arg0 { bit = bit * 2; k = k + 1 } 85 FAKE_CELLS = FAKE_CELLS + bit 86 return 1 87} 88 89func main() -> i64 { 90 nx_test_init() 91 FAKE_CELLS = 0 92 93 // === Cycle 1: initial render === 94 let buf: *u8 = sys_mmap(K_MAGIC_65536) 95 let cap1: *NxGameCapture = nx_capture_start() 96 fake_render() 97 let n1: i64 = nx_capture_end(cap1, buf, K_MAGIC_65536 as i64) 98 nx_test_expect_eq("cycle 1: bytes captured > 0" as *u8, 99 n1 > 0, 1 as i64) 100 nx_test_expect_class_count("cycle 1: cell count = 9" as *u8, 101 buf, n1, "cell" as *u8, 9 as i64) 102 nx_test_expect_tag_count("cycle 1: button tag count = 9" as *u8, 103 buf, n1, "button" as *u8, 9 as i64) 104 nx_test_expect_not_contains("cycle 1: no X yet" as *u8, 105 buf, n1, ">X<" as *u8) 106 107 // === Click cell 4 via the click-intent extractor === 108 let intent: *NxClickIntent = nx_dom_click_intent(buf, n1, 109 "data-cell-idx" as *u8, 110 "4" as *u8) 111 nx_test_expect_click("click intent for cell 4 (action=1, arg0=4)" as *u8, 112 intent, 1 as i64, 4 as i64) 113 fake_action(intent.action, intent.arg0) 114 115 // === Cycle 2: render after click, X should be at cell 4 === 116 let cap2: *NxGameCapture = nx_capture_start() 117 fake_render() 118 let n2: i64 = nx_capture_end(cap2, buf, K_MAGIC_65536 as i64) 119 nx_test_expect_contains("cycle 2: X now visible somewhere" as *u8, 120 buf, n2, ">X<" as *u8) 121 nx_test_expect_contains("cycle 2: cell 4 button contains X" as *u8, 122 buf, n2, "data-cell-idx=\"4\" data-action=\"1\" data-arg0=\"4\">X" as *u8) 123 124 // === URL params primitive integration === 125 let url: *u8 = "/tictactoe/?v=2&debug=1" as *u8 126 var url_len: i64 = 0 127 while url[url_len] != 0 { url_len = url_len + 1 } 128 let v: i64 = nx_url_param_int(url, url_len, "v" as *u8) 129 nx_test_expect_eq("?v=2 parses to 2" as *u8, v, 2 as i64) 130 let d: i64 = nx_url_param_int(url, url_len, "debug" as *u8) 131 nx_test_expect_eq("?debug=1 parses to 1" as *u8, d, 1 as i64) 132 let m: i64 = nx_url_param_int(url, url_len, "missing" as *u8) 133 nx_test_expect_eq("?missing absent returns -1" as *u8, m, -1 as i64) 134 135 return nx_test_summary() 136}