LCOV - code coverage report
Current view: top level - tests/unit - test_logger.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 54 54
Test Date: 2026-04-15 21:12:52 Functions: 100.0 % 1 1

            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              : }
        

Generated by: LCOV version 2.0-1