code wiki / (root) / nx_https_redirect_test.nx

nx_https_redirect_test.nx source

↩ module page · 65 lines · 3319 B

1// nx_https_redirect_test.nx -- gate for fetcher upgrade F-1 (redirect logic). 2// Deterministic (canned responses, no network): proves (1) the 3xx status set, 3// (2) Location extraction (exact bytes), (3) case-insensitive header match, 4// (4) absent Location -> 0, (5) a non-redirect 200 is not followed. 5 6import "nx_syscalls.nx" 7import "nx_runtime.nx" 8import "nx_tier.nx" 9import "nx_https_redirect.nx" 10 11func nx_assert_eq(label: *u8, got: nx_int, want: nx_int, pass_n: *nx_int, fail_n: *nx_int) { 12 print(label); print(": got=" as *u8); print_i64(got); print(" want=" as *u8); print_i64(want) 13 if got == want { println(" PASS" as *u8); pass_n[0] = pass_n[0] + 1; return } 14 println(" FAIL" as *u8); fail_n[0] = fail_n[0] + 1 15} 16 17func t_slen(s: *u8) -> nx_int { var n: nx_int = 0; while s[n] != 0 as u8 { n = n + 1 } return n } 18func t_bytes_eq(a: *u8, b: *u8, n: nx_int) -> nx_int { 19 var i: nx_int = 0 20 while i < n { if a[i] != b[i] { return 0 } i = i + 1 } 21 return 1 22} 23 24func main() -> nx_exit { 25 let pass_n: *nx_int = (sys_mmap(8)) as *nx_int 26 let fail_n: *nx_int = (sys_mmap(8)) as *nx_int 27 pass_n[0] = 0 28 fail_n[0] = 0 29 let out: *u8 = sys_mmap(512) 30 31 println("=== FETCHER F-1: redirect logic ===" as *u8) 32 33 // --- is_redirect status set --- 34 nx_assert_eq("301 -> follow " as *u8, nx_redir_is_redirect(301), 1, pass_n, fail_n) 35 nx_assert_eq("302 -> follow " as *u8, nx_redir_is_redirect(302), 1, pass_n, fail_n) 36 nx_assert_eq("303 -> follow " as *u8, nx_redir_is_redirect(303), 1, pass_n, fail_n) 37 nx_assert_eq("307 -> follow " as *u8, nx_redir_is_redirect(307), 1, pass_n, fail_n) 38 nx_assert_eq("308 -> follow " as *u8, nx_redir_is_redirect(308), 1, pass_n, fail_n) 39 nx_assert_eq("200 -> no follow " as *u8, nx_redir_is_redirect(200), 0, pass_n, fail_n) 40 nx_assert_eq("404 -> no follow " as *u8, nx_redir_is_redirect(404), 0, pass_n, fail_n) 41 42 // --- Location extraction (exact bytes) --- 43 let r1: *u8 = "HTTP/1.1 301 Moved Permanently\r\nServer: x\r\nLocation: https://www.example.com/path\r\nContent-Length: 0\r\n\r\n" as *u8 44 let exp1: *u8 = "https://www.example.com/path" as *u8 45 let n1: nx_int = nx_redir_location(r1, t_slen(r1), out, 512) 46 nx_assert_eq("location length " as *u8, n1, t_slen(exp1), pass_n, fail_n) 47 nx_assert_eq("location bytes match " as *u8, t_bytes_eq(out, exp1, n1), 1, pass_n, fail_n) 48 49 // --- case-insensitive header name (lowercase 'location') --- 50 let r2: *u8 = "HTTP/1.1 302 Found\r\nlocation: https://a.io/b\r\n\r\n" as *u8 51 let exp2: *u8 = "https://a.io/b" as *u8 52 let n2: nx_int = nx_redir_location(r2, t_slen(r2), out, 512) 53 nx_assert_eq("ci location length " as *u8, n2, t_slen(exp2), pass_n, fail_n) 54 nx_assert_eq("ci location bytes " as *u8, t_bytes_eq(out, exp2, n2), 1, pass_n, fail_n) 55 56 // --- absent Location -> 0 --- 57 let r3: *u8 = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" as *u8 58 nx_assert_eq("no Location -> 0 " as *u8, nx_redir_location(r3, t_slen(r3), out, 512), 0, pass_n, fail_n) 59 60 println("" as *u8) 61 print("PASS=" as *u8); print_i64(pass_n[0]) 62 print(" FAIL=" as *u8); print_i64(fail_n[0]); println("" as *u8) 63 if fail_n[0] > 0 { return 1 } 64 return 0 65}