blob: e7e48623a6303abce5620fb196fa9d372ccedde3 [file] [log] [blame]
/*
* Copyright (c) 2021 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mock_backend.h"
#include <ztest.h>
#include <logging/log_core.h>
void mock_log_backend_reset(const struct log_backend *backend)
{
struct mock_log_backend *mock = backend->cb->ctx;
mock->msg_rec_idx = 0;
mock->msg_proc_idx = 0;
mock->do_check = true;
mock->exp_drop_cnt = 0;
mock->drop_cnt = 0;
mock->panic = false;
}
void mock_log_backend_check_enable(const struct log_backend *backend)
{
struct mock_log_backend *mock = backend->cb->ctx;
mock->do_check = true;
}
void mock_log_backend_check_disable(const struct log_backend *backend)
{
struct mock_log_backend *mock = backend->cb->ctx;
mock->do_check = false;
}
void mock_log_backend_dummy_record(const struct log_backend *backend, int cnt)
{
struct mock_log_backend *mock = backend->cb->ctx;
for (int i = 0; i < cnt; i++) {
mock->exp_msgs[mock->msg_rec_idx + i].check = false;
}
mock->msg_rec_idx += cnt;
}
void mock_log_backend_drop_record(const struct log_backend *backend, int cnt)
{
struct mock_log_backend *mock = backend->cb->ctx;
mock->exp_drop_cnt = cnt;
}
void mock_log_backend_generic_record(const struct log_backend *backend,
uint16_t source_id,
uint16_t domain_id,
uint8_t level,
log_timestamp_t timestamp,
const char *str,
uint8_t *data,
uint32_t data_len)
{
struct mock_log_backend *mock = backend->cb->ctx;
struct mock_log_backend_msg *exp = &mock->exp_msgs[mock->msg_rec_idx];
exp->check = true;
exp->timestamp = timestamp;
exp->source_id = source_id;
exp->domain_id = domain_id;
exp->level = level;
int len = strlen(str);
__ASSERT_NO_MSG(len < sizeof(exp->str));
memcpy(exp->str, str, len);
exp->str[len] = 0;
if (data_len <= sizeof(exp->data)) {
memcpy(exp->data, data, data_len);
}
exp->data_len = data_len;
mock->msg_rec_idx++;
}
void mock_log_backend_validate(const struct log_backend *backend, bool panic)
{
struct mock_log_backend *mock = backend->cb->ctx;
zassert_equal(mock->exp_drop_cnt, mock->drop_cnt,
"Got: %u, Expected: %u", mock->drop_cnt, mock->exp_drop_cnt);
zassert_equal(mock->msg_rec_idx, mock->msg_proc_idx, NULL);
zassert_equal(mock->panic, panic, NULL);
}
static void fmt_cmp(struct log_msg *msg, char *exp_str)
{
char str[128];
const char *fmt = msg->str;
uint32_t nargs = log_msg_nargs_get(msg);
log_arg_t *args = alloca(sizeof(log_arg_t)*nargs);
for (int i = 0; i < nargs; i++) {
args[i] = log_msg_arg_get(msg, i);
}
switch (log_msg_nargs_get(msg)) {
case 0:
snprintk(str, sizeof(str), fmt, NULL);
break;
case 1:
snprintk(str, sizeof(str), fmt, args[0]);
break;
case 2:
snprintk(str, sizeof(str), fmt, args[0], args[1]);
break;
case 3:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2]);
break;
case 4:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3]);
break;
case 5:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4]);
break;
case 6:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5]);
break;
case 7:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5], args[6]);
break;
case 8:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5], args[6], args[7]);
break;
case 9:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5], args[6], args[7],
args[8]);
break;
case 10:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5], args[6], args[7],
args[8], args[9]);
break;
case 11:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5], args[6], args[7],
args[8], args[9], args[10]);
break;
case 12:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11]);
break;
case 13:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11], args[12]);
break;
case 14:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11], args[12],
args[13]);
break;
case 15:
snprintk(str, sizeof(str), fmt, args[0], args[1], args[2],
args[3], args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11], args[12],
args[13], args[14]);
break;
default:
/* Unsupported number of arguments. */
__ASSERT_NO_MSG(true);
break;
}
zassert_equal(0, strcmp(str, exp_str), NULL);
}
static void hexdump_cmp(struct log_msg *msg, uint8_t *exp_data,
uint32_t exp_len, bool skip_data_check)
{
uint32_t len = msg->hdr.params.hexdump.length;
size_t offset = 0;
size_t l;
zassert_equal(len, exp_len, "Got: %u, expected: %u", len, exp_len);
if (skip_data_check) {
return;
}
do {
uint8_t d;
l = 1;
log_msg_hexdump_data_get(msg, &d, &l, offset);
if (l) {
zassert_equal(d, exp_data[offset],
"Got:%02x, Expected:%02x", d, exp_data[offset]);
}
offset += l;
} while (l > 0);
zassert_equal(offset, exp_len, NULL);
}
static void put(const struct log_backend *const backend,
struct log_msg *msg)
{
struct mock_log_backend *mock = backend->cb->ctx;
struct mock_log_backend_msg *exp = &mock->exp_msgs[mock->msg_proc_idx];
mock->msg_proc_idx++;
if (!exp->check) {
return;
}
zassert_equal(msg->hdr.timestamp, exp->timestamp,
"Got: %u, expected: %u", msg->hdr.timestamp, exp->timestamp);
zassert_equal(msg->hdr.ids.level, exp->level, NULL);
zassert_equal(msg->hdr.ids.source_id, exp->source_id, NULL);
zassert_equal(msg->hdr.ids.domain_id, exp->domain_id, NULL);
if (msg->hdr.params.generic.type == LOG_MSG_TYPE_STD) {
zassert_equal(exp->data_len, 0, NULL);
fmt_cmp(msg, exp->str);
} else {
zassert_equal(0, strcmp(msg->str, exp->str), NULL);
hexdump_cmp(msg, exp->data, exp->data_len,
exp->data_len > sizeof(exp->data));
}
}
struct test_str {
char *str;
int cnt;
};
static int out(int c, void *ctx)
{
struct test_str *s = ctx;
s->str[s->cnt++] = (char)c;
return c;
}
static void process(const struct log_backend *const backend,
union log_msg2_generic *msg)
{
struct mock_log_backend *mock = backend->cb->ctx;
struct mock_log_backend_msg *exp = &mock->exp_msgs[mock->msg_proc_idx];
mock->msg_proc_idx++;
if (!exp->check) {
return;
}
zassert_equal(msg->log.hdr.timestamp, exp->timestamp,
"Got: %u, expected: %u",
msg->log.hdr.timestamp, exp->timestamp);
zassert_equal(msg->log.hdr.desc.level, exp->level, NULL);
zassert_equal(msg->log.hdr.desc.domain, exp->domain_id, NULL);
uint32_t source_id = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ?
log_dynamic_source_id((struct log_source_dynamic_data *)msg->log.hdr.source) :
log_const_source_id((const struct log_source_const_data *)msg->log.hdr.source);
zassert_equal(source_id, exp->source_id, NULL);
size_t len;
uint8_t *data;
data = log_msg2_get_data(&msg->log, &len);
zassert_equal(exp->data_len, len, NULL);
if (exp->data_len <= sizeof(exp->data)) {
zassert_equal(memcmp(data, exp->data, len), 0, NULL);
}
char str[128];
struct test_str s = { .str = str };
data = log_msg2_get_package(&msg->log, &len);
len = cbpprintf(out, &s, data);
if (len > 0) {
str[len] = '\0';
}
zassert_equal(strcmp(str, exp->str), 0, "Got \"%s\", Expected:\"%s\"",
str, exp->str);
}
static void mock_init(struct log_backend const *const backend)
{
}
static void panic(struct log_backend const *const backend)
{
struct mock_log_backend *mock = backend->cb->ctx;
mock->panic = true;
}
static void dropped(const struct log_backend *const backend, uint32_t cnt)
{
struct mock_log_backend *mock = backend->cb->ctx;
mock->drop_cnt += cnt;
}
static void sync_string(const struct log_backend *const backend,
struct log_msg_ids src_level, uint32_t timestamp,
const char *fmt, va_list ap)
{
struct mock_log_backend *mock = backend->cb->ctx;
struct mock_log_backend_msg *exp = &mock->exp_msgs[mock->msg_proc_idx];
mock->msg_proc_idx++;
if (!exp->check) {
return;
}
zassert_equal(timestamp, exp->timestamp,
"Got: %u, expected: %u", timestamp, exp->timestamp);
zassert_equal(src_level.level, exp->level, NULL);
zassert_equal(src_level.source_id, exp->source_id, NULL);
zassert_equal(src_level.domain_id, exp->domain_id, NULL);
zassert_equal(exp->data_len, 0, NULL);
char str[128];
vsnprintk(str, sizeof(str), fmt, ap);
zassert_equal(0, strcmp(str, exp->str), NULL);
}
static void sync_hexdump(const struct log_backend *const backend,
struct log_msg_ids src_level, uint32_t timestamp,
const char *metadata, const uint8_t *data, uint32_t length)
{
struct mock_log_backend *mock = backend->cb->ctx;
struct mock_log_backend_msg *exp = &mock->exp_msgs[mock->msg_proc_idx];
mock->msg_proc_idx++;
if (!exp->check) {
return;
}
zassert_equal(timestamp, exp->timestamp,
"Got: %u, expected: %u", timestamp, exp->timestamp);
zassert_equal(src_level.level, exp->level, NULL);
zassert_equal(src_level.source_id, exp->source_id, NULL);
zassert_equal(src_level.domain_id, exp->domain_id, NULL);
zassert_equal(0, strcmp(metadata, exp->str), NULL);
zassert_equal(length, exp->data_len, NULL);
if (length <= sizeof(exp->data)) {
zassert_equal(memcmp(data, exp->data, length), 0, NULL);
}
}
const struct log_backend_api mock_log_backend_api = {
.process = IS_ENABLED(CONFIG_LOG2) ? process : NULL,
.put = IS_ENABLED(CONFIG_LOG_MODE_DEFERRED) ? put : NULL,
.put_sync_string = IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE) ?
sync_string : NULL,
.put_sync_hexdump = IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE) ?
sync_hexdump : NULL,
.panic = panic,
.init = mock_init,
.dropped = IS_ENABLED(CONFIG_LOG_IMMEDIATE) ? NULL : dropped,
};