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_msg.h>
13 #include <zephyr/logging/log_internal.h>
14 #include <zephyr/logging/log_ctrl.h>
15 
16 #include <zephyr/tc_util.h>
17 #include <stdbool.h>
18 #include <zephyr/kernel.h>
19 #include <zephyr/ztest.h>
20 #include <zephyr/sys/cbprintf.h>
21 
22 #if CONFIG_NO_OPTIMIZATIONS
23 #define EXP_MODE(name) Z_LOG_MSG_MODE_RUNTIME
24 #else
25 #define EXP_MODE(name) Z_LOG_MSG_MODE_##name
26 #endif
27 
28 #define TEST_TIMESTAMP_INIT_VALUE \
29 	COND_CODE_1(CONFIG_LOG_TIMESTAMP_64BIT, (0x1234123412), (0x11223344))
30 
31 static log_timestamp_t timestamp;
32 
get_timestamp(void)33 log_timestamp_t get_timestamp(void)
34 {
35 	return timestamp;
36 }
37 
test_init(void)38 static void test_init(void)
39 {
40 	timestamp = TEST_TIMESTAMP_INIT_VALUE;
41 	z_log_msg_init();
42 	log_set_timestamp_func(get_timestamp, 0);
43 }
44 
print_msg(struct log_msg * msg)45 void print_msg(struct log_msg *msg)
46 {
47 	printk("-----------------------printing message--------------------\n");
48 	printk("message %p\n", msg);
49 	printk("package len: %d, data len: %d\n",
50 			msg->hdr.desc.package_len,
51 			msg->hdr.desc.data_len);
52 	for (int i = 0; i < msg->hdr.desc.package_len; i++) {
53 		printk("%02x ", msg->data[i]);
54 	}
55 	printk("\n");
56 	printk("source: %p\n", msg->hdr.source);
57 	printk("timestamp: %d\n", (int)msg->hdr.timestamp);
58 	printk("-------------------end of printing message-----------------\n");
59 }
60 
61 struct test_buf {
62 	char *buf;
63 	int idx;
64 };
65 
out(int c,void * ctx)66 int out(int c, void *ctx)
67 {
68 	struct test_buf *t = ctx;
69 
70 	t->buf[t->idx++] = c;
71 
72 	return c;
73 }
74 
basic_validate(struct log_msg * msg,const struct log_source_const_data * source,uint8_t domain,uint8_t level,log_timestamp_t t,const void * data,size_t data_len,char * str)75 static void basic_validate(struct log_msg *msg,
76 			   const struct log_source_const_data *source,
77 			   uint8_t domain, uint8_t level, log_timestamp_t t,
78 			   const void *data, size_t data_len, char *str)
79 {
80 	int rv;
81 	uint8_t *d;
82 	size_t len = 0;
83 	char buf[256];
84 	struct test_buf tbuf = { .buf = buf, .idx = 0 };
85 
86 	zassert_equal(log_msg_get_source(msg), (void *)source);
87 	zassert_equal(log_msg_get_domain(msg), domain);
88 	zassert_equal(log_msg_get_level(msg), level);
89 	zassert_equal(log_msg_get_timestamp(msg), t);
90 
91 	d = log_msg_get_data(msg, &len);
92 	zassert_equal(len, data_len);
93 	if (len) {
94 		rv = memcmp(d, data, data_len);
95 		zassert_equal(rv, 0);
96 	}
97 
98 	d = log_msg_get_package(msg, &len);
99 	if (str) {
100 		rv = cbpprintf(out, &tbuf, d);
101 		zassert_true(rv > 0);
102 		buf[rv] = '\0';
103 
104 		rv = strncmp(buf, str, sizeof(buf));
105 		zassert_equal(rv, 0, "expected:\n%s,\ngot:\n%s", str, buf);
106 	}
107 }
108 
msg_copy_and_free(union log_msg_generic * msg,uint8_t * buf,size_t buf_len)109 union log_msg_generic *msg_copy_and_free(union log_msg_generic *msg,
110 					  uint8_t *buf, size_t buf_len)
111 {
112 	size_t len = sizeof(int) *
113 		     log_msg_generic_get_wlen((union mpsc_pbuf_generic *)msg);
114 
115 	zassert_true(len < buf_len);
116 
117 	memcpy(buf, msg, len);
118 
119 	z_log_msg_free(msg);
120 
121 	return (union log_msg_generic *)buf;
122 }
123 
clear_pkg_flags(struct log_msg * msg)124 void clear_pkg_flags(struct log_msg *msg)
125 {
126 #ifdef CONFIG_CBPRINTF_PACKAGE_HEADER_STORE_CREATION_FLAGS
127 	/*
128 	 * The various tests create cbprintf packages differently
129 	 * for the same log message. This results in different
130 	 * package flags stored in those packages. These package
131 	 * flags can be ignored as we only want to make sure
132 	 * the remaining header bits, the format string, and
133 	 * the format arguments are all the same.
134 	 */
135 
136 	uint8_t *d;
137 	size_t len;
138 
139 	d = log_msg_get_package(msg, &len);
140 	if (len > 0) {
141 		union cbprintf_package_hdr *hdr = (void *)d;
142 
143 		hdr->desc.pkg_flags = 0U;
144 	}
145 #else
146 	ARG_UNUSED(msg);
147 #endif
148 }
149 
validate_base_message_set(const struct log_source_const_data * source,uint8_t domain,uint8_t level,log_timestamp_t t,const void * data,size_t data_len,char * str)150 void validate_base_message_set(const struct log_source_const_data *source,
151 				uint8_t domain, uint8_t level,
152 				log_timestamp_t t, const void *data,
153 				size_t data_len, char *str)
154 {
155 	uint8_t __aligned(Z_LOG_MSG_ALIGNMENT) buf0[256];
156 	uint8_t __aligned(Z_LOG_MSG_ALIGNMENT) buf1[256];
157 	uint8_t __aligned(Z_LOG_MSG_ALIGNMENT) buf2[256];
158 	size_t len0, len1, len2;
159 	union log_msg_generic *msg0, *msg1, *msg2;
160 
161 	msg0 = z_log_msg_claim(NULL);
162 	zassert_true(msg0, "Unexpected null message");
163 	len0 = log_msg_generic_get_wlen((union mpsc_pbuf_generic *)msg0);
164 	msg0 = msg_copy_and_free(msg0, buf0, sizeof(buf0));
165 	clear_pkg_flags(&msg0->log);
166 
167 	msg1 = z_log_msg_claim(NULL);
168 	zassert_true(msg1, "Unexpected null message");
169 	len1 = log_msg_generic_get_wlen((union mpsc_pbuf_generic *)msg1);
170 	msg1 = msg_copy_and_free(msg1, buf1, sizeof(buf1));
171 	clear_pkg_flags(&msg1->log);
172 
173 	msg2 = z_log_msg_claim(NULL);
174 	zassert_true(msg2, "Unexpected null message");
175 	len2 = log_msg_generic_get_wlen((union mpsc_pbuf_generic *)msg2);
176 	msg2 = msg_copy_and_free(msg2, buf2, sizeof(buf2));
177 	clear_pkg_flags(&msg2->log);
178 
179 	print_msg(&msg0->log);
180 	print_msg(&msg1->log);
181 	print_msg(&msg2->log);
182 
183 	/* Messages created with static packaging should have same output.
184 	 * Runtime created message (msg2) may have strings copied in and thus
185 	 * different length.
186 	 */
187 	zassert_equal(len0, len1);
188 
189 	int rv = memcmp(msg0, msg1, sizeof(int) * len0);
190 
191 	zassert_equal(rv, 0, "Unexpected memcmp result: %d", rv);
192 
193 	/* msg1 is not validated because it should be the same as msg0. */
194 	basic_validate(&msg0->log, source, domain, level,
195 			t, data, data_len, str);
196 	basic_validate(&msg2->log, source, domain, level,
197 			t, data, data_len, str);
198 }
199 
ZTEST(log_msg,test_log_msg_0_args_msg)200 ZTEST(log_msg, test_log_msg_0_args_msg)
201 {
202 #undef TEST_MSG
203 #define TEST_MSG "0 args"
204 	static const uint8_t domain = 3;
205 	static const uint8_t level = 2;
206 	const void *source = (const void *)123;
207 	int mode;
208 
209 	test_init();
210 	printk("Test string:%s\n", TEST_MSG);
211 
212 	Z_LOG_MSG_CREATE3(1, mode, 0, domain, source, level,
213 			  NULL, 0, TEST_MSG);
214 	zassert_equal(mode, EXP_MODE(ZERO_COPY));
215 
216 	Z_LOG_MSG_CREATE3(0, mode, 0, domain, source, level,
217 			  NULL, 0, TEST_MSG);
218 	zassert_equal(mode, EXP_MODE(FROM_STACK));
219 
220 	z_log_msg_runtime_create(domain, source,
221 				  level, NULL, 0, 0, TEST_MSG);
222 
223 	validate_base_message_set(source, domain, level,
224 				   TEST_TIMESTAMP_INIT_VALUE,
225 				   NULL, 0, TEST_MSG);
226 }
227 
ZTEST(log_msg,test_log_msg_various_args)228 ZTEST(log_msg, test_log_msg_various_args)
229 {
230 #undef TEST_MSG
231 #define TEST_MSG "%d %d %lld %p %lld %p"
232 	static const uint8_t domain = 3;
233 	static const uint8_t level = 2;
234 	const void *source = (const void *)123;
235 	int mode;
236 	uint8_t u = 0x45;
237 	signed char s8 = -5;
238 	long long lld = 0x12341234563412;
239 	char str[256];
240 	static const int iarray[] = {1, 2, 3, 4};
241 
242 	test_init();
243 	printk("Test string:%s\n", TEST_MSG);
244 
245 	Z_LOG_MSG_CREATE3(1, mode, 0, domain, source, level, NULL, 0,
246 			TEST_MSG, s8, u, lld, (void *)str, lld, (void *)iarray);
247 	zassert_equal(mode, EXP_MODE(ZERO_COPY));
248 
249 	Z_LOG_MSG_CREATE3(0, mode, 0, domain, source, level, NULL, 0,
250 			TEST_MSG, s8, u, lld, (void *)str, lld, (void *)iarray);
251 	zassert_equal(mode, EXP_MODE(FROM_STACK));
252 
253 	z_log_msg_runtime_create(domain, (void *)source, level, NULL,
254 				  0, 0, TEST_MSG, s8, u, lld, str, lld, iarray);
255 	snprintfcb(str, sizeof(str), TEST_MSG, s8, u, lld, str, lld, iarray);
256 
257 	validate_base_message_set(source, domain, level,
258 				   TEST_TIMESTAMP_INIT_VALUE,
259 				   NULL, 0, str);
260 }
261 
ZTEST(log_msg,test_log_msg_only_data)262 ZTEST(log_msg, test_log_msg_only_data)
263 {
264 	static const uint8_t domain = 3;
265 	static const uint8_t level = 2;
266 	const void *source = (const void *)123;
267 	int mode;
268 	static const uint8_t array[] = {1, 2, 3, 4};
269 
270 	test_init();
271 
272 	Z_LOG_MSG_CREATE3(1, mode, 0, domain, source, level, array,
273 			   sizeof(array));
274 	zassert_equal(mode, EXP_MODE(FROM_STACK));
275 
276 	Z_LOG_MSG_CREATE3(0, mode, 0, domain, source, level, array,
277 			   sizeof(array));
278 	zassert_equal(mode, EXP_MODE(FROM_STACK));
279 
280 	z_log_msg_runtime_create(domain, (void *)source, level, array,
281 				  sizeof(array), 0, NULL);
282 
283 	validate_base_message_set(source, domain, level,
284 				   TEST_TIMESTAMP_INIT_VALUE,
285 				   array, sizeof(array), NULL);
286 }
287 
ZTEST(log_msg,test_log_msg_string_and_data)288 ZTEST(log_msg, test_log_msg_string_and_data)
289 {
290 #undef TEST_MSG
291 #define TEST_MSG "test"
292 
293 	static const uint8_t domain = 3;
294 	static const uint8_t level = 2;
295 	const void *source = (const void *)123;
296 	int mode;
297 	static const uint8_t array[] = {1, 2, 3, 4};
298 
299 	test_init();
300 
301 	Z_LOG_MSG_CREATE3(1, mode, 0, domain, source, level, array,
302 			   sizeof(array), TEST_MSG);
303 	zassert_equal(mode, EXP_MODE(FROM_STACK));
304 
305 	Z_LOG_MSG_CREATE3(0, mode, 0, domain, source, level, array,
306 			   sizeof(array), TEST_MSG);
307 	zassert_equal(mode, EXP_MODE(FROM_STACK));
308 
309 	z_log_msg_runtime_create(domain, (void *)source, level, array,
310 				  sizeof(array), 0, TEST_MSG);
311 
312 	validate_base_message_set(source, domain, level,
313 				   TEST_TIMESTAMP_INIT_VALUE,
314 				   array, sizeof(array), TEST_MSG);
315 }
316 
ZTEST(log_msg,test_log_msg_fp)317 ZTEST(log_msg, test_log_msg_fp)
318 {
319 	if (!(IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT) && IS_ENABLED(CONFIG_FPU))) {
320 		return;
321 	}
322 
323 #undef TEST_MSG
324 #define TEST_MSG "%d %lld %f %p %f %p"
325 
326 	static const uint8_t domain = 3;
327 	static const uint8_t level = 2;
328 	const void *source = (const void *)123;
329 	int mode;
330 	long long lli = 0x1122334455;
331 	float f = 1.234f;
332 	double d = 11.3434;
333 	char str[256];
334 	int i = -100;
335 
336 	test_init();
337 
338 	Z_LOG_MSG_CREATE3(1, mode, 0, domain, source, level, NULL, 0,
339 			TEST_MSG, i, lli, (double)f, &i, d, source);
340 	zassert_equal(mode, EXP_MODE(ZERO_COPY));
341 
342 	Z_LOG_MSG_CREATE3(0, mode, 0, domain, source, level, NULL, 0,
343 			TEST_MSG, i, lli, (double)f, &i, d, source);
344 	zassert_equal(mode, EXP_MODE(FROM_STACK));
345 
346 	z_log_msg_runtime_create(domain, (void *)source, level, NULL, 0, 0,
347 				  TEST_MSG, i, lli, (double)f, &i, d, source);
348 	snprintfcb(str, sizeof(str), TEST_MSG, i, lli, (double)f, &i, d, source);
349 
350 	validate_base_message_set(source, domain, level,
351 				   TEST_TIMESTAMP_INIT_VALUE,
352 				   NULL, 0, str);
353 }
354 
get_msg_validate_length(uint32_t exp_len)355 static void get_msg_validate_length(uint32_t exp_len)
356 {
357 	uint32_t len;
358 	union log_msg_generic *msg;
359 
360 	msg = z_log_msg_claim(NULL);
361 	len = log_msg_generic_get_wlen((union mpsc_pbuf_generic *)msg);
362 
363 	zassert_equal(len, exp_len, "Unexpected message length %d (exp:%d)",
364 			len, exp_len);
365 
366 	z_log_msg_free(msg);
367 }
368 
ZTEST(log_msg,test_mode_size_plain_string)369 ZTEST(log_msg, test_mode_size_plain_string)
370 {
371 	static const uint8_t domain = 3;
372 	static const uint8_t level = 2;
373 	const void *source = (const void *)123;
374 	uint32_t exp_len;
375 	int mode;
376 
377 	Z_LOG_MSG_CREATE3(1, mode, 0, domain, source, level, NULL, 0,
378 			"test str");
379 	zassert_equal(mode, EXP_MODE(ZERO_COPY),
380 			"Unexpected creation mode");
381 
382 	Z_LOG_MSG_CREATE3(0, mode, 0, domain, source, level, NULL, 0,
383 			"test str");
384 	zassert_equal(mode, EXP_MODE(FROM_STACK),
385 			"Unexpected creation mode");
386 
387 	/* Calculate expected message length. Message consists of:
388 	 * - header
389 	 * - package of plain string header + string pointer
390 	 *
391 	 * Message size is rounded up to the required alignment.
392 	 */
393 	exp_len = offsetof(struct log_msg, data) +
394 			 /* package */sizeof(struct cbprintf_package_hdr_ext);
395 
396 	exp_len = ROUND_UP(exp_len, Z_LOG_MSG_ALIGNMENT) / sizeof(int);
397 	get_msg_validate_length(exp_len);
398 	get_msg_validate_length(exp_len);
399 }
400 
ZTEST(log_msg,test_mode_size_data_only)401 ZTEST(log_msg, test_mode_size_data_only)
402 {
403 	static const uint8_t domain = 3;
404 	static const uint8_t level = 2;
405 	const void *source = (const void *)123;
406 	uint32_t exp_len;
407 	int mode;
408 	/* If data is present then message is created from stack, even though
409 	 * _from_stack is 0.
410 	 */
411 	uint8_t data[] = {1, 2, 3};
412 
413 	Z_LOG_MSG_CREATE3(1, mode, 0, domain, source, level,
414 			   data, sizeof(data));
415 	zassert_equal(mode, EXP_MODE(FROM_STACK),
416 			"Unexpected creation mode");
417 
418 	/* Calculate expected message length. Message consists of:
419 	 * - header
420 	 * - data
421 	 *
422 	 * Message size is rounded up to the required alignment.
423 	 */
424 	exp_len = offsetof(struct log_msg, data) + sizeof(data);
425 	exp_len = ROUND_UP(exp_len, Z_LOG_MSG_ALIGNMENT) / sizeof(int);
426 	get_msg_validate_length(exp_len);
427 }
428 
ZTEST(log_msg,test_mode_size_plain_str_data)429 ZTEST(log_msg, test_mode_size_plain_str_data)
430 {
431 	static const uint8_t domain = 3;
432 	static const uint8_t level = 2;
433 	const void *source = (const void *)123;
434 	uint32_t exp_len;
435 	int mode;
436 	/* If data is present then message is created from stack, even though
437 	 * _from_stack is 0.
438 	 */
439 	uint8_t data[] = {1, 2, 3};
440 
441 	Z_LOG_MSG_CREATE3(1, mode, 0, domain, source, level,
442 			   data, sizeof(data), "test");
443 	zassert_equal(mode, EXP_MODE(FROM_STACK),
444 			"Unexpected creation mode");
445 
446 	/* Calculate expected message length. Message consists of:
447 	 * - header
448 	 * - data
449 	 *
450 	 * Message size is rounded up to the required alignment.
451 	 */
452 	exp_len = offsetof(struct log_msg, data) + sizeof(data) +
453 		  /* package */sizeof(struct cbprintf_package_hdr_ext);
454 	exp_len = ROUND_UP(exp_len, Z_LOG_MSG_ALIGNMENT) / sizeof(int);
455 	get_msg_validate_length(exp_len);
456 }
457 
ZTEST(log_msg,test_mode_size_str_with_strings)458 ZTEST(log_msg, test_mode_size_str_with_strings)
459 {
460 	static const uint8_t domain = 3;
461 	static const uint8_t level = 2;
462 	const void *source = (const void *)123;
463 	uint32_t exp_len;
464 	int mode;
465 	static const char *prefix = "prefix";
466 
467 	Z_LOG_MSG_CREATE3(1, mode,
468 			   1 /* accept one string pointer*/,
469 			   domain, source, level,
470 			   NULL, 0, "test %s", prefix);
471 	zassert_equal(mode, EXP_MODE(ZERO_COPY),
472 			"Unexpected creation mode");
473 	Z_LOG_MSG_CREATE3(0, mode,
474 			   1 /* accept one string pointer*/,
475 			   domain, source, level,
476 			   NULL, 0, "test %s", prefix);
477 	zassert_equal(mode, EXP_MODE(FROM_STACK),
478 			"Unexpected creation mode");
479 
480 	/* Calculate expected message length. Message consists of:
481 	 * - header
482 	 * - package: header + fmt pointer + pointer
483 	 *
484 	 * Message size is rounded up to the required alignment.
485 	 */
486 	exp_len = offsetof(struct log_msg, data) +
487 			 /* package */sizeof(struct cbprintf_package_hdr_ext) +
488 				      sizeof(const char *);
489 	exp_len = ROUND_UP(exp_len, Z_LOG_MSG_ALIGNMENT) / sizeof(int);
490 
491 	get_msg_validate_length(exp_len);
492 	get_msg_validate_length(exp_len);
493 }
494 
ZTEST(log_msg,test_mode_size_str_with_2strings)495 ZTEST(log_msg, test_mode_size_str_with_2strings)
496 {
497 #undef TEST_STR
498 #define TEST_STR "%s test %s"
499 
500 	static const uint8_t domain = 3;
501 	static const uint8_t level = 2;
502 	const void *source = (const void *)123;
503 	uint32_t exp_len;
504 	int mode;
505 	static const char *prefix = "prefix";
506 	char sufix[] = "sufix";
507 
508 	Z_LOG_MSG_CREATE3(1, mode,
509 			   1 /* accept one string pointer*/,
510 			   domain, source, level,
511 			   NULL, 0, TEST_STR, prefix, sufix);
512 	zassert_equal(mode, EXP_MODE(FROM_STACK),
513 			"Unexpected creation mode");
514 	Z_LOG_MSG_CREATE3(0, mode,
515 			   1 /* accept one string pointer*/,
516 			   domain, source, level,
517 			   NULL, 0, TEST_STR, prefix, sufix);
518 	zassert_equal(mode, EXP_MODE(FROM_STACK),
519 			"Unexpected creation mode");
520 
521 	/* Calculate expected message length. Message consists of:
522 	 * - header
523 	 * - package: header + fmt pointer + 2 pointers
524 	 * - index location of read only string
525 	 *
526 	 * Message size is rounded up to the required alignment.
527 	 */
528 	exp_len = offsetof(struct log_msg, data) +
529 			 /* package */sizeof(struct cbprintf_package_hdr_ext) +
530 				      2 * sizeof(const char *) + 2 + strlen(sufix);
531 
532 	exp_len = ROUND_UP(exp_len, Z_LOG_MSG_ALIGNMENT) / sizeof(int);
533 
534 	get_msg_validate_length(exp_len);
535 	get_msg_validate_length(exp_len);
536 }
537 
timestamp_get_inc(void)538 static log_timestamp_t timestamp_get_inc(void)
539 {
540 	return timestamp++;
541 }
542 
ZTEST(log_msg,test_saturate)543 ZTEST(log_msg, test_saturate)
544 {
545 	if (IS_ENABLED(CONFIG_LOG_MODE_OVERFLOW)) {
546 		return;
547 	}
548 
549 	uint32_t exp_len =
550 		ROUND_UP(offsetof(struct log_msg, data) + 2 * sizeof(void *),
551 			 Z_LOG_MSG_ALIGNMENT);
552 	uint32_t exp_capacity = CONFIG_LOG_BUFFER_SIZE / exp_len;
553 	int mode;
554 	union log_msg_generic *msg;
555 
556 	test_init();
557 	timestamp = 0;
558 	log_set_timestamp_func(timestamp_get_inc, 0);
559 
560 	for (int i = 0; i < exp_capacity; i++) {
561 		Z_LOG_MSG_CREATE3(1, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
562 	}
563 
564 	zassert_equal(z_log_dropped_read_and_clear(), 0, "No dropped messages.");
565 
566 	/* Message should not fit in and be dropped. */
567 	Z_LOG_MSG_CREATE3(1, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
568 	Z_LOG_MSG_CREATE3(0, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
569 	z_log_msg_runtime_create(0, (void *)1, 2, NULL, 0, 0, "test");
570 
571 	zassert_equal(z_log_dropped_read_and_clear(), 3, "No dropped messages.");
572 
573 	for (int i = 0; i < exp_capacity; i++) {
574 		msg = z_log_msg_claim(NULL);
575 		zassert_equal(log_msg_get_timestamp(&msg->log), i,
576 				"Unexpected timestamp used for message id");
577 		z_log_msg_free(msg);
578 	}
579 
580 	msg = z_log_msg_claim(NULL);
581 
582 	zassert_equal(msg, NULL, "Expected no pending messages");
583 }
584 
585 /*test case main entry*/
586 ZTEST_SUITE(log_msg, NULL, NULL, NULL, NULL, NULL);
587