X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=tests%2Ftest-select.c;h=9c6fb9dbc74c4eae28a22d70e85212c6ab346911;hb=1aeca770e12bdc87d6cfe0e43cc2f37a910213a0;hp=4c9cdc02dc1af7435babcd49a8f55a9f24c92644;hpb=d2f1849bc5d58a288656d8346ce6111dfd93c8d7;p=gnulib.git diff --git a/tests/test-select.c b/tests/test-select.c index 4c9cdc02d..9c6fb9dbc 100644 --- a/tests/test-select.c +++ b/tests/test-select.c @@ -1,5 +1,5 @@ /* Test of select() substitute. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,357 +20,15 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sockets.h" +#include "signature.h" -enum { SEL_IN = 1, SEL_OUT = 2, SEL_EXC = 4 }; +SIGNATURE_CHECK (select, int, (int, fd_set *, fd_set *, fd_set *, + struct timeval *)); -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -# define WIN32_NATIVE -#endif - -#ifdef WIN32_NATIVE -#include -#define pipe(x) _pipe(x, 256, O_BINARY) -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifndef SO_REUSEPORT -#define SO_REUSEPORT SO_REUSEADDR -#endif - -#define TEST_PORT 12345 - - -/* Minimal testing infrastructure. */ - -static int failures; - -static void -failed (const char *reason) -{ - if (++failures > 1) - printf (" "); - printf ("failed (%s)\n", reason); -} - -static int -test (void (*fn) (void), const char *msg) -{ - failures = 0; - printf ("%s... ", msg); - fflush (stdout); - fn (); - - if (!failures) - printf ("passed\n"); - - return failures; -} - - -/* Funny socket code. */ - -static int -open_server_socket () -{ - int s, x; - struct sockaddr_in ia; - - s = socket (AF_INET, SOCK_STREAM, 0); - - memset (&ia, 0, sizeof (ia)); - ia.sin_family = AF_INET; - inet_pton (AF_INET, "127.0.0.1", &ia.sin_addr); - ia.sin_port = htons (TEST_PORT); - if (bind (s, (struct sockaddr *) &ia, sizeof (ia)) < 0) - { - perror ("bind"); - exit (77); - } - - x = 1; - setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x)); - - if (listen (s, 1) < 0) - { - perror ("listen"); - exit (77); - } - - return s; -} - -static int -connect_to_socket (int blocking) -{ - int s; - struct sockaddr_in ia; - - s = socket (AF_INET, SOCK_STREAM, 0); - - memset (&ia, 0, sizeof (ia)); - ia.sin_family = AF_INET; - inet_pton (AF_INET, "127.0.0.1", &ia.sin_addr); - ia.sin_port = htons (TEST_PORT); - - if (!blocking) - { -#ifdef WIN32_NATIVE - unsigned long iMode = 1; - ioctl (s, FIONBIO, (char *) &iMode); - -#elif defined F_GETFL - int oldflags = fcntl (s, F_GETFL, NULL); - - if (!(oldflags & O_NONBLOCK)) - fcntl (s, F_SETFL, oldflags | O_NONBLOCK); -#endif - } - - if (connect (s, (struct sockaddr *) &ia, sizeof (ia)) < 0 - && (blocking || errno != EINPROGRESS)) - { - perror ("connect"); - exit (77); - } - - return s; -} - - -/* A slightly more convenient interface to select(2). */ - -static int -do_select (int fd, int ev, struct timeval *tv) -{ - fd_set rfds, wfds, xfds; - int r, rev; - - FD_ZERO (&rfds); - FD_ZERO (&wfds); - FD_ZERO (&xfds); - if (ev & SEL_IN) - FD_SET (fd, &rfds); - if (ev & SEL_OUT) - FD_SET (fd, &wfds); - if (ev & SEL_EXC) - FD_SET (fd, &xfds); - r = select (fd + 1, &rfds, &wfds, &xfds, tv); - if (r < 0) - return r; - - rev = 0; - if (FD_ISSET (fd, &rfds)) - rev |= SEL_IN; - if (FD_ISSET (fd, &wfds)) - rev |= SEL_OUT; - if (FD_ISSET (fd, &xfds)) - rev |= SEL_EXC; - if (rev && r == 0) - failed ("select returned 0"); - if (rev & ~ev) - failed ("select returned unrequested events"); - - return rev; -} - -static int -do_select_nowait (int fd, int ev) -{ - static struct timeval tv0; - return do_select (fd, ev, &tv0); -} - -static int -do_select_wait (int fd, int ev) -{ - return do_select (fd, ev, NULL); -} - - -/* Test poll(2) for TTYs. */ - -#ifdef INTERACTIVE -static void -test_tty (void) -{ - if (do_select_nowait (0, SEL_IN) != 0) - failed ("can read"); - if (do_select_nowait (0, SEL_OUT) == 0) - failed ("cannot write"); - - if (do_select_wait (0, SEL_IN) == 0) - failed ("return with infinite timeout"); - - getchar (); - if (do_select_nowait (0, SEL_IN) != 0) - failed ("can read after getc"); -} -#endif - - -/* Test poll(2) for unconnected nonblocking sockets. */ - -static void -test_connect_first (void) -{ - int s = open_server_socket (); - struct sockaddr_in ia; - socklen_t addrlen; - - int c1, c2; - - if (do_select_nowait (s, SEL_IN | SEL_EXC) != 0) - failed ("can read, socket not connected"); - - c1 = connect_to_socket (false); - - if (do_select_wait (s, SEL_IN | SEL_EXC) != SEL_IN) - failed ("expecting readability on passive socket"); - if (do_select_nowait (s, SEL_IN | SEL_EXC) != SEL_IN) - failed ("expecting readability on passive socket"); - - addrlen = sizeof (ia); - c2 = accept (s, (struct sockaddr *) &ia, &addrlen); - close (s); - close (c1); - close (c2); -} - - -/* Test poll(2) for unconnected blocking sockets. */ - -static void -test_accept_first (void) -{ -#ifndef WIN32_NATIVE - int s = open_server_socket (); - struct sockaddr_in ia; - socklen_t addrlen; - char buf[3]; - int c, pid; - - pid = fork (); - if (pid < 0) - return; - - if (pid == 0) - { - addrlen = sizeof (ia); - c = accept (s, (struct sockaddr *) &ia, &addrlen); - close (s); - write (c, "foo", 3); - read (c, buf, 3); - shutdown (c, SHUT_RD); - close (c); - exit (0); - } - else - { - close (s); - c = connect_to_socket (true); - if (do_select_nowait (c, SEL_OUT) != SEL_OUT) - failed ("cannot write after blocking connect"); - write (c, "foo", 3); - wait (&pid); - if (do_select_wait (c, SEL_IN) != SEL_IN) - failed ("cannot read data left in the socket by closed process"); - read (c, buf, 3); - write (c, "foo", 3); - close (c); - } -#endif -} - - -/* Common code for pipes and connected sockets. */ - -static void -test_pair (int rd, int wd) -{ - char buf[3]; - if (do_select_wait (wd, SEL_IN | SEL_OUT | SEL_EXC) != SEL_OUT) - failed ("expecting writability before writing"); - if (do_select_nowait (wd, SEL_IN | SEL_OUT | SEL_EXC) != SEL_OUT) - failed ("expecting writability before writing"); - - write (wd, "foo", 3); - if (do_select_wait (rd, SEL_IN) != SEL_IN) - failed ("expecting readability after writing"); - if (do_select_nowait (rd, SEL_IN) != SEL_IN) - failed ("expecting readability after writing"); - - read (rd, buf, 3); -} - - -/* Test poll(2) on connected sockets. */ - -static void -test_socket_pair (void) -{ - struct sockaddr_in ia; - - socklen_t addrlen = sizeof (ia); - int s = open_server_socket (); - int c1 = connect_to_socket (false); - int c2 = accept (s, (struct sockaddr *) &ia, &addrlen); - - close (s); - - test_pair (c1, c2); - close (c1); - write (c2, "foo", 3); - close (c2); -} - - -/* Test poll(2) on pipes. */ - -static void -test_pipe (void) -{ - int fd[2]; - - pipe (fd); - test_pair (fd[0], fd[1]); - close (fd[0]); - close (fd[1]); -} - - -/* Do them all. */ +#include "test-select.h" int -main () +main (void) { - int result; - - gl_sockets_startup (SOCKETS_1_1); - -#ifdef INTERACTIVE - printf ("Please press Enter\n"); - test (test_tty, "TTY"); -#endif - - result = test (test_connect_first, "Unconnected socket test"); - result += test (test_socket_pair, "Connected sockets test"); - result += test (test_accept_first, "General socket test with fork"); - result += test (test_pipe, "Pipe test"); - - exit (result); + return test_function (select); }