test_vfs_select.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. // Copyright 2018 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdio.h>
  15. #include <unistd.h>
  16. #include <sys/fcntl.h>
  17. #include <sys/param.h>
  18. #include "unity.h"
  19. #include "soc/uart_struct.h"
  20. #include "freertos/FreeRTOS.h"
  21. #include "driver/uart.h"
  22. #include "esp_vfs.h"
  23. #include "esp_vfs_dev.h"
  24. #include "lwip/sockets.h"
  25. #include "lwip/netdb.h"
  26. #include "test_utils.h"
  27. typedef struct {
  28. int fd;
  29. int delay_ms;
  30. xSemaphoreHandle sem;
  31. } test_task_param_t;
  32. static const char message[] = "Hello world!";
  33. static int open_dummy_socket()
  34. {
  35. const struct addrinfo hints = {
  36. .ai_family = AF_INET,
  37. .ai_socktype = SOCK_DGRAM,
  38. };
  39. struct addrinfo *res = NULL;
  40. const int err = getaddrinfo("localhost", "80", &hints, &res);
  41. TEST_ASSERT_EQUAL(0, err);
  42. TEST_ASSERT_NOT_NULL(res);
  43. const int dummy_socket_fd = socket(res->ai_family, res->ai_socktype, 0);
  44. TEST_ASSERT(dummy_socket_fd >= 0);
  45. return dummy_socket_fd;
  46. }
  47. static int socket_init()
  48. {
  49. const struct addrinfo hints = {
  50. .ai_family = AF_INET,
  51. .ai_socktype = SOCK_DGRAM,
  52. };
  53. struct addrinfo *res;
  54. int err;
  55. struct sockaddr_in saddr = { 0 };
  56. int socket_fd = -1;
  57. err = getaddrinfo("localhost", "80", &hints, &res);
  58. TEST_ASSERT_EQUAL(err, 0);
  59. TEST_ASSERT_NOT_NULL(res);
  60. socket_fd = socket(res->ai_family, res->ai_socktype, 0);
  61. TEST_ASSERT(socket_fd >= 0);
  62. saddr.sin_family = PF_INET;
  63. saddr.sin_port = htons(80);
  64. saddr.sin_addr.s_addr = htonl(INADDR_ANY);
  65. err = bind(socket_fd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in));
  66. TEST_ASSERT(err >= 0);
  67. err = connect(socket_fd, res->ai_addr, res->ai_addrlen);
  68. TEST_ASSERT_EQUAL_MESSAGE(err, 0, "Socket connection failed");
  69. freeaddrinfo(res);
  70. return socket_fd;
  71. }
  72. static void uart1_init()
  73. {
  74. uart_config_t uart_config = {
  75. .baud_rate = 115200,
  76. .data_bits = UART_DATA_8_BITS,
  77. .parity = UART_PARITY_DISABLE,
  78. .stop_bits = UART_STOP_BITS_1,
  79. .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
  80. };
  81. uart_param_config(UART_NUM_1, &uart_config);
  82. uart_driver_install(UART_NUM_1, 256, 256, 0, NULL, 0);
  83. }
  84. static void send_task(void *param)
  85. {
  86. const test_task_param_t *test_task_param = param;
  87. vTaskDelay(test_task_param->delay_ms / portTICK_PERIOD_MS);
  88. write(test_task_param->fd, message, sizeof(message));
  89. if (test_task_param->sem) {
  90. xSemaphoreGive(test_task_param->sem);
  91. }
  92. vTaskDelete(NULL);
  93. }
  94. static inline void start_task(const test_task_param_t *test_task_param)
  95. {
  96. xTaskCreate(send_task, "send_task", 4*1024, (void *) test_task_param, 5, NULL);
  97. }
  98. static void init(int *uart_fd, int *socket_fd)
  99. {
  100. test_case_uses_tcpip();
  101. uart1_init();
  102. UART1.conf0.loopback = 1;
  103. *uart_fd = open("/dev/uart/1", O_RDWR);
  104. TEST_ASSERT_NOT_EQUAL_MESSAGE(*uart_fd, -1, "Cannot open UART");
  105. esp_vfs_dev_uart_use_driver(1);
  106. *socket_fd = socket_init();
  107. }
  108. static void deinit(int uart_fd, int socket_fd)
  109. {
  110. esp_vfs_dev_uart_use_nonblocking(1);
  111. close(uart_fd);
  112. UART1.conf0.loopback = 0;
  113. uart_driver_delete(UART_NUM_1);
  114. close(socket_fd);
  115. }
  116. TEST_CASE("UART can do select()", "[vfs]")
  117. {
  118. int uart_fd;
  119. int socket_fd;
  120. struct timeval tv = {
  121. .tv_sec = 0,
  122. .tv_usec = 100000,
  123. };
  124. char recv_message[sizeof(message)];
  125. init(&uart_fd, &socket_fd);
  126. fd_set rfds;
  127. FD_ZERO(&rfds);
  128. FD_SET(uart_fd, &rfds);
  129. //without socket in rfds it will not use the same signalization
  130. const test_task_param_t test_task_param = {
  131. .fd = uart_fd,
  132. .delay_ms = 50,
  133. .sem = xSemaphoreCreateBinary(),
  134. };
  135. TEST_ASSERT_NOT_NULL(test_task_param.sem);
  136. start_task(&test_task_param);
  137. int s = select(uart_fd + 1, &rfds, NULL, NULL, &tv);
  138. TEST_ASSERT_EQUAL(s, 1);
  139. TEST_ASSERT(FD_ISSET(uart_fd, &rfds));
  140. TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rfds));
  141. int read_bytes = read(uart_fd, recv_message, sizeof(message));
  142. TEST_ASSERT_EQUAL(read_bytes, sizeof(message));
  143. TEST_ASSERT_EQUAL_MEMORY(message, recv_message, sizeof(message));
  144. TEST_ASSERT_EQUAL(xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS), pdTRUE);
  145. FD_ZERO(&rfds);
  146. FD_SET(uart_fd, &rfds);
  147. FD_SET(socket_fd, &rfds);
  148. start_task(&test_task_param);
  149. s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv);
  150. TEST_ASSERT_EQUAL(s, 1);
  151. TEST_ASSERT(FD_ISSET(uart_fd, &rfds));
  152. TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rfds));
  153. read_bytes = read(uart_fd, recv_message, sizeof(message));
  154. TEST_ASSERT_EQUAL(read_bytes, sizeof(message));
  155. TEST_ASSERT_EQUAL_MEMORY(message, recv_message, sizeof(message));
  156. TEST_ASSERT_EQUAL(xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS), pdTRUE);
  157. vSemaphoreDelete(test_task_param.sem);
  158. deinit(uart_fd, socket_fd);
  159. }
  160. TEST_CASE("socket can do select()", "[vfs]")
  161. {
  162. int uart_fd;
  163. int socket_fd;
  164. struct timeval tv = {
  165. .tv_sec = 0,
  166. .tv_usec = 100000,
  167. };
  168. char recv_message[sizeof(message)];
  169. init(&uart_fd, &socket_fd);
  170. const int dummy_socket_fd = open_dummy_socket();
  171. fd_set rfds;
  172. FD_ZERO(&rfds);
  173. FD_SET(uart_fd, &rfds);
  174. FD_SET(socket_fd, &rfds);
  175. FD_SET(dummy_socket_fd, &rfds);
  176. const test_task_param_t test_task_param = {
  177. .fd = socket_fd,
  178. .delay_ms = 50,
  179. .sem = xSemaphoreCreateBinary(),
  180. };
  181. TEST_ASSERT_NOT_NULL(test_task_param.sem);
  182. start_task(&test_task_param);
  183. const int s = select(MAX(MAX(uart_fd, socket_fd), dummy_socket_fd) + 1, &rfds, NULL, NULL, &tv);
  184. TEST_ASSERT_EQUAL(1, s);
  185. TEST_ASSERT_UNLESS(FD_ISSET(uart_fd, &rfds));
  186. TEST_ASSERT_UNLESS(FD_ISSET(dummy_socket_fd, &rfds));
  187. TEST_ASSERT(FD_ISSET(socket_fd, &rfds));
  188. int read_bytes = read(socket_fd, recv_message, sizeof(message));
  189. TEST_ASSERT_EQUAL(read_bytes, sizeof(message));
  190. TEST_ASSERT_EQUAL_MEMORY(message, recv_message, sizeof(message));
  191. TEST_ASSERT_EQUAL(xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS), pdTRUE);
  192. vSemaphoreDelete(test_task_param.sem);
  193. deinit(uart_fd, socket_fd);
  194. close(dummy_socket_fd);
  195. }
  196. TEST_CASE("select() timeout", "[vfs]")
  197. {
  198. int uart_fd;
  199. int socket_fd;
  200. struct timeval tv = {
  201. .tv_sec = 0,
  202. .tv_usec = 100000,
  203. };
  204. init(&uart_fd, &socket_fd);
  205. fd_set rfds;
  206. FD_ZERO(&rfds);
  207. FD_SET(uart_fd, &rfds);
  208. FD_SET(socket_fd, &rfds);
  209. int s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv);
  210. TEST_ASSERT_EQUAL(s, 0);
  211. TEST_ASSERT_UNLESS(FD_ISSET(uart_fd, &rfds));
  212. TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rfds));
  213. FD_ZERO(&rfds);
  214. s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv);
  215. TEST_ASSERT_EQUAL(s, 0);
  216. TEST_ASSERT_UNLESS(FD_ISSET(uart_fd, &rfds));
  217. TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rfds));
  218. deinit(uart_fd, socket_fd);
  219. }
  220. static void select_task(void *param)
  221. {
  222. const test_task_param_t *test_task_param = param;
  223. struct timeval tv = {
  224. .tv_sec = 0,
  225. .tv_usec = 100000,
  226. };
  227. fd_set rfds;
  228. FD_ZERO(&rfds);
  229. FD_SET(test_task_param->fd, &rfds);
  230. int s = select(test_task_param->fd + 1, &rfds, NULL, NULL, &tv);
  231. TEST_ASSERT_EQUAL(0, s); //timeout
  232. if (test_task_param->sem) {
  233. xSemaphoreGive(test_task_param->sem);
  234. }
  235. vTaskDelete(NULL);
  236. }
  237. TEST_CASE("concurent selects work", "[vfs]")
  238. {
  239. struct timeval tv = {
  240. .tv_sec = 0,
  241. .tv_usec = 100000,//irrelevant
  242. };
  243. int uart_fd, socket_fd;
  244. init(&uart_fd, &socket_fd);
  245. const int dummy_socket_fd = open_dummy_socket();
  246. fd_set rfds;
  247. FD_ZERO(&rfds);
  248. FD_SET(uart_fd, &rfds);
  249. test_task_param_t test_task_param = {
  250. .fd = uart_fd,
  251. .sem = xSemaphoreCreateBinary(),
  252. };
  253. TEST_ASSERT_NOT_NULL(test_task_param.sem);
  254. xTaskCreate(select_task, "select_task", 4*1024, (void *) &test_task_param, 5, NULL);
  255. vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select()
  256. int s = select(uart_fd + 1, &rfds, NULL, NULL, &tv);
  257. TEST_ASSERT_EQUAL(-1, s); //this select should fail because two selects are accessing UART
  258. //(the other one is waiting for the timeout)
  259. TEST_ASSERT_EQUAL(EINTR, errno);
  260. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS));
  261. FD_ZERO(&rfds);
  262. FD_SET(socket_fd, &rfds);
  263. test_task_param.fd = dummy_socket_fd;
  264. xTaskCreate(select_task, "select_task", 4*1024, (void *) &test_task_param, 5, NULL);
  265. vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select()
  266. s = select(socket_fd + 1, &rfds, NULL, NULL, &tv);
  267. TEST_ASSERT_EQUAL(0, s); //this select should timeout as well as the concurrent one because
  268. //concurrent socket select should work
  269. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS));
  270. vSemaphoreDelete(test_task_param.sem);
  271. deinit(uart_fd, socket_fd);
  272. close(dummy_socket_fd);
  273. }