Logging in C with support for monoid logging
logging jsonl monoid c
0

Configure Feed

Select the types of activity you want to include in your feed.

clog / tests / test_clog.c
3.6 kB 136 lines
1#define _POSIX_C_SOURCE 200809L 2#include <stdio.h> 3#include <string.h> 4#include <unistd.h> 5#include "test.h" 6#include "clog.h" 7#include "dynarr.h" 8 9/* --- stdout capture helpers -------------------------------------------- */ 10 11static FILE *capture_begin(int *saved_fd) { 12 FILE *tmp = tmpfile(); 13 *saved_fd = dup(STDOUT_FILENO); 14 dup2(fileno(tmp), STDOUT_FILENO); 15 return tmp; 16} 17 18static void capture_end(FILE *tmp, int saved_fd, char *buf, size_t size) { 19 fflush(stdout); 20 dup2(saved_fd, STDOUT_FILENO); 21 close(saved_fd); 22 rewind(tmp); 23 if (fgets(buf, (int)size, tmp) == NULL) buf[0] = '\0'; 24 fclose(tmp); 25} 26 27/* --- monoid tests ------------------------------------------------------- */ 28 29static void test_init_empty(void) { 30 CLog log = clog_log_init(); 31 ASSERT_NOT_NULL(log); 32 ASSERT_EQ(da_length(log), (size_t)0); 33 clog_log_free(log); 34} 35 36static void test_append_count(void) { 37 CLog log = clog_log_init(); 38 clogm(CLOG_INF, log, "one"); 39 clogm(CLOG_DBG, log, "two"); 40 clogm(CLOG_ERR, log, "three"); 41 ASSERT_EQ(da_length(log), (size_t)3); 42 clog_log_free(log); 43} 44 45static void test_entry_fields(void) { 46 CLog log = clog_log_init(); 47 clogm(CLOG_WRN, log, "hello"); 48 ClogEntry *e = &log[0]; 49 ASSERT_EQ(e->level, CLOG_WRN); 50 ASSERT_STR_EQ(e->msg, "hello"); 51 ASSERT_NOT_NULL(e->file); 52 ASSERT_NOT_NULL(e->func); 53 ASSERT(e->line > 0); 54 ASSERT(e->ts[0] != '\0'); 55 clog_log_free(log); 56} 57 58static void test_msg_truncation(void) { 59 CLog log = clog_log_init(); 60 char big[CLOG_MSG_MAX + 64]; 61 memset(big, 'a', sizeof(big) - 1); 62 big[sizeof(big) - 1] = '\0'; 63 clogm(CLOG_INF, log, big); 64 ASSERT_EQ(strlen(log[0].msg), (size_t)(CLOG_MSG_MAX - 1)); 65 clog_log_free(log); 66} 67 68/* --- format tests ------------------------------------------------------- */ 69 70static void test_jsonl_fields(void) { 71 clog_set_fmt(CLOG_FMT_JSONL); 72 int saved; char buf[4096]; 73 FILE *tmp = capture_begin(&saved); 74 clog(CLOG_ERR, "boom"); 75 capture_end(tmp, saved, buf, sizeof(buf)); 76 77 ASSERT_NOT_NULL(strstr(buf, "\"level\":\"ERR\"")); 78 ASSERT_NOT_NULL(strstr(buf, "\"msg\":\"boom\"")); 79 ASSERT_NOT_NULL(strstr(buf, "\"ts\":\"")); 80 ASSERT_NOT_NULL(strstr(buf, "\"file\":\"")); 81 ASSERT_NOT_NULL(strstr(buf, "\"func\":\"")); 82 clog_set_fmt(CLOG_FMT_JSONL); 83} 84 85static void test_jsonl_escaping(void) { 86 clog_set_fmt(CLOG_FMT_JSONL); 87 int saved; char buf[4096]; 88 FILE *tmp = capture_begin(&saved); 89 clog(CLOG_INF, "say \"hello\""); 90 capture_end(tmp, saved, buf, sizeof(buf)); 91 92 ASSERT_NOT_NULL(strstr(buf, "say \\\"hello\\\"")); 93 clog_set_fmt(CLOG_FMT_JSONL); 94} 95 96static void test_text_fields(void) { 97 clog_set_fmt(CLOG_FMT_TEXT); 98 int saved; char buf[4096]; 99 FILE *tmp = capture_begin(&saved); 100 clog(CLOG_INF, "hello world"); 101 capture_end(tmp, saved, buf, sizeof(buf)); 102 103 ASSERT_NOT_NULL(strstr(buf, "INF")); 104 ASSERT_NOT_NULL(strstr(buf, "hello world")); 105 clog_set_fmt(CLOG_FMT_JSONL); 106} 107 108static void test_print_smoke(void) { 109 clog_set_fmt(CLOG_FMT_JSONL); 110 CLog log = clog_log_init(); 111 clogm(CLOG_INF, log, "a"); 112 clogm(CLOG_WRN, log, "b"); 113 int saved; char buf[4096]; 114 FILE *tmp = capture_begin(&saved); 115 clog_log_print(log); 116 capture_end(tmp, saved, buf, sizeof(buf)); 117 118 ASSERT_NOT_NULL(strstr(buf, "\"level\":\"INF\"")); 119 clog_log_free(log); 120 clog_set_fmt(CLOG_FMT_JSONL); 121} 122 123/* ----------------------------------------------------------------------- */ 124 125int main(void) { 126 test_init_empty(); 127 test_append_count(); 128 test_entry_fields(); 129 test_msg_truncation(); 130 test_jsonl_fields(); 131 test_jsonl_escaping(); 132 test_text_fields(); 133 test_print_smoke(); 134 printf("test_clog: all tests passed\n"); 135 return 0; 136}