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 		/* This verification should run only once, hence the static
71 		 * `i`. As soon as the tracing thread has a chance to run,
72 		 * right at the sleep at the async version of
73 		 * test_tracing_sys_api, it should have everything needed
74 		 * for this check on its buffer, which is sent here.
75 		 * Should SMP be ever enabled for this test, this logic
76 		 * will break down and one will need some sort of internal
77 		 * buffer to keep track of the tracing strings (or do the
78 		 * verification in some other way).
79 		 */
80 		static int i;
81 
82 		while (string_tracked[i] != NULL) {
83 			if (strstr(data, string_tracked[i]) != NULL) {
84 				tracing_api_found = true;
85 			} else {
86 				tracing_api_not_found = true;
87 			}
88 			i++;
89 		}
90 	}
91 #endif
92 	if (strstr(data, "tracing_format_data_testing") != NULL) {
93 		data_format_found = true;
94 	}
95 	if (strstr(data, "tracing_format_raw_data_testing") != NULL) {
96 		raw_data_format_found = true;
97 	}
98 	if (strstr(data, "tracing_format_string_testing") != NULL) {
99 		sync_string_format_found = true;
100 	}
101 }
102 
103 const struct tracing_backend_api tracing_uart_backend_api = {
104 	.init = NULL,
105 	.output  = tracing_backends_output
106 };
107 
108 TRACING_BACKEND_DEFINE(tracing_backend_uart, tracing_uart_backend_api);
109 #endif
110 
111 #ifdef CONFIG_TRACING_ASYNC
112 /**
113  * @brief Test tracing APIS
114  *
115  * @details For asynchronous mode, self-designed tracing uart backend
116  * firstly, and called tracing APIs one by one directly, check if the
117  * output from the backend is equal to the input.
118  *
119  * @ingroup tracing_api_tests
120  */
ZTEST(tracing_api,test_tracing_sys_api)121 ZTEST(tracing_api, test_tracing_sys_api)
122 {
123 	int ret = 0, prio = 0;
124 	size_t stack = 0;
125 	struct k_mutex mutex;
126 	struct k_thread thread;
127 	struct k_condvar condvar;
128 	struct k_sem sem, sem2;
129 	struct k_timer timer;
130 	k_timeout_t timeout = K_MSEC(1);
131 
132 	tracing_buffer_init();
133 	async_tracing_api = true;
134 	/* thread api */
135 	sys_trace_k_thread_switched_out();
136 	sys_trace_k_thread_switched_in();
137 	sys_trace_k_thread_priority_set(&thread);
138 	sys_trace_k_thread_sched_set_priority(&thread, prio);
139 	sys_trace_k_thread_create(&thread, stack, prio);
140 	sys_trace_k_thread_start(&thread);
141 	sys_trace_k_thread_abort(&thread);
142 	sys_trace_k_thread_suspend(&thread);
143 	sys_trace_k_thread_resume(&thread);
144 	sys_trace_k_thread_ready(&thread);
145 	sys_trace_k_thread_sched_ready(&thread);
146 	sys_trace_k_thread_sched_abort(&thread);
147 	sys_trace_k_thread_sched_resume(&thread);
148 	sys_trace_k_thread_sched_suspend(&thread);
149 	sys_trace_k_thread_sleep_enter(timeout);
150 	sys_trace_k_thread_sleep_exit(timeout, ret);
151 	sys_trace_k_thread_abort_enter(&thread);
152 	sys_trace_k_thread_abort_exit(&thread);
153 	sys_trace_k_thread_yield();
154 	sys_trace_k_thread_wakeup(&thread);
155 	sys_trace_k_thread_pend(&thread);
156 	sys_trace_k_thread_info(&thread);
157 	sys_trace_k_thread_name_set(&thread, ret);
158 	sys_trace_k_thread_sched_lock();
159 	sys_port_trace_k_thread_sched_unlock();
160 	sys_trace_k_thread_join_blocking(&thread, timeout);
161 	sys_trace_k_thread_join_exit(&thread, timeout, ret);
162 	/* ISR api */
163 	sys_trace_isr_enter();
164 	sys_trace_isr_exit();
165 	sys_trace_idle();
166 	/* condvar api */
167 	sys_trace_k_condvar_broadcast_enter(&condvar);
168 	sys_trace_k_condvar_broadcast_exit(&condvar, ret);
169 	sys_trace_k_condvar_init(&condvar, ret);
170 	sys_trace_k_condvar_signal_enter(&condvar);
171 	sys_trace_k_condvar_signal_blocking(&condvar);
172 	sys_trace_k_condvar_signal_exit(&condvar, ret);
173 	sys_trace_k_condvar_wait_enter(&condvar, &mutex, timeout);
174 	sys_trace_k_condvar_wait_exit(&condvar, &mutex, timeout, ret);
175 	/* sem api */
176 	sys_trace_k_sem_init(&sem, ret);
177 	sys_trace_k_sem_give_enter(&sem);
178 	sys_trace_k_sem_take_enter(&sem2, timeout);
179 	sys_trace_k_sem_take_exit(&sem, timeout, ret);
180 	sys_trace_k_sem_take_blocking(&sem, timeout);
181 	/* mutex api */
182 	sys_trace_k_mutex_init(&mutex, ret);
183 	sys_trace_k_mutex_lock_enter(&mutex, timeout);
184 	sys_trace_k_mutex_lock_exit(&mutex, timeout, ret);
185 	sys_trace_k_mutex_lock_blocking(&mutex, timeout);
186 	sys_trace_k_mutex_unlock_enter(&mutex);
187 	sys_trace_k_mutex_unlock_exit(&mutex, ret);
188 	/* timer api */
189 	sys_trace_k_timer_start(&timer, timeout, timeout);
190 	sys_trace_k_timer_init(&timer, NULL, NULL);
191 
192 	/* wait for some actions finished */
193 	k_sleep(K_MSEC(100));
194 	zassert_true(tracing_api_found, "Failed to check output from backend");
195 	zassert_true(tracing_api_not_found == false, "Failed to check output from backend");
196 	async_tracing_api = false;
197 }
198 #else
199 /**
200  * @brief Test tracing APIS
201  *
202  * @details For synchronize mode, self-designed tracing uart backend
203  * firstly, called API tracing_format_string to put a string, meanwhile,
204  * check the output for the backend.
205  *
206  * @ingroup tracing_api_tests
207  */
ZTEST(tracing_api,test_tracing_sys_api)208 ZTEST(tracing_api, test_tracing_sys_api)
209 {
210 	tracing_buffer_init();
211 	tracing_format_string("tracing_format_string_testing");
212 	k_sleep(K_MSEC(100));
213 
214 	zassert_true(sync_string_format_found == true, "Failed to check output from backend");
215 }
216 #endif /* CONFIG_TRACING_ASYNC */
217 
218 /**
219  * @brief Test tracing APIS
220  *
221  * @details Packaged the data by different format as the tracing input,
222  * check the output for the self-designed uart backend.
223  *
224  * @ingroup tracing_api_tests
225  */
ZTEST(tracing_api,test_tracing_data_format)226 ZTEST(tracing_api, test_tracing_data_format)
227 {
228 	tracing_data_t tracing_data, tracing_raw_data;
229 	uint8_t data[] = "tracing_format_data_testing";
230 	uint8_t raw_data[] = "tracing_format_raw_data_testing";
231 
232 	tracing_buffer_init();
233 	tracing_data.data = data;
234 	tracing_data.length = sizeof(data);
235 	tracing_raw_data.data = raw_data;
236 	tracing_raw_data.length = sizeof(raw_data);
237 
238 	tracing_format_data(&tracing_data, 1);
239 	k_sleep(K_MSEC(100));
240 	zassert_true(data_format_found == true, "Failed to check output from backend");
241 
242 	tracing_format_raw_data(tracing_raw_data.data, tracing_raw_data.length);
243 	k_sleep(K_MSEC(100));
244 	zassert_true(raw_data_format_found == true, "Failed to check output from backend");
245 }
246 
247 /**
248  * @brief Test tracing APIS
249  *
250  * @details Simulate the host computer command to pass to the function
251  * tracing_cmd_handle to detect the tracing behavior.
252  *
253  * @ingroup tracing_api_tests
254  */
ZTEST(tracing_api,test_tracing_cmd_manual)255 ZTEST(tracing_api, test_tracing_cmd_manual)
256 {
257 	uint32_t length = 0;
258 	uint8_t *cmd = NULL;
259 	uint8_t cmd0[] = " ";
260 	uint8_t cmd1[] = "disable";
261 	uint8_t cmd2[] = "enable";
262 
263 	length = tracing_cmd_buffer_alloc(&cmd);
264 	cmd = cmd0;
265 	zassert_true(sizeof(cmd0) < length, "cmd0 is too long");
266 	tracing_cmd_handle(cmd, sizeof(cmd0));
267 	zassert_true(is_tracing_enabled(),
268 		"Failed to check default status of tracing");
269 
270 	length = tracing_cmd_buffer_alloc(&cmd);
271 	cmd = cmd1;
272 	zassert_true(sizeof(cmd1) < length, "cmd1 is too long");
273 	tracing_cmd_handle(cmd, sizeof(cmd1));
274 	zassert_false(is_tracing_enabled(), "Failed to disable tracing");
275 
276 	length = tracing_cmd_buffer_alloc(&cmd);
277 	cmd = cmd2;
278 	zassert_true(sizeof(cmd2) < length, "cmd2 is too long");
279 	tracing_cmd_handle(cmd, sizeof(cmd2));
280 	zassert_true(is_tracing_enabled(), "Failed to enable tracing");
281 }
282 ZTEST_SUITE(tracing_api, NULL, NULL, NULL, NULL, NULL);
283