nx_http_metrics_test.nx source
↩ module page · 180 lines · 7285 B
1// nx_http_metrics_test.nx -- smoke for Prometheus /metrics emitter.
2//
3// expect_exit: 0
4//
5// license_tier: ORIGINAL
6
7import "nx_syscalls_x86_64.nx"
8import "nx_http_metrics.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 + type enum gates ----
31 if nxm_verdict_is_valid(NXM_OK) != 1 { return 1 }
32 if nxm_verdict_is_valid(NXM_VERDICT_N) != 0 { return 2 }
33 if nxm_type_is_valid(NXM_TYPE_COUNTER) != 1 { return 3 }
34 if nxm_type_is_valid(NXM_TYPE_GAUGE) != 1 { return 4 }
35 if nxm_type_is_valid(NXM_TYPE_N) != 0 { return 5 }
36
37 if bytes_eq(nxm_type_name(NXM_TYPE_COUNTER), "counter" as *u8, 7) != 1 { return 6 }
38 if bytes_eq(nxm_type_name(NXM_TYPE_GAUGE), "gauge" as *u8, 5) != 1 { return 7 }
39 if nxm_type_name_len(NXM_TYPE_COUNTER) != 7 { return 8 }
40 if nxm_type_name_len(NXM_TYPE_GAUGE) != 5 { return 9 }
41
42 // ---- Name validator ----
43 if nxm_validate_name("nishi_uptime_ms" as *u8, 15) != 1 { return 20 }
44 if nxm_validate_name("_underscore_ok" as *u8, 14) != 1 { return 21 }
45 if nxm_validate_name("HTTPCount" as *u8, 9) != 1 { return 22 }
46 // Leading digit -> invalid
47 if nxm_validate_name("9metrics" as *u8, 8) != 0 { return 23 }
48 // Dash not in valid set
49 if nxm_validate_name("nishi-uptime" as *u8, 12) != 0 { return 24 }
50 // Empty
51 if nxm_validate_name("" as *u8, 0) != 0 { return 25 }
52
53 // ---- emit_one for a gauge ----
54 let buf: *u8 = sys_mmap(1024)
55 let off: *i64 = sys_mmap(8) as *i64
56 off[0] = 0
57 let scratch: *u8 = sys_mmap(64)
58 let rc1: i64 = nx_http_metrics_emit_one(buf, off, 1024,
59 "nishi_uptime_ms" as *u8, 15,
60 "Daemon uptime in ms" as *u8, 19,
61 NXM_TYPE_GAUGE, 12345,
62 scratch)
63 if rc1 != NXM_OK { return 30 }
64 // Verify lines
65 if bytes_contains(buf, off[0],
66 "# HELP nishi_uptime_ms Daemon uptime in ms\n" as *u8, 43) != 1 { return 31 }
67 if bytes_contains(buf, off[0],
68 "# TYPE nishi_uptime_ms gauge\n" as *u8, 29) != 1 { return 32 }
69 if bytes_contains(buf, off[0],
70 "nishi_uptime_ms 12345\n" as *u8, 22) != 1 { return 33 }
71
72 // ---- emit_one for a counter ----
73 off[0] = 0
74 let rc2: i64 = nx_http_metrics_emit_one(buf, off, 1024,
75 "requests_total" as *u8, 14,
76 "Total requests" as *u8, 14,
77 NXM_TYPE_COUNTER, 42,
78 scratch)
79 if rc2 != NXM_OK { return 40 }
80 if bytes_contains(buf, off[0],
81 "# TYPE requests_total counter\n" as *u8, 30) != 1 { return 41 }
82 if bytes_contains(buf, off[0],
83 "requests_total 42\n" as *u8, 18) != 1 { return 42 }
84
85 // ---- BAD_METRIC_NAME ----
86 off[0] = 0
87 if nx_http_metrics_emit_one(buf, off, 1024,
88 "9bad" as *u8, 4,
89 "" as *u8, 0,
90 NXM_TYPE_GAUGE, 1,
91 scratch) != NXM_BAD_METRIC_NAME { return 50 }
92
93 // ---- BAD_TYPE ----
94 off[0] = 0
95 if nx_http_metrics_emit_one(buf, off, 1024,
96 "ok_name" as *u8, 7,
97 "" as *u8, 0,
98 99, 1,
99 scratch) != NXM_BAD_TYPE { return 60 }
100
101 // ---- emit_response: full HTTP response with 2 metrics ----
102 let names_buf: *u8 = sys_mmap(256)
103 let name_offs: *i64 = sys_mmap(16) as *i64
104 let name_lens: *i64 = sys_mmap(16) as *i64
105 let helps_buf: *u8 = sys_mmap(256)
106 let help_offs: *i64 = sys_mmap(16) as *i64
107 let help_lens: *i64 = sys_mmap(16) as *i64
108 let types: *i64 = sys_mmap(16) as *i64
109 let values: *i64 = sys_mmap(16) as *i64
110
111 // Metric 0: nishi_uptime_ms (gauge, value=12345)
112 let n0: *u8 = "nishi_uptime_ms" as *u8
113 var i: i64 = 0
114 while i < 15 { names_buf[i] = n0[i]; i = i + 1 }
115 name_offs[0] = 0
116 name_lens[0] = 15
117 let h0: *u8 = "Uptime" as *u8
118 var j: i64 = 0
119 while j < 6 { helps_buf[j] = h0[j]; j = j + 1 }
120 help_offs[0] = 0
121 help_lens[0] = 6
122 types[0] = NXM_TYPE_GAUGE
123 values[0] = 12345
124
125 // Metric 1: nishi_requests_total (counter, value=42)
126 let n1: *u8 = "nishi_requests_total" as *u8
127 var k: i64 = 0
128 while k < 20 { names_buf[15 + k] = n1[k]; k = k + 1 }
129 name_offs[1] = 15
130 name_lens[1] = 20
131 let h1: *u8 = "Total requests" as *u8
132 var m: i64 = 0
133 while m < 14 { helps_buf[6 + m] = h1[m]; m = m + 1 }
134 help_offs[1] = 6
135 help_lens[1] = 14
136 types[1] = NXM_TYPE_COUNTER
137 values[1] = 42
138
139 let resp: *u8 = sys_mmap(2048)
140 let resp_n: *i64 = sys_mmap(8) as *i64
141 let scratch2: *u8 = sys_mmap(64)
142 let rc3: i64 = nx_http_metrics_emit_response(
143 resp, 2048, resp_n,
144 names_buf, name_offs, name_lens,
145 helps_buf, help_offs, help_lens,
146 types, values, 2,
147 scratch2)
148 if rc3 != NXM_OK { return 70 }
149 if resp_n[0] <= 0 { return 71 }
150
151 // Verify response shape
152 if bytes_contains(resp, resp_n[0],
153 "HTTP/1.1 200 OK" as *u8, 15) != 1 { return 72 }
154 if bytes_contains(resp, resp_n[0],
155 "text/plain; version=0.0.4" as *u8, 25) != 1 { return 73 }
156 if bytes_contains(resp, resp_n[0],
157 "nishi_uptime_ms 12345\n" as *u8, 22) != 1 { return 74 }
158 if bytes_contains(resp, resp_n[0],
159 "nishi_requests_total 42\n" as *u8, 24) != 1 { return 75 }
160 if bytes_contains(resp, resp_n[0],
161 "# TYPE nishi_uptime_ms gauge\n" as *u8, 29) != 1 { return 76 }
162 if bytes_contains(resp, resp_n[0],
163 "# TYPE nishi_requests_total counter\n" as *u8, 36) != 1 { return 77 }
164
165 // ---- BAD_ARG paths ----
166 if nx_http_metrics_emit_one(0 as *u8, off, 1024,
167 "x" as *u8, 1, "" as *u8, 0,
168 NXM_TYPE_GAUGE, 1, scratch) != NXM_BAD_ARG { return 80 }
169 if nx_http_metrics_emit_one(buf, 0 as *i64, 1024,
170 "x" as *u8, 1, "" as *u8, 0,
171 NXM_TYPE_GAUGE, 1, scratch) != NXM_BAD_ARG { return 81 }
172 if nx_http_metrics_emit_one(buf, off, 0,
173 "x" as *u8, 1, "" as *u8, 0,
174 NXM_TYPE_GAUGE, 1, scratch) != NXM_BAD_ARG { return 82 }
175 if nx_http_metrics_emit_one(buf, off, 1024,
176 "x" as *u8, 1, "" as *u8, 0,
177 NXM_TYPE_GAUGE, 1, 0 as *u8) != NXM_BAD_ARG { return 83 }
178
179 return 0
180}