From b055a3310e3268bcff0d4b11e3b896466a1eb959 Mon Sep 17 00:00:00 2001 From: Tomasz Gromadzki Date: Fri, 23 Feb 2024 08:48:51 +0100 Subject: [PATCH] test: core_log_last tests implementation Signed-off-by: Tomasz Gromadzki --- src/test/core_log_last/TESTS.py | 8 - src/test/core_log_last/core_log_last.c | 313 ++++++++----------------- src/test/unittest/unittest.h | 2 +- 3 files changed, 102 insertions(+), 221 deletions(-) diff --git a/src/test/core_log_last/TESTS.py b/src/test/core_log_last/TESTS.py index db541c78975..f8a4a79342d 100755 --- a/src/test/core_log_last/TESTS.py +++ b/src/test/core_log_last/TESTS.py @@ -42,12 +42,4 @@ class TEST5(CORE_LOG): class TEST6(CORE_LOG): - test_case = 'test_CORE_LOG_LAST_BASIC_LONG' - - -class TEST7(CORE_LOG): - test_case = 'test_CORE_LOG_LAST_BASIC_TOO_LONG' - - -class TEST8(CORE_LOG): test_case = 'test_CORE_LOG_TRESHOLD' diff --git a/src/test/core_log_last/core_log_last.c b/src/test/core_log_last/core_log_last.c index 0078c19b260..fb28d3c09d1 100644 --- a/src/test/core_log_last/core_log_last.c +++ b/src/test/core_log_last/core_log_last.c @@ -15,24 +15,6 @@ #define NO_ARGS_CONSUMED 0 -/* - * Prevent abort() from CORE_LOG_FATAL() - * Use core_log_abort() instead. - * Use core_log_abort() mock to monitor usage of abort() function - * inside CORE_LOG_FATAL(); - */ -#define abort() core_log_abort() -extern void core_log_abort(void); - -/* core_log_abort() - mock for abort() function in CORE_LOG_FATAL() */ -static int Core_log_abort_no_of_calls = 0; - -FUNC_MOCK(core_log_abort, void, void) -FUNC_MOCK_RUN_DEFAULT { - Core_log_abort_no_of_calls++; -} -FUNC_MOCK_END - /* strerror_r mock */ #define CORE_LOG_UT_ERRNO_SHORT 1 #define CORE_LOG_UT_ERRNO_SHORT_STR "Short errno str" @@ -64,261 +46,172 @@ static int Syslog_no_of_calls = 0; FUNC_MOCK(syslog, void, int __pri, const char *__fmt, ...) FUNC_MOCK_RUN_DEFAULT { - char buf[4096]; + char buf[1024]; va_list arg; va_start(arg, __fmt); - vsnprintf(buf, 4096, __fmt, arg); + vsnprintf(buf, 1024, __fmt, arg); va_end(arg); - __real_syslog(__pri, buf); + // __real_syslog(__pri, buf); Syslog_no_of_calls ++; } FUNC_MOCK_END -static int Fprintf_no_of_calls = 0; +/* core_log_to_last() mock */ +struct core_log_to_last_moc_context { + int initialized; + const char *file_name; + int line_no; + const char *function_name; + char message[1024]; + int no_of_calls; +}; +struct core_log_to_last_moc_context Core_log_to_last_moc_context = {0}; -FUNC_MOCK(fprintf, int, FILE *__restrict __stream, - const char *__restrict __fmt, ...) +FUNC_MOCK(core_log_to_last, void, int errnum, const char *file_name, + int line_no, const char *function_name, const char *message_format, ...) FUNC_MOCK_RUN_DEFAULT { char buf[4096]; va_list arg; - va_start(arg, __fmt); - vsnprintf(buf, 4096, __fmt, arg); + va_start(arg, message_format); + vsnprintf(buf, 4096, message_format, arg); va_end(arg); - Fprintf_no_of_calls ++; - return __real_fprintf(__stream, buf); + Core_log_to_last_moc_context.no_of_calls ++; + UT_ASSERTeq( + strcmp(Core_log_to_last_moc_context.file_name, file_name), 0); + UT_ASSERTeq(Core_log_to_last_moc_context.line_no, line_no); + UT_ASSERTeq(strcmp(Core_log_to_last_moc_context.function_name, + function_name), 0); + + __real_core_log_to_last(errnum, file_name, line_no, function_name, buf); } FUNC_MOCK_END #define CORE_LOG_UT_MESSAGE "Test message" -#define CORE_LOG_UT_MESSAGE_LONG "Test message long 20Test message long 40" \ -"Test message long 60Test message long 80Test message long100" \ -"Test message long120Test message long140Test message long160" \ -"Test message long180Test message long200Test message long220" \ -"Test message long240Test message long260Test message long280" \ -"Test message long300Test message long320Test message long340" \ -"Test message long360Test message long380Test message long400 407" +#define CORE_LOG_UT_MESSAGE_LONG \ +"Test message long 20Test message long 40Test message long 60" \ +"Test message long 80Test message long100Test message long120" \ +"Test message long140Test message long160Test message long180" \ +"Test message long200Test message long220Test message long240" \ +"Test message long260Test message long280Test message long300" #define CORE_LOG_UT_MESSAGE_TOO_LONG CORE_LOG_UT_MESSAGE_LONG \ -"Test message long 428" - -#define TEST_SETUP(message_to_test) \ - struct log_function_context context; \ - context.initialized = 0; \ - core_log_set_function(log_function, &context); \ - context.file_name = __FILE__; \ - context.function_name = __func__; \ - Core_log_abort_no_of_calls = 0; \ - Log_function_no_of_calls = 0; \ - strcpy(context.message, message_to_test); \ - context.initialized = 1 - -#define CONCAT2(A, B) A##B -#define CONCAT3(A, B, C) A##B##C - -#define TEST_STEP(step_level) \ - context.level = CORE_LOG_LEVEL_##step_level; \ - context.line_no = __LINE__; CONCAT2(CORE_LOG_, step_level) \ - (CORE_LOG_UT_MESSAGE) - -#define TEST_STEP_LONG(step_level) \ - context.level = CORE_LOG_LEVEL_##step_level; \ - context.line_no = __LINE__; CONCAT2(CORE_LOG_, step_level) \ - (CORE_LOG_UT_MESSAGE_LONG) - -#define TEST_STEP_W_ERRNO(step_level) \ - context.level = CORE_LOG_LEVEL_##step_level; \ - context.line_no = __LINE__; CONCAT3(CORE_LOG_, step_level, _W_ERRNO) \ - (CORE_LOG_UT_MESSAGE) +"Test message long 321" /* tests */ -/* structure for test context to be delivered to log_function */ -struct log_function_context { - int initialized; - enum core_log_level level; - const char *file_name; - int line_no; - const char *function_name; - char message[8196]; -}; - -/* log_function - the main place for log message correctnes verification */ -static int Log_function_no_of_calls = 0; - -static void -log_function(void *context, enum core_log_level level, const char *file_name, - const int line_no, const char *function_name, const char *message) { - struct log_function_context *context_in = - (struct log_function_context *)context; - if (!context_in->initialized) - return; - UT_ASSERTeq(context_in->level, level); - UT_ASSERTeq(strcmp(context_in->file_name, file_name), 0); - UT_ASSERTeq(context_in->line_no, line_no); - UT_ASSERTeq(strcmp(context_in->function_name, function_name), 0); - UT_ASSERTeq(strcmp(context_in->message, message), 0); - UT_ASSERTeq(strlen(context_in->message), strlen(message)); - Log_function_no_of_calls ++; -} - +#define TEST_SETUP(message_to_test) \ + Core_log_to_last_moc_context.file_name = __FILE__; \ + Core_log_to_last_moc_context.function_name = __func__; \ + Core_log_to_last_moc_context.no_of_calls = 0; \ + strncpy(Core_log_to_last_moc_context.message, message_to_test, \ + CORE_LAST_ERROR_MSG_MAXPRINT); \ + Core_log_to_last_moc_context.initialized = 1 + +#define TEST_STEP_SETUP() \ + Syslog_no_of_calls = 0; \ + Core_log_to_last_moc_context.no_of_calls = 0; \ + Core_log_to_last_moc_context.line_no = __LINE__; \ + (*(char *)last_error_msg_get()) = '\0' + +#define TEST_STEP_CHECK() \ + UT_OUT("%s", last_error_msg_get()); \ + UT_ASSERTeq(strcmp(Core_log_to_last_moc_context.message, \ + last_error_msg_get()), 0); \ + UT_ASSERTeq(Core_log_to_last_moc_context.no_of_calls, 1); \ + UT_ASSERTeq(Syslog_no_of_calls, 1) + +#define TEST_STEP(MESSAGE) \ + TEST_STEP_SETUP(); \ + CORE_LOG_ERROR_LAST(MESSAGE); \ + TEST_STEP_CHECK() + +#define TEST_STEP_W_ERRNO(MESSAGE) \ + TEST_STEP_SETUP(); \ + CORE_LOG_ERROR_W_ERRNO_LAST(MESSAGE); \ + TEST_STEP_CHECK() + +/* basic tests with normal message */ static int test_CORE_LOG_BASIC(const struct test_case *tc, int argc, char *argv[]) { TEST_SETUP(CORE_LOG_UT_MESSAGE); - TEST_STEP(FATAL); - UT_ASSERTeq(Core_log_abort_no_of_calls, 1); - TEST_STEP(ERROR); - TEST_STEP(WARNING); - TEST_STEP(NOTICE); - TEST_STEP(HARK); - UT_ASSERTeq(Log_function_no_of_calls, 5); - UT_ASSERTeq(Core_log_abort_no_of_calls, 1); + TEST_STEP(CORE_LOG_UT_MESSAGE); return NO_ARGS_CONSUMED; } +/* basic tests with max length message */ static int test_CORE_LOG_BASIC_LONG(const struct test_case *tc, int argc, char *argv[]) { TEST_SETUP(CORE_LOG_UT_MESSAGE_LONG); - TEST_STEP_LONG(FATAL); - UT_ASSERTeq(Core_log_abort_no_of_calls, 1); - TEST_STEP_LONG(ERROR); - TEST_STEP_LONG(WARNING); - TEST_STEP_LONG(NOTICE); - TEST_STEP_LONG(HARK); - UT_ASSERTeq(Log_function_no_of_calls, 5); - UT_ASSERTeq(Core_log_abort_no_of_calls, 1); + TEST_STEP(CORE_LOG_UT_MESSAGE_LONG); return NO_ARGS_CONSUMED; } +/* basic tests with too long message */ static int test_CORE_LOG_BASIC_TOO_LONG(const struct test_case *tc, int argc, char *argv[]) { TEST_SETUP(CORE_LOG_UT_MESSAGE_LONG); - context.level = CORE_LOG_LEVEL_ERROR; - context.line_no = __LINE__ + 1; - CORE_LOG_ERROR(CORE_LOG_UT_MESSAGE_TOO_LONG); - context.level = CORE_LOG_LEVEL_WARNING; - context.line_no = __LINE__ + 1; - CORE_LOG_WARNING(CORE_LOG_UT_MESSAGE_TOO_LONG); - UT_ASSERTeq(Log_function_no_of_calls, 2); - return NO_ARGS_CONSUMED; -} - -static int -test_CORE_LOG_LAST_BASIC_LONG(const struct test_case *tc, int argc, - char *argv[]) -{ - TEST_SETUP(CORE_LOG_UT_MESSAGE_LONG); - context.message[CORE_LAST_ERROR_MSG_MAXPRINT - 1] = '\0'; - context.level = CORE_LOG_LEVEL_ERROR; - context.line_no = __LINE__ + 1; - CORE_LOG_ERROR_LAST(CORE_LOG_UT_MESSAGE_LONG); - UT_ASSERTeq(Log_function_no_of_calls, 1); + TEST_STEP(CORE_LOG_UT_MESSAGE_TOO_LONG); return NO_ARGS_CONSUMED; } +/* basic test with errno message */ static int -test_CORE_LOG_LAST_BASIC_TOO_LONG(const struct test_case *tc, int argc, - char *argv[]) +test_CORE_LOG_BASIC_W_ERRNO(const struct test_case *tc, int argc, char *argv[]) { - TEST_SETUP(CORE_LOG_UT_MESSAGE_LONG); - context.message[CORE_LAST_ERROR_MSG_MAXPRINT - 1] = '\0'; - context.level = CORE_LOG_LEVEL_ERROR; - context.line_no = __LINE__ + 1; - CORE_LOG_ERROR_LAST(CORE_LOG_UT_MESSAGE_TOO_LONG); - UT_ASSERTeq(Log_function_no_of_calls, 1); + TEST_SETUP(CORE_LOG_UT_MESSAGE ": " CORE_LOG_UT_ERRNO_SHORT_STR); + errno = CORE_LOG_UT_ERRNO_SHORT; + TEST_STEP_W_ERRNO(CORE_LOG_UT_MESSAGE); + UT_ASSERTeq(errno, CORE_LOG_UT_ERRNO_SHORT); return NO_ARGS_CONSUMED; } +/* basic test with errno message and too long error message */ static int test_CORE_LOG_BASIC_TOO_LONG_W_ERRNO(const struct test_case *tc, int argc, char *argv[]) { TEST_SETUP(CORE_LOG_UT_MESSAGE_LONG); errno = CORE_LOG_UT_ERRNO_SHORT; - context.level = CORE_LOG_LEVEL_ERROR; - context.line_no = __LINE__ + 1; - CORE_LOG_ERROR_W_ERRNO(CORE_LOG_UT_MESSAGE_TOO_LONG); - context.level = CORE_LOG_LEVEL_WARNING; - context.line_no = __LINE__ + 1; - CORE_LOG_WARNING_W_ERRNO(CORE_LOG_UT_MESSAGE_TOO_LONG); - UT_ASSERTeq(errno, CORE_LOG_UT_ERRNO_SHORT); - UT_ASSERTeq(Log_function_no_of_calls, 2); - return NO_ARGS_CONSUMED; -} - -static int -test_CORE_LOG_BASIC_W_ERRNO(const struct test_case *tc, int argc, char *argv[]) -{ - TEST_SETUP(CORE_LOG_UT_MESSAGE ": " CORE_LOG_UT_ERRNO_SHORT_STR); - errno = CORE_LOG_UT_ERRNO_SHORT; - TEST_STEP_W_ERRNO(FATAL); - UT_ASSERTeq(Core_log_abort_no_of_calls, 1); - TEST_STEP_W_ERRNO(ERROR); - TEST_STEP_W_ERRNO(WARNING); - UT_ASSERTeq(Log_function_no_of_calls, 3); - UT_ASSERTeq(Core_log_abort_no_of_calls, 1); + TEST_STEP_W_ERRNO(CORE_LOG_UT_MESSAGE_TOO_LONG); UT_ASSERTeq(errno, CORE_LOG_UT_ERRNO_SHORT); return NO_ARGS_CONSUMED; } +/* basic test with errno message that does not produce error text */ static int test_CORE_LOG_BASIC_W_ERRNO_BAD(const struct test_case *tc, int argc, char *argv[]) { TEST_SETUP(CORE_LOG_UT_MESSAGE ": "); errno = CORE_LOG_UT_ERRNO_INVALID; - TEST_STEP_W_ERRNO(FATAL); - UT_ASSERTeq(Core_log_abort_no_of_calls, 1); - TEST_STEP_W_ERRNO(ERROR); - TEST_STEP_W_ERRNO(WARNING); - UT_ASSERTeq(Log_function_no_of_calls, 3); + TEST_STEP_W_ERRNO(CORE_LOG_UT_MESSAGE); return NO_ARGS_CONSUMED; } -#define CORE_LOG_TRESHOLD_STEP(_call_type, _abort_no, _syslog_no, _fprintf_no) \ - do { \ - Syslog_no_of_calls = 0; \ - Fprintf_no_of_calls = 0; \ - _call_type(CORE_LOG_UT_MESSAGE); \ - UT_ASSERTeq(Core_log_abort_no_of_calls, _abort_no); \ - UT_ASSERTeq(Syslog_no_of_calls, _syslog_no); \ - UT_ASSERTeq(Fprintf_no_of_calls, _fprintf_no); \ - } while (0) - -#define CORE_LOG_TRESHOLD_STEP_ALL(_fs, _fe, _es, _ee, _ws, _we, _ns, _ne, \ - _as) \ - Core_log_abort_no_of_calls = 0; \ - CORE_LOG_TRESHOLD_STEP(CORE_LOG_FATAL, 1, _fs, _fe); \ - Core_log_abort_no_of_calls = 0; \ - CORE_LOG_TRESHOLD_STEP(CORE_LOG_ERROR, 0, _es, _es); \ - CORE_LOG_TRESHOLD_STEP(CORE_LOG_WARNING, 0, _ws, _we); \ - CORE_LOG_TRESHOLD_STEP(CORE_LOG_NOTICE, 0, _ns, _ne); \ - CORE_LOG_TRESHOLD_STEP(CORE_LOG_HARK, 0, _as, 0); - +/* test to check that core_log_to_last() works w/ every thresholds */ static int test_CORE_LOG_TRESHOLD(const struct test_case *tc, int argc, char *argv[]) { - Core_log_abort_no_of_calls = 0; - core_log_set_function(CORE_LOG_USE_DEFAULT_FUNCTION, NULL); - CORE_LOG_TRESHOLD_STEP(CORE_LOG_FATAL, 1, 1, 1); - Core_log_abort_no_of_calls = 0; - CORE_LOG_TRESHOLD_STEP(CORE_LOG_ERROR, 0, 1, 1); - CORE_LOG_TRESHOLD_STEP(CORE_LOG_WARNING, 0, 1, 1); - CORE_LOG_TRESHOLD_STEP(CORE_LOG_NOTICE, 0, 1, 0); - CORE_LOG_TRESHOLD_STEP(CORE_LOG_HARK, 0, 1, 0); - core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_HARK); - CORE_LOG_TRESHOLD_STEP_ALL(0, 0, 0, 0, 0, 0, 0, 0, 1); - core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_FATAL); - CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 0, 0, 0, 0, 0, 0, 1); - core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_ERROR); - CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 1, 1, 0, 0, 0, 0, 1); - core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_WARNING); - CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 1, 1, 1, 1, 0, 0, 1); - core_log_set_threshold(CORE_LOG_THRESHOLD, CORE_LOG_LEVEL_NOTICE); - CORE_LOG_TRESHOLD_STEP_ALL(1, 1, 1, 1, 1, 1, 1, 0, 1); + // core_log_set_function(CORE_LOG_USE_DEFAULT_FUNCTION, NULL); + TEST_SETUP(CORE_LOG_UT_MESSAGE); + for (enum core_log_level level = CORE_LOG_LEVEL_HARK; + level < CORE_LOG_LEVEL_MAX; level ++) { + core_log_set_threshold(CORE_LOG_THRESHOLD, level); + /* must be in one line for proper __LINE__ value */ + TEST_STEP_SETUP(); CORE_LOG_ERROR_LAST(CORE_LOG_UT_MESSAGE); + UT_OUT("%s", last_error_msg_get()); + UT_ASSERTeq(strcmp(Core_log_to_last_moc_context.message, + last_error_msg_get()), 0); + if (level < CORE_LOG_LEVEL_ERROR) { + UT_ASSERTeq(Syslog_no_of_calls, 0); + } else { + UT_ASSERTeq(Syslog_no_of_calls, 1); + } + } return NO_ARGS_CONSUMED; } @@ -326,20 +219,13 @@ static struct test_case test_cases[] = { TEST_CASE(test_CORE_LOG_BASIC), TEST_CASE(test_CORE_LOG_BASIC_LONG), TEST_CASE(test_CORE_LOG_BASIC_TOO_LONG), - TEST_CASE(test_CORE_LOG_LAST_BASIC_LONG), - TEST_CASE(test_CORE_LOG_LAST_BASIC_TOO_LONG), TEST_CASE(test_CORE_LOG_BASIC_TOO_LONG_W_ERRNO), TEST_CASE(test_CORE_LOG_BASIC_W_ERRNO), TEST_CASE(test_CORE_LOG_BASIC_W_ERRNO_BAD), TEST_CASE(test_CORE_LOG_TRESHOLD), }; -#define NTESTS ARRAY_SIZE(test_cases) - -/* Restore original abort() definition as it is defined in stdlib.h */ -#undef abort -extern void abort(void) __THROW __attribute__((__noreturn__)); - +/* force test tu use default lgging function */ #undef LOG_SET_PMEMCORE_FUNC #define LOG_SET_PMEMCORE_FUNC @@ -347,9 +233,12 @@ int main(int argc, char *argv[]) { START(argc, argv, "core_log_last_last"); + core_log_set_function(NULL, NULL); + core_log_set_threshold(CORE_LOG_THRESHOLD_AUX, CORE_LOG_LEVEL_HARK); openlog("core_log_last", 0, 0); - TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); + TEST_CASE_PROCESS(argc, argv, test_cases, ARRAY_SIZE(test_cases)); + closelog(); DONE(NULL); } diff --git a/src/test/unittest/unittest.h b/src/test/unittest/unittest.h index 7b4285d7662..f865c2d07cc 100644 --- a/src/test/unittest/unittest.h +++ b/src/test/unittest/unittest.h @@ -624,7 +624,7 @@ TEST_CASE_PROCESS(int argc, char *argv[], if (argc < 2) UT_FATAL("usage: %s []", argv[0]); - if (!strcmp("ALL", argv[1])) { + if (strcmp("ALL", argv[1]) == 0) { for (size_t i = 0; i < ntests; i++) { int ret = test_cases[i].func(&test_cases[i], 0, NULL); if (ret < 0)