1 /*
2 * Copyright (c) 2018 Nordic Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Test log message
10 */
11
12 #include <zephyr/logging/log.h>
13 #include <zephyr/logging/log_output.h>
14
15 #include <zephyr/tc_util.h>
16 #include <stdbool.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/ztest.h>
19
20 #define LOG_MODULE_NAME test
21 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
22
23 #define SNAME "src"
24 #define DNAME "domain"
25 #define TEST_STR "test"
26
27 static uint8_t mock_buffer[512];
28 static uint8_t log_output_buf[4];
29 static uint32_t mock_len;
30
reset_mock_buffer(void)31 static void reset_mock_buffer(void)
32 {
33 mock_len = 0U;
34 memset(mock_buffer, 0, sizeof(mock_buffer));
35 }
36
mock_output_func(uint8_t * buf,size_t size,void * ctx)37 static int mock_output_func(uint8_t *buf, size_t size, void *ctx)
38 {
39 memcpy(&mock_buffer[mock_len], buf, size);
40 mock_len += size;
41
42 return size;
43 }
44
45 LOG_OUTPUT_DEFINE(log_output, mock_output_func,
46 log_output_buf, sizeof(log_output_buf));
47
ZTEST(test_log_output,test_no_flags)48 ZTEST(test_log_output, test_no_flags)
49 {
50 char package[256];
51 static const char *exp_str = SNAME ": " TEST_STR "\r\n";
52 int err;
53
54 err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
55 zassert_true(err > 0);
56
57 log_output_process(&log_output, 0, NULL, SNAME, NULL, LOG_LEVEL_INF, package, NULL, 0, 0);
58
59 mock_buffer[mock_len] = '\0';
60 zassert_str_equal(exp_str, mock_buffer);
61 }
62
ZTEST(test_log_output,test_raw)63 ZTEST(test_log_output, test_raw)
64 {
65 char package[256];
66 static const char *exp_str = TEST_STR;
67 int err;
68
69 err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
70 zassert_true(err > 0);
71
72 log_output_process(&log_output, 0, NULL, SNAME, NULL, LOG_LEVEL_INTERNAL_RAW_STRING,
73 package, NULL, 0, 0);
74
75 mock_buffer[mock_len] = '\0';
76 zassert_str_equal(exp_str, mock_buffer);
77 }
78
ZTEST(test_log_output,test_no_flags_dname)79 ZTEST(test_log_output, test_no_flags_dname)
80 {
81 char package[256];
82 static const char *exp_str = DNAME "/" SNAME ": " TEST_STR "\r\n";
83 int err;
84
85 err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
86 zassert_true(err > 0);
87
88 log_output_process(&log_output, 0, DNAME, SNAME, NULL, LOG_LEVEL_INF, package, NULL, 0, 0);
89
90 mock_buffer[mock_len] = '\0';
91 zassert_str_equal(exp_str, mock_buffer);
92 }
93
ZTEST(test_log_output,test_level_flag)94 ZTEST(test_log_output, test_level_flag)
95 {
96 char package[256];
97 static const char *exp_str = "<inf> " DNAME "/" SNAME ": " TEST_STR "\r\n";
98 uint32_t flags = LOG_OUTPUT_FLAG_LEVEL;
99 int err;
100
101 err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
102 zassert_true(err > 0);
103
104 log_output_process(&log_output, 0, DNAME, SNAME, NULL, LOG_LEVEL_INF,
105 package, NULL, 0, flags);
106
107 mock_buffer[mock_len] = '\0';
108 zassert_str_equal(exp_str, mock_buffer);
109 }
110
ZTEST(test_log_output,test_ts_flag)111 ZTEST(test_log_output, test_ts_flag)
112 {
113 char package[256];
114 static const char *exp_str = IS_ENABLED(CONFIG_LOG_TIMESTAMP_64BIT) ?
115 "[0000000000000000] " DNAME "/" SNAME ": " TEST_STR "\r\n" :
116 "[00000000] " DNAME "/" SNAME ": " TEST_STR "\r\n";
117 uint32_t flags = LOG_OUTPUT_FLAG_TIMESTAMP;
118 int err;
119
120 err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
121 zassert_true(err > 0);
122
123 log_output_process(&log_output, 0, DNAME, SNAME, NULL, LOG_LEVEL_INF,
124 package, NULL, 0, flags);
125
126 mock_buffer[mock_len] = '\0';
127 zassert_str_equal(exp_str, mock_buffer);
128 }
129
ZTEST(test_log_output,test_format_ts)130 ZTEST(test_log_output, test_format_ts)
131 {
132 #ifdef CONFIG_LOG_OUTPUT_FORMAT_DATE_TIMESTAMP
133 #define TIMESTAMP_STR "[1970-01-01 00:00:01.000,000] "
134 #elif defined(CONFIG_LOG_OUTPUT_FORMAT_ISO8601_TIMESTAMP)
135 #define TIMESTAMP_STR "[1970-01-01T00:00:01,000000Z] "
136 #else
137 #define TIMESTAMP_STR "[00:00:01.000,000] "
138 #endif
139 char package[256];
140 static const char *exp_str = TIMESTAMP_STR DNAME "/" SNAME ": " TEST_STR "\r\n";
141 uint32_t flags = LOG_OUTPUT_FLAG_TIMESTAMP | LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
142 int err;
143
144 log_output_timestamp_freq_set(1000000);
145
146 err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
147 zassert_true(err > 0);
148
149 log_output_process(&log_output, 1000000, DNAME, SNAME, NULL, LOG_LEVEL_INF,
150 package, NULL, 0, flags);
151
152 mock_buffer[mock_len] = '\0';
153 printk("%s", mock_buffer);
154 zassert_str_equal(exp_str, mock_buffer);
155 }
156
ZTEST(test_log_output,test_ts_to_us)157 ZTEST(test_log_output, test_ts_to_us)
158 {
159 log_output_timestamp_freq_set(1000000);
160
161 zassert_equal(log_output_timestamp_to_us(1000), 1000);
162
163 log_output_timestamp_freq_set(32768);
164
165 zassert_equal(log_output_timestamp_to_us(10), 305);
166 }
167
ZTEST(test_log_output,test_levels)168 ZTEST(test_log_output, test_levels)
169 {
170 char package[256];
171 static const char *const exp_strs[] = {
172 "<err> " SNAME ": " TEST_STR "\r\n",
173 "<wrn> " SNAME ": " TEST_STR "\r\n",
174 "<inf> " SNAME ": " TEST_STR "\r\n",
175 "<dbg> " SNAME ": " TEST_STR "\r\n"
176 };
177 uint8_t levels[] = {LOG_LEVEL_ERR, LOG_LEVEL_WRN, LOG_LEVEL_INF, LOG_LEVEL_DBG};
178 uint32_t flags = LOG_OUTPUT_FLAG_LEVEL;
179 int err;
180
181 err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
182 zassert_true(err > 0);
183
184 for (int i = 0; i < ARRAY_SIZE(exp_strs); i++) {
185 reset_mock_buffer();
186
187 log_output_process(&log_output, 0, NULL, SNAME, NULL, levels[i],
188 package, NULL, 0, flags);
189
190 mock_buffer[mock_len] = '\0';
191 zassert_str_equal(exp_strs[i], mock_buffer);
192 }
193 }
194
ZTEST(test_log_output,test_colors)195 ZTEST(test_log_output, test_colors)
196 {
197 #define LOG_COLOR_CODE_DEFAULT "\x1B[0m"
198 #define LOG_COLOR_CODE_RED "\x1B[1;31m"
199 #define LOG_COLOR_CODE_GREEN "\x1B[1;32m"
200 #define LOG_COLOR_CODE_YELLOW "\x1B[1;33m"
201 #define LOG_COLOR_CODE_BLUE "\x1B[1;34m"
202
203 #ifdef CONFIG_LOG_BACKEND_SHOW_COLOR
204 #define LOG_COLOR_ERR LOG_COLOR_CODE_RED
205 #define LOG_COLOR_WRN LOG_COLOR_CODE_YELLOW
206 #define LOG_COLOR_INF LOG_COLOR_CODE_GREEN
207 #define LOG_COLOR_DBG LOG_COLOR_CODE_BLUE
208 #else
209 #define LOG_COLOR_ERR LOG_COLOR_CODE_DEFAULT
210 #define LOG_COLOR_WRN LOG_COLOR_CODE_DEFAULT
211 #define LOG_COLOR_INF LOG_COLOR_CODE_DEFAULT
212 #define LOG_COLOR_DBG LOG_COLOR_CODE_DEFAULT
213 #endif /* CONFIG_LOG_BACKEND_SHOW_COLOR */
214
215 char package[256];
216 static const char *const exp_strs[] = {
217 LOG_COLOR_ERR "<err> " SNAME ": " TEST_STR LOG_COLOR_CODE_DEFAULT "\r\n",
218 LOG_COLOR_WRN "<wrn> " SNAME ": " TEST_STR LOG_COLOR_CODE_DEFAULT "\r\n",
219 LOG_COLOR_INF "<inf> " SNAME ": " TEST_STR LOG_COLOR_CODE_DEFAULT "\r\n",
220 LOG_COLOR_DBG "<dbg> " SNAME ": " TEST_STR LOG_COLOR_CODE_DEFAULT "\r\n"
221 };
222 uint8_t levels[] = {LOG_LEVEL_ERR, LOG_LEVEL_WRN, LOG_LEVEL_INF, LOG_LEVEL_DBG};
223 uint32_t flags = LOG_OUTPUT_FLAG_LEVEL | LOG_OUTPUT_FLAG_COLORS;
224 int err;
225
226 err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
227 zassert_true(err > 0);
228
229 for (int i = 0; i < ARRAY_SIZE(exp_strs); i++) {
230 reset_mock_buffer();
231
232 log_output_process(&log_output, 0, NULL, SNAME, NULL, levels[i],
233 package, NULL, 0, flags);
234
235 mock_buffer[mock_len] = '\0';
236 zassert_str_equal(exp_strs[i], mock_buffer);
237 }
238 }
239
ZTEST(test_log_output,test_thread_id)240 ZTEST(test_log_output, test_thread_id)
241 {
242 if (!IS_ENABLED(CONFIG_LOG_THREAD_ID_PREFIX)) {
243 return;
244 }
245
246 char exp_str[256];
247 char package[256];
248
249 if (IS_ENABLED(CONFIG_THREAD_NAME)) {
250 sprintf(exp_str, "<err> [%s] src: Test\r\n", k_thread_name_get(k_current_get()));
251 } else {
252 sprintf(exp_str, "<err> [%p] src: Test\r\n", k_current_get());
253 }
254
255 uint32_t flags = LOG_OUTPUT_FLAG_LEVEL | LOG_OUTPUT_FLAG_THREAD;
256 int err;
257
258 err = cbprintf_package(package, sizeof(package), 0, "Test");
259 zassert_true(err > 0);
260
261 log_output_process(&log_output, 0, NULL, SNAME, k_current_get(), 1,
262 package, NULL, 0, flags);
263
264 mock_buffer[mock_len] = '\0';
265 printk("%s", mock_buffer);
266 zassert_str_equal(exp_str, mock_buffer);
267 }
268
ZTEST(test_log_output,test_skip_src)269 ZTEST(test_log_output, test_skip_src)
270 {
271 char package[256];
272 const char exp_str[] = TEST_STR "\r\n";
273 uint32_t flags = LOG_OUTPUT_FLAG_SKIP_SOURCE;
274 int err;
275
276 err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
277 zassert_true(err > 0);
278
279 reset_mock_buffer();
280 log_output_process(&log_output, 0, NULL, SNAME, NULL, LOG_LEVEL_INF,
281 package, NULL, 0, flags);
282
283 mock_buffer[mock_len] = '\0';
284 zassert_str_equal(exp_str, mock_buffer);
285 }
286
before(void * notused)287 static void before(void *notused)
288 {
289 reset_mock_buffer();
290 }
291
292 ZTEST_SUITE(test_log_output, NULL, NULL, before, NULL, NULL);
293