1 /*
2  * Copyright (c) 2019 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/logging/log.h>
9 #include "mock_backend.h"
10 #include <zephyr/sys/printk.h>
11 
12 #include <zephyr/logging/log_ctrl.h>
13 #include <zephyr/logging/log_output.h>
14 #include <zephyr/logging/log_output_dict.h>
15 #include <zephyr/logging/log_output_custom.h>
16 #include <zephyr/ztest.h>
17 
18 #define LOG_MODULE_NAME log_switch_format
19 LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_ERR);
20 
21 extern size_t log_format_table_size(void);
22 K_SEM_DEFINE(my_sem, 0, 1);
23 
log_msgs(void)24 void log_msgs(void)
25 {
26 	/* standard print */
27 	LOG_ERR("Error message example.");
28 
29 #if CONFIG_LOG_MODE_DEFERRED && !(CONFIG_LOG_CUSTOM_FORMAT_SUPPORT)
30 	/*
31 	 * When deferred logging is enabled, the work is being performed by
32 	 * another thread. The semaphore my_sem gives that thread time to process
33 	 * those messages.
34 	 */
35 
36 	k_sem_take(&my_sem, K_FOREVER);
37 #endif
38 
39 	/* raw string */
40 	printk("hello sys-t on board %s\n", CONFIG_BOARD);
41 }
42 
test_log_switch_format_success_case(void)43 void test_log_switch_format_success_case(void)
44 {
45 	const struct log_backend *backend;
46 	const char *raw_data_str;
47 	uint32_t log_type = LOG_OUTPUT_SYST;
48 	const char *text_raw_data_str = "<err> log_switch_format: Error message example.";
49 	const char *syst_raw_data_str = "SYS-T RAW DATA: ";
50 
51 	raw_data_str = syst_raw_data_str;
52 	log_msgs();
53 	validate_log_type(raw_data_str, log_type);
54 
55 	log_type = LOG_OUTPUT_TEXT;
56 	raw_data_str = text_raw_data_str;
57 	backend = log_format_set_all_active_backends(log_type);
58 
59 	zassert_is_null(backend, "Unexpected failure in switching log format");
60 
61 	log_msgs();
62 	validate_log_type(raw_data_str, log_type);
63 
64 	log_type = LOG_OUTPUT_SYST;
65 	raw_data_str = syst_raw_data_str;
66 	backend = log_format_set_all_active_backends(log_type);
67 
68 	zassert_is_null(backend, "Unexpected failure in switching log format");
69 
70 	log_msgs();
71 	validate_log_type(raw_data_str, log_type);
72 
73 	log_type = LOG_OUTPUT_TEXT;
74 	raw_data_str = text_raw_data_str;
75 	backend = log_format_set_all_active_backends(log_type);
76 
77 	zassert_is_null(backend, "Unexpected failure in switching log format");
78 
79 	log_msgs();
80 	validate_log_type(raw_data_str, log_type);
81 }
82 
test_log_switch_format_set(void)83 void test_log_switch_format_set(void)
84 {
85 	const char *backend_name;
86 	const struct log_backend *backend;
87 	int ret;
88 	uint32_t log_type;
89 
90 	log_type = LOG_OUTPUT_TEXT;
91 	backend_name = "not_exists";
92 
93 	backend = log_backend_get_by_name(backend_name);
94 	zassert_is_null(backend, "Backend unexpectedly found");
95 
96 	ret = log_backend_format_set(backend, log_type);
97 
98 	zassert_equal(ret, -EINVAL, "Expected -EINVAL, Got %d\n", ret);
99 
100 	backend_name = CONFIG_LOG_BACKEND_DEFAULT;
101 	backend = log_backend_get_by_name(backend_name);
102 
103 	zassert_not_null(backend, "Backend not found");
104 
105 	log_type = log_format_table_size() + 1;
106 	ret = log_backend_format_set(backend, log_type);
107 
108 	zassert_equal(ret, -EINVAL, "Log type not supported, Invalid value returned");
109 }
110 
test_log_switch_format_set_all_active_backends(void)111 void test_log_switch_format_set_all_active_backends(void)
112 {
113 	size_t log_type = log_format_table_size() + 1;
114 	const struct log_backend *backend;
115 
116 	backend = log_format_set_all_active_backends(log_type);
117 
118 	zassert_not_null(backend, "Unexpectedly all active backends switched the logging format");
119 
120 	log_type = LOG_OUTPUT_SYST;
121 	backend = log_format_set_all_active_backends(log_type);
122 
123 	zassert_is_null(backend, "Not all active backends have switched logging formats");
124 }
125 
126 /* Testcase to verify the entries in function pointer table */
test_log_switch_format_func_t_get(void)127 void test_log_switch_format_func_t_get(void)
128 {
129 	const log_format_func_t expected_values[] = {
130 		[LOG_OUTPUT_TEXT] = IS_ENABLED(CONFIG_LOG_OUTPUT) ? log_output_msg_process : NULL,
131 		[LOG_OUTPUT_SYST] = IS_ENABLED(CONFIG_LOG_MIPI_SYST_ENABLE)
132 					    ? log_output_msg_syst_process
133 					    : NULL,
134 		[LOG_OUTPUT_DICT] = IS_ENABLED(CONFIG_LOG_DICTIONARY_SUPPORT)
135 					    ? log_dict_output_msg_process
136 					    : NULL,
137 		[LOG_OUTPUT_CUSTOM] = IS_ENABLED(CONFIG_LOG_CUSTOM_FORMAT_SUPPORT)
138 					      ? log_custom_output_msg_process
139 					      : NULL,
140 	};
141 
142 	zassert_equal(log_format_table_size(), ARRAY_SIZE(expected_values),
143 		      "Update test for expected_values table");
144 
145 	for (int i = 0; i < ARRAY_SIZE(expected_values); i++) {
146 		zassert_equal(log_format_func_t_get(i), expected_values[i],
147 			      "Log Format Not supported");
148 	}
149 }
150 
ZTEST(log_switch_format,test_log_switch_format)151 ZTEST(log_switch_format, test_log_switch_format)
152 {
153 	test_log_switch_format_success_case();
154 	test_log_switch_format_set();
155 	test_log_switch_format_set_all_active_backends();
156 	test_log_switch_format_func_t_get();
157 }
158 
159 #if CONFIG_LOG_CUSTOM_FORMAT_SUPPORT
custom_formatting(const struct log_output * output,struct log_msg * msg,uint32_t flags)160 void custom_formatting(const struct log_output *output, struct log_msg *msg, uint32_t flags)
161 {
162 	uint8_t buffer[] = "Hello world";
163 
164 	output->func((uint8_t *)buffer, sizeof(buffer), (void *)output);
165 }
166 
ZTEST(log_switch_format,test_log_switch_format_custom_output_handles_null)167 ZTEST(log_switch_format, test_log_switch_format_custom_output_handles_null)
168 {
169 	const char *backend_name;
170 	const struct log_backend *backend;
171 
172 	backend_name = CONFIG_LOG_BACKEND_DEFAULT;
173 	backend = log_backend_get_by_name(backend_name);
174 
175 	log_backend_format_set(backend, LOG_OUTPUT_CUSTOM);
176 
177 	log_custom_output_msg_set(NULL);
178 
179 	log_msgs();
180 
181 	validate_log_type("", LOG_OUTPUT_CUSTOM);
182 }
183 
ZTEST(log_switch_format,test_log_switch_format_custom_output_called_when_set)184 ZTEST(log_switch_format, test_log_switch_format_custom_output_called_when_set)
185 {
186 	uint32_t log_type;
187 	const char *backend_name;
188 	const char *raw_data_str;
189 	const char *text_custom_data_str = "Hello world";
190 	const struct log_backend *backend;
191 
192 	backend_name = CONFIG_LOG_BACKEND_DEFAULT;
193 	backend = log_backend_get_by_name(backend_name);
194 
195 	log_backend_format_set(backend, LOG_OUTPUT_CUSTOM);
196 
197 	log_custom_output_msg_set(custom_formatting);
198 
199 	log_msgs();
200 
201 	log_type = LOG_OUTPUT_CUSTOM;
202 	raw_data_str = text_custom_data_str;
203 	validate_log_type(raw_data_str, log_type);
204 }
205 
ZTEST(log_switch_format,test_log_switch_format_does_not_log_when_uninit)206 ZTEST(log_switch_format, test_log_switch_format_does_not_log_when_uninit)
207 {
208 	const char *backend_name;
209 	const struct log_backend *backend;
210 
211 	backend_name = CONFIG_LOG_BACKEND_DEFAULT;
212 	backend = log_backend_get_by_name(backend_name);
213 
214 	log_backend_format_set(backend, LOG_OUTPUT_CUSTOM);
215 
216 	log_msgs();
217 
218 	validate_log_type("", LOG_OUTPUT_CUSTOM);
219 }
220 #endif
221 
222 ZTEST_SUITE(log_switch_format, NULL, NULL, NULL, NULL, NULL);
223