messagequeue_tc.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-08-28 Sherman the first version
  9. * 2023-09-15 xqyjlj change stack size in cpu64
  10. * fix in smp
  11. * 2025-11-17 Ze-Hou add standardized utest documentation block
  12. */
  13. /**
  14. * Test Case Name: Kernel Core Message Queue Test
  15. *
  16. * Test Objectives:
  17. * - Validate the RT-Thread kernel message queue (rt_messagequeue) functionality
  18. * - Test static and dynamic message queue creation, initialization, sending,
  19. * receiving, urgent send, priority send, reset, detach, and delete APIs
  20. *
  21. * Test Scenarios:
  22. * - Initialize a static message queue and verify correct setup
  23. * - Create a dynamic message queue and verify allocation
  24. * - Send messages to the queue until full, test blocking and non-blocking send,
  25. * urgent send, and priority send (if enabled)
  26. * - Receive messages from the queue, verify order and data integrity, including
  27. * priority receive (if enabled)
  28. * - Reset the message queue and verify it is empty
  29. * - Detach and delete message queues, ensuring resources are released
  30. * - Use multiple threads to simulate concurrent send/receive operations
  31. *
  32. * Verification Metrics:
  33. * - All uassert assertions pass without failure
  34. * - Message queues are created, initialized, detached, and deleted successfully
  35. * - Messages are sent and received in correct order and with correct data
  36. * - Blocking and non-blocking operations behave as expected
  37. * - Urgent and priority send/receive functions work correctly (if enabled)
  38. *
  39. * Dependencies:
  40. * - Enable message queue priority (RT-Thread Kernel -> Inter-Thread communication
  41. * -> Enable message queue priority)
  42. * - Enable Message Queue Test (RT-Thread Utestcases -> Kernel Core -> Message Queue Test)
  43. * - Test on any RT-Thread supported platform (e.g., qemu-virt64-riscv)
  44. *
  45. * Expected Results:
  46. * - After executing this test in msh, the expected output should be:
  47. * "[ PASSED ] [ result ] testcase (core.messagequeue)"
  48. */
  49. #include <rtthread.h>
  50. #include "utest.h"
  51. #define THREAD_STACKSIZE UTEST_THR_STACK_SIZE
  52. #define MSG_SIZE 4
  53. #define MAX_MSGS 5
  54. static struct rt_messagequeue static_mq;
  55. static rt_uint8_t mq_buf[RT_MQ_BUF_SIZE(MSG_SIZE, MAX_MSGS)];
  56. static struct rt_thread mq_send_thread;
  57. static struct rt_thread mq_recv_thread;
  58. static rt_uint8_t mq_send_stack[UTEST_THR_STACK_SIZE];
  59. static rt_uint8_t mq_recv_stack[UTEST_THR_STACK_SIZE];
  60. static struct rt_event finish_e;
  61. #define MQSEND_FINISH 0x01
  62. #define MQRECV_FINIHS 0x02
  63. #ifdef RT_USING_HEAP
  64. static rt_mq_t dynamic_mq;
  65. #endif /* RT_USING_HEAP */
  66. static void test_mq_init(void)
  67. {
  68. rt_err_t ret;
  69. ret = rt_mq_init(&static_mq,"testmq1", mq_buf, MSG_SIZE, sizeof(mq_buf), RT_IPC_FLAG_FIFO);
  70. uassert_true(ret == RT_EOK);
  71. }
  72. static void test_mq_create(void)
  73. {
  74. #ifdef RT_USING_HEAP
  75. dynamic_mq = rt_mq_create("testmq2", MSG_SIZE, MAX_MSGS, RT_IPC_FLAG_FIFO);
  76. uassert_true(dynamic_mq != RT_NULL);
  77. #endif /* RT_USING_HEAP */
  78. }
  79. static void mq_send_case(rt_mq_t testmq)
  80. {
  81. rt_uint32_t send_buf[MAX_MSGS+1] = {0};
  82. rt_err_t ret = RT_EOK;
  83. for (int var = 0; var < MAX_MSGS; ++var)
  84. {
  85. send_buf[var] = var + 1;
  86. ret = rt_mq_send_wait(testmq, &send_buf[var], sizeof(send_buf[0]), RT_WAITING_FOREVER);
  87. uassert_true(ret == RT_EOK);
  88. }
  89. send_buf[MAX_MSGS] = MAX_MSGS + 1;
  90. ret = rt_mq_send(testmq, &send_buf[MAX_MSGS], sizeof(send_buf[0]));
  91. uassert_true(ret == -RT_EFULL);
  92. ret = rt_mq_send_wait(testmq, &send_buf[MAX_MSGS], sizeof(send_buf[0]), RT_WAITING_FOREVER);
  93. uassert_true(ret == RT_EOK);
  94. while (testmq->entry != 0)
  95. {
  96. rt_thread_delay(100);
  97. }
  98. ret = rt_mq_send(testmq, &send_buf[1], sizeof(send_buf[0]));
  99. uassert_true(ret == RT_EOK);
  100. ret = rt_mq_send(testmq, &send_buf[2], sizeof(send_buf[0]));
  101. uassert_true(ret == RT_EOK);
  102. ret = rt_mq_urgent(testmq, &send_buf[0], sizeof(send_buf[0]));
  103. uassert_true(ret == RT_EOK);
  104. while (testmq->entry != 0)
  105. {
  106. rt_thread_delay(100);
  107. }
  108. #ifdef RT_USING_MESSAGEQUEUE_PRIORITY
  109. ret = rt_mq_send_wait_prio(testmq, &send_buf[3], sizeof(send_buf[0]), 3, 0, RT_UNINTERRUPTIBLE);
  110. uassert_true(ret == RT_EOK);
  111. ret = rt_mq_send_wait_prio(testmq, &send_buf[0], sizeof(send_buf[0]), 0, 0, RT_UNINTERRUPTIBLE);
  112. uassert_true(ret == RT_EOK);
  113. ret = rt_mq_send_wait_prio(testmq, &send_buf[2], sizeof(send_buf[0]), 1, 0, RT_UNINTERRUPTIBLE);
  114. uassert_true(ret == RT_EOK);
  115. ret = rt_mq_send_wait_prio(testmq, &send_buf[4], sizeof(send_buf[0]), 4, 0, RT_UNINTERRUPTIBLE);
  116. uassert_true(ret == RT_EOK);
  117. ret = rt_mq_send_wait_prio(testmq, &send_buf[1], sizeof(send_buf[0]), 1, 0, RT_UNINTERRUPTIBLE);
  118. uassert_true(ret == RT_EOK);
  119. while (testmq->entry != 0)
  120. {
  121. rt_thread_delay(100);
  122. }
  123. #endif
  124. ret = rt_mq_send(testmq, &send_buf[1], sizeof(send_buf[0]));
  125. uassert_true(ret == RT_EOK);
  126. ret = rt_mq_control(testmq, RT_IPC_CMD_RESET, RT_NULL);
  127. uassert_true(ret == RT_EOK);
  128. uassert_true(testmq->entry == 0);
  129. }
  130. static void mq_send_entry(void *param)
  131. {
  132. mq_send_case(&static_mq);
  133. #ifdef RT_USING_HEAP
  134. if(dynamic_mq != RT_NULL)
  135. {
  136. mq_send_case(dynamic_mq);
  137. }
  138. #endif /* RT_USING_HEAP */
  139. rt_event_send(&finish_e, MQSEND_FINISH);
  140. }
  141. static void mq_recv_case(rt_mq_t testmq)
  142. {
  143. rt_uint32_t recv_buf[MAX_MSGS+1] = {0};
  144. rt_ssize_t ret = RT_EOK;
  145. for (int var = 0; var < MAX_MSGS + 1; ++var)
  146. {
  147. ret = rt_mq_recv(testmq, &recv_buf[var], sizeof(recv_buf[0]), RT_WAITING_FOREVER);
  148. uassert_true(ret >= 0);
  149. uassert_true(recv_buf[var] == (var + 1));
  150. }
  151. for (int var = 0; var < 3; ++var)
  152. {
  153. ret = rt_mq_recv(testmq, &recv_buf[var], sizeof(recv_buf[0]), RT_WAITING_FOREVER);
  154. uassert_true(ret >= 0);
  155. uassert_true(recv_buf[var] == (var + 1));
  156. }
  157. #ifdef RT_USING_MESSAGEQUEUE_PRIORITY
  158. rt_int32_t msg_prio;
  159. while (testmq->entry == MAX_MSGS)
  160. {
  161. rt_thread_delay(100);
  162. }
  163. for (int var = 0; var < MAX_MSGS; ++var)
  164. {
  165. ret = rt_mq_recv_prio(testmq, &recv_buf[var], sizeof(recv_buf[0]), &msg_prio, RT_WAITING_FOREVER, RT_UNINTERRUPTIBLE);
  166. rt_kprintf("msg_prio = %d\r\n", msg_prio);
  167. uassert_true(ret >= 0);
  168. uassert_true(recv_buf[var] == (MAX_MSGS - var));
  169. }
  170. #endif
  171. }
  172. static void mq_recv_entry(void *param)
  173. {
  174. mq_recv_case(&static_mq);
  175. #ifdef RT_USING_HEAP
  176. if(dynamic_mq != RT_NULL)
  177. {
  178. mq_recv_case(dynamic_mq);
  179. }
  180. #endif /* RT_USING_HEAP */
  181. rt_event_send(&finish_e, MQRECV_FINIHS);
  182. }
  183. static void test_mq_testcase(void)
  184. {
  185. rt_thread_startup(&mq_send_thread);
  186. rt_thread_startup(&mq_recv_thread);
  187. rt_event_recv(&finish_e, MQSEND_FINISH | MQRECV_FINIHS, RT_EVENT_FLAG_AND, RT_WAITING_FOREVER, RT_NULL);
  188. }
  189. static void test_mq_detach(void)
  190. {
  191. rt_err_t ret = rt_mq_detach(&static_mq);
  192. uassert_true(ret == RT_EOK);
  193. }
  194. static void test_mq_delete(void)
  195. {
  196. #ifdef RT_USING_HEAP
  197. rt_err_t ret = rt_mq_delete(dynamic_mq);
  198. uassert_true(ret == RT_EOK);
  199. #endif /* RT_USING_HEAP */
  200. }
  201. static rt_err_t utest_tc_init(void)
  202. {
  203. rt_err_t ret ;
  204. ret = rt_thread_init(&mq_send_thread, "mq_send", mq_send_entry, RT_NULL, mq_send_stack, sizeof(mq_send_stack), 22, 20);
  205. if(ret != RT_EOK)
  206. return -RT_ERROR;
  207. ret = rt_thread_init(&mq_recv_thread, "mq_recv", mq_recv_entry, RT_NULL, mq_recv_stack, sizeof(mq_recv_stack), 23, 20);
  208. if(ret != RT_EOK)
  209. return -RT_ERROR;
  210. #ifdef RT_USING_SMP
  211. rt_thread_control(&mq_send_thread, RT_THREAD_CTRL_BIND_CPU, (void *)0);
  212. rt_thread_control(&mq_recv_thread, RT_THREAD_CTRL_BIND_CPU, (void *)0);
  213. #endif
  214. ret = rt_event_init(&finish_e, "finish", RT_IPC_FLAG_FIFO);
  215. if(ret != RT_EOK)
  216. return -RT_ERROR;
  217. return RT_EOK;
  218. }
  219. static rt_err_t utest_tc_cleanup(void)
  220. {
  221. /* wait for threads to finish */
  222. rt_thread_mdelay(100);
  223. /* detach event object */
  224. rt_event_detach(&finish_e);
  225. return RT_EOK;
  226. }
  227. static void testcase(void)
  228. {
  229. UTEST_UNIT_RUN(test_mq_init);
  230. UTEST_UNIT_RUN(test_mq_create);
  231. UTEST_UNIT_RUN(test_mq_testcase);
  232. UTEST_UNIT_RUN(test_mq_detach);
  233. UTEST_UNIT_RUN(test_mq_delete);
  234. }
  235. UTEST_TC_EXPORT(testcase, "core.messagequeue", utest_tc_init, utest_tc_cleanup, 1000);