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}