Line data Source code
1 : #include "test_helpers.h"
2 : #include "logger.h"
3 : #include "fs_util.h"
4 : #include "raii.h"
5 : #include <stdio.h>
6 : #include <string.h>
7 : #include <stdlib.h>
8 : #include <unistd.h>
9 : #include <sys/stat.h>
10 :
11 1 : void test_logger(void) {
12 1 : const char *test_log_dir = "/tmp/email-cli-log-test";
13 1 : const char *test_log_file = "/tmp/email-cli-log-test/test.log";
14 1 : const char *rotated_log_file = "/tmp/email-cli-log-test/test.log.1";
15 :
16 : // 1. Prepare directory
17 1 : fs_mkdir_p(test_log_dir, 0700);
18 :
19 : // 2. Test Init
20 1 : int res = logger_init(test_log_file, LOG_DEBUG);
21 1 : ASSERT(res == 0, "logger_init should return 0");
22 :
23 : // 3. Test Logging at various levels
24 1 : logger_log(LOG_DEBUG, "Test debug message");
25 1 : logger_log(LOG_INFO, "Test info message");
26 1 : logger_log(LOG_WARN, "Test warn message");
27 1 : logger_log(LOG_ERROR, "Test error message");
28 :
29 : // 4. Verify file exists and has content
30 1 : struct stat st;
31 1 : ASSERT(stat(test_log_file, &st) == 0, "Log file should exist");
32 1 : ASSERT(st.st_size > 0, "Log file should not be empty");
33 :
34 : // 5. Test level filtering: reinit with LOG_ERROR, lower-level messages suppressed
35 1 : logger_close();
36 1 : res = logger_init(test_log_file, LOG_ERROR);
37 1 : ASSERT(res == 0, "logger_init with LOG_ERROR should succeed");
38 1 : logger_log(LOG_DEBUG, "This should be filtered out");
39 1 : logger_log(LOG_INFO, "This should be filtered out");
40 1 : logger_log(LOG_WARN, "This should be filtered out");
41 :
42 : // 6. Test Clean Logs
43 : {
44 2 : RAII_FILE FILE *f = fopen("/tmp/email-cli-log-test/session.log.old", "w");
45 1 : if (f) {
46 1 : fprintf(f, "old data");
47 : }
48 : }
49 1 : res = logger_clean_logs(test_log_dir);
50 1 : ASSERT(res == 0, "logger_clean_logs should return 0");
51 1 : ASSERT(access("/tmp/email-cli-log-test/session.log.old", F_OK) == -1,
52 : "Old log should be deleted");
53 :
54 : // 7. Close and verify logger_log with NULL fp does not crash
55 1 : logger_close();
56 1 : logger_log(LOG_ERROR, "Should not crash with NULL fp");
57 :
58 : // 8. Test logger_init with invalid (non-existent) path
59 1 : res = logger_init("/nonexistent/dir/path/test.log", LOG_INFO);
60 1 : ASSERT(res == -1, "logger_init should return -1 for invalid path");
61 :
62 : // 9. Test logger_clean_logs with non-existent directory
63 1 : res = logger_clean_logs("/nonexistent/dir/path");
64 1 : ASSERT(res == -1, "logger_clean_logs should return -1 for non-existent dir");
65 :
66 : // 10. Test log rotation: create a file > 5MB, then init should rotate it
67 1 : unlink(test_log_file);
68 : {
69 2 : RAII_FILE FILE *big = fopen(test_log_file, "wb");
70 1 : if (big) {
71 1 : fseek(big, 5 * 1024 * 1024, SEEK_SET);
72 1 : fputc('\0', big);
73 : }
74 : }
75 1 : res = logger_init(test_log_file, LOG_INFO);
76 1 : ASSERT(res == 0, "logger_init should succeed after rotating oversized log");
77 1 : ASSERT(stat(test_log_file, &st) == 0, "Log file should exist after rotation");
78 1 : ASSERT(st.st_size < 5 * 1024 * 1024,
79 : "Current log should be small after rotation");
80 1 : ASSERT(access(rotated_log_file, F_OK) == 0,
81 : "Rotated log file should exist");
82 1 : logger_close();
83 :
84 : // 11. Test stderr mirror path (lines 100-104): re-enable stderr, log error
85 : {
86 1 : logger_init(test_log_file, LOG_DEBUG);
87 1 : logger_set_stderr(1); /* re-enable stderr mirror */
88 1 : logger_log(LOG_ERROR, "stderr mirror test");
89 1 : logger_set_stderr(0); /* restore for subsequent tests */
90 1 : logger_close();
91 : }
92 :
93 : // 12. Unknown log level → level_to_str returns "UNKNOWN"
94 : {
95 1 : logger_init(test_log_file, LOG_DEBUG);
96 1 : logger_log(99, "unknown level test"); /* level 99 → "UNKNOWN" */
97 1 : logger_close();
98 : }
99 :
100 : // Manual cleanup
101 1 : unlink(test_log_file);
102 1 : unlink(rotated_log_file);
103 1 : rmdir(test_log_dir);
104 : }
|