1*10465441SEvalZero #include "tc_comm.h"
2*10465441SEvalZero #ifdef RT_USING_FINSH
3*10465441SEvalZero #include <finsh.h>
4*10465441SEvalZero #endif
5*10465441SEvalZero
6*10465441SEvalZero #ifdef RT_USING_TC
7*10465441SEvalZero #define TC_PRIORITY 25
8*10465441SEvalZero #define TC_STACK_SIZE 0x400
9*10465441SEvalZero
10*10465441SEvalZero static rt_uint8_t _tc_stat;
11*10465441SEvalZero static struct rt_semaphore _tc_sem;
12*10465441SEvalZero static struct rt_thread _tc_thread;
13*10465441SEvalZero static rt_uint8_t _tc_stack[TC_STACK_SIZE];
14*10465441SEvalZero static char _tc_prefix[64];
15*10465441SEvalZero static const char* _tc_current;
16*10465441SEvalZero static void (*_tc_cleanup)(void) = RT_NULL;
17*10465441SEvalZero
18*10465441SEvalZero static rt_uint32_t _tc_scale = 1;
19*10465441SEvalZero FINSH_VAR_EXPORT(_tc_scale, finsh_type_int, the testcase timer timeout scale)
20*10465441SEvalZero
21*10465441SEvalZero static rt_uint32_t _tc_loop;
22*10465441SEvalZero
tc_thread_entry(void * parameter)23*10465441SEvalZero void tc_thread_entry(void* parameter)
24*10465441SEvalZero {
25*10465441SEvalZero unsigned int fail_count = 0;
26*10465441SEvalZero struct finsh_syscall* index;
27*10465441SEvalZero
28*10465441SEvalZero /* create tc semaphore */
29*10465441SEvalZero rt_sem_init(&_tc_sem, "tc", 0, RT_IPC_FLAG_FIFO);
30*10465441SEvalZero
31*10465441SEvalZero do {
32*10465441SEvalZero for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
33*10465441SEvalZero {
34*10465441SEvalZero /* search testcase */
35*10465441SEvalZero if (rt_strstr(index->name, _tc_prefix) == index->name)
36*10465441SEvalZero {
37*10465441SEvalZero long tick;
38*10465441SEvalZero
39*10465441SEvalZero _tc_current = index->name + 4;
40*10465441SEvalZero rt_kprintf("Run TestCase: %s\n", _tc_current);
41*10465441SEvalZero _tc_stat = TC_STAT_PASSED | TC_STAT_RUNNING;
42*10465441SEvalZero tick = index->func();
43*10465441SEvalZero if (tick > 0)
44*10465441SEvalZero {
45*10465441SEvalZero /* Make sure we are going to be blocked. */
46*10465441SEvalZero rt_sem_control(&_tc_sem, RT_IPC_CMD_RESET, 0);
47*10465441SEvalZero rt_sem_take(&_tc_sem, tick * _tc_scale);
48*10465441SEvalZero }
49*10465441SEvalZero
50*10465441SEvalZero if (_tc_cleanup != RT_NULL)
51*10465441SEvalZero {
52*10465441SEvalZero /* perform testcase cleanup */
53*10465441SEvalZero _tc_cleanup();
54*10465441SEvalZero _tc_cleanup = RT_NULL;
55*10465441SEvalZero }
56*10465441SEvalZero
57*10465441SEvalZero if (_tc_stat & TC_STAT_RUNNING)
58*10465441SEvalZero {
59*10465441SEvalZero rt_kprintf("TestCase[%s] exit with stat TC_STAT_RUNNING."
60*10465441SEvalZero " Please fix the TC.\n",
61*10465441SEvalZero _tc_current);
62*10465441SEvalZero /* If the TC forgot to clear the flag, we do it. */
63*10465441SEvalZero _tc_stat &= ~TC_STAT_RUNNING;
64*10465441SEvalZero }
65*10465441SEvalZero
66*10465441SEvalZero if (_tc_stat & TC_STAT_FAILED)
67*10465441SEvalZero {
68*10465441SEvalZero rt_kprintf("TestCase[%s] failed\n", _tc_current);
69*10465441SEvalZero fail_count++;
70*10465441SEvalZero }
71*10465441SEvalZero else
72*10465441SEvalZero {
73*10465441SEvalZero rt_kprintf("TestCase[%s] passed\n", _tc_current);
74*10465441SEvalZero }
75*10465441SEvalZero }
76*10465441SEvalZero }
77*10465441SEvalZero } while (_tc_loop);
78*10465441SEvalZero
79*10465441SEvalZero rt_kprintf("RT-Thread TestCase Running Done!\n");
80*10465441SEvalZero if (fail_count)
81*10465441SEvalZero {
82*10465441SEvalZero rt_kprintf("%d tests failed\n", fail_count);
83*10465441SEvalZero }
84*10465441SEvalZero else
85*10465441SEvalZero {
86*10465441SEvalZero rt_kprintf("All tests passed\n");
87*10465441SEvalZero }
88*10465441SEvalZero /* detach tc semaphore */
89*10465441SEvalZero rt_sem_detach(&_tc_sem);
90*10465441SEvalZero }
91*10465441SEvalZero
tc_stop()92*10465441SEvalZero void tc_stop()
93*10465441SEvalZero {
94*10465441SEvalZero _tc_loop = 0;
95*10465441SEvalZero
96*10465441SEvalZero rt_thread_delay(10 * RT_TICK_PER_SECOND);
97*10465441SEvalZero if (_tc_thread.stat != RT_THREAD_INIT)
98*10465441SEvalZero {
99*10465441SEvalZero /* lock scheduler */
100*10465441SEvalZero rt_enter_critical();
101*10465441SEvalZero
102*10465441SEvalZero /* detach old tc thread */
103*10465441SEvalZero rt_thread_detach(&_tc_thread);
104*10465441SEvalZero rt_sem_detach(&_tc_sem);
105*10465441SEvalZero
106*10465441SEvalZero /* unlock scheduler */
107*10465441SEvalZero rt_exit_critical();
108*10465441SEvalZero }
109*10465441SEvalZero rt_thread_delay(RT_TICK_PER_SECOND/2);
110*10465441SEvalZero }
111*10465441SEvalZero FINSH_FUNCTION_EXPORT(tc_stop, stop testcase thread);
112*10465441SEvalZero
tc_done(rt_uint8_t stat)113*10465441SEvalZero void tc_done(rt_uint8_t stat)
114*10465441SEvalZero {
115*10465441SEvalZero _tc_stat |= stat;
116*10465441SEvalZero _tc_stat &= ~TC_STAT_RUNNING;
117*10465441SEvalZero
118*10465441SEvalZero /* release semaphore */
119*10465441SEvalZero rt_sem_release(&_tc_sem);
120*10465441SEvalZero }
121*10465441SEvalZero
tc_stat(rt_uint8_t stat)122*10465441SEvalZero void tc_stat(rt_uint8_t stat)
123*10465441SEvalZero {
124*10465441SEvalZero if (stat & TC_STAT_FAILED)
125*10465441SEvalZero {
126*10465441SEvalZero rt_kprintf("TestCases[%s] failed\n", _tc_current);
127*10465441SEvalZero }
128*10465441SEvalZero _tc_stat |= stat;
129*10465441SEvalZero }
130*10465441SEvalZero
tc_cleanup(void (* cleanup)())131*10465441SEvalZero void tc_cleanup(void (*cleanup)())
132*10465441SEvalZero {
133*10465441SEvalZero _tc_cleanup = cleanup;
134*10465441SEvalZero }
135*10465441SEvalZero
tc_start(const char * tc_prefix)136*10465441SEvalZero void tc_start(const char* tc_prefix)
137*10465441SEvalZero {
138*10465441SEvalZero rt_err_t result;
139*10465441SEvalZero
140*10465441SEvalZero /* tesecase prefix is null */
141*10465441SEvalZero if (tc_prefix == RT_NULL)
142*10465441SEvalZero {
143*10465441SEvalZero rt_kprintf("TestCase Usage: tc_start(prefix)\n\n");
144*10465441SEvalZero rt_kprintf("list_tc() can list all testcases.\n");
145*10465441SEvalZero return ;
146*10465441SEvalZero }
147*10465441SEvalZero
148*10465441SEvalZero /* init tc thread */
149*10465441SEvalZero if (_tc_stat & TC_STAT_RUNNING)
150*10465441SEvalZero {
151*10465441SEvalZero /* stop old tc thread */
152*10465441SEvalZero tc_stop();
153*10465441SEvalZero }
154*10465441SEvalZero
155*10465441SEvalZero rt_memset(_tc_prefix, 0, sizeof(_tc_prefix));
156*10465441SEvalZero rt_snprintf(_tc_prefix, sizeof(_tc_prefix), "_tc_%s", tc_prefix);
157*10465441SEvalZero
158*10465441SEvalZero result = rt_thread_init(&_tc_thread, "tc",
159*10465441SEvalZero tc_thread_entry, RT_NULL,
160*10465441SEvalZero &_tc_stack[0], sizeof(_tc_stack),
161*10465441SEvalZero TC_PRIORITY - 3, 5);
162*10465441SEvalZero
163*10465441SEvalZero /* set tc stat */
164*10465441SEvalZero _tc_stat = TC_STAT_RUNNING | TC_STAT_FAILED;
165*10465441SEvalZero
166*10465441SEvalZero if (result == RT_EOK)
167*10465441SEvalZero rt_thread_startup(&_tc_thread);
168*10465441SEvalZero }
169*10465441SEvalZero FINSH_FUNCTION_EXPORT(tc_start, start testcase with testcase prefix or name);
170*10465441SEvalZero
tc_loop(const char * tc_prefix)171*10465441SEvalZero void tc_loop(const char *tc_prefix)
172*10465441SEvalZero {
173*10465441SEvalZero _tc_loop = 1;
174*10465441SEvalZero tc_start(tc_prefix);
175*10465441SEvalZero }
176*10465441SEvalZero FINSH_FUNCTION_EXPORT(tc_loop, start testcase with testcase prefix or name in loop mode);
177*10465441SEvalZero
list_tc()178*10465441SEvalZero void list_tc()
179*10465441SEvalZero {
180*10465441SEvalZero struct finsh_syscall* index;
181*10465441SEvalZero
182*10465441SEvalZero rt_kprintf("TestCases List:\n");
183*10465441SEvalZero for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
184*10465441SEvalZero {
185*10465441SEvalZero /* search testcase */
186*10465441SEvalZero if (rt_strstr(index->name, "_tc_") == index->name)
187*10465441SEvalZero {
188*10465441SEvalZero #ifdef FINSH_USING_DESCRIPTION
189*10465441SEvalZero rt_kprintf("%-16s -- %s\n", index->name + 4, index->desc);
190*10465441SEvalZero #else
191*10465441SEvalZero rt_kprintf("%s\n", index->name + 4);
192*10465441SEvalZero #endif
193*10465441SEvalZero }
194*10465441SEvalZero }
195*10465441SEvalZero }
196*10465441SEvalZero FINSH_FUNCTION_EXPORT(list_tc, list all testcases);
197*10465441SEvalZero #endif
198*10465441SEvalZero
199