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