PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/gnulib-tests/test-select.h

https://bitbucket.org/vaporoid/coreutils
C Header | 461 lines | 323 code | 90 blank | 48 comment | 97 complexity | 7a356c48a5f365b493398d4fca3c9bef MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0
  1. /* Test of select() substitute.
  2. Copyright (C) 2008-2012 Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. /* Written by Paolo Bonzini, 2008. */
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <netinet/in.h>
  17. #include <arpa/inet.h>
  18. #include <unistd.h>
  19. #include <fcntl.h>
  20. #include <stdlib.h>
  21. #include <stdbool.h>
  22. #include <sys/ioctl.h>
  23. #include <errno.h>
  24. #include "macros.h"
  25. #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  26. # define WINDOWS_NATIVE
  27. #endif
  28. #ifdef HAVE_SYS_WAIT_H
  29. # include <sys/wait.h>
  30. #endif
  31. #ifndef SO_REUSEPORT
  32. # define SO_REUSEPORT SO_REUSEADDR
  33. #endif
  34. #define TEST_PORT 12345
  35. typedef int (*select_fn) (int, fd_set *, fd_set *, fd_set *, struct timeval *);
  36. /* Minimal testing infrastructure. */
  37. static int failures;
  38. static void
  39. failed (const char *reason)
  40. {
  41. if (++failures > 1)
  42. printf (" ");
  43. printf ("failed (%s)\n", reason);
  44. }
  45. static int
  46. test (void (*fn) (select_fn), select_fn my_select, const char *msg)
  47. {
  48. failures = 0;
  49. printf ("%s... ", msg);
  50. fflush (stdout);
  51. fn (my_select);
  52. if (!failures)
  53. printf ("passed\n");
  54. return failures;
  55. }
  56. /* Funny socket code. */
  57. static int
  58. open_server_socket (void)
  59. {
  60. int s, x;
  61. struct sockaddr_in ia;
  62. s = socket (AF_INET, SOCK_STREAM, 0);
  63. x = 1;
  64. setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
  65. memset (&ia, 0, sizeof (ia));
  66. ia.sin_family = AF_INET;
  67. inet_pton (AF_INET, "127.0.0.1", &ia.sin_addr);
  68. ia.sin_port = htons (TEST_PORT);
  69. if (bind (s, (struct sockaddr *) &ia, sizeof (ia)) < 0)
  70. {
  71. perror ("bind");
  72. exit (77);
  73. }
  74. if (listen (s, 1) < 0)
  75. {
  76. perror ("listen");
  77. exit (77);
  78. }
  79. return s;
  80. }
  81. static int
  82. connect_to_socket (bool blocking)
  83. {
  84. int s;
  85. struct sockaddr_in ia;
  86. s = socket (AF_INET, SOCK_STREAM, 0);
  87. memset (&ia, 0, sizeof (ia));
  88. ia.sin_family = AF_INET;
  89. inet_pton (AF_INET, "127.0.0.1", &ia.sin_addr);
  90. ia.sin_port = htons (TEST_PORT);
  91. if (!blocking)
  92. {
  93. #ifdef WINDOWS_NATIVE
  94. unsigned long iMode = 1;
  95. ioctl (s, FIONBIO, (char *) &iMode);
  96. #elif defined F_GETFL
  97. int oldflags = fcntl (s, F_GETFL, NULL);
  98. if (!(oldflags & O_NONBLOCK))
  99. fcntl (s, F_SETFL, oldflags | O_NONBLOCK);
  100. #endif
  101. }
  102. if (connect (s, (struct sockaddr *) &ia, sizeof (ia)) < 0
  103. && (blocking || errno != EINPROGRESS))
  104. {
  105. perror ("connect");
  106. exit (77);
  107. }
  108. return s;
  109. }
  110. /* A slightly more convenient interface to select(2).
  111. Waits until a specific event occurs on a file descriptor FD.
  112. EV is a bit mask of events to look for:
  113. SEL_IN - input can be polled without blocking,
  114. SEL_OUT - output can be provided without blocking,
  115. SEL_EXC - an exception occurred,
  116. A maximum wait time is specified by TIMEOUT.
  117. *TIMEOUT = { 0, 0 } means to return immediately,
  118. TIMEOUT = NULL means to wait indefinitely. */
  119. enum { SEL_IN = 1, SEL_OUT = 2, SEL_EXC = 4 };
  120. static int
  121. do_select (int fd, int ev, struct timeval *timeout, select_fn my_select)
  122. {
  123. fd_set rfds, wfds, xfds;
  124. int r, rev;
  125. FD_ZERO (&rfds);
  126. FD_ZERO (&wfds);
  127. FD_ZERO (&xfds);
  128. if (ev & SEL_IN)
  129. FD_SET (fd, &rfds);
  130. if (ev & SEL_OUT)
  131. FD_SET (fd, &wfds);
  132. if (ev & SEL_EXC)
  133. FD_SET (fd, &xfds);
  134. r = my_select (fd + 1, &rfds, &wfds, &xfds, timeout);
  135. if (r < 0)
  136. return r;
  137. rev = 0;
  138. if (FD_ISSET (fd, &rfds))
  139. rev |= SEL_IN;
  140. if (FD_ISSET (fd, &wfds))
  141. rev |= SEL_OUT;
  142. if (FD_ISSET (fd, &xfds))
  143. rev |= SEL_EXC;
  144. if (rev && r == 0)
  145. failed ("select returned 0");
  146. if (rev & ~ev)
  147. failed ("select returned unrequested events");
  148. return rev;
  149. }
  150. static int
  151. do_select_nowait (int fd, int ev, select_fn my_select)
  152. {
  153. struct timeval tv0;
  154. tv0.tv_sec = 0;
  155. tv0.tv_usec = 0;
  156. return do_select (fd, ev, &tv0, my_select);
  157. }
  158. static int
  159. do_select_wait (int fd, int ev, select_fn my_select)
  160. {
  161. return do_select (fd, ev, NULL, my_select);
  162. }
  163. /* Test select(2) for TTYs. */
  164. #ifdef INTERACTIVE
  165. static void
  166. test_tty (select_fn my_select)
  167. {
  168. if (do_select_nowait (0, SEL_IN, my_select) != 0)
  169. failed ("can read");
  170. if (do_select_nowait (0, SEL_OUT, my_select) == 0)
  171. failed ("cannot write");
  172. if (do_select_wait (0, SEL_IN, my_select) == 0)
  173. failed ("return with infinite timeout");
  174. getchar ();
  175. if (do_select_nowait (0, SEL_IN, my_select) != 0)
  176. failed ("can read after getc");
  177. }
  178. #endif
  179. static int
  180. do_select_bad_nfd_nowait (int nfd, select_fn my_select)
  181. {
  182. struct timeval tv0;
  183. tv0.tv_sec = 0;
  184. tv0.tv_usec = 0;
  185. errno = 0;
  186. return my_select (nfd, NULL, NULL, NULL, &tv0);
  187. }
  188. static void
  189. test_bad_nfd (select_fn my_select)
  190. {
  191. if (do_select_bad_nfd_nowait (-1, my_select) != -1 || errno != EINVAL)
  192. failed ("invalid errno after negative nfds");
  193. /* Can't test FD_SETSIZE + 1 for EINVAL, since some systems allow
  194. dynamically larger set size by redefining FD_SETSIZE anywhere up
  195. to the actual maximum fd. */
  196. /* if (do_select_bad_nfd_nowait (FD_SETSIZE + 1, my_select) != -1 */
  197. /* || errno != EINVAL) */
  198. /* failed ("invalid errno after bogus nfds"); */
  199. }
  200. /* Test select(2) on invalid file descriptors. */
  201. static int
  202. do_select_bad_fd (int fd, int ev, struct timeval *timeout, select_fn my_select)
  203. {
  204. fd_set rfds, wfds, xfds;
  205. FD_ZERO (&rfds);
  206. FD_ZERO (&wfds);
  207. FD_ZERO (&xfds);
  208. if (ev & SEL_IN)
  209. FD_SET (fd, &rfds);
  210. if (ev & SEL_OUT)
  211. FD_SET (fd, &wfds);
  212. if (ev & SEL_EXC)
  213. FD_SET (fd, &xfds);
  214. errno = 0;
  215. return my_select (fd + 1, &rfds, &wfds, &xfds, timeout);
  216. /* In this case, when fd is invalid, on some platforms, the bit for fd
  217. is left alone in the fd_set, whereas on other platforms it is cleared.
  218. So, don't check the bit for fd here. */
  219. }
  220. static int
  221. do_select_bad_fd_nowait (int fd, int ev, select_fn my_select)
  222. {
  223. struct timeval tv0;
  224. tv0.tv_sec = 0;
  225. tv0.tv_usec = 0;
  226. return do_select_bad_fd (fd, ev, &tv0, my_select);
  227. }
  228. static void
  229. test_bad_fd (select_fn my_select)
  230. {
  231. /* This tests fails on OSF/1 and native Windows, even with fd = 16. */
  232. #if !(defined __osf__ || defined WINDOWS_NATIVE)
  233. int fd;
  234. /* On Linux, Mac OS X, *BSD, values of fd like 99 or 399 are discarded
  235. by the kernel early and therefore do *not* lead to EBADF, as required
  236. by POSIX. */
  237. # if defined __linux__ || (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
  238. fd = 16;
  239. # else
  240. fd = 99;
  241. # endif
  242. if (do_select_bad_fd_nowait (fd, SEL_IN, my_select) == 0 || errno != EBADF)
  243. failed ("invalid fd among rfds");
  244. if (do_select_bad_fd_nowait (fd, SEL_OUT, my_select) == 0 || errno != EBADF)
  245. failed ("invalid fd among wfds");
  246. if (do_select_bad_fd_nowait (fd, SEL_EXC, my_select) == 0 || errno != EBADF)
  247. failed ("invalid fd among xfds");
  248. #endif
  249. }
  250. /* Test select(2) for unconnected nonblocking sockets. */
  251. static void
  252. test_connect_first (select_fn my_select)
  253. {
  254. int s = open_server_socket ();
  255. struct sockaddr_in ia;
  256. socklen_t addrlen;
  257. int c1, c2;
  258. if (do_select_nowait (s, SEL_IN | SEL_EXC, my_select) != 0)
  259. failed ("can read, socket not connected");
  260. c1 = connect_to_socket (false);
  261. if (do_select_wait (s, SEL_IN | SEL_EXC, my_select) != SEL_IN)
  262. failed ("expecting readability on passive socket");
  263. if (do_select_nowait (s, SEL_IN | SEL_EXC, my_select) != SEL_IN)
  264. failed ("expecting readability on passive socket");
  265. addrlen = sizeof (ia);
  266. c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
  267. ASSERT (close (s) == 0);
  268. ASSERT (close (c1) == 0);
  269. ASSERT (close (c2) == 0);
  270. }
  271. /* Test select(2) for unconnected blocking sockets. */
  272. static void
  273. test_accept_first (select_fn my_select)
  274. {
  275. #ifndef WINDOWS_NATIVE
  276. int s = open_server_socket ();
  277. struct sockaddr_in ia;
  278. socklen_t addrlen;
  279. char buf[3];
  280. int c, pid;
  281. pid = fork ();
  282. if (pid < 0)
  283. return;
  284. if (pid == 0)
  285. {
  286. addrlen = sizeof (ia);
  287. c = accept (s, (struct sockaddr *) &ia, &addrlen);
  288. ASSERT (close (s) == 0);
  289. ASSERT (write (c, "foo", 3) == 3);
  290. ASSERT (read (c, buf, 3) == 3);
  291. shutdown (c, SHUT_RD);
  292. ASSERT (close (c) == 0);
  293. exit (0);
  294. }
  295. else
  296. {
  297. ASSERT (close (s) == 0);
  298. c = connect_to_socket (true);
  299. if (do_select_nowait (c, SEL_OUT, my_select) != SEL_OUT)
  300. failed ("cannot write after blocking connect");
  301. ASSERT (write (c, "foo", 3) == 3);
  302. wait (&pid);
  303. if (do_select_wait (c, SEL_IN, my_select) != SEL_IN)
  304. failed ("cannot read data left in the socket by closed process");
  305. ASSERT (read (c, buf, 3) == 3);
  306. ASSERT (write (c, "foo", 3) == 3);
  307. (void) close (c); /* may fail with errno = ECONNRESET */
  308. }
  309. #endif
  310. }
  311. /* Common code for pipes and connected sockets. */
  312. static void
  313. test_pair (int rd, int wd, select_fn my_select)
  314. {
  315. char buf[3];
  316. if (do_select_wait (wd, SEL_IN | SEL_OUT | SEL_EXC, my_select) != SEL_OUT)
  317. failed ("expecting writability before writing");
  318. if (do_select_nowait (wd, SEL_IN | SEL_OUT | SEL_EXC, my_select) != SEL_OUT)
  319. failed ("expecting writability before writing");
  320. ASSERT (write (wd, "foo", 3) == 3);
  321. if (do_select_wait (rd, SEL_IN, my_select) != SEL_IN)
  322. failed ("expecting readability after writing");
  323. if (do_select_nowait (rd, SEL_IN, my_select) != SEL_IN)
  324. failed ("expecting readability after writing");
  325. ASSERT (read (rd, buf, 3) == 3);
  326. }
  327. /* Test select(2) on connected sockets. */
  328. static void
  329. test_socket_pair (select_fn my_select)
  330. {
  331. struct sockaddr_in ia;
  332. socklen_t addrlen = sizeof (ia);
  333. int s = open_server_socket ();
  334. int c1 = connect_to_socket (false);
  335. int c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
  336. ASSERT (close (s) == 0);
  337. test_pair (c1, c2, my_select);
  338. ASSERT (close (c1) == 0);
  339. ASSERT (write (c2, "foo", 3) == 3);
  340. (void) close (c2); /* may fail with errno = ECONNRESET */
  341. }
  342. /* Test select(2) on pipes. */
  343. static void
  344. test_pipe (select_fn my_select)
  345. {
  346. int fd[2];
  347. ASSERT (pipe (fd) == 0);
  348. test_pair (fd[0], fd[1], my_select);
  349. ASSERT (close (fd[0]) == 0);
  350. ASSERT (close (fd[1]) == 0);
  351. }
  352. /* Do them all. */
  353. static int
  354. test_function (select_fn my_select)
  355. {
  356. int result = 0;
  357. #ifdef INTERACTIVE
  358. printf ("Please press Enter\n");
  359. test (test_tty, "TTY", my_select);
  360. #endif
  361. result += test (test_bad_nfd, my_select, "Invalid nfd test");
  362. result += test (test_bad_fd, my_select, "Invalid fd test");
  363. result += test (test_connect_first, my_select, "Unconnected socket test");
  364. result += test (test_socket_pair, my_select, "Connected sockets test");
  365. result += test (test_accept_first, my_select, "General socket test with fork");
  366. result += test (test_pipe, my_select, "Pipe test");
  367. return result;
  368. }