LCOV - code coverage report
Current view: top level - gltests - test-select.c (source / functions) Hit Total Coverage
Test: GNU SASL Lines: 122 147 83.0 %
Date: 2010-09-27 Functions: 12 13 92.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 38 60 63.3 %

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

Generated by: LCOV version 1.8