#include "test_framework.h"
#include "../src/logging.h"
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
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();
}