doc: use ASCII in .texi files where UTF-8 isn't needed
[gnulib.git] / tests / test-select.h
index 1ddfda3..adf1dd4 100644 (file)
@@ -1,5 +1,5 @@
 /* Test of select() substitute.
-   Copyright (C) 2008-2011 Free Software Foundation, Inc.
+   Copyright (C) 2008-2014 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
@@ -30,7 +30,7 @@
 #include "macros.h"
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-# define WIN32_NATIVE
+# define WINDOWS_NATIVE
 #endif
 
 #ifdef HAVE_SYS_WAIT_H
@@ -84,6 +84,9 @@ open_server_socket (void)
 
   s = socket (AF_INET, SOCK_STREAM, 0);
 
+  x = 1;
+  setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
+
   memset (&ia, 0, sizeof (ia));
   ia.sin_family = AF_INET;
   inet_pton (AF_INET, "127.0.0.1", &ia.sin_addr);
@@ -94,9 +97,6 @@ open_server_socket (void)
       exit (77);
     }
 
-  x = 1;
-  setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
-
   if (listen (s, 1) < 0)
     {
       perror ("listen");
@@ -121,7 +121,7 @@ connect_to_socket (bool blocking)
 
   if (!blocking)
     {
-#ifdef WIN32_NATIVE
+#ifdef WINDOWS_NATIVE
       unsigned long iMode = 1;
       ioctl (s, FIONBIO, (char *) &iMode);
 
@@ -227,6 +227,88 @@ test_tty (select_fn my_select)
 #endif
 
 
+static int
+do_select_bad_nfd_nowait (int nfd, select_fn my_select)
+{
+  struct timeval tv0;
+  tv0.tv_sec = 0;
+  tv0.tv_usec = 0;
+  errno = 0;
+  return my_select (nfd, NULL, NULL, NULL, &tv0);
+}
+
+static void
+test_bad_nfd (select_fn my_select)
+{
+  if (do_select_bad_nfd_nowait (-1, my_select) != -1 || errno != EINVAL)
+    failed ("invalid errno after negative nfds");
+  /* Can't test FD_SETSIZE + 1 for EINVAL, since some systems allow
+     dynamically larger set size by redefining FD_SETSIZE anywhere up
+     to the actual maximum fd.  */
+  /* if (do_select_bad_nfd_nowait (FD_SETSIZE + 1, my_select) != -1 */
+  /*     || errno != EINVAL) */
+  /*   failed ("invalid errno after bogus nfds"); */
+}
+
+/* Test select(2) on invalid file descriptors.  */
+
+static int
+do_select_bad_fd (int fd, int ev, struct timeval *timeout, select_fn my_select)
+{
+  fd_set rfds, wfds, xfds;
+
+  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);
+  errno = 0;
+  return my_select (fd + 1, &rfds, &wfds, &xfds, timeout);
+  /* In this case, when fd is invalid, on some platforms, the bit for fd
+     is left alone in the fd_set, whereas on other platforms it is cleared.
+     So, don't check the bit for fd here.  */
+}
+
+static int
+do_select_bad_fd_nowait (int fd, int ev, select_fn my_select)
+{
+  struct timeval tv0;
+  tv0.tv_sec = 0;
+  tv0.tv_usec = 0;
+  return do_select_bad_fd (fd, ev, &tv0, my_select);
+}
+
+static void
+test_bad_fd (select_fn my_select)
+{
+  /* This tests fails on OSF/1 and native Windows, even with fd = 16.  */
+#if !(defined __osf__ || defined WINDOWS_NATIVE)
+  int fd;
+
+  /* On Linux, Mac OS X, *BSD, values of fd like 99 or 399 are discarded
+     by the kernel early and therefore do *not* lead to EBADF, as required
+     by POSIX.  */
+# if defined __linux__ || (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
+  fd = 16;
+# else
+  fd = 99;
+# endif
+  close (fd);
+
+  if (do_select_bad_fd_nowait (fd, SEL_IN, my_select) == 0 || errno != EBADF)
+    failed ("invalid fd among rfds");
+  if (do_select_bad_fd_nowait (fd, SEL_OUT, my_select) == 0 || errno != EBADF)
+    failed ("invalid fd among wfds");
+  if (do_select_bad_fd_nowait (fd, SEL_EXC, my_select) == 0 || errno != EBADF)
+    failed ("invalid fd among xfds");
+#endif
+}
+
+
 /* Test select(2) for unconnected nonblocking sockets.  */
 
 static void
@@ -261,7 +343,7 @@ test_connect_first (select_fn my_select)
 static void
 test_accept_first (select_fn my_select)
 {
-#ifndef WIN32_NATIVE
+#ifndef WINDOWS_NATIVE
   int s = open_server_socket ();
   struct sockaddr_in ia;
   socklen_t addrlen;
@@ -362,14 +444,16 @@ test_pipe (select_fn my_select)
 static int
 test_function (select_fn my_select)
 {
-  int result;
+  int result = 0;
 
 #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_bad_nfd, my_select, "Invalid nfd test");
+  result += test (test_bad_fd, my_select, "Invalid fd test");
+  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");