/* Test of select() substitute.
- Copyright (C) 2008-2010 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
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/ioctl.h>
#include <errno.h>
-enum { SEL_IN = 1, SEL_OUT = 2, SEL_EXC = 4 };
+#include "macros.h"
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
# define WIN32_NATIVE
#endif
-#ifdef WIN32_NATIVE
-#include <io.h>
-#define pipe(x) _pipe(x, 256, O_BINARY)
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
+# include <sys/wait.h>
#endif
#ifndef SO_REUSEPORT
-#define SO_REUSEPORT SO_REUSEADDR
+# define SO_REUSEPORT SO_REUSEADDR
#endif
#define TEST_PORT 12345
}
static int
-connect_to_socket (int blocking)
+connect_to_socket (bool blocking)
{
int s;
struct sockaddr_in ia;
}
-/* A slightly more convenient interface to select(2). */
+/* 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 *tv)
+do_select (int fd, int ev, struct timeval *timeout)
{
fd_set rfds, wfds, xfds;
int r, rev;
FD_SET (fd, &wfds);
if (ev & SEL_EXC)
FD_SET (fd, &xfds);
- r = select (fd + 1, &rfds, &wfds, &xfds, tv);
+ r = select (fd + 1, &rfds, &wfds, &xfds, timeout);
if (r < 0)
return r;
static int
do_select_nowait (int fd, int ev)
{
- static struct timeval tv0;
+ struct timeval tv0;
+ tv0.tv_sec = 0;
+ tv0.tv_usec = 0;
return do_select (fd, ev, &tv0);
}
}
-/* Test poll(2) for TTYs. */
+/* Test select(2) for TTYs. */
#ifdef INTERACTIVE
static void
#endif
-/* Test poll(2) for unconnected nonblocking sockets. */
+/* Test select(2) for unconnected nonblocking sockets. */
static void
test_connect_first (void)
addrlen = sizeof (ia);
c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
- close (s);
- close (c1);
- close (c2);
+ ASSERT (close (s) == 0);
+ ASSERT (close (c1) == 0);
+ ASSERT (close (c2) == 0);
}
-/* Test poll(2) for unconnected blocking sockets. */
+/* Test select(2) for unconnected blocking sockets. */
static void
test_accept_first (void)
{
addrlen = sizeof (ia);
c = accept (s, (struct sockaddr *) &ia, &addrlen);
- close (s);
- write (c, "foo", 3);
- read (c, buf, 3);
+ ASSERT (close (s) == 0);
+ ASSERT (write (c, "foo", 3) == 3);
+ ASSERT (read (c, buf, 3) == 3);
shutdown (c, SHUT_RD);
- close (c);
+ ASSERT (close (c) == 0);
exit (0);
}
else
{
- close (s);
+ ASSERT (close (s) == 0);
c = connect_to_socket (true);
if (do_select_nowait (c, SEL_OUT) != SEL_OUT)
failed ("cannot write after blocking connect");
- write (c, "foo", 3);
+ 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");
- read (c, buf, 3);
- write (c, "foo", 3);
- close (c);
+ ASSERT (read (c, buf, 3) == 3);
+ ASSERT (write (c, "foo", 3) == 3);
+ (void) close (c); /* may fail with errno = ECONNRESET */
}
#endif
}
if (do_select_nowait (wd, SEL_IN | SEL_OUT | SEL_EXC) != SEL_OUT)
failed ("expecting writability before writing");
- write (wd, "foo", 3);
+ 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");
- read (rd, buf, 3);
+ ASSERT (read (rd, buf, 3) == 3);
}
-/* Test poll(2) on connected sockets. */
+/* Test select(2) on connected sockets. */
static void
test_socket_pair (void)
int c1 = connect_to_socket (false);
int c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
- close (s);
+ ASSERT (close (s) == 0);
test_pair (c1, c2);
- close (c1);
- write (c2, "foo", 3);
- close (c2);
+ ASSERT (close (c1) == 0);
+ ASSERT (write (c2, "foo", 3) == 3);
+ (void) close (c2); /* may fail with errno = ECONNRESET */
}
-/* Test poll(2) on pipes. */
+/* Test select(2) on pipes. */
static void
test_pipe (void)
{
int fd[2];
- pipe (fd);
+ ASSERT (pipe (fd) == 0);
test_pair (fd[0], fd[1]);
- close (fd[0]);
- close (fd[1]);
+ ASSERT (close (fd[0]) == 0);
+ ASSERT (close (fd[1]) == 0);
}