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