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