code wiki / (root) / nx_navigation_test.nx

nx_navigation_test.nx source

↩ module page · 144 lines · 6952 B

1// nx_navigation_test.nx -- combined KAT for link extraction + 2// 3xx redirect resolution. Together these primitives unlock 3// anchor-click navigation in the bits-up browser. 4// 5// expect_exit: 0 6// license_tier: ORIGINAL 7 8import "nx_syscalls.nx" 9import "nx_html_extract_links.nx" 10import "nx_http_resolve_redirect.nx" 11 12func _fail(n: i64) -> i64 { 13 let b: *u8 = sys_mmap(16) 14 b[0]=0x46; b[1]=0x41; b[2]=0x49; b[3]=0x4C; b[4]=0x3D 15 sys_write(2, b, 5) 16 var x: i64 = n 17 if x < 0 { let m: *u8 = sys_mmap(4); m[0]=0x2D; sys_write(2, m, 1); x = 0 - x } 18 if x == 0 { let z: *u8 = sys_mmap(4); z[0]=0x30; sys_write(2, z, 1) } 19 else { 20 let buf: *u8 = sys_mmap(16) 21 var pos: i64 = 0 22 while x > 0 { buf[pos] = (0x30 + (x % 10)) as u8; x = x / 10; pos = pos + 1 } 23 let out: *u8 = sys_mmap(16) 24 var i: i64 = 0 25 while i < pos { out[i] = buf[pos - 1 - i]; i = i + 1 } 26 sys_write(2, out, pos) 27 } 28 let nl: *u8 = sys_mmap(4); nl[0]=0x0A; sys_write(2, nl, 1) 29 return 0 30} 31 32func _bytes_eq_lit(buf: *u8, off: i64, n: i64, lit: *u8) -> i64 { 33 var i: i64 = 0 34 while i < n { 35 if buf[off + i] != lit[i] { return 0 } 36 i = i + 1 37 } 38 if lit[n] != 0 { return 0 } 39 return 1 40} 41 42func _strlen(s: *u8) -> i64 { 43 var n: i64 = 0 44 while s[n] != 0 { n = n + 1 } 45 return n 46} 47 48func main() -> i64 { 49 // ============================================================ 50 // Section A: nx_html_extract_links 51 // ============================================================ 52 let html: *u8 = "<html><head><script>var s='<a href=\"trap.html\">TRAP</a>';</script></head><body><a href=\"about.html\">about</a><A HREF='/contact'>c</A><a href=\"https://other.com/x\">x</a><a href=\"//cdn/y.html\">y</a></body></html>" 53 var hlen: i64 = 0 54 while html[hlen] != 0 { hlen = hlen + 1 } 55 56 let base: *u8 = "https://www.example.com/path/page.html" 57 let blen: i64 = _strlen(base) 58 59 let url_buf: *u8 = sys_mmap(2048) 60 let offsets: *i64 = sys_mmap(256) as *i64 61 let lengths: *i64 = sys_mmap(256) as *i64 62 63 let n: i64 = nx_html_extract_links(html, hlen, base, blen, 64 url_buf, 2048, offsets, lengths, 32) 65 if n != 4 { _fail(1000 + n); return 1 } // 4 real links, NOT script trap 66 67 if _bytes_eq_lit(url_buf, offsets[0], lengths[0], "https://www.example.com/path/about.html" as *u8) != 1 { _fail(2); return 2 } 68 if _bytes_eq_lit(url_buf, offsets[1], lengths[1], "https://www.example.com/contact" as *u8) != 1 { _fail(3); return 3 } 69 if _bytes_eq_lit(url_buf, offsets[2], lengths[2], "https://other.com/x" as *u8) != 1 { _fail(4); return 4 } 70 if _bytes_eq_lit(url_buf, offsets[3], lengths[3], "https://cdn/y.html" as *u8) != 1 { _fail(5); return 5 } 71 72 // ============================================================ 73 // Section B: status predicates 74 // ============================================================ 75 if nx_redirect_status_is_followable(301) != 1 { _fail(10); return 10 } 76 if nx_redirect_status_is_followable(302) != 1 { _fail(11); return 11 } 77 if nx_redirect_status_is_followable(303) != 1 { _fail(12); return 12 } 78 if nx_redirect_status_is_followable(307) != 1 { _fail(13); return 13 } 79 if nx_redirect_status_is_followable(308) != 1 { _fail(14); return 14 } 80 if nx_redirect_status_is_followable(200) != 0 { _fail(15); return 15 } 81 if nx_redirect_status_is_followable(304) != 0 { _fail(16); return 16 } // not-modified, NOT followable 82 if nx_redirect_status_is_followable(404) != 0 { _fail(17); return 17 } 83 84 if nx_redirect_status_is_permanent(301) != 1 { _fail(20); return 20 } 85 if nx_redirect_status_is_permanent(308) != 1 { _fail(21); return 21 } 86 if nx_redirect_status_is_permanent(302) != 0 { _fail(22); return 22 } 87 if nx_redirect_status_is_permanent(303) != 0 { _fail(23); return 23 } 88 if nx_redirect_status_is_permanent(307) != 0 { _fail(24); return 24 } 89 90 if nx_redirect_status_preserves_method(307) != 1 { _fail(30); return 30 } 91 if nx_redirect_status_preserves_method(308) != 1 { _fail(31); return 31 } 92 if nx_redirect_status_preserves_method(301) != 0 { _fail(32); return 32 } 93 if nx_redirect_status_preserves_method(302) != 0 { _fail(33); return 33 } 94 if nx_redirect_status_preserves_method(303) != 0 { _fail(34); return 34 } 95 96 // ============================================================ 97 // Section C: nx_http_resolve_redirect 98 // ============================================================ 99 // C1: absolute Location 100 let r1: *u8 = "HTTP/1.1 302 Found\r\nLocation: https://new.example.com/\r\nContent-Length: 0\r\n\r\n" 101 let r1n: i64 = _strlen(r1) 102 let next_url: *u8 = sys_mmap(2048) 103 let next_len_p: *i64 = sys_mmap(8) as *i64 104 var rc: i64 = nx_http_resolve_redirect(r1, r1n, 302, 105 base, blen, 106 next_url, 2048, next_len_p) 107 if rc != NX_REDIRECT_RESOLVED { _fail(40 + rc); return 40 } 108 if _bytes_eq_lit(next_url, 0, next_len_p[0], "https://new.example.com/" as *u8) != 1 { _fail(41); return 41 } 109 110 // C2: relative path Location resolves against base 111 let r2: *u8 = "HTTP/1.1 301 Moved Permanently\r\nLocation: /new-path\r\nContent-Length: 0\r\n\r\n" 112 let r2n: i64 = _strlen(r2) 113 rc = nx_http_resolve_redirect(r2, r2n, 301, base, blen, 114 next_url, 2048, next_len_p) 115 if rc != NX_REDIRECT_RESOLVED { _fail(50 + rc); return 50 } 116 if _bytes_eq_lit(next_url, 0, next_len_p[0], "https://www.example.com/new-path" as *u8) != 1 { _fail(51); return 51 } 117 118 // C3: case-insensitive header name (location: not Location:) 119 let r3: *u8 = "HTTP/1.1 303 See Other\r\nlocation: thanks.html\r\nContent-Length: 0\r\n\r\n" 120 let r3n: i64 = _strlen(r3) 121 rc = nx_http_resolve_redirect(r3, r3n, 303, base, blen, 122 next_url, 2048, next_len_p) 123 if rc != NX_REDIRECT_RESOLVED { _fail(60 + rc); return 60 } 124 if _bytes_eq_lit(next_url, 0, next_len_p[0], "https://www.example.com/path/thanks.html" as *u8) != 1 { _fail(61); return 61 } 125 126 // C4: non-3xx status declines politely 127 let r4: *u8 = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n" 128 let r4n: i64 = _strlen(r4) 129 rc = nx_http_resolve_redirect(r4, r4n, 200, base, blen, 130 next_url, 2048, next_len_p) 131 if rc != NX_REDIRECT_NOT_3XX { _fail(70); return 70 } 132 133 // C5: 3xx without Location header 134 let r5: *u8 = "HTTP/1.1 302 Found\r\nContent-Length: 0\r\n\r\n" 135 let r5n: i64 = _strlen(r5) 136 rc = nx_http_resolve_redirect(r5, r5n, 302, base, blen, 137 next_url, 2048, next_len_p) 138 if rc != NX_REDIRECT_NO_LOCATION { _fail(80); return 80 } 139 140 let pass: *u8 = sys_mmap(16) 141 pass[0]=0x50; pass[1]=0x41; pass[2]=0x53; pass[3]=0x53; pass[4]=0x0A 142 sys_write(1, pass, 5) 143 return 0 144}