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