1 /*
2 * Copyright (c) 2021 Nordic Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "mock_backend.h"
8 #include <zephyr/ztest.h>
9 #include <zephyr/logging/log_core.h>
10
mock_log_backend_reset(const struct log_backend * backend)11 void mock_log_backend_reset(const struct log_backend *backend)
12 {
13 struct mock_log_backend *mock = backend->cb->ctx;
14
15 mock->msg_rec_idx = 0;
16 mock->msg_proc_idx = 0;
17 mock->do_check = true;
18 mock->exp_drop_cnt = 0;
19 mock->drop_cnt = 0;
20 mock->panic = false;
21 }
22
mock_log_backend_check_enable(const struct log_backend * backend)23 void mock_log_backend_check_enable(const struct log_backend *backend)
24 {
25 struct mock_log_backend *mock = backend->cb->ctx;
26
27 mock->do_check = true;
28 }
29
mock_log_backend_check_disable(const struct log_backend * backend)30 void mock_log_backend_check_disable(const struct log_backend *backend)
31 {
32 struct mock_log_backend *mock = backend->cb->ctx;
33
34 mock->do_check = false;
35 }
36
mock_log_backend_dummy_record(const struct log_backend * backend,int cnt)37 void mock_log_backend_dummy_record(const struct log_backend *backend, int cnt)
38 {
39 struct mock_log_backend *mock = backend->cb->ctx;
40
41 for (int i = 0; i < cnt; i++) {
42 mock->exp_msgs[mock->msg_rec_idx + i].check = false;
43 }
44
45 mock->msg_rec_idx += cnt;
46 }
47
mock_log_backend_drop_record(const struct log_backend * backend,int cnt)48 void mock_log_backend_drop_record(const struct log_backend *backend, int cnt)
49 {
50 struct mock_log_backend *mock = backend->cb->ctx;
51
52 mock->exp_drop_cnt = cnt;
53 }
54
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)55 void mock_log_backend_generic_record(const struct log_backend *backend,
56 uint16_t source_id,
57 uint16_t domain_id,
58 uint8_t level,
59 log_timestamp_t timestamp,
60 const char *str,
61 uint8_t *data,
62 uint32_t data_len)
63 {
64 if (backend->cb == NULL) {
65 return;
66 }
67
68 if (IS_ENABLED(CONFIG_LOG_FRONTEND_ONLY) && timestamp != (log_timestamp_t)UINT32_MAX) {
69 return;
70 }
71
72 struct mock_log_backend *mock = backend->cb->ctx;
73 struct mock_log_backend_msg *exp = &mock->exp_msgs[mock->msg_rec_idx];
74
75 exp->check = true;
76 exp->timestamp = timestamp;
77 exp->source_id = source_id;
78 exp->domain_id = domain_id;
79 exp->level = level;
80
81 int len = strlen(str);
82
83 __ASSERT_NO_MSG(len < sizeof(exp->str));
84
85 memcpy(exp->str, str, len);
86 exp->str[len] = 0;
87
88 if (data_len <= sizeof(exp->data)) {
89 memcpy(exp->data, data, data_len);
90 }
91 exp->data_len = data_len;
92
93 mock->msg_rec_idx++;
94 }
95
mock_log_backend_validate(const struct log_backend * backend,bool panic)96 void mock_log_backend_validate(const struct log_backend *backend, bool panic)
97 {
98 struct mock_log_backend *mock = backend->cb->ctx;
99
100 zassert_equal(mock->exp_drop_cnt, mock->drop_cnt,
101 "Got: %u, Expected: %u", mock->drop_cnt, mock->exp_drop_cnt);
102 zassert_equal(mock->msg_rec_idx, mock->msg_proc_idx,
103 "%p Recored:%d, Got: %d", mock, mock->msg_rec_idx, mock->msg_proc_idx);
104 zassert_equal(mock->panic, panic);
105
106 #if defined(CONFIG_LOG_MODE_DEFERRED) && \
107 defined(CONFIG_LOG_PROCESS_THREAD)
108 zassert_true(mock->evt_notified);
109 #endif
110 }
111
112 struct test_str {
113 char *str;
114 int cnt;
115 };
116
out(int c,void * ctx)117 static int out(int c, void *ctx)
118 {
119 struct test_str *s = ctx;
120
121 s->str[s->cnt++] = (char)c;
122
123 return c;
124 }
125
process(const struct log_backend * const backend,union log_msg_generic * msg)126 static void process(const struct log_backend *const backend,
127 union log_msg_generic *msg)
128 {
129 struct mock_log_backend *mock = backend->cb->ctx;
130 struct mock_log_backend_msg *exp = &mock->exp_msgs[mock->msg_proc_idx];
131
132 if (!mock->do_check) {
133 return;
134 }
135
136 mock->msg_proc_idx++;
137
138 if (!exp->check) {
139 return;
140 }
141
142 zassert_equal(msg->log.hdr.timestamp, exp->timestamp,
143 #ifdef CONFIG_LOG_TIMESTAMP_64BIT
144 "Got: %llu, expected: %llu",
145 #else
146 "Got: %u, expected: %u",
147 #endif
148 msg->log.hdr.timestamp, exp->timestamp);
149 zassert_equal(msg->log.hdr.desc.level, exp->level);
150 zassert_equal(msg->log.hdr.desc.domain, exp->domain_id);
151
152 uint32_t source_id;
153 const void *source = msg->log.hdr.source;
154
155 if (exp->level == LOG_LEVEL_INTERNAL_RAW_STRING) {
156 source_id = (uintptr_t)source;
157 } else if (source == NULL) {
158 source_id = 0;
159 } else {
160 source_id = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ?
161 log_dynamic_source_id((struct log_source_dynamic_data *)source) :
162 log_const_source_id((const struct log_source_const_data *)source);
163 }
164
165 zassert_equal(source_id, exp->source_id, "source_id:%p (exp: %d)",
166 source_id, exp->source_id);
167
168 size_t len;
169 uint8_t *data;
170 struct cbprintf_package_desc *package_desc;
171
172 data = log_msg_get_data(&msg->log, &len);
173
174 zassert_equal(exp->data_len, len);
175 if (exp->data_len <= sizeof(exp->data)) {
176 zassert_equal(memcmp(data, exp->data, len), 0);
177 }
178
179 char str[128];
180 struct test_str s = { .str = str };
181
182 data = log_msg_get_package(&msg->log, &len);
183 package_desc = (struct cbprintf_package_desc *)data;
184
185 if (IS_ENABLED(CONFIG_LOG_MSG_APPEND_RO_STRING_LOC)) {
186 /* If RO string locations are appended there is always at least 1: format string. */
187 zassert_true(package_desc->ro_str_cnt > 0);
188 } else {
189 zassert_equal(package_desc->ro_str_cnt, 0);
190 }
191
192 len = cbpprintf(out, &s, data);
193 if (len > 0) {
194 str[len] = '\0';
195 }
196
197 zassert_equal(strcmp(str, exp->str), 0, "Got \"%s\", Expected:\"%s\"",
198 str, exp->str);
199 }
200
mock_init(struct log_backend const * const backend)201 static void mock_init(struct log_backend const *const backend)
202 {
203
204 }
205
panic(struct log_backend const * const backend)206 static void panic(struct log_backend const *const backend)
207 {
208 struct mock_log_backend *mock = backend->cb->ctx;
209
210 mock->panic = true;
211 }
212
dropped(const struct log_backend * const backend,uint32_t cnt)213 static void dropped(const struct log_backend *const backend, uint32_t cnt)
214 {
215 struct mock_log_backend *mock = backend->cb->ctx;
216
217 mock->drop_cnt += cnt;
218 }
219
220
221 #if defined(CONFIG_LOG_MODE_DEFERRED) && \
222 defined(CONFIG_LOG_PROCESS_THREAD)
notify(const struct log_backend * const backend,enum log_backend_evt event,union log_backend_evt_arg * arg)223 static void notify(const struct log_backend *const backend,
224 enum log_backend_evt event,
225 union log_backend_evt_arg *arg)
226 {
227 struct mock_log_backend *mock = backend->cb->ctx;
228
229 mock->evt_notified = true;
230 }
231 #endif
232
233 const struct log_backend_api mock_log_backend_api = {
234 .process = process,
235 .panic = panic,
236 .init = mock_init,
237 .dropped = IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE) ? NULL : dropped,
238
239 #if defined(CONFIG_LOG_MODE_DEFERRED) && \
240 defined(CONFIG_LOG_PROCESS_THREAD)
241 .notify = notify,
242 #endif
243 };
244