failed approach
This commit is contained in:
165
gomspace/libutil/src/test/log.c
Normal file
165
gomspace/libutil/src/test/log.c
Normal file
@ -0,0 +1,165 @@
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#include <gs/util/test/log.h>
|
||||
#include <gs/util/test/cmocka.h>
|
||||
#include <gs/util/log/log.h>
|
||||
#include <gs/util/log/appender/appender.h>
|
||||
#include <gs/util/mutex.h>
|
||||
#include <gs/util/bytebuffer.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <fnmatch.h>
|
||||
|
||||
// cmocka
|
||||
void cm_print_error(const char * const format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2);
|
||||
|
||||
static gs_mutex_t g_lock;
|
||||
|
||||
#define GS_TEST_LOG_MAX_LEVELS 6
|
||||
#define GS_TEST_LOG_MAX_LOG_MESSAGES 200
|
||||
|
||||
typedef struct {
|
||||
// Overall count per log level.
|
||||
unsigned int count[GS_TEST_LOG_MAX_LEVELS];
|
||||
// Log messages.
|
||||
struct {
|
||||
// Level.
|
||||
gs_log_level_t level;
|
||||
// Format log message.
|
||||
char msg[150];
|
||||
} logs[GS_TEST_LOG_MAX_LOG_MESSAGES];
|
||||
// Index of next entry in \a logs.
|
||||
unsigned int next_log;
|
||||
} gs_test_log_stats_t;
|
||||
|
||||
static gs_test_log_stats_t gs_test_log_stats;
|
||||
|
||||
static void log_callback(gs_log_appender_t *appender, gs_log_level_t level, const gs_log_group_t * group, const gs_timestamp_t * ts, const char * format, va_list va)
|
||||
{
|
||||
gs_mutex_lock(g_lock);
|
||||
gs_test_log_stats.count[level]++;
|
||||
|
||||
{
|
||||
gs_bytebuffer_t bb;
|
||||
gs_bytebuffer_init(&bb,
|
||||
gs_test_log_stats.logs[gs_test_log_stats.next_log].msg,
|
||||
sizeof(gs_test_log_stats.logs[gs_test_log_stats.next_log].msg));
|
||||
|
||||
va_list my_va;
|
||||
va_copy(my_va, va);
|
||||
gs_bytebuffer_printf(&bb, "%s: ", group->name);
|
||||
gs_bytebuffer_vprintf(&bb, format, my_va);
|
||||
va_end(my_va);
|
||||
gs_bytebuffer_get_as_string(&bb, NULL); // ensure NUL termination
|
||||
gs_test_log_stats.logs[gs_test_log_stats.next_log].level = level;
|
||||
|
||||
++gs_test_log_stats.next_log;
|
||||
if (gs_test_log_stats.next_log >= GS_TEST_LOG_MAX_LOG_MESSAGES) {
|
||||
gs_test_log_stats.next_log = 0;
|
||||
}
|
||||
gs_test_log_stats.logs[gs_test_log_stats.next_log].msg[0] = 0; // clear next entry
|
||||
gs_test_log_stats.logs[gs_test_log_stats.next_log].level = GS_TEST_LOG_MAX_LEVELS;
|
||||
}
|
||||
|
||||
gs_mutex_unlock(g_lock);
|
||||
}
|
||||
|
||||
static gs_log_appender_driver_t g_log_test_appender_driver = {
|
||||
.init = 0,
|
||||
.append = log_callback,
|
||||
.append_isr = log_callback,
|
||||
};
|
||||
|
||||
static gs_log_appender_t g_log_test_appender = {
|
||||
.name = "test_appender",
|
||||
.drv = &g_log_test_appender_driver,
|
||||
.drv_config = NULL,
|
||||
.drv_data = NULL,
|
||||
.mask = LOG_ALL_MASK,
|
||||
};
|
||||
|
||||
void gs_test_log_init(bool verbose)
|
||||
{
|
||||
gs_log_init(true);
|
||||
|
||||
if (g_lock == NULL) {
|
||||
GS_ASSERT_ERROR_EQUAL(gs_mutex_create(&g_lock), GS_OK);
|
||||
|
||||
/* Add/Register appender - Only first time that init is called. */
|
||||
gs_log_appender_add(&g_log_test_appender, 1);
|
||||
gs_log_group_register_appender("root", "test_appender");
|
||||
}
|
||||
if (verbose) {
|
||||
gs_log_appender_set_level_mask("console", LOG_ALL_MASK);
|
||||
} else {
|
||||
gs_log_appender_set_level_mask("console", 0);
|
||||
}
|
||||
|
||||
gs_test_log_clear();
|
||||
}
|
||||
|
||||
void gs_test_log_clear(void)
|
||||
{
|
||||
gs_mutex_lock(g_lock);
|
||||
memset(&gs_test_log_stats, 0, sizeof(gs_test_log_stats));
|
||||
gs_mutex_unlock(g_lock);
|
||||
}
|
||||
|
||||
void gs_assert_log_count(int level, unsigned int count, const char * file, int line)
|
||||
{
|
||||
if (level < 0) {
|
||||
unsigned int tot = 0;
|
||||
for (int i = 0; i < GS_TEST_LOG_MAX_LEVELS; ++i) {
|
||||
tot += gs_test_log_stats.count[i];
|
||||
}
|
||||
if (tot != count) {
|
||||
cm_print_error("Unexpected total log count: %u != %u\n", tot, count);
|
||||
_fail(file, line);
|
||||
}
|
||||
} else if (level >= GS_TEST_LOG_MAX_LEVELS) {
|
||||
cm_print_error("Unknown log level: %d - valid levels 0 - %d\n", level, GS_TEST_LOG_MAX_LEVELS - 1);
|
||||
_fail(file, line);
|
||||
} else if (gs_test_log_stats.count[level] != count) {
|
||||
cm_print_error("Unexpected log count: %u != %u\n", gs_test_log_stats.count[level], count);
|
||||
_fail(file, line);
|
||||
}
|
||||
}
|
||||
|
||||
void gs_assert_log(unsigned int stack_index, unsigned int count, gs_log_level_t level, const char * pattern, const char * file, int line)
|
||||
{
|
||||
if (stack_index == UINT32_MAX) {
|
||||
// loop through all logs
|
||||
unsigned int next = gs_test_log_stats.next_log;
|
||||
unsigned int hits = 0;
|
||||
for (unsigned int i = next - 1; i != next; --i) {
|
||||
if (i >= GS_TEST_LOG_MAX_LOG_MESSAGES) {
|
||||
i = (GS_TEST_LOG_MAX_LOG_MESSAGES - 1);
|
||||
}
|
||||
if ((gs_test_log_stats.logs[i].level == level) && (gs_test_log_stats.logs[i].msg[0])) {
|
||||
if (fnmatch(pattern, gs_test_log_stats.logs[i].msg, 0) == 0) {
|
||||
++hits;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hits != count) {
|
||||
cm_print_error("Unexpected log count: %u != %u\n", hits, count);
|
||||
_fail(file, line);
|
||||
}
|
||||
} else if (stack_index >= GS_TEST_LOG_MAX_LOG_MESSAGES) {
|
||||
cm_print_error("Invalid stack_index: %u - valid 0 - %d\n", stack_index, GS_TEST_LOG_MAX_LOG_MESSAGES - 1);
|
||||
_fail(file, line);
|
||||
} else {
|
||||
unsigned int i = (((gs_test_log_stats.next_log + GS_TEST_LOG_MAX_LOG_MESSAGES) - 1 - stack_index) % GS_TEST_LOG_MAX_LOG_MESSAGES);
|
||||
if ((gs_test_log_stats.logs[i].level == level) &&
|
||||
(gs_test_log_stats.logs[i].msg[0]) &&
|
||||
(fnmatch(pattern, gs_test_log_stats.logs[i].msg, 0) == 0)) {
|
||||
// match
|
||||
} else {
|
||||
cm_print_error("[%c][%s] != [%c][%s]\n",
|
||||
gs_log_level_to_char(gs_test_log_stats.logs[i].level), gs_test_log_stats.logs[i].msg,
|
||||
gs_log_level_to_char(level), pattern);
|
||||
_fail(file, line);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user