Merge commit 'a39d4083cab589d7cd6a13e8a4b8db8875261d75'
[gnulib.git] / tests / test-pipe.c
index 3018186..c951d1d 100644 (file)
@@ -1,5 +1,5 @@
-/* Test of create_pipe_bidi/wait_subprocess.
-   Copyright (C) 2009 Free Software Foundation, Inc.
+/* Test of pipe.
+   Copyright (C) 2009-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
    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, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#include "pipe.h"
-#include "wait-process.h"
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (pipe, int, (int[2]));
 
-#include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* Depending on arguments, this test intentionally closes stderr or
-   starts life with stderr closed.  So, the error messages might not
-   always print, but at least the exit status will be reliable.  */
-#define ASSERT(expr) \
-  do                                                                         \
-    {                                                                        \
-      if (!(expr))                                                           \
-        {                                                                    \
-          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
-          fflush (stderr);                                                   \
-          abort ();                                                          \
-        }                                                                    \
-    }                                                                        \
-  while (0)
 
-/* Create a bi-directional pipe to a test child, and validate that the
-   child program returns the expected output.  The child is the same
-   program as the parent ARGV0, but with different arguments.
-   STDERR_CLOSED is true if we have already closed fd 2.  */
-static void
-test_pipe (const char *argv0, bool stderr_closed)
-{
-  int fd[2];
-  const char *argv[3];
-  pid_t pid;
-  char buffer[2] = { 'a', 'a' };
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Get declarations of the native Windows API functions.  */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+/* Get _get_osfhandle.  */
+# include "msvc-nothrow.h"
+#endif
 
-  /* Set up child.  */
-  argv[0] = argv0;
-  argv[1] = stderr_closed ? "9" : "8";
-  argv[2] = NULL;
-  pid = create_pipe_bidi(argv0, argv0, (char **) argv,
-                         false, true, true, fd);
-  ASSERT (0 <= pid);
-  ASSERT (STDERR_FILENO < fd[0]);
-  ASSERT (STDERR_FILENO < fd[1]);
+#include "binary-io.h"
+#include "macros.h"
 
-  /* Push child's input.  */
-  ASSERT (write (fd[1], buffer, 1) == 1);
-
-  /* Get child's output.  */
-  ASSERT (read (fd[0], buffer, 2) == 1);
+/* Return true if FD is open.  */
+static bool
+is_open (int fd)
+{
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+  /* On native Windows, the initial state of unassigned standard file
+     descriptors is that they are open but point to an
+     INVALID_HANDLE_VALUE, and there is no fcntl.  */
+  return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
+#else
+# ifndef F_GETFL
+#  error Please port fcntl to your platform
+# endif
+  return 0 <= fcntl (fd, F_GETFL);
+#endif
+}
 
-  /* Wait for child.  */
-  ASSERT (wait_subprocess (pid, argv0, true, false, false, true, NULL) == 0);
-  ASSERT (close (fd[0]) == 0);
-  ASSERT (close (fd[1]) == 0);
+/* Return true if FD is not inherited to child processes.  */
+static bool
+is_cloexec (int fd)
+{
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+  HANDLE h = (HANDLE) _get_osfhandle (fd);
+  DWORD flags;
+  ASSERT (GetHandleInformation (h, &flags));
+  return (flags & HANDLE_FLAG_INHERIT) == 0;
+#else
+  int flags;
+  ASSERT ((flags = fcntl (fd, F_GETFD)) >= 0);
+  return (flags & FD_CLOEXEC) != 0;
+#endif
+}
 
-  /* Check the result.  */
-  ASSERT (buffer[0] == 'b');
-  ASSERT (buffer[1] == 'a');
+/* Return true if FD is in non-blocking mode.  */
+static bool
+is_nonblocking (int fd)
+{
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+  /* We don't use the non-blocking mode for sockets here.  */
+  return 0;
+#else
+  int flags;
+  ASSERT ((flags = fcntl (fd, F_GETFL)) >= 0);
+  return (flags & O_NONBLOCK) != 0;
+#endif
 }
 
 int
-main (int argc, const char *argv[])
+main ()
 {
-  int i;
-  int test;
-  ASSERT (argc == 2);
-  test = atoi (argv[1]);
-  switch (test)
-    {
-      /* Driver cases.  Selectively close various standard fds, to
-         ensure the child process is not impacted by this.  */
-    case 0:
-      break;
-    case 1:
-      close (0);
-      break;
-    case 2:
-      close (1);
-      break;
-    case 3:
-      close (0);
-      close (1);
-      break;
-    case 4:
-      close (2);
-      break;
-    case 5:
-      close (0);
-      close (2);
-      break;
-    case 6:
-      close (1);
-      close (2);
-      break;
-    case 7:
-      close (0);
-      close (1);
-      close (2);
-      break;
+  int fd[2];
+
+  fd[0] = -1;
+  fd[1] = -1;
+  ASSERT (pipe (fd) >= 0);
+  ASSERT (fd[0] >= 0);
+  ASSERT (fd[1] >= 0);
+  ASSERT (fd[0] != fd[1]);
+  ASSERT (is_open (fd[0]));
+  ASSERT (is_open (fd[1]));
+  ASSERT (!is_cloexec (fd[0]));
+  ASSERT (!is_cloexec (fd[1]));
+  ASSERT (!is_nonblocking (fd[0]));
+  ASSERT (!is_nonblocking (fd[1]));
 
-      /* Slave cases.  Read one byte from fd 0, and write its value
-         plus one to fd 1.  fd 2 should be closed iff the argument is
-         9.  Check that no other fd's leaked.  */
-    case 8:
-    case 9:
-      {
-        char buffer[1];
-        ASSERT (read (STDIN_FILENO, buffer, 1) == 1);
-        buffer[0]++;
-        ASSERT (write (STDOUT_FILENO, buffer, 1) == 1);
-        errno = 0;
-        i = fcntl (STDERR_FILENO, F_GETFL);
-        if (test == 8)
-          ASSERT (0 <= i);
-        else
-          {
-            ASSERT (i < 0);
-            ASSERT (errno == EBADF);
-          }
-        for (i = 3; i < 7; i++)
-          {
-            errno = 0;
-            ASSERT (close (i) == -1);
-            ASSERT (errno == EBADF);
-          }
-        return 0;
-      }
-    default:
-      ASSERT (0);
-    }
-  /* All remaining code is for the driver.  Plug any leaks inherited
-     from outside world before starting, so that child has a clean
-     slate (at least for the fds that we might be manipulating).  */
-  for (i = 3; i < 7; i++)
-    close (i);
-  test_pipe (argv[0], 3 < test);
   return 0;
 }