1 /* tc_utilities.h - testcase utilities header file */
2 
3 /*
4  * Copyright (c) 2012-2015 Wind River Systems, Inc.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #ifndef ZEPHYR_TESTSUITE_INCLUDE_TC_UTIL_H_
10 #define ZEPHYR_TESTSUITE_INCLUDE_TC_UTIL_H_
11 
12 #include <zephyr/kernel.h>
13 
14 #include <string.h>
15 #ifdef CONFIG_SHELL
16 #include <zephyr/shell/shell.h>
17 #endif
18 #include <zephyr/sys/printk.h>
19 
20 #if defined CONFIG_ZTEST_TC_UTIL_USER_OVERRIDE
21 #include <tc_util_user_override.h>
22 #endif
23 
24 #ifndef PRINT_DATA
25 #define PRINT_DATA(fmt, ...) printk(fmt, ##__VA_ARGS__)
26 #endif
27 
28 #if defined CONFIG_ARCH_POSIX
29 #include "posix_board_if.h"
30 #endif
31 
32 /**
33  * @def TC_PRINT_RUNID
34  * @brief Report a Run ID
35  *
36  * When the CPP symbol \c TC_RUNID is defined (for example, from the
37  * compile environment), print the defined string ``RunID:
38  * <TC_RUNID>`` when called (TC_END_REPORT() will also call it).
39  *
40  * This is used mainly when automating the execution and running of
41  * multiple test cases, to verify that the expected image is being
42  * executed (as sometimes the targets fail to flash or reset
43  * properly).
44  *
45  * TC_RUNID is any string, that will be converted to a string literal.
46  */
47 #define TC_STR_HELPER(x) #x
48 #define TC_STR(x) TC_STR_HELPER(x)
49 #ifdef TC_RUNID
50 #define TC_PRINT_RUNID PRINT_DATA("RunID: " TC_STR(TC_RUNID) "\n")
51 #else
52 #define TC_PRINT_RUNID do {} while (0)
53 #endif
54 
55 #ifndef PRINT_LINE
56 #define PRINT_LINE                          \
57 	PRINT_DATA(                                                        \
58 		"============================================================" \
59 		"=======\n")
60 #endif
61 
62 /* stack size and priority for test suite task */
63 #define TASK_STACK_SIZE (1024 * 2)
64 
65 #define FMT_ERROR "%s - %s@%d. "
66 
67 #define TC_PASS 0
68 #define TC_FAIL 1
69 #define TC_SKIP 2
70 
71 #ifndef TC_PASS_STR
72 #define TC_PASS_STR "PASS"
73 #endif
74 #ifndef TC_FAIL_STR
75 #define TC_FAIL_STR "FAIL"
76 #endif
77 #ifndef TC_SKIP_STR
78 #define TC_SKIP_STR "SKIP"
79 #endif
80 
TC_RESULT_TO_STR(int result)81 static inline const char *TC_RESULT_TO_STR(int result)
82 {
83 	switch (result) {
84 	case TC_PASS:
85 		return TC_PASS_STR;
86 	case TC_FAIL:
87 		return TC_FAIL_STR;
88 	case TC_SKIP:
89 		return TC_SKIP_STR;
90 	default:
91 		return "?";
92 	}
93 }
94 
95 static uint32_t tc_start_time;
96 static uint32_t tc_spend_time;
97 
get_start_time_cyc(void)98 static inline void get_start_time_cyc(void)
99 {
100 	tc_start_time = k_cycle_get_32();
101 }
102 
get_test_duration_ms(void)103 static inline void get_test_duration_ms(void)
104 {
105 	uint32_t spend_cycle = k_cycle_get_32() - tc_start_time;
106 
107 	tc_spend_time = k_cyc_to_ms_ceil32(spend_cycle);
108 }
109 
110 #ifndef TC_ERROR
111 #define TC_ERROR(fmt, ...)                               \
112 	do {                                                 \
113 		PRINT_DATA(FMT_ERROR, "FAIL", __func__, __LINE__); \
114 		PRINT_DATA(fmt, ##__VA_ARGS__);                  \
115 	} while (0)
116 #endif
117 
print_nothing(const char * fmt,...)118 static inline void print_nothing(const char *fmt, ...)
119 {
120 	ARG_UNUSED(fmt);
121 }
122 
123 #ifndef TC_PRINT
124 /* Need to check for CONFIG_ZTEST_NEW_API since the TC_PRINT
125  * is also used by the old ztest.
126  */
127 #ifdef CONFIG_ZTEST_NEW_API
128 #if defined(CONFIG_ZTEST_VERBOSE_OUTPUT)
129 #define TC_PRINT(fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__)
130 #else
131 #define TC_PRINT(fmt, ...) print_nothing(fmt, ##__VA_ARGS__)
132 #endif /* CONFIG_ZTEST_VERBOSE_OUTPUT */
133 #else
134 #define TC_PRINT(fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__)
135 #endif /* CONFIG_ZTEST_NEW_API */
136 #endif /* TC_PRINT */
137 
138 #ifndef TC_SUMMARY_PRINT
139 #define TC_SUMMARY_PRINT(fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__)
140 #endif
141 
142 #ifndef TC_START_PRINT
143 #ifdef CONFIG_ZTEST_NEW_API
144 #if defined(CONFIG_ZTEST_VERBOSE_OUTPUT)
145 #define TC_START_PRINT(name) PRINT_DATA("START - %s\n", name);
146 #else
147 #define TC_START_PRINT(name) print_nothing(name)
148 #endif /* CONFIG_ZTEST_VERBOSE_OUTPUT */
149 #else
150 #define TC_START_PRINT(name) PRINT_DATA("START - %s\n", name);
151 #endif /* CONFIG_ZTEST_NEW_API */
152 #endif /* TC_START_PRINT */
153 
154 #ifndef TC_START
155 #define TC_START(name)							\
156 	do {								\
157 		TC_START_PRINT(name);			\
158 	} while (0)
159 #endif
160 
161 #ifndef TC_END
162 #define TC_END(result, fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__)
163 #endif
164 
165 #ifndef TC_END_PRINT
166 #ifdef CONFIG_ZTEST_NEW_API
167 #if defined(CONFIG_ZTEST_VERBOSE_OUTPUT)
168 #define TC_END_PRINT(result, fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__); PRINT_LINE
169 #else
170 #define TC_END_PRINT(result, fmt, ...) print_nothing(fmt)
171 #endif /* CONFIG_ZTEST_VERBOSE_OUTPUT */
172 #else
173 #define TC_END_PRINT(result, fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__); PRINT_LINE
174 #endif /* CONFIG_ZTEST_NEW_API */
175 #endif /* TC_END_PRINT */
176 
177 /* prints result and the function name */
178 #ifndef Z_TC_END_RESULT
179 #define Z_TC_END_RESULT(result, func)						\
180 	do {									\
181 		TC_END_PRINT(result, " %s - %s in %u.%03u seconds\n",		\
182 			TC_RESULT_TO_STR(result), func, tc_spend_time/1000,	\
183 			tc_spend_time%1000);					\
184 	} while (0)
185 #endif
186 
187 #ifndef TC_END_RESULT
188 #define TC_END_RESULT(result)                           \
189 	Z_TC_END_RESULT((result), __func__)
190 #endif
191 
192 #ifndef TC_END_RESULT_CUSTOM
193 #define TC_END_RESULT_CUSTOM(result, func)                           \
194 	Z_TC_END_RESULT((result), func)
195 #endif
196 
197 #ifndef TC_SUITE_PRINT
198 #define TC_SUITE_PRINT(fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__)
199 #endif
200 
201 #ifndef TC_SUITE_START
202 #define TC_SUITE_START(name)					\
203 	do {							\
204 		TC_SUITE_PRINT("Running TESTSUITE %s\n", name);	\
205 		PRINT_LINE;					\
206 	} while (0)
207 #endif
208 
209 #ifndef TC_SUITE_END
210 #define TC_SUITE_END(name, result)				\
211 	do {								\
212 		if (result != TC_FAIL) {				\
213 			TC_SUITE_PRINT("TESTSUITE %s succeeded\n", name);	\
214 		} else {						\
215 			TC_SUITE_PRINT("TESTSUITE %s failed.\n", name);	\
216 		}							\
217 	} while (0)
218 #endif
219 
220 #if defined(CONFIG_ARCH_POSIX)
221 #include <zephyr/logging/log_ctrl.h>
222 #define TC_END_POST(result) do { \
223 	LOG_PANIC(); \
224 	posix_exit(result); \
225 } while (0)
226 #else
227 #define TC_END_POST(result)
228 #endif /* CONFIG_ARCH_POSIX */
229 
230 #ifndef TC_END_REPORT
231 #define TC_END_REPORT(result)                               \
232 	do {                                                    \
233 		PRINT_LINE;                                         \
234 		TC_PRINT_RUNID;                                         \
235 		TC_END(result,                                      \
236 		       "PROJECT EXECUTION %s\n",               \
237 		       (result) == TC_PASS ? "SUCCESSFUL" : "FAILED");	\
238 		TC_END_POST(result);                                    \
239 	} while (0)
240 #endif
241 
242 #if defined(CONFIG_SHELL)
243 #define TC_CMD_DEFINE(name)						\
244 	static int cmd_##name(const struct shell *sh, size_t argc,	\
245 			      char **argv) \
246 	{								\
247 		TC_START(__func__);					\
248 		name();							\
249 		TC_END_RESULT(TC_PASS);					\
250 		return 0;						\
251 	}
252 #define TC_CMD_ITEM(name)	cmd_##name
253 #else
254 #define TC_CMD_DEFINE(name)				\
255 	int cmd_##name(int argc, char *argv[])		\
256 	{						\
257 		TC_START(__func__);			\
258 		name();					\
259 		TC_END_RESULT(TC_PASS);			\
260 		return 0;				\
261 	}
262 #define TC_CMD_ITEM(name) {STRINGIFY(name), cmd_##name, "none"}
263 #endif
264 
265 #endif /* ZEPHYR_TESTSUITE_INCLUDE_TC_UTIL_H_ */
266