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