spawn-pipe tests: Fix a NULL program name in a diagnostic.
[gnulib.git] / tests / test-spawn-pipe-main.c
1 /* Test of create_pipe_bidi/wait_subprocess.
2    Copyright (C) 2009-2012 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 #include <config.h>
19
20 #include "spawn-pipe.h"
21 #include "wait-process.h"
22 #include "progname.h"
23
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 /* Depending on arguments, this test intentionally closes stderr or
31    starts life with stderr closed.  So, we arrange to have fd 10
32    (outside the range of interesting fd's during the test) set up to
33    duplicate the original stderr.  */
34
35 #define BACKUP_STDERR_FILENO 10
36 #define ASSERT_STREAM myerr
37 #include "macros.h"
38
39 static FILE *myerr;
40
41 /* Create a bi-directional pipe to a test child, and validate that the
42    child program returns the expected output.
43    PROG is the program to run in the child process.
44    STDERR_CLOSED is true if we have already closed fd 2.  */
45 static void
46 test_pipe (const char *prog, bool stderr_closed)
47 {
48   int fd[2];
49   char *argv[3];
50   pid_t pid;
51   char buffer[2] = { 'a', 't' };
52
53   /* Set up child.  */
54   argv[0] = (char *) prog;
55   argv[1] = (char *) (stderr_closed ? "1" : "0");
56   argv[2] = NULL;
57   pid = create_pipe_bidi (prog, prog, argv, false, true, true, fd);
58   ASSERT (0 <= pid);
59   ASSERT (STDERR_FILENO < fd[0]);
60   ASSERT (STDERR_FILENO < fd[1]);
61
62   /* Push child's input.  */
63   ASSERT (write (fd[1], buffer, 1) == 1);
64   ASSERT (close (fd[1]) == 0);
65
66   /* Get child's output.  */
67   ASSERT (read (fd[0], buffer, 2) == 1);
68
69   /* Wait for child.  */
70   ASSERT (wait_subprocess (pid, prog, true, false, true, true, NULL) == 0);
71   ASSERT (close (fd[0]) == 0);
72
73   /* Check the result.  */
74   ASSERT (buffer[0] == 'b');
75   ASSERT (buffer[1] == 't');
76 }
77
78 int
79 main (int argc, char *argv[])
80 {
81   int test;
82   int fd;
83
84   set_program_name (argv[0]);
85
86   if (argc != 3)
87     {
88       fprintf (stderr, "%s: need 2 arguments\n", argv[0]);
89       return 2;
90     }
91   /* We might close fd 2 later, so save it in fd 10.  */
92   if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
93       || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
94     return 2;
95
96   /* Selectively close various standard fds, to verify the child process is
97      not impacted by this.  */
98   test = atoi (argv[2]);
99   switch (test)
100     {
101     case 0:
102       break;
103     case 1:
104       close (0);
105       break;
106     case 2:
107       close (1);
108       break;
109     case 3:
110       close (0);
111       close (1);
112       break;
113     case 4:
114       close (2);
115       break;
116     case 5:
117       close (0);
118       close (2);
119       break;
120     case 6:
121       close (1);
122       close (2);
123       break;
124     case 7:
125       close (0);
126       close (1);
127       close (2);
128       break;
129     default:
130       ASSERT (false);
131     }
132
133   /* Plug any file descriptor leaks inherited from outside world before
134      starting, so that child has a clean slate (at least for the fds that we
135      might be manipulating).  */
136   for (fd = 3; fd < 7; fd++)
137     close (fd);
138
139   test_pipe (argv[1], test >= 4);
140
141   return 0;
142 }