# HG changeset patch # User Bruno Haible # Date 1307353120 -7200 # Node ID 3b19d2cdc47f9e26b6b477905d0d0087f78f7781 # Parent 344b70fb76a23bcc5d2d463b9397983cbfc1deea spawn-pipe tests: Like the child program only against libc. * tests/test-spawn-pipe-child.c: New file, extracted from tests/test-spawn-pipe.c. (main): Expect only one argument. (is_open): New function, copied from tests/test-pipe.c. * tests/test-spawn-pipe.c: Don't include . (child_main): Remove function. (test_pipe): Pass only one argument to the child program. (main): Remove child process code. Expect the child program's name as first argument. * tests/test-spawn-pipe.sh: Pass the child program's name as first argument. * modules/spawn-pipe-tests (Files): Add tests/test-spawn-pipe-child.c. (Makefile.am): Add test-spawn-pipe-child to check_PROGRAMS. Link test-spawn-pipe-child against no libraries. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2011-06-06 Bruno Haible + + spawn-pipe tests: Like the child program only against libc. + * tests/test-spawn-pipe-child.c: New file, extracted from + tests/test-spawn-pipe.c. + (main): Expect only one argument. + (is_open): New function, copied from tests/test-pipe.c. + * tests/test-spawn-pipe.c: Don't include . + (child_main): Remove function. + (test_pipe): Pass only one argument to the child program. + (main): Remove child process code. Expect the child program's name as + first argument. + * tests/test-spawn-pipe.sh: Pass the child program's name as first + argument. + * modules/spawn-pipe-tests (Files): Add tests/test-spawn-pipe-child.c. + (Makefile.am): Add test-spawn-pipe-child to check_PROGRAMS. Link + test-spawn-pipe-child against no libraries. + 2011-06-06 Bruno Haible careadlinkat: Avoid mismatch between ssize_t and int. diff --git a/modules/spawn-pipe-tests b/modules/spawn-pipe-tests --- a/modules/spawn-pipe-tests +++ b/modules/spawn-pipe-tests @@ -1,6 +1,7 @@ Files: tests/test-spawn-pipe.sh tests/test-spawn-pipe.c +tests/test-spawn-pipe-child.c tests/macros.h Depends-on: @@ -10,5 +11,9 @@ Makefile.am: TESTS += test-spawn-pipe.sh -check_PROGRAMS += test-spawn-pipe +check_PROGRAMS += test-spawn-pipe test-spawn-pipe-child test_spawn_pipe_LDADD = $(LDADD) @LIBINTL@ +# The test-spawn-pipe-child program must be a real executable, not a libtool +# wrapper script, and should link against as few libraries as possible. +# Therefore don't link it against any libraries other than -lc. +test_spawn_pipe_child_LDADD = diff --git a/tests/test-spawn-pipe-child.c b/tests/test-spawn-pipe-child.c new file mode 100644 --- /dev/null +++ b/tests/test-spawn-pipe-child.c @@ -0,0 +1,113 @@ +/* Child program invoked by test-spawn-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 + the Free Software Foundation; either version 3, 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, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include + +#include +#include +#include +#include +#include + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the Win32 API functions. */ +# define WIN32_LEAN_AND_MEAN +# include +#endif + +/* Depending on arguments, this test intentionally closes stderr or + starts life with stderr closed. So, we arrange to have fd 10 + (outside the range of interesting fd's during the test) set up to + duplicate the original stderr. */ + +#define BACKUP_STDERR_FILENO 10 +#define ASSERT_STREAM myerr +#include "macros.h" + +static FILE *myerr; + +/* In this file, we use only system functions, no overrides from gnulib. */ +#undef atoi +#undef close +#undef fcntl +#undef fdopen +#undef read +#undef write + +/* Return non-zero if FD is open. */ +static int +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 +} + +int +main (int argc, char *argv[]) +{ + char buffer[2] = { 's', 't' }; + int fd; + + /* fd 2 might be closed, but fd BACKUP_STDERR_FILENO is the original + stderr. */ + myerr = fdopen (BACKUP_STDERR_FILENO, "w"); + if (!myerr) + return 2; + + ASSERT (argc == 2); + + /* Read one byte from fd 0, and write its value plus one to fd 1. + fd 2 should be closed iff the argument is 1. Check that no other file + descriptors leaked. */ + + ASSERT (read (STDIN_FILENO, buffer, 2) == 1); + + buffer[0]++; + ASSERT (write (STDOUT_FILENO, buffer, 1) == 1); + + switch (atoi (argv[1])) + { + case 0: + /* Expect fd 2 is open. */ + ASSERT (is_open (STDERR_FILENO)); + break; + case 1: + /* Expect fd 2 is closed. */ + ASSERT (! is_open (STDERR_FILENO)); + break; + default: + ASSERT (0); + } + + for (fd = 3; fd < 7; fd++) + { + errno = 0; + ASSERT (close (fd) == -1); + ASSERT (errno == EBADF); + } + + return 0; +} diff --git a/tests/test-spawn-pipe.c b/tests/test-spawn-pipe.c --- a/tests/test-spawn-pipe.c +++ b/tests/test-spawn-pipe.c @@ -20,7 +20,6 @@ #include "spawn-pipe.h" #include "wait-process.h" -#include #include #include #include @@ -38,70 +37,23 @@ static FILE *myerr; -/* Code executed by the child process. argv[1] = "child". */ -static int -child_main (int argc, char *argv[]) -{ - char buffer[2] = { 's', 't' }; - int fd; - int ret; - - ASSERT (argc == 3); - - /* Read one byte from fd 0, and write its value plus one to fd 1. - fd 2 should be closed iff the argument is 1. Check that no other file - descriptors leaked. */ - - ASSERT (read (STDIN_FILENO, buffer, 2) == 1); - - buffer[0]++; - ASSERT (write (STDOUT_FILENO, buffer, 1) == 1); - - errno = 0; - ret = dup2 (STDERR_FILENO, STDERR_FILENO); - switch (atoi (argv[2])) - { - case 0: - /* Expect fd 2 is open. */ - ASSERT (ret == STDERR_FILENO); - break; - case 1: - /* Expect fd 2 is closed. */ - ASSERT (ret == -1); - ASSERT (errno == EBADF); - break; - default: - ASSERT (false); - } - - for (fd = 3; fd < 7; fd++) - { - errno = 0; - ASSERT (close (fd) == -1); - ASSERT (errno == EBADF); - } - - return 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. + child program returns the expected output. + PROG is the program to run in the child process. STDERR_CLOSED is true if we have already closed fd 2. */ static void -test_pipe (const char *argv0, bool stderr_closed) +test_pipe (const char *prog, bool stderr_closed) { int fd[2]; - char *argv[4]; + char *argv[3]; pid_t pid; char buffer[2] = { 'a', 't' }; /* Set up child. */ - argv[0] = (char *) argv0; - argv[1] = (char *) "child"; - argv[2] = (char *) (stderr_closed ? "1" : "0"); - argv[3] = NULL; - pid = create_pipe_bidi (argv0, argv0, argv, false, true, true, fd); + argv[0] = (char *) prog; + argv[1] = (char *) (stderr_closed ? "1" : "0"); + argv[2] = NULL; + pid = create_pipe_bidi (prog, prog, argv, false, true, true, fd); ASSERT (0 <= pid); ASSERT (STDERR_FILENO < fd[0]); ASSERT (STDERR_FILENO < fd[1]); @@ -114,7 +66,7 @@ ASSERT (read (fd[0], buffer, 2) == 1); /* Wait for child. */ - ASSERT (wait_subprocess (pid, argv0, true, false, true, true, NULL) == 0); + ASSERT (wait_subprocess (pid, prog, true, false, true, true, NULL) == 0); ASSERT (close (fd[0]) == 0); /* Check the result. */ @@ -122,18 +74,25 @@ ASSERT (buffer[1] == 't'); } -/* Code executed by the parent process. */ -static int -parent_main (int argc, char *argv[]) +int +main (int argc, char *argv[]) { int test; int fd; - ASSERT (argc == 2); + if (argc != 3) + { + fprintf (stderr, "%s: need 2 arguments\n", argv[0]); + return 2; + } + /* We might close fd 2 later, so save it in fd 10. */ + if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO + || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL) + return 2; /* Selectively close various standard fds, to verify the child process is not impacted by this. */ - test = atoi (argv[1]); + test = atoi (argv[2]); switch (test) { case 0: @@ -174,31 +133,7 @@ for (fd = 3; fd < 7; fd++) close (fd); - test_pipe (argv[0], test >= 4); + test_pipe (argv[1], test >= 4); return 0; } - -int -main (int argc, char *argv[]) -{ - if (argc < 2) - { - fprintf (stderr, "%s: need arguments\n", argv[0]); - return 2; - } - if (strcmp (argv[1], "child") == 0) - { - /* fd 2 might be closed, but fd BACKUP_STDERR_FILENO is the original - stderr. */ - myerr = fdopen (BACKUP_STDERR_FILENO, "w"); - if (!myerr) - return 2; - return child_main (argc, argv); - } - /* We might close fd 2 later, so save it in fd 10. */ - if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO - || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL) - return 2; - return parent_main (argc, argv); -} diff --git a/tests/test-spawn-pipe.sh b/tests/test-spawn-pipe.sh --- a/tests/test-spawn-pipe.sh +++ b/tests/test-spawn-pipe.sh @@ -2,7 +2,7 @@ st=0 for i in 0 1 2 3 4 5 6 7 ; do - ./test-spawn-pipe${EXEEXT} $i \ + ./test-spawn-pipe${EXEEXT} ./test-spawn-pipe-child${EXEEXT} $i \ || { echo test-spawn-pipe.sh: iteration $i failed >&2; st=1; } done exit $st