#include "test_framework.h" #include "../src/logging.h" #include #include #include #include #include void test_logging_debug_mode(void) { TEST_SUITE_BEGIN("Logging Debug Mode"); logging_set_debug(0); TEST_ASSERT_EQ(0, logging_get_debug(), "Debug mode disabled"); logging_set_debug(1); TEST_ASSERT_EQ(1, logging_get_debug(), "Debug mode enabled"); logging_set_debug(0); TEST_ASSERT_EQ(0, logging_get_debug(), "Debug mode disabled again"); TEST_SUITE_END(); } void test_logging_set_file(void) { TEST_SUITE_BEGIN("Logging Set File"); char tmp_path[] = "/tmp/test_rproxy_log_XXXXXX"; int fd = mkstemp(tmp_path); TEST_ASSERT(fd >= 0, "Temp file created"); close(fd); int result = logging_set_file(tmp_path); TEST_ASSERT_EQ(0, result, "Set log file succeeds"); log_info("Test log message"); struct stat st; stat(tmp_path, &st); TEST_ASSERT(st.st_size > 0, "Log file has content"); logging_cleanup(); unlink(tmp_path); TEST_SUITE_END(); } void test_logging_set_file_null(void) { TEST_SUITE_BEGIN("Logging Set File NULL"); int result = logging_set_file(NULL); TEST_ASSERT_EQ(0, result, "NULL path returns to stdout"); log_info("Test message to stdout"); TEST_ASSERT(1, "Logging to stdout works"); TEST_SUITE_END(); } void test_logging_set_file_invalid(void) { TEST_SUITE_BEGIN("Logging Set File Invalid Path"); int result = logging_set_file("/nonexistent/directory/log.txt"); TEST_ASSERT_EQ(-1, result, "Invalid path returns -1"); TEST_SUITE_END(); } void test_logging_log_functions(void) { TEST_SUITE_BEGIN("Logging Log Functions"); char tmp_path[] = "/tmp/test_rproxy_log_XXXXXX"; int fd = mkstemp(tmp_path); close(fd); logging_set_file(tmp_path); log_info("Info message: %d", 42); log_error("Error message: %s", "test error"); logging_set_debug(1); log_debug("Debug message: %s", "debug info"); logging_set_debug(0); log_debug("This should not appear"); struct stat st; stat(tmp_path, &st); TEST_ASSERT(st.st_size > 0, "Log messages written"); FILE *f = fopen(tmp_path, "r"); char content[4096] = {0}; if (f) { size_t bytes_read = fread(content, 1, sizeof(content) - 1, f); (void)bytes_read; fclose(f); } TEST_ASSERT(strstr(content, "INFO") != NULL, "INFO level present"); TEST_ASSERT(strstr(content, "ERROR") != NULL, "ERROR level present"); TEST_ASSERT(strstr(content, "DEBUG") != NULL, "DEBUG level present"); TEST_ASSERT(strstr(content, "42") != NULL, "Info param present"); TEST_ASSERT(strstr(content, "test error") != NULL, "Error param present"); logging_cleanup(); unlink(tmp_path); TEST_SUITE_END(); } void test_logging_cleanup(void) { TEST_SUITE_BEGIN("Logging Cleanup"); char tmp_path[] = "/tmp/test_rproxy_log_XXXXXX"; int fd = mkstemp(tmp_path); close(fd); logging_set_file(tmp_path); log_info("Before cleanup"); logging_cleanup(); log_info("After cleanup to stdout"); TEST_ASSERT(1, "Cleanup completed and logging works"); unlink(tmp_path); TEST_SUITE_END(); } void test_logging_multiple_files(void) { TEST_SUITE_BEGIN("Logging Multiple File Switches"); char tmp1[] = "/tmp/test_rproxy_log1_XXXXXX"; char tmp2[] = "/tmp/test_rproxy_log2_XXXXXX"; int fd1 = mkstemp(tmp1); int fd2 = mkstemp(tmp2); close(fd1); close(fd2); logging_set_file(tmp1); log_info("Message to file 1"); logging_set_file(tmp2); log_info("Message to file 2"); struct stat st1, st2; stat(tmp1, &st1); stat(tmp2, &st2); TEST_ASSERT(st1.st_size > 0, "First file has content"); TEST_ASSERT(st2.st_size > 0, "Second file has content"); logging_cleanup(); unlink(tmp1); unlink(tmp2); TEST_SUITE_END(); } void test_logging_error_with_errno(void) { TEST_SUITE_BEGIN("Logging Error With Errno"); char tmp_path[] = "/tmp/test_rproxy_log_XXXXXX"; int fd = mkstemp(tmp_path); close(fd); logging_set_file(tmp_path); errno = ENOENT; log_error("File not found error"); errno = 0; log_error("Error without errno"); errno = EPERM; log_error("Permission denied: %s", "/test/file"); errno = 0; logging_cleanup(); FILE *f = fopen(tmp_path, "r"); char content[4096] = {0}; if (f) { size_t bytes_read = fread(content, 1, sizeof(content) - 1, f); (void)bytes_read; fclose(f); } TEST_ASSERT(strstr(content, "File not found") != NULL, "First error logged"); TEST_ASSERT(strstr(content, "without errno") != NULL, "Second error logged"); unlink(tmp_path); TEST_SUITE_END(); } void test_logging_debug_disabled(void) { TEST_SUITE_BEGIN("Logging Debug Disabled"); char tmp_path[] = "/tmp/test_rproxy_log_XXXXXX"; int fd = mkstemp(tmp_path); close(fd); logging_set_file(tmp_path); logging_set_debug(0); log_debug("This should not appear"); log_info("This should appear"); struct stat st; stat(tmp_path, &st); TEST_ASSERT(st.st_size > 0, "File has some content"); FILE *f = fopen(tmp_path, "r"); char content[4096] = {0}; if (f) { size_t bytes_read = fread(content, 1, sizeof(content) - 1, f); (void)bytes_read; fclose(f); } TEST_ASSERT(strstr(content, "should appear") != NULL, "Info message present"); logging_cleanup(); unlink(tmp_path); TEST_SUITE_END(); } void test_logging_format_strings(void) { TEST_SUITE_BEGIN("Logging Format Strings"); char tmp_path[] = "/tmp/test_rproxy_log_XXXXXX"; int fd = mkstemp(tmp_path); close(fd); logging_set_file(tmp_path); log_info("Int: %d, String: %s, Float: %.2f", 42, "test", 3.14); log_error("Code: %d, Msg: %s", 500, "Internal error"); logging_set_debug(1); log_debug("Debug: %s %d", "value", 123); logging_set_debug(0); logging_cleanup(); FILE *f = fopen(tmp_path, "r"); char content[4096] = {0}; if (f) { size_t bytes_read = fread(content, 1, sizeof(content) - 1, f); (void)bytes_read; fclose(f); } TEST_ASSERT(strstr(content, "42") != NULL, "Int formatted"); TEST_ASSERT(strstr(content, "test") != NULL, "String formatted"); TEST_ASSERT(strstr(content, "500") != NULL, "Error code formatted"); unlink(tmp_path); TEST_SUITE_END(); } void run_logging_tests(void) { test_logging_debug_mode(); test_logging_set_file(); test_logging_set_file_null(); test_logging_set_file_invalid(); test_logging_log_functions(); test_logging_cleanup(); test_logging_multiple_files(); test_logging_error_with_errno(); test_logging_debug_disabled(); test_logging_format_strings(); }