xref: /nrf52832-nimble/rt-thread/examples/kernel/tc_comm.c (revision 104654410c56c573564690304ae786df310c91fc)
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