nx_http_cache_test.nx source
↩ module page · 141 lines · 5708 B
1// nx_http_cache_test.nx -- smoke for HTTP cache primitive.
2//
3// expect_exit: 0
4//
5// license_tier: ORIGINAL
6
7import "nx_syscalls_x86_64.nx"
8import "nx_http_cache.nx"
9
10func bytes_eq(a: *u8, b: *u8, n: i64) -> i64 {
11 var i: i64 = 0
12 while i < n {
13 if a[i] != b[i] { return 0 }
14 i = i + 1
15 }
16 return 1
17}
18
19func bytes_contains(haystack: *u8, h_n: i64, needle: *u8, n_n: i64) -> i64 {
20 if n_n > h_n { return 0 }
21 var i: i64 = 0
22 while i <= h_n - n_n {
23 if bytes_eq(((haystack as i64) + i) as *u8, needle, n_n) == 1 { return 1 }
24 i = i + 1
25 }
26 return 0
27}
28
29func main() -> i64 {
30 // ---- Verdict enum gates ----
31 if nxc_verdict_is_valid(NXC_OK_FRESH) != 1 { return 1 }
32 if nxc_verdict_is_valid(NXC_OK_NOT_MODIFIED) != 1 { return 2 }
33 if nxc_verdict_is_valid(NXC_VERDICT_N) != 0 { return 3 }
34 if bytes_eq(nxc_verdict_name(NXC_OK_FRESH), "OK_FRESH" as *u8, 8) != 1 { return 4 }
35 if bytes_eq(nxc_verdict_name(NXC_OK_NOT_MODIFIED), "OK_NOT_MODIFIED" as *u8, 15) != 1 { return 5 }
36
37 // ---- FNV-1a 64-bit determinism ----
38 let h1: i64 = nxc_fnv1a_64("hello" as *u8, 5)
39 let h2: i64 = nxc_fnv1a_64("hello" as *u8, 5)
40 if h1 != h2 { return 10 }
41 // Different inputs produce different hashes.
42 let h3: i64 = nxc_fnv1a_64("hellp" as *u8, 5)
43 if h1 == h3 { return 11 }
44 let h4: i64 = nxc_fnv1a_64("" as *u8, 0)
45 // Init constant for FNV-1a-64 = -3750763034362895579
46 if h4 != -3750763034362895579 { return 12 }
47
48 // ---- Hex emission of a known value ----
49 let hex_buf: *u8 = sys_mmap(32)
50 let hex_off: *i64 = sys_mmap(8) as *i64
51 hex_off[0] = 0
52 let known_val: i64 = 0x0123456789abcdef
53 nxc_put_hex_64(hex_buf, hex_off, 32, known_val)
54 if hex_off[0] != 16 { return 20 }
55 if bytes_eq(hex_buf, "0123456789abcdef" as *u8, 16) != 1 { return 21 }
56
57 // ---- ETag compute: write 16-char hex ----
58 let etag_buf: *u8 = sys_mmap(32)
59 let etag_off: *i64 = sys_mmap(8) as *i64
60 etag_off[0] = 0
61 let body: *u8 = "Hello, World!" as *u8
62 let rc1: i64 = nx_http_etag_compute(body, 13, etag_buf, etag_off, 32)
63 if rc1 != NXC_OK_FRESH { return 30 }
64 if etag_off[0] != 16 { return 31 }
65 // Same body should produce same hash.
66 let etag_buf2: *u8 = sys_mmap(32)
67 let etag_off2: *i64 = sys_mmap(8) as *i64
68 etag_off2[0] = 0
69 nx_http_etag_compute(body, 13, etag_buf2, etag_off2, 32)
70 if bytes_eq(etag_buf, etag_buf2, 16) != 1 { return 32 }
71
72 // ---- If-None-Match: exact match ----
73 let etag: *u8 = "abc123def4567890" as *u8
74 if nx_http_if_none_match_matches(
75 "\"abc123def4567890\"" as *u8, 18,
76 etag, 16) != 1 { return 40 }
77 // Mismatch
78 if nx_http_if_none_match_matches(
79 "\"xyz789def4567890\"" as *u8, 18,
80 etag, 16) != 0 { return 41 }
81 // Wildcard
82 if nx_http_if_none_match_matches(
83 "*" as *u8, 1, etag, 16) != 1 { return 42 }
84 // Multiple values, one matches
85 if nx_http_if_none_match_matches(
86 "\"first\", \"abc123def4567890\"" as *u8, 27,
87 etag, 16) != 1 { return 43 }
88
89 // ---- Cache decide: no If-None-Match -> FRESH ----
90 if nx_http_cache_decide(0 as *u8, 0, etag, 16) != NXC_OK_FRESH { return 50 }
91 // Empty If-None-Match -> FRESH
92 if nx_http_cache_decide(0 as *u8, 0, etag, 16) != NXC_OK_FRESH { return 51 }
93 // Matching If-None-Match -> NOT_MODIFIED
94 if nx_http_cache_decide("\"abc123def4567890\"" as *u8, 18,
95 etag, 16) != NXC_OK_NOT_MODIFIED { return 52 }
96 // Non-matching If-None-Match -> FRESH
97 if nx_http_cache_decide("\"zzzzzzzzzzzzzzz\"" as *u8, 17,
98 etag, 16) != NXC_OK_FRESH { return 53 }
99
100 // ---- 304 emit ----
101 let resp_buf: *u8 = sys_mmap(512)
102 let resp_off: *i64 = sys_mmap(8) as *i64
103 resp_off[0] = 0
104 let rc_304: i64 = nx_http_emit_304(resp_buf, resp_off, 512,
105 etag, 16, 300)
106 if rc_304 != NXC_OK_FRESH { return 60 }
107 if resp_off[0] <= 0 { return 61 }
108 // Verify shape
109 if bytes_contains(resp_buf, resp_off[0],
110 "HTTP/1.1 304 Not Modified" as *u8, 25) != 1 { return 62 }
111 if bytes_contains(resp_buf, resp_off[0],
112 "ETag: \"abc123def4567890\"" as *u8, 24) != 1 { return 63 }
113 if bytes_contains(resp_buf, resp_off[0],
114 "Cache-Control: public, max-age=300" as *u8, 33) != 1 { return 64 }
115 if bytes_contains(resp_buf, resp_off[0],
116 "Content-Length: 0" as *u8, 17) != 1 { return 65 }
117
118 // ---- Cache-Control header injection ----
119 let cc_buf: *u8 = sys_mmap(128)
120 let cc_off: *i64 = sys_mmap(8) as *i64
121 cc_off[0] = 0
122 let rc_cc: i64 = nx_http_emit_cache_control_header(cc_buf, cc_off, 128, 60)
123 if rc_cc != NXC_OK_FRESH { return 70 }
124 if bytes_contains(cc_buf, cc_off[0],
125 "Cache-Control: public, max-age=60\r\n" as *u8, 35) != 1 { return 71 }
126
127 // Max-age=0
128 cc_off[0] = 0
129 nx_http_emit_cache_control_header(cc_buf, cc_off, 128, 0)
130 if bytes_contains(cc_buf, cc_off[0],
131 "max-age=0\r\n" as *u8, 11) != 1 { return 72 }
132
133 // ---- BAD_ARG paths ----
134 if nx_http_etag_compute(0 as *u8, 5, etag_buf, etag_off, 32) != NXC_BAD_ARG { return 80 }
135 if nx_http_etag_compute(body, 13, 0 as *u8, etag_off, 32) != NXC_BAD_ARG { return 81 }
136 if nx_http_etag_compute(body, 13, etag_buf, 0 as *i64, 32) != NXC_BAD_ARG { return 82 }
137 if nx_http_emit_304(0 as *u8, resp_off, 512, etag, 16, 0) != NXC_BAD_ARG { return 83 }
138 if nx_http_emit_304(resp_buf, resp_off, 512, etag, 16, -1) != NXC_BAD_ARG { return 84 }
139
140 return 0
141}