From 513d0e346ee8b3d4457e00e1e2a8b9352b8e240d Mon Sep 17 00:00:00 2001 From: MooZ Date: Tue, 3 Sep 2024 23:18:55 +0200 Subject: [PATCH] Update message API Add missing unit tests --- message.c | 6 +-- message.h | 9 ++-- message/console.c | 14 ++---- message/file.c | 51 ++++++++------------ test/message.c | 117 +++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 145 insertions(+), 52 deletions(-) diff --git a/message.c b/message.c index 455f7cd..461d465 100644 --- a/message.c +++ b/message.c @@ -49,7 +49,7 @@ void message_printer_init() { void message_printer_destroy() { for(MessagePrinter *it = g_message_printer_head; it != NULL; it = it->next) { if(it->close) { - it->close(it); + it->close(); } } g_message_printer_head = NULL; @@ -59,7 +59,7 @@ void message_printer_destroy() { bool message_printer_add(MessagePrinter *printer) { bool ret = false; if((printer != NULL) && (printer->open != NULL)) { - ret = printer->open(printer); + ret = printer->open(); if(ret) { printer->next = g_message_printer_head; g_message_printer_head = printer; @@ -82,7 +82,7 @@ void message_print(MessageType type, const char* file, size_t line, const char* if(it->output != NULL) { va_list args; va_start(args, format); - (void)it->output(it, type, filename, line, function, format, args); + (void)it->output(type, filename, line, function, format, args); va_end(args); } } diff --git a/message.h b/message.h index 5a04384..4839791 100644 --- a/message.h +++ b/message.h @@ -53,19 +53,16 @@ typedef enum { struct MessagePrinter; /// Initializes and allocates any resources necessary for the message printer. -/// \param [in out] printer Message printer. /// \return true if the message printer was successfully opened. /// \return false if an error occured. -typedef bool (*MessagePrinterOpen)(struct MessagePrinter* printer); +typedef bool (*MessagePrinterOpen)(); /// Releases resources used by the message printer. -/// \param [in] printer Message printer. /// \return true if the resources used by the message printer were successfully released. /// \return false if an error occured. -typedef bool (*MessagePrinterClose)(struct MessagePrinter* printer); +typedef bool (*MessagePrinterClose)(); /// \brief Prints message. -/// \param [in] printer Message printer. /// \param [in] type Message type. /// \param [in] file Name of the file where the print message command was issued. /// \param [in] line Line number in the file where the print message command was issued. @@ -74,7 +71,7 @@ typedef bool (*MessagePrinterClose)(struct MessagePrinter* printer); /// \param [in] args Argument lists. /// \return true if the message was successfully formatted and printed. /// \return false if an error occured. -typedef bool (*MessagePrinterOutput)(struct MessagePrinter* printer, MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args); +typedef bool (*MessagePrinterOutput)(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args); /// Message printer implementation. typedef struct MessagePrinter { diff --git a/message/console.c b/message/console.c index cb926cf..69f3e73 100644 --- a/message/console.c +++ b/message/console.c @@ -39,22 +39,19 @@ static bool g_use_escape_code = false; /// Tests if the console has support for colors and other things. -/// \param [in] printer Console message printer. /// \return true always. -static bool console_message_printer_open(MessagePrinter* printer __attribute__((unused))) { +static bool console_message_printer_open() { g_use_escape_code = isatty(fileno(stdout)) ? true : false; return true; } /// Do nothing. -/// \param [in] printer Message printer. /// \return true always. -static bool console_message_printer_close(MessagePrinter *printer __attribute__((unused))) { +static bool console_message_printer_close() { return true; } /// Prints message to console. -/// \param [in] printer Console message printer. /// \param [in] type Message type. /// \param [in] file Name of the file where the print message command was issued. /// \param [in] line Line number in the file where the print message command was issued. @@ -62,7 +59,7 @@ static bool console_message_printer_close(MessagePrinter *printer __attribute__( /// \param [in] format Format string. /// \param [in] args Argument lists. /// \return true upon success. -static bool console_message_printer_output(MessagePrinter *printer, MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { +static bool console_message_printer_output(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { static const char *message_type_name[] = { "[Error]", "[Warning]", @@ -75,10 +72,7 @@ static bool console_message_printer_output(MessagePrinter *printer, MessageType }; bool ret = true; - if(printer == NULL) { - fprintf(stderr, "Invalid console logger.\n"); - ret = false; - } else if(g_use_escape_code) { + if(g_use_escape_code) { fprintf(stderr, "%s%s\x1b[0m %s:%zd \x1b[0;33m %s \x1b[1;37m : " , message_type_prefix[type] , message_type_name[type] diff --git a/message/file.c b/message/file.c index 0a234db..ae8c5e6 100644 --- a/message/file.c +++ b/message/file.c @@ -39,35 +39,28 @@ static const char* g_log_filename = "etripator.log"; /// Check if the log file can be opened and written to. -/// \param [in] printer Message printer implementation. /// \return true if the log file was successfully opened. /// \return false if an error occured. -static bool file_message_printer_open(MessagePrinter* printer) { +static bool file_message_printer_open() { bool ret = false; - if(printer == NULL) { - fprintf(stderr, "Invalid file message printer"); + int fd = open(g_log_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if(fd < 0) { + fprintf(stderr, "Failed to open log file %s: %s\n", g_log_filename, strerror(errno)); + } else if(close(fd) < 0) { + fprintf(stderr, "Failed to close log file %s: %s\n", g_log_filename, strerror(errno)); } else { - int fd = open(g_log_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); - if(fd < 0) { - fprintf(stderr, "Failed to open log file %s: %s\n", g_log_filename, strerror(errno)); - } else if(close(fd) < 0) { - fprintf(stderr, "Failed to close log file %s: %s\n", g_log_filename, strerror(errno)); - } else { - ret = true; - } + ret = true; } return ret; } /// Do nothing. -/// \param [in] printer Message printer implementation. /// \return true always. -static bool file_message_printer_close(MessagePrinter *printer __attribute__((unused))) { +static bool file_message_printer_close() { return true; } /// Prints message to file. -/// \param [in] printer Msg printer implementation. /// \param [in] type Message type. /// \param [in] file Name of the file where the print message command was issued. /// \param [in] line Line number in the file where the print message command was issued. @@ -76,7 +69,7 @@ static bool file_message_printer_close(MessagePrinter *printer __attribute__((un /// \param [in] args Argument lists. /// \return true if the message was successfully written to the log file. /// \return false if an error occured. -static bool file_message_printer_output(MessagePrinter* printer, MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { +static bool file_message_printer_output(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { static const char *message_type_name[MESSAGE_TYPE_COUNT] = { "[Error]", "[Warning]", @@ -84,24 +77,20 @@ static bool file_message_printer_output(MessagePrinter* printer, MessageType typ "[Debug]" }; bool ret = false; - if(printer == NULL) { - fprintf(stderr, "Invalid file logger.\n"); + FILE *out = fopen(g_log_filename, "a+"); + if(out == NULL) { + fprintf(stderr, "Failed to open log file %s: %s\n", g_log_filename, strerror(errno)); } else { - FILE *out = fopen(g_log_filename, "a+"); - if(out == NULL) { - fprintf(stderr, "Failed to open log file %s: %s\n", g_log_filename, strerror(errno)); + fprintf(out, "%s %s:%zd %s : ", message_type_name[type], file, line, function); + vfprintf(out, format, args); + fputc('\n', out); + fflush(out); + if(ferror(out)) { + fprintf(stderr, "Failed to output log to %s: %s\n", g_log_filename, strerror(errno)); } else { - fprintf(out, "%s %s:%zd %s : ", message_type_name[type], file, line, function); - vfprintf(out, format, args); - fputc('\n', out); - fflush(out); - if(ferror(out)) { - fprintf(stderr, "Failed to output log to %s: %s\n", g_log_filename, strerror(errno)); - } else { - ret = true; - } - fclose(out); + ret = true; } + fclose(out); } return ret; } diff --git a/test/message.c b/test/message.c index b5680b9..cf660b6 100644 --- a/test/message.c +++ b/test/message.c @@ -101,11 +101,124 @@ MunitResult message_add_test(const MunitParameter params[] __attribute__((unused return MUNIT_OK; } +static int dummy_close_call_count; + +static bool dummy_close(MessagePrinter *printer __attribute__((unused))) { + dummy_close_call_count++; + return true; +} + +MunitResult message_destroy_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { + message_printer_init(); + munit_assert_ptr_null(g_message_printer_head); + + MessagePrinter printer[4] = { + [0] = { .open = dummy_open_0, .close = dummy_close }, + [1] = { .open = dummy_open_0, .close = dummy_close }, + [2] = { .open = dummy_open_0, .close = dummy_close }, + [3] = { .open = dummy_open_0, .close = dummy_close }, + }; + + dummy_open_0_call_count = 0; + dummy_close_call_count = 0; + + message_printer_init(); + munit_assert_true(message_printer_add(&printer[0])); + munit_assert_true(message_printer_add(&printer[1])); + munit_assert_true(message_printer_add(&printer[2])); + munit_assert_true(message_printer_add(&printer[3])); + + munit_assert_ptr_equal(g_message_printer_head, &printer[3]); + + munit_assert_uint(dummy_open_0_call_count, ==, 4); + munit_assert_uint(dummy_close_call_count, ==, 0); + + message_printer_destroy(); + munit_assert_uint(dummy_close_call_count, ==, 4); + munit_assert_null(g_message_printer_head); + + return MUNIT_OK; +} + +static unsigned int dummy_print_index = 0; +static size_t dummy_print_line = 0; +static unsigned int dummy_print_history[4] = {-1}; + +static bool dummy_print_0(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { + dummy_print_history[dummy_print_index++] = 0; + munit_assert_uint(type, ==, MESSAGE_TYPE_INFO); + munit_assert_size(line, ==, dummy_print_line); + return true; +} +static bool dummy_print_1(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { + dummy_print_history[dummy_print_index++] = 1; + munit_assert_uint(type, ==, MESSAGE_TYPE_INFO); + munit_assert_size(line, ==, dummy_print_line); + return true; +} +static bool dummy_print_2(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { + dummy_print_history[dummy_print_index++] = 2; + munit_assert_uint(type, ==, MESSAGE_TYPE_INFO); + munit_assert_size(line, ==, dummy_print_line); + return true; +} +static bool dummy_print_3(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { + dummy_print_history[dummy_print_index++] = 3; + munit_assert_uint(type, ==, MESSAGE_TYPE_INFO); + munit_assert_size(line, ==, dummy_print_line); + return true; +} + +MunitResult message_print_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { + message_printer_init(); + munit_assert_ptr_null(g_message_printer_head); + + MessagePrinter printer[4] = { + [0] = { .open = dummy_open_0, .close = dummy_close, .output = dummy_print_0 }, + [1] = { .open = dummy_open_0, .close = dummy_close, .output = dummy_print_1 }, + [2] = { .open = dummy_open_0, .close = dummy_close, .output = dummy_print_2 }, + [3] = { .open = dummy_open_0, .close = dummy_close, .output = dummy_print_3 }, + }; + + dummy_open_0_call_count = 0; + dummy_close_call_count = 0; + dummy_print_index = 0; + + for(unsigned int i=0; i<4; i++) { + dummy_print_history[i] = -1; + } + + message_printer_init(); + munit_assert_true(message_printer_add(&printer[0])); + munit_assert_true(message_printer_add(&printer[1])); + munit_assert_true(message_printer_add(&printer[2])); + munit_assert_true(message_printer_add(&printer[3])); + + munit_assert_ptr_equal(g_message_printer_head, &printer[3]); + + munit_assert_uint(dummy_open_0_call_count, ==, 4); + munit_assert_uint(dummy_close_call_count, ==, 0); + + dummy_print_line = __LINE__; INFO_MSG("test"); + munit_assert_uint(dummy_print_index, ==, 4); + munit_assert_uint(dummy_print_history[0], ==, 3); + munit_assert_uint(dummy_print_history[1], ==, 2); + munit_assert_uint(dummy_print_history[2], ==, 1); + munit_assert_uint(dummy_print_history[3], ==, 0); + + message_printer_destroy(); + munit_assert_uint(dummy_close_call_count, ==, 4); + munit_assert_null(g_message_printer_head); + + return MUNIT_OK; +} + + static MunitTest message_tests[] = { { "/init", message_init_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { "/add", message_add_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, - // [todo] destroy - // [todo] print + { "/destroy", message_destroy_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, + { "/print", message_print_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } };