From: Bruno Haible Date: Sun, 5 Oct 2008 15:30:02 +0000 (+0200) Subject: Split sys_select-tests module into select-tests and sys_select-tests. X-Git-Tag: v0.1~6895 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=6f49a1f423ec8069604c2a335f19c3cad6b3de14;p=gnulib.git Split sys_select-tests module into select-tests and sys_select-tests. --- diff --git a/ChangeLog b/ChangeLog index e713ca7d6..3bac4c3fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,26 @@ 2008-10-05 Bruno Haible + * modules/select-tests: New file, mostly copied from + modules/sys_select-tests. + * tests/test-select.c: New file, mostly copied from + tests/test-sys_select.c. + * tests/test-sys_select.c: Move most of the code to tests/test-select.c. + * modules/sys_select-tests (Depends-on): Remove all dependencies. + (Makefile.am): Remove test_sys_select_LDADD. + + * lib/sys_select.in.h (select): If GNULIB_SELECT is not set, define it + to an undefined symbol, for an error message. + * m4/sys_select_h.m4 (gl_SYS_SELECT_MODULE_INDICATOR): New macro. + (gl_SYS_SELECT_H_DEFAULTS): New macro. + (gl_HEADER_SYS_SELECT): Require it. Don't require compilation of + winsock-select.c here. + * modules/sys_select (Files): Remove lib/winsock-select.c. + (Depends-on): Remove alloca. + (Makefile.am): Substitute GNULIB_SELECT. + * modules/select: New file. + +2008-10-05 Bruno Haible + * lib/spawn_faction_addclose.c (__sysconf): Use getdtablesize always. * lib/spawn_faction_adddup2.c (__sysconf): Likewise. * lib/spawn_faction_addopen.c (__sysconf): Likewise. diff --git a/modules/select-tests b/modules/select-tests new file mode 100644 index 000000000..2285033d1 --- /dev/null +++ b/modules/select-tests @@ -0,0 +1,22 @@ +Files: +tests/test-select.c + +Depends-on: +stdbool +netinet_in +arpa_inet +extensions +inet_pton +errno +perror +sockets + +configure.ac: + +Makefile.am: +TESTS += test-select +check_PROGRAMS += test-select +test_select_LDADD = $(LDADD) @LIBSOCKET@ + +License: +LGPL diff --git a/modules/sys_select-tests b/modules/sys_select-tests index 7520ee301..a07d40a38 100644 --- a/modules/sys_select-tests +++ b/modules/sys_select-tests @@ -2,21 +2,12 @@ Files: tests/test-sys_select.c Depends-on: -stdbool -netinet_in -arpa_inet -extensions -inet_pton -errno -perror -sockets configure.ac: Makefile.am: TESTS += test-sys_select check_PROGRAMS += test-sys_select -test_sys_select_LDADD = $(LDADD) @LIBSOCKET@ License: LGPL diff --git a/tests/test-select.c b/tests/test-select.c new file mode 100644 index 000000000..50f7559fa --- /dev/null +++ b/tests/test-select.c @@ -0,0 +1,375 @@ +/* Test of select() substitute. + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paolo Bonzini, 2008. */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sockets.h" + +enum { SEL_IN = 1, SEL_OUT = 2, SEL_EXC = 4 }; + +#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. */ + +int +main () +{ + 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); +} diff --git a/tests/test-sys_select.c b/tests/test-sys_select.c index a4e0f3e58..6449dafde 100644 --- a/tests/test-sys_select.c +++ b/tests/test-sys_select.c @@ -1,5 +1,5 @@ /* Test of substitute. - Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2007-2008 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 @@ -15,7 +15,6 @@ along with this program. If not, see . */ /* Written by Bruno Haible , 2007. */ -/* Enhanced by Paolo Bonzini, 2008. */ #include @@ -24,356 +23,8 @@ /* Check that the 'struct timeval' type is defined. */ struct timeval t1; -#include -#include -#include -#include -#include -#include -#include -#include -#include "sockets.h" - -enum { SEL_IN = 1, SEL_OUT = 2, SEL_EXC = 4 }; - -#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. */ - int main () { - 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 0; }