strengthen self-containedness check for sys/select.h
[gnulib.git] / tests / test-sys_select.c
1 /* Test of <sys/select.h> substitute.
2    Copyright (C) 2007, 2008 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 Bruno Haible <bruno@clisp.org>, 2007.  */
18 /* Enhanced by Paolo Bonzini, 2008.  */
19
20 #include <config.h>
21
22 #include <sys/select.h>
23
24 /* Check that the 'struct timeval' type is defined.  */
25 struct timeval t1;
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <fcntl.h>
32 #include <stdlib.h>
33 #include <stdbool.h>
34 #include <errno.h>
35 #include "sockets.h"
36
37 enum { SEL_IN = 1, SEL_OUT = 2, SEL_EXC = 4 };
38
39 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
40 # define WIN32_NATIVE
41 #endif
42
43 #ifdef WIN32_NATIVE
44 #include <io.h>
45 #define pipe(x) _pipe(x, 256, O_BINARY)
46 #endif
47 #ifdef HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif
50 #ifdef HAVE_SYS_WAIT_H
51 #include <sys/wait.h>
52 #endif
53
54 #ifndef SO_REUSEPORT
55 #define SO_REUSEPORT    SO_REUSEADDR
56 #endif
57
58 #define TEST_PORT       12345
59
60
61 /* Minimal testing infrastructure.  */
62
63 static int failures;
64
65 static void
66 failed (const char *reason)
67 {
68   if (++failures > 1)
69     printf ("  ");
70   printf ("failed (%s)\n", reason);
71 }
72
73 static int
74 test (void (*fn) (void), const char *msg)
75 {
76   failures = 0;
77   printf ("%s... ", msg);
78   fflush (stdout);
79   fn ();
80
81   if (!failures)
82     printf ("passed\n");
83
84   return failures;
85 }
86
87
88 /* Funny socket code.  */
89
90 static int
91 open_server_socket ()
92 {
93   int s, x;
94   struct sockaddr_in ia;
95
96   s = socket (AF_INET, SOCK_STREAM, 0);
97
98   memset (&ia, 0, sizeof (ia));
99   ia.sin_family = AF_INET;
100   inet_pton (AF_INET, "127.0.0.1", &ia.sin_addr);
101   ia.sin_port = htons (TEST_PORT);
102   if (bind (s, (struct sockaddr *) &ia, sizeof (ia)) < 0)
103     {
104       perror ("bind");
105       exit (77);
106     }
107
108   x = 1;
109   setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
110
111   if (listen (s, 1) < 0)
112     {
113       perror ("listen");
114       exit (77);
115     }
116
117   return s;
118 }
119
120 static int
121 connect_to_socket (int blocking)
122 {
123   int s;
124   struct sockaddr_in ia;
125
126   s = socket (AF_INET, SOCK_STREAM, 0);
127
128   memset (&ia, 0, sizeof (ia));
129   ia.sin_family = AF_INET;
130   inet_pton (AF_INET, "127.0.0.1", &ia.sin_addr);
131   ia.sin_port = htons (TEST_PORT);
132
133   if (!blocking)
134     {
135 #ifdef WIN32_NATIVE
136       unsigned long iMode = 1;
137       ioctl (s, FIONBIO, (char *) &iMode);
138  
139 #elif defined F_GETFL
140       int oldflags = fcntl (s, F_GETFL, NULL);
141  
142       if (!(oldflags & O_NONBLOCK))
143         fcntl (s, F_SETFL, oldflags | O_NONBLOCK);
144 #endif
145     }
146
147   if (connect (s, (struct sockaddr *) &ia, sizeof (ia)) < 0
148       && (blocking || errno != EINPROGRESS))
149     {
150       perror ("connect");
151       exit (77);
152     }
153
154   return s;
155 }
156
157
158 /* A slightly more convenient interface to select(2).  */
159
160 static int
161 do_select (int fd, int ev, struct timeval *tv)
162 {
163   fd_set rfds, wfds, xfds;
164   int r, rev;
165
166   FD_ZERO (&rfds);
167   FD_ZERO (&wfds);
168   FD_ZERO (&xfds);
169   if (ev & SEL_IN)
170     FD_SET (fd, &rfds);
171   if (ev & SEL_OUT)
172     FD_SET (fd, &wfds);
173   if (ev & SEL_EXC)
174     FD_SET (fd, &xfds);
175   r = select (fd + 1, &rfds, &wfds, &xfds, tv);
176   if (r < 0)
177     return r;
178
179   rev = 0;
180   if (FD_ISSET (fd, &rfds))
181     rev |= SEL_IN;
182   if (FD_ISSET (fd, &wfds))
183     rev |= SEL_OUT;
184   if (FD_ISSET (fd, &xfds))
185     rev |= SEL_EXC;
186   if (rev && r == 0)
187     failed ("select returned 0");
188   if (rev & ~ev)
189     failed ("select returned unrequested events");
190
191   return rev;
192 }
193
194 static int
195 do_select_nowait (int fd, int ev)
196 {
197   static struct timeval tv0;
198   return do_select (fd, ev, &tv0);
199 }
200
201 static int
202 do_select_wait (int fd, int ev)
203 {
204   return do_select (fd, ev, NULL);
205 }
206
207
208 /* Test poll(2) for TTYs.  */
209
210 #ifdef INTERACTIVE
211 static void
212 test_tty (void)
213 {
214   if (do_select_nowait (0, SEL_IN) != 0)
215     failed ("can read");
216   if (do_select_nowait (0, SEL_OUT) == 0)
217     failed ("cannot write");
218
219   if (do_select_wait (0, SEL_IN) == 0)
220     failed ("return with infinite timeout");
221
222   getchar ();
223   if (do_select_nowait (0, SEL_IN) != 0)
224     failed ("can read after getc");
225 }
226 #endif
227
228
229 /* Test poll(2) for unconnected nonblocking sockets.  */
230
231 static void
232 test_connect_first (void)
233 {
234   int s = open_server_socket ();
235   struct sockaddr_in ia;
236   socklen_t addrlen;
237
238   int c1, c2;
239
240   if (do_select_nowait (s, SEL_IN | SEL_EXC) != 0)
241     failed ("can read, socket not connected");
242
243   c1 = connect_to_socket (false);
244
245   if (do_select_wait (s, SEL_IN | SEL_EXC) != SEL_IN)
246     failed ("expecting readability on passive socket");
247   if (do_select_nowait (s, SEL_IN | SEL_EXC) != SEL_IN)
248     failed ("expecting readability on passive socket");
249
250   addrlen = sizeof (ia);
251   c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
252   close (s);
253   close (c1);
254   close (c2);
255 }
256
257
258 /* Test poll(2) for unconnected blocking sockets.  */
259
260 static void
261 test_accept_first (void)
262 {
263 #ifndef WIN32_NATIVE
264   int s = open_server_socket ();
265   struct sockaddr_in ia;
266   socklen_t addrlen;
267   char buf[3];
268   int c, pid;
269
270   pid = fork ();
271   if (pid < 0)
272     return;
273
274   if (pid == 0)
275     {
276       addrlen = sizeof (ia);
277       c = accept (s, (struct sockaddr *) &ia, &addrlen);
278       close (s);
279       write (c, "foo", 3);
280       read (c, buf, 3);
281       shutdown (c, SHUT_RD);
282       close (c);
283       exit (0);
284     }
285   else
286     {
287       close (s);
288       c = connect_to_socket (true);
289       if (do_select_nowait (c, SEL_OUT) != SEL_OUT)
290         failed ("cannot write after blocking connect");
291       write (c, "foo", 3);
292       wait (&pid);
293       if (do_select_wait (c, SEL_IN) != SEL_IN)
294         failed ("cannot read data left in the socket by closed process");
295       read (c, buf, 3);
296       write (c, "foo", 3);
297       close (c);
298     }
299 #endif
300 }
301
302
303 /* Common code for pipes and connected sockets.  */
304
305 static void
306 test_pair (int rd, int wd)
307 {
308   char buf[3];
309   if (do_select_wait (wd, SEL_IN | SEL_OUT | SEL_EXC) != SEL_OUT)
310     failed ("expecting writability before writing");
311   if (do_select_nowait (wd, SEL_IN | SEL_OUT | SEL_EXC) != SEL_OUT)
312     failed ("expecting writability before writing");
313
314   write (wd, "foo", 3);
315   if (do_select_wait (rd, SEL_IN) != SEL_IN)
316     failed ("expecting readability after writing");
317   if (do_select_nowait (rd, SEL_IN) != SEL_IN)
318     failed ("expecting readability after writing");
319
320   read (rd, buf, 3);
321 }
322
323
324 /* Test poll(2) on connected sockets.  */
325
326 static void
327 test_socket_pair (void)
328 {
329   struct sockaddr_in ia;
330
331   socklen_t addrlen = sizeof (ia);
332   int s = open_server_socket ();
333   int c1 = connect_to_socket (false);
334   int c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
335
336   close (s);
337
338   test_pair (c1, c2);
339   close (c1);
340   write (c2, "foo", 3);
341   close (c2);
342 }
343
344
345 /* Test poll(2) on pipes.  */
346
347 static void
348 test_pipe (void)
349 {
350   int fd[2];
351
352   pipe (fd);
353   test_pair (fd[0], fd[1]);
354   close (fd[0]);
355   close (fd[1]);
356 }
357
358
359 /* Do them all.  */
360
361 int
362 main ()
363 {
364   int result;
365
366   gl_sockets_startup (SOCKETS_1_1);
367
368 #ifdef INTERACTIVE
369   printf ("Please press Enter\n");
370   test (test_tty, "TTY");
371 #endif
372
373   result = test (test_connect_first, "Unconnected socket test");
374   result += test (test_socket_pair, "Connected sockets test");
375   result += test (test_accept_first, "General socket test with fork");
376   result += test (test_pipe, "Pipe test");
377
378   exit (result);
379 }