code wiki / (root) / nx_log_jsonl_test.nx

nx_log_jsonl_test.nx source

↩ module page · 177 lines · 7429 B

1// nx_log_jsonl_test.nx -- smoke for structured JSONL log emitter. 2// 3// expect_exit: 0 4// 5// license_tier: ORIGINAL 6 7import "nx_syscalls_x86_64.nx" 8import "nx_log_jsonl.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 // ---- Level + verdict enum gates ---- 31 if nxl_level_is_valid(NXL_DEBUG) != 1 { return 1 } 32 if nxl_level_is_valid(NXL_ERROR) != 1 { return 2 } 33 if nxl_level_is_valid(NXL_LEVEL_N) != 0 { return 3 } 34 if nxl_verdict_is_valid(NXL_OK) != 1 { return 4 } 35 if nxl_verdict_is_valid(NXL_VERDICT_N) != 0 { return 5 } 36 37 if bytes_eq(nxl_level_name(NXL_DEBUG), "DEBUG" as *u8, 5) != 1 { return 6 } 38 if bytes_eq(nxl_level_name(NXL_INFO), "INFO" as *u8, 4) != 1 { return 7 } 39 if bytes_eq(nxl_level_name(NXL_WARN), "WARN" as *u8, 4) != 1 { return 8 } 40 if bytes_eq(nxl_level_name(NXL_ERROR), "ERROR" as *u8, 5) != 1 { return 9 } 41 if nxl_level_name_len(NXL_INFO) != 4 { return 10 } 42 if nxl_level_name_len(NXL_DEBUG) != 5 { return 11 } 43 44 // ---- Simple INFO line ---- 45 let buf: *u8 = sys_mmap(1024) 46 let off: *i64 = sys_mmap(8) as *i64 47 let scratch: *u8 = sys_mmap(64) 48 off[0] = 0 49 let rc1: i64 = nx_log_emit_line(buf, off, 1024, 50 1234, 51 NXL_INFO, 52 "nx_audit" as *u8, 8, 53 "daemon started" as *u8, 14, 54 scratch) 55 if rc1 != NXL_OK { return 20 } 56 // Expected: 57 // {"ts_ms":1234,"level":"INFO","module":"nx_audit","msg":"daemon started"}\n 58 let exp1: *u8 = "{\"ts_ms\":1234,\"level\":\"INFO\",\"module\":\"nx_audit\",\"msg\":\"daemon started\"}\n" as *u8 59 if off[0] != 73 { return 21 } 60 if bytes_eq(buf, exp1, 73) != 1 { return 22 } 61 62 // ---- WARN line with int field ---- 63 off[0] = 0 64 let rc2: i64 = nx_log_emit_line_with_int(buf, off, 1024, 65 5000, 66 NXL_WARN, 67 "nx_super" as *u8, 8, 68 "crash detected" as *u8, 14, 69 "n_restarts" as *u8, 10, 70 3, 71 scratch) 72 if rc2 != NXL_OK { return 30 } 73 if bytes_contains(buf, off[0], 74 "\"level\":\"WARN\"" as *u8, 14) != 1 { return 31 } 75 if bytes_contains(buf, off[0], 76 "\"n_restarts\":3" as *u8, 14) != 1 { return 32 } 77 if bytes_contains(buf, off[0], 78 "\"ts_ms\":5000" as *u8, 12) != 1 { return 33 } 79 80 // ---- ERROR line with string field ---- 81 off[0] = 0 82 let rc3: i64 = nx_log_emit_line_with_str(buf, off, 1024, 83 9999, 84 NXL_ERROR, 85 "nx_dns" as *u8, 6, 86 "bind failed" as *u8, 11, 87 "err" as *u8, 3, 88 "EADDRINUSE" as *u8, 10, 89 scratch) 90 if rc3 != NXL_OK { return 40 } 91 if bytes_contains(buf, off[0], 92 "\"level\":\"ERROR\"" as *u8, 15) != 1 { return 41 } 93 if bytes_contains(buf, off[0], 94 "\"err\":\"EADDRINUSE\"" as *u8, 18) != 1 { return 42 } 95 96 // ---- JSON escape: quotes + backslash in msg ---- 97 off[0] = 0 98 let evil: *u8 = "user said \"hi\\there\"" as *u8 99 let rc4: i64 = nx_log_emit_line(buf, off, 1024, 100 1, NXL_INFO, 101 "x" as *u8, 1, 102 evil, 20, 103 scratch) 104 if rc4 != NXL_OK { return 50 } 105 // Quotes must be escaped to \" 106 if bytes_contains(buf, off[0], 107 "user said \\\"hi" as *u8, 14) != 1 { return 51 } 108 // Backslash must be escaped to \\ 109 if bytes_contains(buf, off[0], 110 "\\\\there" as *u8, 7) != 1 { return 52 } 111 112 // ---- JSON escape: control char (newline in user input) ---- 113 off[0] = 0 114 let injection: *u8 = sys_mmap(32) 115 injection[0] = 0x68 as u8 // h 116 injection[1] = 0x65 as u8 // e 117 injection[2] = 0x6c as u8 // l 118 injection[3] = 0x6c as u8 // l 119 injection[4] = 0x6f as u8 // o 120 injection[5] = 0x0a as u8 // \n (injection attempt) 121 injection[6] = 0x65 as u8 // e 122 injection[7] = 0x76 as u8 // v 123 injection[8] = 0x69 as u8 // i 124 injection[9] = 0x6c as u8 // l 125 let rc5: i64 = nx_log_emit_line(buf, off, 1024, 126 1, NXL_WARN, 127 "x" as *u8, 1, 128 injection, 10, 129 scratch) 130 if rc5 != NXL_OK { return 60 } 131 // The newline INSIDE the message must be encoded as \n, not 132 // actual newline. Verify by counting actual newlines in output 133 // -- should be exactly ONE (the terminating \n after }). 134 var nl_count: i64 = 0 135 var i: i64 = 0 136 while i < off[0] { 137 if buf[i] == 0x0a as u8 { nl_count = nl_count + 1 } 138 i = i + 1 139 } 140 if nl_count != 1 { return 61 } 141 // Verify the escaped form is in the body. 142 if bytes_contains(buf, off[0], "hello\\nevil" as *u8, 11) != 1 { return 62 } 143 144 // ---- BAD_LEVEL ---- 145 off[0] = 0 146 if nx_log_emit_line(buf, off, 1024, 1, 99, 147 "x" as *u8, 1, "y" as *u8, 1, 148 scratch) != NXL_BAD_LEVEL { return 70 } 149 150 // ---- BAD_ARG paths ---- 151 off[0] = 0 152 if nx_log_emit_line(0 as *u8, off, 1024, 1, NXL_INFO, 153 "x" as *u8, 1, "y" as *u8, 1, 154 scratch) != NXL_BAD_ARG { return 80 } 155 if nx_log_emit_line(buf, 0 as *i64, 1024, 1, NXL_INFO, 156 "x" as *u8, 1, "y" as *u8, 1, 157 scratch) != NXL_BAD_ARG { return 81 } 158 if nx_log_emit_line(buf, off, 1024, 1, NXL_INFO, 159 0 as *u8, 1, "y" as *u8, 1, 160 scratch) != NXL_BAD_ARG { return 82 } 161 if nx_log_emit_line(buf, off, 1024, 1, NXL_INFO, 162 "x" as *u8, 0, "y" as *u8, 1, 163 scratch) != NXL_BAD_ARG { return 83 } 164 if nx_log_emit_line(buf, off, 1024, 1, NXL_INFO, 165 "x" as *u8, 1, 0 as *u8, 1, 166 scratch) != NXL_BAD_ARG { return 84 } 167 168 // ---- OOM_BUFFER on too-small buffer ---- 169 let tiny: *u8 = sys_mmap(16) 170 let t_off: *i64 = sys_mmap(8) as *i64 171 t_off[0] = 0 172 if nx_log_emit_line(tiny, t_off, 16, 1, NXL_INFO, 173 "x" as *u8, 1, "abcdefg" as *u8, 7, 174 scratch) != NXL_OOM_BUFFER { return 90 } 175 176 return 0 177}