root/maint/gnulib/tests/test-poll.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. failed
  2. test
  3. open_server_socket
  4. connect_to_socket
  5. poll1
  6. poll1_nowait
  7. poll1_wait
  8. test_tty
  9. test_connect_first
  10. test_accept_first
  11. test_pair
  12. test_socket_pair
  13. test_pipe
  14. main

   1 /* Test of poll() function.
   2    Copyright (C) 2008-2021 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, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Paolo Bonzini.  */
  18 
  19 #include <config.h>
  20 
  21 /* Specification.  */
  22 #include <poll.h>
  23 
  24 #include "signature.h"
  25 SIGNATURE_CHECK (poll, int, (struct pollfd[], nfds_t, int));
  26 
  27 #include <stdio.h>
  28 #include <string.h>
  29 #include <sys/socket.h>
  30 #include <netinet/in.h>
  31 #include <arpa/inet.h>
  32 #include <fcntl.h>
  33 #include <stdlib.h>
  34 #include <stdbool.h>
  35 #include <sys/ioctl.h>
  36 #include <errno.h>
  37 
  38 #include "macros.h"
  39 
  40 #if defined _WIN32 && ! defined __CYGWIN__
  41 # define WINDOWS_NATIVE
  42 #endif
  43 
  44 #ifdef WINDOWS_NATIVE
  45 #include <io.h>
  46 #define pipe(x) _pipe(x, 256, O_BINARY)
  47 #endif
  48 #ifdef HAVE_UNISTD_H
  49 #include <unistd.h>
  50 #endif
  51 #ifdef HAVE_SYS_WAIT_H
  52 #include <sys/wait.h>
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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 ()
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90   int s, x;
  91   struct sockaddr_in ia;
  92 
  93   s = socket (AF_INET, SOCK_STREAM, 0);
  94 
  95   x = 1;
  96   setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
  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   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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 WINDOWS_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 poll(2).  */
 156 
 157 static int
 158 poll1 (int fd, int ev, int time)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160   struct pollfd pfd;
 161   int r;
 162 
 163   pfd.fd = fd;
 164   pfd.events = ev;
 165   pfd.revents = -1;
 166   r = poll (&pfd, 1, time);
 167   if (r < 0)
 168     return r;
 169 
 170   if (pfd.revents & ~(POLLHUP | POLLERR | POLLNVAL | ev))
 171     failed ("invalid flag combination (unrequested events)");
 172 
 173   return pfd.revents;
 174 }
 175 
 176 static int
 177 poll1_nowait (int fd, int ev)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179   return poll1 (fd, ev, 0);
 180 }
 181 
 182 static int
 183 poll1_wait (int fd, int ev)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185   return poll1 (fd, ev, -1);
 186 }
 187 
 188 
 189 /* Test poll(2) for TTYs.  */
 190 
 191 #ifdef INTERACTIVE
 192 static void
 193 test_tty (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 194 {
 195   if (poll1_nowait (0, POLLIN | POLLRDNORM) != 0)
 196     failed ("can read");
 197   if (poll1_nowait (0, POLLOUT) == 0)
 198     failed ("cannot write");
 199 
 200   if (poll1_wait (0, POLLIN | POLLRDNORM) == 0)
 201     failed ("return with infinite timeout");
 202 
 203   getchar ();
 204   if (poll1_nowait (0, POLLIN | POLLRDNORM) != 0)
 205     failed ("can read after getc");
 206 }
 207 #endif
 208 
 209 
 210 /* Test poll(2) for unconnected nonblocking sockets.  */
 211 
 212 static void
 213 test_connect_first (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 214 {
 215   int s = open_server_socket ();
 216   struct sockaddr_in ia;
 217   socklen_t addrlen;
 218 
 219   int c1, c2;
 220 
 221   if (poll1_nowait (s, POLLIN | POLLRDNORM | POLLRDBAND) != 0)
 222     failed ("can read, socket not connected");
 223 
 224   c1 = connect_to_socket (false);
 225 
 226   if (poll1_wait (s, POLLIN | POLLRDNORM | POLLRDBAND) != (POLLIN | POLLRDNORM))
 227     failed ("expecting POLLIN | POLLRDNORM on passive socket");
 228   if (poll1_nowait (s, POLLIN | POLLRDBAND) != POLLIN)
 229     failed ("expecting POLLIN on passive socket");
 230   if (poll1_nowait (s, POLLRDNORM | POLLRDBAND) != POLLRDNORM)
 231     failed ("expecting POLLRDNORM on passive socket");
 232 
 233   addrlen = sizeof (ia);
 234   c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
 235   close (s);
 236   close (c1);
 237   close (c2);
 238 }
 239 
 240 
 241 /* Test poll(2) for unconnected blocking sockets.  */
 242 
 243 static void
 244 test_accept_first (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 245 {
 246 #ifndef WINDOWS_NATIVE
 247   int s = open_server_socket ();
 248   struct sockaddr_in ia;
 249   socklen_t addrlen;
 250   char buf[3];
 251   int c, pid;
 252 
 253   pid = fork ();
 254   if (pid < 0)
 255     return;
 256 
 257   if (pid == 0)
 258     {
 259       addrlen = sizeof (ia);
 260       c = accept (s, (struct sockaddr *) &ia, &addrlen);
 261       ASSERT (c >= 0);
 262       close (s);
 263       ASSERT (write (c, "foo", 3) == 3);
 264       ASSERT (read (c, buf, 3) == 3);
 265       shutdown (c, SHUT_RD);
 266       close (c);
 267       exit (0);
 268     }
 269   else
 270     {
 271       close (s);
 272       c = connect_to_socket (true);
 273       ASSERT (c >= 0);
 274       if (poll1_nowait (c, POLLOUT | POLLWRNORM | POLLRDBAND)
 275           != (POLLOUT | POLLWRNORM))
 276         failed ("cannot write after blocking connect");
 277       ASSERT (write (c, "foo", 3) == 3);
 278       wait (&pid);
 279       if (poll1_wait (c, POLLIN) != POLLIN)
 280         failed ("cannot read data left in the socket by closed process");
 281       ASSERT (read (c, buf, 3) == 3);
 282       ASSERT (write (c, "foo", 3) == 3);
 283       int revents = poll1_wait (c, POLLIN | POLLOUT);
 284 # ifdef __linux__
 285       if ((revents & (POLLHUP | POLLERR)) == 0)
 286         failed ("expecting POLLHUP after shutdown");
 287 # else
 288       (void) revents;
 289 # endif
 290       close (c);
 291     }
 292 #endif
 293 }
 294 
 295 
 296 /* Common code for pipes and connected sockets.  */
 297 
 298 static void
 299 test_pair (int rd, int wd)
     /* [previous][next][first][last][top][bottom][index][help] */
 300 {
 301   char buf[3];
 302   if (poll1_wait (wd, POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND)
 303       != (POLLOUT | POLLWRNORM))
 304     failed ("expecting POLLOUT | POLLWRNORM before writing");
 305   if (poll1_nowait (wd, POLLIN | POLLRDNORM | POLLOUT | POLLRDBAND) != POLLOUT)
 306     failed ("expecting POLLOUT before writing");
 307   if (poll1_nowait (wd, POLLIN | POLLRDNORM | POLLWRNORM | POLLRDBAND)
 308       != POLLWRNORM)
 309     failed ("expecting POLLWRNORM before writing");
 310 
 311   ASSERT (write (wd, "foo", 3) == 3);
 312   if (poll1_wait (rd, POLLIN | POLLRDNORM) != (POLLIN | POLLRDNORM))
 313     failed ("expecting POLLIN | POLLRDNORM after writing");
 314   if (poll1_nowait (rd, POLLIN) != POLLIN)
 315     failed ("expecting POLLIN after writing");
 316   if (poll1_nowait (rd, POLLRDNORM) != POLLRDNORM)
 317     failed ("expecting POLLRDNORM after writing");
 318 
 319   ASSERT (read (rd, buf, 3) == 3);
 320 }
 321 
 322 
 323 /* Test poll(2) on connected sockets.  */
 324 
 325 static void
 326 test_socket_pair (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 327 {
 328   struct sockaddr_in ia;
 329 
 330   socklen_t addrlen = sizeof (ia);
 331   int s = open_server_socket ();
 332   int c1 = connect_to_socket (false);
 333   int c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
 334   ASSERT (s >= 0);
 335   ASSERT (c1 >= 0);
 336   ASSERT (c2 >= 0);
 337 
 338   close (s);
 339 
 340   test_pair (c1, c2);
 341   close (c1);
 342   ASSERT (write (c2, "foo", 3) == 3);
 343   int revents = poll1_nowait (c2, POLLIN | POLLOUT);
 344 #ifdef __linux__
 345   if ((revents & (POLLHUP | POLLERR)) == 0)
 346     failed ("expecting POLLHUP after shutdown");
 347 #else
 348   (void) revents;
 349 #endif
 350 
 351   close (c2);
 352 }
 353 
 354 
 355 /* Test poll(2) on pipes.  */
 356 
 357 static void
 358 test_pipe (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 359 {
 360   int fd[2];
 361 
 362   ASSERT (pipe (fd) >= 0);
 363   test_pair (fd[0], fd[1]);
 364   close (fd[0]);
 365   int revents = poll1_wait (fd[1], POLLIN | POLLOUT);
 366 #if !defined _AIX
 367   if ((revents & (POLLHUP | POLLERR)) == 0)
 368     failed ("expecting POLLHUP after shutdown");
 369 #else
 370   (void) revents;
 371 #endif
 372 
 373   close (fd[1]);
 374 }
 375 
 376 
 377 /* Do them all.  */
 378 
 379 int
 380 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
 381 {
 382   int result;
 383 
 384 #ifdef INTERACTIVE
 385   printf ("Please press Enter\n");
 386   test (test_tty, "TTY");
 387 #endif
 388 
 389   result = test (test_connect_first, "Unconnected socket test");
 390   result += test (test_socket_pair, "Connected sockets test");
 391   result += test (test_accept_first, "General socket test with fork");
 392   result += test (test_pipe, "Pipe test");
 393 
 394   exit (result);
 395 }

/* [previous][next][first][last][top][bottom][index][help] */