timer_tc.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /*
  2. * Copyright (c) 2006-2019, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-08-12 luckyzjq the first version
  9. */
  10. #include <rtthread.h>
  11. #include <stdlib.h>
  12. #include "utest.h"
  13. #undef uassert_true
  14. #define uassert_true(value) \
  15. do \
  16. { \
  17. if (!(value)) \
  18. { \
  19. __utest_assert(value, "(" #value ") is false"); \
  20. } \
  21. } while (0)
  22. static rt_uint8_t timer_flag_oneshot[] = {
  23. RT_TIMER_FLAG_ONE_SHOT,
  24. RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_HARD_TIMER,
  25. RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER,
  26. };
  27. static rt_uint8_t timer_flag_periodic[] = {
  28. RT_TIMER_FLAG_PERIODIC,
  29. RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_HARD_TIMER,
  30. RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER,
  31. };
  32. typedef struct test_timer_struct
  33. {
  34. struct rt_timer static_timer; /* static timer handler */
  35. rt_timer_t dynamic_timer; /* dynamic timer pointer */
  36. rt_tick_t expect_tick; /* expect tick */
  37. rt_ubase_t callbacks; /* timer callback times */
  38. rt_bool_t is_static; /* static or dynamic timer */
  39. } timer_struct;
  40. static timer_struct timer;
  41. static void timer_oneshot(void *param)
  42. {
  43. timer_struct *timer_call;
  44. timer_call = (timer_struct *)param;
  45. timer_call->callbacks++;
  46. uassert_true(rt_tick_get() == timer_call->expect_tick);
  47. }
  48. static void timer_periodic(void *param)
  49. {
  50. rt_err_t result;
  51. timer_struct *timer_call;
  52. timer_call = (timer_struct *)param;
  53. timer_call->callbacks++;
  54. uassert_true(rt_tick_get() == timer_call->expect_tick);
  55. if (timer_call->is_static)
  56. {
  57. timer_call->expect_tick = rt_tick_get() + timer_call->static_timer.init_tick;
  58. }
  59. else
  60. {
  61. timer_call->expect_tick = rt_tick_get() + timer_call->dynamic_timer->init_tick;
  62. }
  63. if (timer_call->callbacks == 5)
  64. {
  65. /* periodic timer can stop */
  66. if (timer_call->is_static)
  67. {
  68. result = rt_timer_stop(&timer_call->static_timer);
  69. }
  70. else
  71. {
  72. result = rt_timer_stop(timer_call->dynamic_timer);
  73. }
  74. uassert_true(result == RT_EOK);
  75. }
  76. }
  77. static void test_static_timer(void)
  78. {
  79. rt_err_t result;
  80. timer.callbacks = 0;
  81. timer.is_static = RT_TRUE;
  82. /* one shot timer test */
  83. for (int time_out = 1; time_out < 10; time_out++)
  84. {
  85. for (int i = 0; i < sizeof(timer_flag_oneshot); i++)
  86. {
  87. rt_timer_init(&timer.static_timer,
  88. "static_timer",
  89. timer_oneshot,
  90. &timer,
  91. time_out,
  92. timer_flag_oneshot[i]);
  93. /* calc expect tick */
  94. timer.expect_tick = rt_tick_get() + time_out;
  95. /* start timer */
  96. result = rt_timer_start(&timer.static_timer);
  97. uassert_true(result == RT_EOK);
  98. /* wait for timerout */
  99. rt_thread_delay(3 * time_out + 1);
  100. uassert_true(timer.callbacks == 1);
  101. /* detach timer */
  102. result = rt_timer_detach(&timer.static_timer);
  103. uassert_true(result == RT_EOK);
  104. timer.callbacks = 0;
  105. }
  106. }
  107. /* periodic timer test */
  108. for (int time_out = 1; time_out < 10; time_out++)
  109. {
  110. for (int i = 0; i < sizeof(timer_flag_periodic); i++)
  111. {
  112. rt_timer_init(&timer.static_timer,
  113. "static_timer",
  114. timer_periodic,
  115. &timer,
  116. time_out,
  117. timer_flag_periodic[i]);
  118. /* calc expect tick */
  119. timer.expect_tick = rt_tick_get() + time_out;
  120. /* start timer */
  121. result = rt_timer_start(&timer.static_timer);
  122. uassert_true(result == RT_EOK);
  123. /* wait for timerout */
  124. rt_thread_delay(5 * time_out + 1);
  125. uassert_true(timer.callbacks >= 5);
  126. /* detach timer */
  127. result = rt_timer_detach(&timer.static_timer);
  128. uassert_true(result == RT_EOK);
  129. timer.callbacks = 0;
  130. }
  131. }
  132. }
  133. static void test_static_timer_start_twice(void)
  134. {
  135. rt_err_t result;
  136. timer.callbacks = 0;
  137. timer.is_static = RT_TRUE;
  138. /* timer start twice test */
  139. for (int time_out = 2; time_out < 10; time_out++)
  140. {
  141. for (int i = 0; i < sizeof(timer_flag_oneshot); i++)
  142. {
  143. rt_timer_init(&timer.static_timer,
  144. "static_timer",
  145. timer_oneshot,
  146. &timer,
  147. time_out,
  148. timer_flag_oneshot[i]);
  149. /* calc expect tick */
  150. timer.expect_tick = rt_tick_get() + time_out;
  151. /* start timer */
  152. result = rt_timer_start(&timer.static_timer);
  153. uassert_true(result == RT_EOK);
  154. rt_thread_delay(1);
  155. /* calc expect tick */
  156. timer.expect_tick = rt_tick_get() + time_out;
  157. /* start timer */
  158. result = rt_timer_start(&timer.static_timer);
  159. uassert_true(result == RT_EOK);
  160. /* wait for timerout */
  161. rt_thread_delay(3 * time_out + 1);
  162. uassert_true(timer.callbacks == 1);
  163. /* detach timer */
  164. result = rt_timer_detach(&timer.static_timer);
  165. uassert_true(result == RT_EOK);
  166. timer.callbacks = 0;
  167. }
  168. }
  169. }
  170. static void timer_control(void *param)
  171. {
  172. rt_err_t result;
  173. timer_struct *timer_call;
  174. timer_call = (timer_struct *)param;
  175. timer_call->callbacks++;
  176. uassert_true(rt_tick_get() == timer_call->expect_tick);
  177. /* periodic timer can stop */
  178. if (timer_call->is_static)
  179. {
  180. result = rt_timer_stop(&timer_call->static_timer);
  181. }
  182. else
  183. {
  184. result = rt_timer_stop(timer_call->dynamic_timer);
  185. }
  186. uassert_true(result == RT_EOK);
  187. }
  188. static void test_static_timer_control(void)
  189. {
  190. rt_err_t result;
  191. int set_data;
  192. int get_data;
  193. timer.callbacks = 0;
  194. timer.is_static = RT_TRUE;
  195. rt_timer_init(&timer.static_timer,
  196. "static_timer",
  197. timer_control,
  198. &timer,
  199. 5,
  200. RT_TIMER_FLAG_PERIODIC);
  201. /* test set data */
  202. set_data = 10;
  203. result = rt_timer_control(&timer.static_timer, RT_TIMER_CTRL_SET_TIME, &set_data);
  204. uassert_true(result == RT_EOK);
  205. /* test get data */
  206. result = rt_timer_control(&timer.static_timer, RT_TIMER_CTRL_GET_TIME, &get_data);
  207. uassert_true(result == RT_EOK);
  208. uassert_true(set_data == get_data);
  209. /* calc expect tick */
  210. timer.expect_tick = rt_tick_get() + set_data;
  211. /* start timer */
  212. result = rt_timer_start(&timer.static_timer);
  213. uassert_true(result == RT_EOK);
  214. rt_thread_delay(3 * set_data + 1);
  215. /* detach timer */
  216. result = rt_timer_detach(&timer.static_timer);
  217. uassert_true(result == RT_EOK);
  218. uassert_true(timer.callbacks == 1);
  219. }
  220. static void timer_start_in_callback(void *param)
  221. {
  222. rt_err_t result;
  223. timer_struct *timer_call;
  224. timer_call = (timer_struct *)param;
  225. timer_call->callbacks++;
  226. uassert_true(rt_tick_get() == timer_call->expect_tick);
  227. if (timer_call->is_static)
  228. {
  229. timer_call->expect_tick = rt_tick_get() + timer_call->static_timer.init_tick;
  230. result = rt_timer_start(&timer_call->static_timer);
  231. }
  232. else
  233. {
  234. timer_call->expect_tick = rt_tick_get() + timer_call->dynamic_timer->init_tick;
  235. result = rt_timer_start(timer_call->dynamic_timer);
  236. }
  237. uassert_true(result == RT_EOK);
  238. }
  239. static void timer_start_stop_in_callback(void *param)
  240. {
  241. rt_err_t result;
  242. timer_struct *timer_call;
  243. timer_call = (timer_struct *)param;
  244. timer_call->callbacks++;
  245. uassert_true(rt_tick_get() == timer_call->expect_tick);
  246. if (timer_call->is_static)
  247. {
  248. result = rt_timer_start(&timer_call->static_timer);
  249. }
  250. else
  251. {
  252. result = rt_timer_start(timer_call->dynamic_timer);
  253. }
  254. uassert_true(result == RT_EOK);
  255. if (timer_call->is_static)
  256. {
  257. result = rt_timer_stop(&timer_call->static_timer);
  258. }
  259. else
  260. {
  261. result = rt_timer_stop(timer_call->dynamic_timer);
  262. }
  263. uassert_true(result == RT_EOK);
  264. }
  265. static void test_static_timer_op_in_callback(void)
  266. {
  267. rt_err_t result;
  268. timer.callbacks = 0;
  269. timer.is_static = RT_TRUE;
  270. /* start in callback test */
  271. for (int time_out = 1; time_out < 10; time_out++)
  272. {
  273. for (int i = 0; i < sizeof(timer_flag_oneshot); i++)
  274. {
  275. rt_timer_init(&timer.static_timer,
  276. "static_timer",
  277. timer_start_in_callback,
  278. &timer,
  279. time_out,
  280. timer_flag_oneshot[i]);
  281. /* calc expect tick */
  282. timer.expect_tick = rt_tick_get() + time_out;
  283. /* start timer */
  284. result = rt_timer_start(&timer.static_timer);
  285. uassert_true(result == RT_EOK);
  286. /* wait for timerout */
  287. rt_thread_delay(5 * time_out + 1);
  288. uassert_true(timer.callbacks >= 5);
  289. /* detach timer */
  290. result = rt_timer_detach(&timer.static_timer);
  291. uassert_true(result == RT_EOK);
  292. timer.callbacks = 0;
  293. }
  294. }
  295. /* start & stop in callback test */
  296. for (int time_out = 1; time_out < 10; time_out++)
  297. {
  298. for (int i = 0; i < sizeof(timer_flag_periodic); i++)
  299. {
  300. rt_timer_init(&timer.static_timer,
  301. "static_timer",
  302. timer_start_stop_in_callback,
  303. &timer,
  304. time_out,
  305. timer_flag_periodic[i]);
  306. /* calc expect tick */
  307. timer.expect_tick = rt_tick_get() + time_out;
  308. /* start timer */
  309. result = rt_timer_start(&timer.static_timer);
  310. uassert_true(result == RT_EOK);
  311. /* wait for timerout */
  312. rt_thread_delay(3 * time_out + 1);
  313. uassert_true(timer.callbacks == 1);
  314. /* detach timer */
  315. result = rt_timer_detach(&timer.static_timer);
  316. uassert_true(result == RT_EOK);
  317. timer.callbacks = 0;
  318. }
  319. }
  320. }
  321. #ifdef RT_USING_HEAP
  322. static void test_dynamic_timer(void)
  323. {
  324. rt_err_t result;
  325. timer.callbacks = 0;
  326. timer.is_static = RT_FALSE;
  327. /* one shot timer test */
  328. for (int time_out = 1; time_out < 10; time_out++)
  329. {
  330. for (int i = 0; i < sizeof(timer_flag_oneshot); i++)
  331. {
  332. timer.dynamic_timer = rt_timer_create("dynamic_timer",
  333. timer_oneshot,
  334. &timer,
  335. time_out,
  336. timer_flag_oneshot[i]);
  337. /* calc expect tick */
  338. timer.expect_tick = rt_tick_get() + time_out;
  339. /* start timer */
  340. result = rt_timer_start(timer.dynamic_timer);
  341. uassert_true(result == RT_EOK);
  342. /* wait for timerout */
  343. rt_thread_delay(3 * time_out + 1);
  344. uassert_true(timer.callbacks == 1);
  345. /* detach timer */
  346. result = rt_timer_delete(timer.dynamic_timer);
  347. uassert_true(result == RT_EOK);
  348. timer.callbacks = 0;
  349. }
  350. }
  351. /* periodic timer test */
  352. for (int time_out = 1; time_out < 10; time_out++)
  353. {
  354. for (int i = 0; i < sizeof(timer_flag_periodic); i++)
  355. {
  356. timer.dynamic_timer = rt_timer_create("dynamic_timer",
  357. timer_periodic,
  358. &timer,
  359. time_out,
  360. timer_flag_periodic[i]);
  361. /* calc expect tick */
  362. timer.expect_tick = rt_tick_get() + time_out;
  363. /* start timer */
  364. result = rt_timer_start(timer.dynamic_timer);
  365. uassert_true(result == RT_EOK);
  366. /* wait for timerout */
  367. rt_thread_delay(5 * time_out + 1);
  368. uassert_true(timer.callbacks >= 5);
  369. /* detach timer */
  370. result = rt_timer_delete(timer.dynamic_timer);
  371. uassert_true(result == RT_EOK);
  372. timer.callbacks = 0;
  373. }
  374. }
  375. }
  376. static void test_dynamic_timer_control(void)
  377. {
  378. rt_err_t result;
  379. int set_data;
  380. int get_data;
  381. timer.callbacks = 0;
  382. timer.is_static = RT_FALSE;
  383. timer.dynamic_timer = rt_timer_create("dynamic_timer",
  384. timer_control,
  385. &timer,
  386. 5,
  387. RT_TIMER_FLAG_PERIODIC);
  388. /* test set data */
  389. set_data = 10;
  390. result = rt_timer_control(timer.dynamic_timer, RT_TIMER_CTRL_SET_TIME, &set_data);
  391. uassert_true(result == RT_EOK);
  392. /* test get data */
  393. result = rt_timer_control(timer.dynamic_timer, RT_TIMER_CTRL_GET_TIME, &get_data);
  394. uassert_true(result == RT_EOK);
  395. uassert_true(set_data == get_data);
  396. /* calc expect tick */
  397. timer.expect_tick = rt_tick_get() + set_data;
  398. /* start timer */
  399. result = rt_timer_start(timer.dynamic_timer);
  400. uassert_true(result == RT_EOK);
  401. rt_thread_delay(3 * set_data + 1);
  402. /* detach timer */
  403. result = rt_timer_delete(timer.dynamic_timer);
  404. uassert_true(result == RT_EOK);
  405. uassert_true(timer.callbacks == 1);
  406. }
  407. static void test_dynamic_timer_start_twice(void)
  408. {
  409. rt_err_t result;
  410. timer.callbacks = 0;
  411. timer.is_static = RT_FALSE;
  412. /* timer start twice test */
  413. for (int time_out = 2; time_out < 10; time_out++)
  414. {
  415. for (int i = 0; i < sizeof(timer_flag_oneshot); i++)
  416. {
  417. timer.dynamic_timer = rt_timer_create("dynamic_timer",
  418. timer_oneshot,
  419. &timer,
  420. time_out,
  421. timer_flag_oneshot[i]);
  422. /* calc expect tick */
  423. timer.expect_tick = rt_tick_get() + time_out;
  424. /* start timer */
  425. result = rt_timer_start(timer.dynamic_timer);
  426. uassert_true(result == RT_EOK);
  427. rt_thread_delay(1);
  428. /* calc expect tick */
  429. timer.expect_tick = rt_tick_get() + time_out;
  430. /* start timer */
  431. result = rt_timer_start(timer.dynamic_timer);
  432. uassert_true(result == RT_EOK);
  433. /* wait for timerout */
  434. rt_thread_delay(3 * time_out + 1);
  435. uassert_true(timer.callbacks == 1);
  436. /* detach timer */
  437. result = rt_timer_delete(timer.dynamic_timer);
  438. uassert_true(result == RT_EOK);
  439. timer.callbacks = 0;
  440. }
  441. }
  442. }
  443. static void test_dynamic_timer_op_in_callback(void)
  444. {
  445. rt_err_t result;
  446. timer.callbacks = 0;
  447. timer.is_static = RT_FALSE;
  448. /* start in callback test */
  449. for (int time_out = 1; time_out < 10; time_out++)
  450. {
  451. for (int i = 0; i < sizeof(timer_flag_oneshot); i++)
  452. {
  453. timer.dynamic_timer = rt_timer_create("dynamic_timer",
  454. timer_start_in_callback,
  455. &timer,
  456. time_out,
  457. timer_flag_oneshot[i]);
  458. /* calc expect tick */
  459. timer.expect_tick = rt_tick_get() + time_out;
  460. /* start timer */
  461. result = rt_timer_start(timer.dynamic_timer);
  462. uassert_true(result == RT_EOK);
  463. /* wait for timerout */
  464. rt_thread_delay(5 * time_out + 1);
  465. uassert_true(timer.callbacks >= 5);
  466. /* detach timer */
  467. result = rt_timer_delete(timer.dynamic_timer);
  468. uassert_true(result == RT_EOK);
  469. timer.callbacks = 0;
  470. }
  471. }
  472. /* start & stop in callback test */
  473. for (int time_out = 1; time_out < 10; time_out++)
  474. {
  475. for (int i = 0; i < sizeof(timer_flag_periodic); i++)
  476. {
  477. timer.dynamic_timer = rt_timer_create("dynamic_timer",
  478. timer_start_stop_in_callback,
  479. &timer,
  480. time_out,
  481. timer_flag_periodic[i]);
  482. /* calc expect tick */
  483. timer.expect_tick = rt_tick_get() + time_out;
  484. /* start timer */
  485. result = rt_timer_start(timer.dynamic_timer);
  486. uassert_true(result == RT_EOK);
  487. /* wait for timerout */
  488. rt_thread_delay(3 * time_out + 1);
  489. uassert_true(timer.callbacks == 1);
  490. /* detach timer */
  491. result = rt_timer_delete(timer.dynamic_timer);
  492. uassert_true(result == RT_EOK);
  493. timer.callbacks = 0;
  494. }
  495. }
  496. }
  497. #endif /* RT_USING_HEAP */
  498. #define TEST_TIME_S 60 // test 60 seconds
  499. #define STRESS_TIMERS 100
  500. static struct rt_timer stress_timer[STRESS_TIMERS];
  501. static void timer_stress(void *param)
  502. {
  503. rt_timer_t stress_timer = (rt_timer_t)param;
  504. if (rand() % 2 == 0)
  505. {
  506. rt_timer_start(stress_timer);
  507. }
  508. else
  509. {
  510. rt_timer_stop(stress_timer);
  511. }
  512. }
  513. static void test_timer_stress(void)
  514. {
  515. rt_tick_t start;
  516. rt_ubase_t iters = 0;
  517. LOG_I("timer stress test begin, it will take %d seconds", 3*TEST_TIME_S);
  518. for (int i = 0; i < sizeof(timer_flag_periodic); i++)
  519. {
  520. for (int j = 0; j < STRESS_TIMERS; j++)
  521. {
  522. rt_timer_init(&stress_timer[j],
  523. "stress_timer",
  524. timer_stress,
  525. &stress_timer[j],
  526. j + 1,
  527. timer_flag_periodic[i]);
  528. }
  529. start = rt_tick_get();
  530. while (rt_tick_get() - start <= TEST_TIME_S * RT_TICK_PER_SECOND)
  531. {
  532. for (int j = 0; j < STRESS_TIMERS; j++)
  533. {
  534. if (rand() % 2 == 0)
  535. {
  536. rt_timer_start(&stress_timer[j]);
  537. }
  538. else
  539. {
  540. rt_timer_stop(&stress_timer[j]);
  541. }
  542. }
  543. iters ++;
  544. }
  545. for (int j = 0; j < STRESS_TIMERS; j++)
  546. {
  547. rt_timer_detach(&stress_timer[j]);
  548. }
  549. }
  550. LOG_I("success after %lu iterations", iters);
  551. }
  552. static rt_err_t utest_tc_init(void)
  553. {
  554. timer.dynamic_timer = RT_NULL;
  555. timer.callbacks = 0;
  556. return RT_EOK;
  557. }
  558. static rt_err_t utest_tc_cleanup(void)
  559. {
  560. timer.dynamic_timer = RT_NULL;
  561. timer.callbacks = 0;
  562. return RT_EOK;
  563. }
  564. static void testcase(void)
  565. {
  566. UTEST_UNIT_RUN(test_static_timer);
  567. UTEST_UNIT_RUN(test_static_timer_control);
  568. UTEST_UNIT_RUN(test_static_timer_start_twice);
  569. UTEST_UNIT_RUN(test_static_timer_op_in_callback);
  570. #ifdef RT_USING_HEAP
  571. UTEST_UNIT_RUN(test_dynamic_timer);
  572. UTEST_UNIT_RUN(test_dynamic_timer_control);
  573. UTEST_UNIT_RUN(test_dynamic_timer_start_twice);
  574. UTEST_UNIT_RUN(test_dynamic_timer_op_in_callback);
  575. #endif /* RT_USING_HEAP */
  576. UTEST_UNIT_RUN(test_timer_stress);
  577. }
  578. UTEST_TC_EXPORT(testcase, "testcases.kernel.timer_tc", utest_tc_init, utest_tc_cleanup, 1000);
  579. /*********************** end of file ****************************/