1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2018-11-19 MurphyZhao the first version
9 */
10
11 #include <rtthread.h>
12 #include <string.h>
13 #include "utest.h"
14 #include <utest_log.h>
15
16 #undef DBG_SECTION_NAME
17 #undef DBG_LEVEL
18 #undef DBG_COLOR
19 #undef DBG_ENABLE
20
21 #define DBG_ENABLE
22 #define DBG_SECTION_NAME "utest"
23 #ifdef UTEST_DEBUG
24 #define DBG_LEVEL DBG_LOG
25 #else
26 #define DBG_LEVEL DBG_INFO
27 #endif
28 #define DBG_COLOR
29 #include <rtdbg.h>
30
31 #if RT_CONSOLEBUF_SIZE < 256
32 #error "RT_CONSOLEBUF_SIZE is less than 256!"
33 #endif
34
35 static rt_uint8_t utest_log_lv = UTEST_LOG_ALL;
36 static utest_tc_export_t tc_table = RT_NULL;
37 static rt_size_t tc_num;
38 static struct utest local_utest = {UTEST_PASSED, 0, 0};
39
40 #if defined(__ICCARM__) || defined(__ICCRX__) /* for IAR compiler */
41 #pragma section="UtestTcTab"
42 #endif
43
utest_log_lv_set(rt_uint8_t lv)44 void utest_log_lv_set(rt_uint8_t lv)
45 {
46 if (lv == UTEST_LOG_ALL || lv == UTEST_LOG_ASSERT)
47 {
48 utest_log_lv = lv;
49 }
50 }
51
utest_init(void)52 int utest_init(void)
53 {
54 /* initialize the utest commands table.*/
55 #if defined(__CC_ARM) /* ARM C Compiler */
56 extern const int UtestTcTab$$Base;
57 extern const int UtestTcTab$$Limit;
58 tc_table = (utest_tc_export_t)&UtestTcTab$$Base;
59 tc_num = (utest_tc_export_t)&UtestTcTab$$Limit - tc_table;
60 #elif defined (__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */
61 tc_table = (utest_tc_export_t)__section_begin("UtestTcTab");
62 tc_num = (utest_tc_export_t)__section_end("UtestTcTab") - tc_table;
63 #elif defined (__GNUC__) /* for GCC Compiler */
64 extern const int __rt_utest_tc_tab_start;
65 extern const int __rt_utest_tc_tab_end;
66 tc_table = (utest_tc_export_t)&__rt_utest_tc_tab_start;
67 tc_num = (utest_tc_export_t) &__rt_utest_tc_tab_end - tc_table;
68 #endif /* defined(__CC_ARM) */
69
70 LOG_I("utest is initialize success.");
71 LOG_I("total utest testcase num: (%d)", tc_num);
72 return tc_num;
73 }
74 INIT_COMPONENT_EXPORT(utest_init);
75
utest_tc_list(void)76 static void utest_tc_list(void)
77 {
78 rt_size_t i = 0;
79
80 LOG_I("Commands list : ");
81
82 for (i = 0; i < tc_num; i++)
83 {
84 LOG_I("[testcase name]:%s; [run timeout]:%d", tc_table[i].name, tc_table[i].run_timeout);
85 }
86 }
87 MSH_CMD_EXPORT_ALIAS(utest_tc_list, utest_list, output all utest testcase);
88
file_basename(const char * file)89 static const char *file_basename(const char *file)
90 {
91 char *end_ptr = RT_NULL;
92 char *rst = RT_NULL;
93
94 if (!((end_ptr = strrchr(file, '\\')) != RT_NULL || \
95 (end_ptr = strrchr(file, '/')) != RT_NULL) || \
96 (rt_strlen(file) < 2))
97 {
98 rst = (char *)file;
99 }
100 else
101 {
102 rst = (char *)(end_ptr + 1);
103 }
104 return (const char *)rst;
105 }
106
utest_run(const char * utest_name)107 static void utest_run(const char *utest_name)
108 {
109 rt_size_t i = 0;
110
111 LOG_I("[==========] [ utest ] started");
112 while(i < tc_num)
113 {
114 if (utest_name && rt_strcmp(utest_name, tc_table[i].name))
115 {
116 i++;
117 continue;
118 }
119
120 LOG_I("[----------] [ testcase ] (%s) started", tc_table[i].name);
121 if (tc_table[i].init != RT_NULL)
122 {
123 if (tc_table[i].init() != RT_EOK)
124 {
125 LOG_E("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name);
126 goto __tc_continue;
127 }
128 }
129
130 if (tc_table[i].tc != RT_NULL)
131 {
132 tc_table[i].tc();
133 if (local_utest.failed_num == 0)
134 {
135 LOG_I("[ PASSED ] [ result ] testcase (%s)", tc_table[i].name);
136 }
137 else
138 {
139 LOG_E("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name);
140 }
141 }
142 else
143 {
144 LOG_E("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name);
145 }
146
147 if (tc_table[i].cleanup != RT_NULL)
148 {
149 if (tc_table[i].cleanup() != RT_EOK)
150 {
151 LOG_E("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name);
152 goto __tc_continue;
153 }
154 }
155
156 __tc_continue:
157 LOG_I("[----------] [ testcase ] (%s) finished", tc_table[i].name);
158
159 i++;
160 }
161 LOG_I("[==========] [ utest ] finished");
162 }
163
utest_testcase_run(int argc,char ** argv)164 static void utest_testcase_run(int argc, char** argv)
165 {
166 char utest_name[UTEST_NAME_MAX_LEN];
167
168 if (argc == 1)
169 {
170 utest_run(RT_NULL);
171 }
172 else if (argc == 2)
173 {
174 rt_memset(utest_name, 0x0, sizeof(utest_name));
175 rt_strncpy(utest_name, argv[1], sizeof(utest_name) -1);
176 utest_run(utest_name);
177 }
178 else
179 {
180 LOG_E("[ error ] at (%s:%d), in param error.", __func__, __LINE__);
181 }
182 }
183 MSH_CMD_EXPORT_ALIAS(utest_testcase_run, utest_run, utest_run [testcase name]);
184
utest_handle_get(void)185 utest_t utest_handle_get(void)
186 {
187 return (utest_t)&local_utest;
188 }
189
utest_unit_run(test_unit_func func,const char * unit_func_name)190 void utest_unit_run(test_unit_func func, const char *unit_func_name)
191 {
192 // LOG_I("[==========] utest unit name: (%s)", unit_func_name);
193 local_utest.error = UTEST_PASSED;
194 local_utest.passed_num = 0;
195 local_utest.failed_num = 0;
196
197 if (func != RT_NULL)
198 {
199 func();
200 }
201 }
202
utest_assert(int value,const char * file,int line,const char * func,const char * msg)203 void utest_assert(int value, const char *file, int line, const char *func, const char *msg)
204 {
205 if (!(value))
206 {
207 local_utest.error = UTEST_FAILED;
208 local_utest.failed_num ++;
209 LOG_E("[ ASSERT ] [ unit ] at (%s); func: (%s:%d); msg: (%s)", file_basename(file), func, line, msg);
210 }
211 else
212 {
213 if (utest_log_lv == UTEST_LOG_ALL)
214 {
215 LOG_D("[ OK ] [ unit ] (%s:%d) is passed", func, line);
216 }
217 local_utest.error = UTEST_PASSED;
218 local_utest.passed_num ++;
219 }
220 }
221
utest_assert_string(const char * a,const char * b,rt_bool_t equal,const char * file,int line,const char * func,const char * msg)222 void utest_assert_string(const char *a, const char *b, rt_bool_t equal, const char *file, int line, const char *func, const char *msg)
223 {
224 if (a == RT_NULL || b == RT_NULL)
225 {
226 utest_assert(0, file, line, func, msg);
227 }
228
229 if (equal)
230 {
231 if (rt_strcmp(a, b) == 0)
232 {
233 utest_assert(1, file, line, func, msg);
234 }
235 else
236 {
237 utest_assert(0, file, line, func, msg);
238 }
239 }
240 else
241 {
242 if (rt_strcmp(a, b) == 0)
243 {
244 utest_assert(0, file, line, func, msg);
245 }
246 else
247 {
248 utest_assert(1, file, line, func, msg);
249 }
250 }
251 }
252
utest_assert_buf(const char * a,const char * b,rt_size_t sz,rt_bool_t equal,const char * file,int line,const char * func,const char * msg)253 void utest_assert_buf(const char *a, const char *b, rt_size_t sz, rt_bool_t equal, const char *file, int line, const char *func, const char *msg)
254 {
255 if (a == RT_NULL || b == RT_NULL)
256 {
257 utest_assert(0, file, line, func, msg);
258 }
259
260 if (equal)
261 {
262 if (rt_memcmp(a, b, sz) == 0)
263 {
264 utest_assert(1, file, line, func, msg);
265 }
266 else
267 {
268 utest_assert(0, file, line, func, msg);
269 }
270 }
271 else
272 {
273 if (rt_memcmp(a, b, sz) == 0)
274 {
275 utest_assert(0, file, line, func, msg);
276 }
277 else
278 {
279 utest_assert(1, file, line, func, msg);
280 }
281 }
282 }
283