blob: 5704fa164fe3302b4ea06e6306ff6805dfb06c77 [file] [log] [blame]
/*
* Copyright (c) 2021 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/tc_util.h>
#include <stdbool.h>
#include <zephyr/kernel.h>
#include <zephyr/toolchain.h>
#include <zephyr/ztest.h>
#include <zephyr/logging/log_backend.h>
#include <zephyr/logging/log_ctrl.h>
#include <zephyr/logging/log.h>
#define LOG_MODULE_NAME test
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
struct backend_context {
uint32_t cnt;
const char *exp_str[10];
uint32_t delay;
bool active;
struct k_timer timer;
};
static int cbprintf_callback(int c, void *ctx)
{
char **p = ctx;
**p = c;
(*p)++;
return c;
}
static void backend_process(const struct log_backend *const backend,
union log_msg_generic *msg)
{
char str[100];
char *pstr = str;
struct backend_context *context = (struct backend_context *)backend->cb->ctx;
size_t len;
uint8_t *p = log_msg_get_package(&msg->log, &len);
(void)len;
int slen = cbpprintf(cbprintf_callback, &pstr, p);
str[slen] = '\0';
zassert_equal(strcmp(str, context->exp_str[context->cnt]), 0,
"Unexpected string %s (exp:%s)", str, context->exp_str[context->cnt]);
context->cnt++;
}
static void panic(const struct log_backend *const backend)
{
ARG_UNUSED(backend);
}
static void expire_cb(struct k_timer *timer)
{
void *ctx = k_timer_user_data_get(timer);
struct backend_context *context = (struct backend_context *)ctx;
context->active = true;
}
static void backend_init(const struct log_backend *const backend)
{
struct backend_context *context = (struct backend_context *)backend->cb->ctx;
k_timer_init(&context->timer, expire_cb, NULL);
k_timer_user_data_set(&context->timer, (void *)context);
k_timer_start(&context->timer, K_MSEC(context->delay), K_NO_WAIT);
}
static int backend_is_ready(const struct log_backend *const backend)
{
struct backend_context *context = (struct backend_context *)backend->cb->ctx;
return context->active ? 0 : -EBUSY;
}
static const struct log_backend_api backend_api = {
.process = backend_process,
.init = backend_init,
.is_ready = backend_is_ready,
.panic = panic
};
static struct backend_context context1 = {
.delay = 500
};
static struct backend_context context2 = {
.delay = 1000,
};
LOG_BACKEND_DEFINE(backend1, backend_api, true, &context1);
LOG_BACKEND_DEFINE(backend2, backend_api, true, &context2);
/* Test is using two backends which are configured to be autostarted but have
* prolonged initialization. Backend1 starts earlier.
*
* Logging does not process logs until at least one backend is ready so once
* backend1 is ready first log message is processed. Since backend2 is not yet
* ready it will not receive this message. Second message is created when
* both backends are initialized so both receives the message.
*/
ZTEST(log_backend_init, test_log_backends_initialization)
{
int cnt;
STRUCT_SECTION_COUNT(log_backend, &cnt);
if (cnt != 2) {
/* Other backends should not be enabled. */
ztest_test_skip();
}
context1.cnt = 0;
context2.cnt = 0;
context1.exp_str[0] = "test1";
context1.exp_str[1] = "test2";
context2.exp_str[0] = "test2";
LOG_INF("test1");
/* Backends are not yet active. */
zassert_false(context1.active);
zassert_false(context2.active);
k_msleep(context2.delay + 100);
zassert_true(context1.active);
zassert_true(context2.active);
LOG_INF("test2");
k_msleep(1100);
/* Backend1 gets both messages but backend2 gets only second message
* because when first was processed it was not yet active.
*/
zassert_equal(context1.cnt, 2, "Unexpected value:%d (exp: %d)", context1.cnt, 2);
zassert_equal(context2.cnt, 1);
}
ZTEST_SUITE(log_backend_init, NULL, NULL, NULL, NULL, NULL);