feat: add log levels to logger

Replace log_message with log_debug/info/warn/err and a level filter
controlled by logger_set_level. Extract the printf sink into
log_write so CMock can intercept it in test_logger. Add 9 tests
covering emit and suppression behaviour per level.
This commit is contained in:
2026-05-09 20:43:32 +02:00
parent bee8424782
commit 701c644408
12 changed files with 128 additions and 15 deletions
+9 -3
View File
@@ -25,8 +25,6 @@ function(cmock_generate_mock target header)
VERBATIM
)
target_sources("${target}" PRIVATE "${mock_src}")
# MOCK_GEN_DIR for the generated header; header_dir so the generated
# #include "logger.h" resolves without the ctdd/ prefix
target_include_directories("${target}" PRIVATE "${MOCK_GEN_DIR}" "${header_dir}")
endfunction()
@@ -37,10 +35,18 @@ target_link_libraries(test_str PRIVATE ctdd_str Unity::Unity)
target_compile_features(test_str PRIVATE c_std_23)
add_test(NAME test_str COMMAND test_str)
# report tests — CMock-generated mock for log_message
# report tests — mocks logger.h so log_info calls are intercepted
add_executable(test_report test_report.c)
target_include_directories(test_report PRIVATE "${CMAKE_SOURCE_DIR}")
target_link_libraries(test_report PRIVATE ctdd_report Unity::Unity CMock::CMock)
target_compile_features(test_report PRIVATE c_std_23)
cmock_generate_mock(test_report "${CMAKE_SOURCE_DIR}/ctdd/logger.h")
add_test(NAME test_report COMMAND test_report)
# logger tests — mocks log_write.h so output calls are intercepted
add_executable(test_logger test_logger.c)
target_include_directories(test_logger PRIVATE "${CMAKE_SOURCE_DIR}")
target_link_libraries(test_logger PRIVATE ctdd_logger Unity::Unity CMock::CMock)
target_compile_features(test_logger PRIVATE c_std_23)
cmock_generate_mock(test_logger "${CMAKE_SOURCE_DIR}/ctdd/log_write.h")
add_test(NAME test_logger COMMAND test_logger)
+73
View File
@@ -0,0 +1,73 @@
#include "unity.h"
#include "ctdd/logger.h"
#include "Mocklog_write.h"
void setUp(void) { Mocklog_write_Init(); logger_set_level(LOG_DEBUG); }
void tearDown(void) { Mocklog_write_Verify(); Mocklog_write_Destroy(); }
void test_log_debug_emits_at_debug_level(void) {
log_write_Expect("[DEBUG] hello");
log_debug("hello");
}
void test_log_info_emits_at_debug_level(void) {
log_write_Expect("[INFO] world");
log_info("world");
}
void test_log_warn_emits_at_warn_level(void) {
logger_set_level(LOG_WARN);
log_write_Expect("[WARN] alert");
log_warn("alert");
}
void test_log_err_emits_at_warn_level(void) {
logger_set_level(LOG_WARN);
log_write_Expect("[ERROR] fatal");
log_err("fatal");
}
void test_log_debug_suppressed_at_info_level(void) {
logger_set_level(LOG_INFO);
log_debug("silent");
}
void test_log_info_suppressed_at_warn_level(void) {
logger_set_level(LOG_WARN);
log_info("silent");
}
void test_log_warn_suppressed_at_error_level(void) {
logger_set_level(LOG_ERROR);
log_warn("silent");
}
void test_log_none_suppresses_all(void) {
logger_set_level(LOG_NONE);
log_debug("silent");
log_info("silent");
log_warn("silent");
log_err("silent");
}
void test_level_can_be_raised_then_lowered(void) {
logger_set_level(LOG_ERROR);
log_info("silent");
logger_set_level(LOG_DEBUG);
log_write_Expect("[INFO] now visible");
log_info("now visible");
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_log_debug_emits_at_debug_level);
RUN_TEST(test_log_info_emits_at_debug_level);
RUN_TEST(test_log_warn_emits_at_warn_level);
RUN_TEST(test_log_err_emits_at_warn_level);
RUN_TEST(test_log_debug_suppressed_at_info_level);
RUN_TEST(test_log_info_suppressed_at_warn_level);
RUN_TEST(test_log_warn_suppressed_at_error_level);
RUN_TEST(test_log_none_suppresses_all);
RUN_TEST(test_level_can_be_raised_then_lowered);
return UNITY_END();
}
+4 -4
View File
@@ -6,22 +6,22 @@ void setUp(void) { Mocklogger_Init(); }
void tearDown(void) { Mocklogger_Verify(); Mocklogger_Destroy(); }
void test_report_formats_label_and_value(void) {
log_message_Expect("count: 42");
log_info_Expect("count: 42");
report_value("count", 42);
}
void test_report_negative_value(void) {
log_message_Expect("score: -5");
log_info_Expect("score: -5");
report_value("score", -5);
}
void test_report_zero(void) {
log_message_Expect("total: 0");
log_info_Expect("total: 0");
report_value("total", 0);
}
void test_report_calls_log_exactly_once(void) {
log_message_Expect("x: 1");
log_info_Expect("x: 1");
report_value("x", 1);
}