1 /*
2 * Copyright (c) 2021 Intel Corporation+
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/logging/log.h>
10 #include <tracing_buffer.h>
11 #include <tracing_core.h>
12 #include <zephyr/tracing/tracing_format.h>
13 #if defined(CONFIG_TRACING_BACKEND_UART)
14 #include "../../../../subsys/tracing/include/tracing_backend.h"
15 #endif
16
17 /**
18 * @brief Tests for tracing
19 * @defgroup tracing_api_tests Tracing
20 * @ingroup all_tests
21 * @{
22 * @}
23 */
24
25 /* Check flags */
26 static bool data_format_found;
27 static bool raw_data_format_found;
28 static bool sync_string_format_found;
29 #ifdef CONFIG_TRACING_ASYNC
30 static bool async_tracing_api;
31 static bool tracing_api_found;
32 static bool tracing_api_not_found;
33 static uint8_t *string_tracked[] = {
34 "sys_trace_k_thread_switched_out", "sys_trace_k_thread_switched_in",
35 "sys_trace_k_thread_priority_set", "sys_trace_k_thread_sched_set_priority",
36 "sys_trace_k_thread_create", "sys_trace_k_thread_start",
37 "sys_trace_k_thread_abort", "sys_trace_k_thread_suspend",
38 "sys_trace_k_thread_resume", "sys_trace_k_thread_ready",
39 "sys_trace_k_thread_sched_ready", "sys_trace_k_thread_sched_abort",
40 "sys_trace_k_thread_sched_resume", "sys_trace_k_thread_sched_suspend",
41 "sys_trace_k_thread_sleep_enter", "sys_trace_k_thread_sleep_exit",
42 "sys_trace_k_thread_abort_enter", "sys_trace_k_thread_abort_exit",
43 "sys_trace_k_thread_yield", "sys_trace_k_thread_wakeup",
44 "sys_trace_k_thread_pend", "sys_trace_k_thread_info",
45 "sys_trace_k_thread_name_set", "sys_trace_k_thread_sched_lock",
46 "sys_trace_k_timer_init", "sys_trace_k_thread_join_blocking",
47 "sys_trace_k_thread_join_exit", "sys_trace_isr_enter",
48 "sys_trace_isr_exit", "sys_trace_idle",
49 "sys_trace_k_condvar_broadcast_enter", "sys_trace_k_condvar_broadcast_exit",
50 "sys_trace_k_condvar_init", "sys_trace_k_condvar_signal_enter",
51 "sys_trace_k_condvar_signal_blocking", "sys_trace_k_condvar_signal_exit",
52 "sys_trace_k_condvar_wait_enter", "sys_trace_k_condvar_wait_exit",
53 "sys_trace_k_sem_init", "sys_trace_k_sem_give_enter",
54 "sys_trace_k_sem_take_enter", "sys_trace_k_sem_take_exit",
55 "sys_trace_k_sem_take_blocking", "sys_trace_k_mutex_init",
56 "sys_trace_k_mutex_lock_enter", "sys_trace_k_mutex_lock_exit",
57 "sys_trace_k_mutex_lock_blocking", "sys_trace_k_mutex_unlock_enter",
58 "sys_trace_k_mutex_unlock_exit", "sys_trace_k_timer_start", NULL
59 };
60 #endif
61
62 #if defined(CONFIG_TRACING_BACKEND_UART)
tracing_backends_output(const struct tracing_backend * backend,uint8_t * data,uint32_t length)63 static void tracing_backends_output(
64 const struct tracing_backend *backend,
65 uint8_t *data, uint32_t length)
66 {
67 /* Check the output data. */
68 #ifdef CONFIG_TRACING_ASYNC
69 if (async_tracing_api) {
70 /* Define static 'i' is for guaranteeing all strings of 0 ~ end
71 * of the array string_tracked are tested.
72 */
73 static int i;
74
75 while (string_tracked[i] != NULL) {
76 if (strstr(data, string_tracked[i]) != NULL) {
77 tracing_api_found = true;
78 } else {
79 tracing_api_not_found = true;
80 }
81 i++;
82 }
83 }
84 #endif
85 if (strstr(data, "tracing_format_data_testing") != NULL) {
86 data_format_found = true;
87 }
88 if (strstr(data, "tracing_format_raw_data_testing") != NULL) {
89 raw_data_format_found = true;
90 }
91 if (strstr(data, "tracing_format_string_testing") != NULL) {
92 sync_string_format_found = true;
93 }
94 }
95
96 const struct tracing_backend_api tracing_uart_backend_api = {
97 .init = NULL,
98 .output = tracing_backends_output
99 };
100
101 TRACING_BACKEND_DEFINE(tracing_backend_uart, tracing_uart_backend_api);
102 #endif
103
104 #ifdef CONFIG_TRACING_ASYNC
105 /**
106 * @brief Test tracing APIS
107 *
108 * @details For asynchronous mode, self-designed tracing uart backend
109 * firstly, and called tracing APIs one by one directly, check if the
110 * output from the backend is equal to the input.
111 *
112 * @ingroup tracing_api_tests
113 */
ZTEST(tracing_api,test_tracing_sys_api)114 ZTEST(tracing_api, test_tracing_sys_api)
115 {
116 int ret = 0, prio = 0;
117 size_t stack = 0;
118 struct k_mutex mutex;
119 struct k_thread thread;
120 struct k_condvar condvar;
121 struct k_sem sem, sem2;
122 struct k_timer timer;
123 k_timeout_t timeout = K_MSEC(1);
124
125 tracing_buffer_init();
126 async_tracing_api = true;
127 /* thread api */
128 sys_trace_k_thread_switched_out();
129 sys_trace_k_thread_switched_in();
130 sys_trace_k_thread_priority_set(&thread);
131 sys_trace_k_thread_sched_set_priority(&thread, prio);
132 sys_trace_k_thread_create(&thread, stack, prio);
133 sys_trace_k_thread_start(&thread);
134 sys_trace_k_thread_abort(&thread);
135 sys_trace_k_thread_suspend(&thread);
136 sys_trace_k_thread_resume(&thread);
137 sys_trace_k_thread_ready(&thread);
138 sys_trace_k_thread_sched_ready(&thread);
139 sys_trace_k_thread_sched_abort(&thread);
140 sys_trace_k_thread_sched_resume(&thread);
141 sys_trace_k_thread_sched_suspend(&thread);
142 sys_trace_k_thread_sleep_enter(timeout);
143 sys_trace_k_thread_sleep_exit(timeout, ret);
144 sys_trace_k_thread_abort_enter(&thread);
145 sys_trace_k_thread_abort_exit(&thread);
146 sys_trace_k_thread_yield();
147 sys_trace_k_thread_wakeup(&thread);
148 sys_trace_k_thread_pend(&thread);
149 sys_trace_k_thread_info(&thread);
150 sys_trace_k_thread_name_set(&thread, ret);
151 sys_trace_k_thread_sched_lock();
152 sys_port_trace_k_thread_sched_unlock();
153 sys_trace_k_thread_join_blocking(&thread, timeout);
154 sys_trace_k_thread_join_exit(&thread, timeout, ret);
155 /* ISR api */
156 sys_trace_isr_enter();
157 sys_trace_isr_exit();
158 sys_trace_idle();
159 /* condvar api */
160 sys_trace_k_condvar_broadcast_enter(&condvar);
161 sys_trace_k_condvar_broadcast_exit(&condvar, ret);
162 sys_trace_k_condvar_init(&condvar, ret);
163 sys_trace_k_condvar_signal_enter(&condvar);
164 sys_trace_k_condvar_signal_blocking(&condvar);
165 sys_trace_k_condvar_signal_exit(&condvar, ret);
166 sys_trace_k_condvar_wait_enter(&condvar, &mutex, timeout);
167 sys_trace_k_condvar_wait_exit(&condvar, &mutex, timeout, ret);
168 /* sem api */
169 sys_trace_k_sem_init(&sem, ret);
170 sys_trace_k_sem_give_enter(&sem);
171 sys_trace_k_sem_take_enter(&sem2, timeout);
172 sys_trace_k_sem_take_exit(&sem, timeout, ret);
173 sys_trace_k_sem_take_blocking(&sem, timeout);
174 /* mutex api */
175 sys_trace_k_mutex_init(&mutex, ret);
176 sys_trace_k_mutex_lock_enter(&mutex, timeout);
177 sys_trace_k_mutex_lock_exit(&mutex, timeout, ret);
178 sys_trace_k_mutex_lock_blocking(&mutex, timeout);
179 sys_trace_k_mutex_unlock_enter(&mutex);
180 sys_trace_k_mutex_unlock_exit(&mutex, ret);
181 /* timer api */
182 sys_trace_k_timer_start(&timer, timeout, timeout);
183 sys_trace_k_timer_init(&timer, NULL, NULL);
184
185 /* wait for some actions finished */
186 k_sleep(K_MSEC(100));
187 zassert_true(tracing_api_found, "Failded to check output from backend");
188 zassert_true(tracing_api_not_found == false, "Failded to check output from backend");
189 async_tracing_api = false;
190 }
191 #else
192 /**
193 * @brief Test tracing APIS
194 *
195 * @details For synchronize mode, self-designed tracing uart backend
196 * firstly, called API tracing_format_string to put a string, meanwhile,
197 * check the output for the backend.
198 *
199 * @ingroup tracing_api_tests
200 */
ZTEST(tracing_api,test_tracing_sys_api)201 ZTEST(tracing_api, test_tracing_sys_api)
202 {
203 tracing_buffer_init();
204 tracing_format_string("tracing_format_string_testing");
205 k_sleep(K_MSEC(100));
206
207 zassert_true(sync_string_format_found == true, "Failed to check output from backend");
208 }
209 #endif /* CONFIG_TRACING_ASYNC */
210
211 /**
212 * @brief Test tracing APIS
213 *
214 * @details Packaged the data by different format as the tracing input,
215 * check the output for the self-designed uart backend.
216 *
217 * @ingroup tracing_api_tests
218 */
ZTEST(tracing_api,test_tracing_data_format)219 ZTEST(tracing_api, test_tracing_data_format)
220 {
221 tracing_data_t tracing_data, tracing_raw_data;
222 uint8_t data[] = "tracing_format_data_testing";
223 uint8_t raw_data[] = "tracing_format_raw_data_testing";
224
225 tracing_buffer_init();
226 tracing_data.data = data;
227 tracing_data.length = sizeof(data);
228 tracing_raw_data.data = raw_data;
229 tracing_raw_data.length = sizeof(raw_data);
230
231 tracing_format_data(&tracing_data, 1);
232 k_sleep(K_MSEC(100));
233 zassert_true(data_format_found == true, "Failed to check output from backend");
234
235 tracing_format_raw_data(tracing_raw_data.data, tracing_raw_data.length);
236 k_sleep(K_MSEC(100));
237 zassert_true(raw_data_format_found == true, "Failed to check output from backend");
238 }
239
240 /**
241 * @brief Test tracing APIS
242 *
243 * @details Simulate the host computer command to pass to the function
244 * tracing_cmd_handle to detect the tracing behavior.
245 *
246 * @ingroup tracing_api_tests
247 */
ZTEST(tracing_api,test_tracing_cmd_manual)248 ZTEST(tracing_api, test_tracing_cmd_manual)
249 {
250 uint32_t length = 0;
251 uint8_t *cmd = NULL;
252 uint8_t cmd0[] = " ";
253 uint8_t cmd1[] = "disable";
254 uint8_t cmd2[] = "enable";
255
256 length = tracing_cmd_buffer_alloc(&cmd);
257 cmd = cmd0;
258 zassert_true(sizeof(cmd0) < length, "cmd0 is too long");
259 tracing_cmd_handle(cmd, sizeof(cmd0));
260 zassert_true(is_tracing_enabled(),
261 "Failed to check default status of tracing");
262
263 length = tracing_cmd_buffer_alloc(&cmd);
264 cmd = cmd1;
265 zassert_true(sizeof(cmd1) < length, "cmd1 is too long");
266 tracing_cmd_handle(cmd, sizeof(cmd1));
267 zassert_false(is_tracing_enabled(), "Failed to disable tracing");
268
269 length = tracing_cmd_buffer_alloc(&cmd);
270 cmd = cmd2;
271 zassert_true(sizeof(cmd2) < length, "cmd2 is too long");
272 tracing_cmd_handle(cmd, sizeof(cmd2));
273 zassert_true(is_tracing_enabled(), "Failed to enable tracing");
274 }
275 ZTEST_SUITE(tracing_api, NULL, NULL, NULL, NULL, NULL);
276