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