Skip to content

Commit

Permalink
Update message API
Browse files Browse the repository at this point in the history
Add missing unit tests
  • Loading branch information
BlockoS committed Sep 3, 2024
1 parent 90ce677 commit 513d0e3
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 52 deletions.
6 changes: 3 additions & 3 deletions message.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);
}
}
Expand Down
9 changes: 3 additions & 6 deletions message.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 {
Expand Down
14 changes: 4 additions & 10 deletions message/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,27 @@
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.
/// \param [in] function Function where the print message command was issued.
/// \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]",
Expand All @@ -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]
Expand Down
51 changes: 20 additions & 31 deletions message/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -76,32 +69,28 @@ 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]",
"[Info]",
"[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;
}
Expand Down
117 changes: 115 additions & 2 deletions test/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
};

Expand Down

0 comments on commit 513d0e3

Please sign in to comment.