X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=tests%2Ftest-pipe.c;h=90f41f9107ed801152ae070abf2a346eb05b6774;hb=b12df021ba5b5f12648d84f91d021777c347e9be;hp=9e806869f33be0c671c4059e63c2da128b05667d;hpb=b93b5de531d765fc11ce5a575b9651de0ebe81c2;p=gnulib.git diff --git a/tests/test-pipe.c b/tests/test-pipe.c index 9e806869f..90f41f910 100644 --- a/tests/test-pipe.c +++ b/tests/test-pipe.c @@ -1,5 +1,5 @@ -/* Test of create_pipe_bidi/wait_subprocess. - Copyright (C) 2009 Free Software Foundation, Inc. +/* Test of pipe. + Copyright (C) 2009-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 @@ -17,150 +17,89 @@ #include -#include "pipe.h" -#include "wait-process.h" +#include + +#include "signature.h" +SIGNATURE_CHECK (pipe, int, (int[2])); -#include #include #include -#include -#include -#include - -/* 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' }; - /* 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]); +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the Win32 API functions. */ +# define WIN32_LEAN_AND_MEAN +# include +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" +#endif - /* Push child's input. */ - ASSERT (write (fd[1], buffer, 1) == 1); +#include "binary-io.h" +#include "macros.h" - /* 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 Win32, 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, true, 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; -#ifdef F_GETFL - /* Try to keep stderr open for better diagnostics. */ - i = fcntl (STDERR_FILENO, F_GETFL); -#else - /* But allow compilation on mingw. */ - i = close (STDERR_FILENO); -#endif - 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; }