From 466449b04ceeb8c245a7e364f9c2c812a5259c8f Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 23 Jul 2011 22:43:38 +0200 Subject: [PATCH] select tests, pselect tests: Refactor. * tests/test-select.h: New file, extracted from tests/test-select.c. (select_fn): New type. (test, do_select, do_select_nowait, do_select_wait, test_tty, test_connect_first, test_accept_first, test_pair, test_socket_pair, test_pipe): Add my_select argument. (test_function): Renamed from main. Add my_select argument. * tests/test-select.c: Move most code to tests/test-select.h. Include test-select.h. * modules/select-tests (Files): Add tests/test-select.h. * tests/test-pselect.c: Include test-select.h instead of test-select.c. (my_select, main): New functions. * modules/pselect-tests (Files): Add tests/test-select.h, tests/macros.h, tests/signature.h. (Depends-on): Remove select-tests. Add dependencies of test-select.h. (configure.ac): Check for . --- ChangeLog | 19 +++ modules/pselect-tests | 23 ++- modules/select-tests | 1 + tests/test-pselect.c | 50 +++++- tests/test-select.c | 373 +---------------------------------------- tests/test-select.h | 378 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 470 insertions(+), 374 deletions(-) create mode 100644 tests/test-select.h diff --git a/ChangeLog b/ChangeLog index 137a9fb7bb..31c894857c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2011-07-22 Bruno Haible + + select tests, pselect tests: Refactor. + * tests/test-select.h: New file, extracted from tests/test-select.c. + (select_fn): New type. + (test, do_select, do_select_nowait, do_select_wait, test_tty, + test_connect_first, test_accept_first, test_pair, test_socket_pair, + test_pipe): Add my_select argument. + (test_function): Renamed from main. Add my_select argument. + * tests/test-select.c: Move most code to tests/test-select.h. Include + test-select.h. + * modules/select-tests (Files): Add tests/test-select.h. + * tests/test-pselect.c: Include test-select.h instead of test-select.c. + (my_select, main): New functions. + * modules/pselect-tests (Files): Add tests/test-select.h, + tests/macros.h, tests/signature.h. + (Depends-on): Remove select-tests. Add dependencies of test-select.h. + (configure.ac): Check for . + 2011-07-22 Bruno Haible sys_select tests: Check the signature of FD_*. diff --git a/modules/pselect-tests b/modules/pselect-tests index a5fd9ff08b..0dccb3634d 100644 --- a/modules/pselect-tests +++ b/modules/pselect-tests @@ -1,10 +1,31 @@ Files: tests/test-pselect.c +tests/test-select.h +tests/macros.h +tests/signature.h Depends-on: -select-tests +stdbool +netinet_in +arpa_inet +unistd +sys_ioctl +extensions +inet_pton +errno +perror +pipe-posix +socket +bind +setsockopt +listen +connect +accept +ioctl +close configure.ac: +AC_CHECK_HEADERS_ONCE([sys/wait.h]) Makefile.am: TESTS += test-pselect diff --git a/modules/select-tests b/modules/select-tests index 52e34523d8..a3b13db2d5 100644 --- a/modules/select-tests +++ b/modules/select-tests @@ -2,6 +2,7 @@ Files: tests/macros.h tests/signature.h tests/test-select.c +tests/test-select.h tests/test-select-fd.c tests/test-select-in.sh tests/test-select-out.sh diff --git a/tests/test-pselect.c b/tests/test-pselect.c index 1d80fe09fc..4cf9181c62 100644 --- a/tests/test-pselect.c +++ b/tests/test-pselect.c @@ -1,2 +1,48 @@ -#define TEST_PSELECT -#include "test-select.c" +/* Test of pselect() substitute. + Copyright (C) 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 + 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 . */ + +#include + +#include + +#include "signature.h" + +SIGNATURE_CHECK (pselect, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timespec const *restrict, const sigset_t *restrict)); + +#include "test-select.h" + +static int +my_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + struct timespec ts; + struct timespec *pts = NULL; + if (timeout) + { + ts.tv_sec = timeout->tv_sec; + ts.tv_nsec = timeout->tv_usec * 1000; + pts = &ts; + } + return pselect (nfds, readfds, writefds, exceptfds, pts, NULL); +} + +int +main (void) +{ + return test_function (my_select); +} diff --git a/tests/test-select.c b/tests/test-select.c index 47d775919e..9c6fb9dbc7 100644 --- a/tests/test-select.c +++ b/tests/test-select.c @@ -22,382 +22,13 @@ #include "signature.h" -#ifdef TEST_PSELECT -SIGNATURE_CHECK (pselect, int, - (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, - struct timespec const *restrict, const sigset_t *restrict)); -#else SIGNATURE_CHECK (select, int, (int, fd_set *, fd_set *, fd_set *, struct timeval *)); -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "macros.h" - -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -# define WIN32_NATIVE -#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 (void) -{ - 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 (bool 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). - Waits until a specific event occurs on a file descriptor FD. - EV is a bit mask of events to look for: - SEL_IN - input can be polled without blocking, - SEL_OUT - output can be provided without blocking, - SEL_EXC - an exception occurred, - A maximum wait time is specified by TIMEOUT. - *TIMEOUT = { 0, 0 } means to return immediately, - TIMEOUT = NULL means to wait indefinitely. */ - -enum { SEL_IN = 1, SEL_OUT = 2, SEL_EXC = 4 }; - -static int -do_select (int fd, int ev, struct timeval *timeout) -{ - 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); -#ifdef TEST_PSELECT - { - struct timespec ts, *pts = NULL; - if (timeout) - { - ts.tv_sec = timeout->tv_sec; - ts.tv_nsec = timeout->tv_usec * 1000; - pts = &ts; - } - r = pselect (fd + 1, &rfds, &wfds, &xfds, pts, NULL); - } -#else - r = select (fd + 1, &rfds, &wfds, &xfds, timeout); -#endif - 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) -{ - struct timeval tv0; - tv0.tv_sec = 0; - tv0.tv_usec = 0; - return do_select (fd, ev, &tv0); -} - -static int -do_select_wait (int fd, int ev) -{ - return do_select (fd, ev, NULL); -} - - -/* Test select(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 select(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); - ASSERT (close (s) == 0); - ASSERT (close (c1) == 0); - ASSERT (close (c2) == 0); -} - - -/* Test select(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); - ASSERT (close (s) == 0); - ASSERT (write (c, "foo", 3) == 3); - ASSERT (read (c, buf, 3) == 3); - shutdown (c, SHUT_RD); - ASSERT (close (c) == 0); - exit (0); - } - else - { - ASSERT (close (s) == 0); - c = connect_to_socket (true); - if (do_select_nowait (c, SEL_OUT) != SEL_OUT) - failed ("cannot write after blocking connect"); - ASSERT (write (c, "foo", 3) == 3); - wait (&pid); - if (do_select_wait (c, SEL_IN) != SEL_IN) - failed ("cannot read data left in the socket by closed process"); - ASSERT (read (c, buf, 3) == 3); - ASSERT (write (c, "foo", 3) == 3); - (void) close (c); /* may fail with errno = ECONNRESET */ - } -#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"); - - ASSERT (write (wd, "foo", 3) == 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"); - - ASSERT (read (rd, buf, 3) == 3); -} - - -/* Test select(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); - - ASSERT (close (s) == 0); - - test_pair (c1, c2); - ASSERT (close (c1) == 0); - ASSERT (write (c2, "foo", 3) == 3); - (void) close (c2); /* may fail with errno = ECONNRESET */ -} - - -/* Test select(2) on pipes. */ - -static void -test_pipe (void) -{ - int fd[2]; - - ASSERT (pipe (fd) == 0); - test_pair (fd[0], fd[1]); - ASSERT (close (fd[0]) == 0); - ASSERT (close (fd[1]) == 0); -} - - -/* Do them all. */ +#include "test-select.h" int main (void) { - int result; - -#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); } diff --git a/tests/test-select.h b/tests/test-select.h new file mode 100644 index 0000000000..88abe17821 --- /dev/null +++ b/tests/test-select.h @@ -0,0 +1,378 @@ +/* Test of select() substitute. + 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 + 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 "macros.h" + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define WIN32_NATIVE +#endif + +#ifdef HAVE_SYS_WAIT_H +# include +#endif + +#ifndef SO_REUSEPORT +# define SO_REUSEPORT SO_REUSEADDR +#endif + +#define TEST_PORT 12345 + + +typedef int (*select_fn) (int, fd_set *, fd_set *, fd_set *, struct timeval *); + + +/* 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) (select_fn), select_fn my_select, const char *msg) +{ + failures = 0; + printf ("%s... ", msg); + fflush (stdout); + fn (my_select); + + if (!failures) + printf ("passed\n"); + + return failures; +} + + +/* Funny socket code. */ + +static int +open_server_socket (void) +{ + 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 (bool 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). + Waits until a specific event occurs on a file descriptor FD. + EV is a bit mask of events to look for: + SEL_IN - input can be polled without blocking, + SEL_OUT - output can be provided without blocking, + SEL_EXC - an exception occurred, + A maximum wait time is specified by TIMEOUT. + *TIMEOUT = { 0, 0 } means to return immediately, + TIMEOUT = NULL means to wait indefinitely. */ + +enum { SEL_IN = 1, SEL_OUT = 2, SEL_EXC = 4 }; + +static int +do_select (int fd, int ev, struct timeval *timeout, select_fn my_select) +{ + 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 = my_select (fd + 1, &rfds, &wfds, &xfds, timeout); + 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, select_fn my_select) +{ + struct timeval tv0; + tv0.tv_sec = 0; + tv0.tv_usec = 0; + return do_select (fd, ev, &tv0, my_select); +} + +static int +do_select_wait (int fd, int ev, select_fn my_select) +{ + return do_select (fd, ev, NULL, my_select); +} + + +/* Test select(2) for TTYs. */ + +#ifdef INTERACTIVE +static void +test_tty (select_fn my_select) +{ + if (do_select_nowait (0, SEL_IN, my_select) != 0) + failed ("can read"); + if (do_select_nowait (0, SEL_OUT, my_select) == 0) + failed ("cannot write"); + + if (do_select_wait (0, SEL_IN, my_select) == 0) + failed ("return with infinite timeout"); + + getchar (); + if (do_select_nowait (0, SEL_IN, my_select) != 0) + failed ("can read after getc"); +} +#endif + + +/* Test select(2) for unconnected nonblocking sockets. */ + +static void +test_connect_first (select_fn my_select) +{ + int s = open_server_socket (); + struct sockaddr_in ia; + socklen_t addrlen; + + int c1, c2; + + if (do_select_nowait (s, SEL_IN | SEL_EXC, my_select) != 0) + failed ("can read, socket not connected"); + + c1 = connect_to_socket (false); + + if (do_select_wait (s, SEL_IN | SEL_EXC, my_select) != SEL_IN) + failed ("expecting readability on passive socket"); + if (do_select_nowait (s, SEL_IN | SEL_EXC, my_select) != SEL_IN) + failed ("expecting readability on passive socket"); + + addrlen = sizeof (ia); + c2 = accept (s, (struct sockaddr *) &ia, &addrlen); + ASSERT (close (s) == 0); + ASSERT (close (c1) == 0); + ASSERT (close (c2) == 0); +} + + +/* Test select(2) for unconnected blocking sockets. */ + +static void +test_accept_first (select_fn my_select) +{ +#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); + ASSERT (close (s) == 0); + ASSERT (write (c, "foo", 3) == 3); + ASSERT (read (c, buf, 3) == 3); + shutdown (c, SHUT_RD); + ASSERT (close (c) == 0); + exit (0); + } + else + { + ASSERT (close (s) == 0); + c = connect_to_socket (true); + if (do_select_nowait (c, SEL_OUT, my_select) != SEL_OUT) + failed ("cannot write after blocking connect"); + ASSERT (write (c, "foo", 3) == 3); + wait (&pid); + if (do_select_wait (c, SEL_IN, my_select) != SEL_IN) + failed ("cannot read data left in the socket by closed process"); + ASSERT (read (c, buf, 3) == 3); + ASSERT (write (c, "foo", 3) == 3); + (void) close (c); /* may fail with errno = ECONNRESET */ + } +#endif +} + + +/* Common code for pipes and connected sockets. */ + +static void +test_pair (int rd, int wd, select_fn my_select) +{ + char buf[3]; + if (do_select_wait (wd, SEL_IN | SEL_OUT | SEL_EXC, my_select) != SEL_OUT) + failed ("expecting writability before writing"); + if (do_select_nowait (wd, SEL_IN | SEL_OUT | SEL_EXC, my_select) != SEL_OUT) + failed ("expecting writability before writing"); + + ASSERT (write (wd, "foo", 3) == 3); + if (do_select_wait (rd, SEL_IN, my_select) != SEL_IN) + failed ("expecting readability after writing"); + if (do_select_nowait (rd, SEL_IN, my_select) != SEL_IN) + failed ("expecting readability after writing"); + + ASSERT (read (rd, buf, 3) == 3); +} + + +/* Test select(2) on connected sockets. */ + +static void +test_socket_pair (select_fn my_select) +{ + 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); + + ASSERT (close (s) == 0); + + test_pair (c1, c2, my_select); + ASSERT (close (c1) == 0); + ASSERT (write (c2, "foo", 3) == 3); + (void) close (c2); /* may fail with errno = ECONNRESET */ +} + + +/* Test select(2) on pipes. */ + +static void +test_pipe (select_fn my_select) +{ + int fd[2]; + + ASSERT (pipe (fd) == 0); + test_pair (fd[0], fd[1], my_select); + ASSERT (close (fd[0]) == 0); + ASSERT (close (fd[1]) == 0); +} + + +/* Do them all. */ + +int +test_function (select_fn my_select) +{ + int result; + +#ifdef INTERACTIVE + printf ("Please press Enter\n"); + test (test_tty, "TTY", my_select); +#endif + + result = test (test_connect_first, my_select, "Unconnected socket test"); + result += test (test_socket_pair, my_select, "Connected sockets test"); + result += test (test_accept_first, my_select, "General socket test with fork"); + result += test (test_pipe, my_select, "Pipe test"); + + return result; +} -- 2.30.2