Pass slave_process argument consistently.
[gnulib.git] / tests / test-pipe.c
1 /* Test of create_pipe_bidi/wait_subprocess.
2    Copyright (C) 2009 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 "pipe.h"
21 #include "wait-process.h"
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 /* Depending on arguments, this test intentionally closes stderr or
31    starts life with stderr closed.  So, the error messages might not
32    always print, but at least the exit status will be reliable.  */
33 #define ASSERT(expr) \
34   do                                                                         \
35     {                                                                        \
36       if (!(expr))                                                           \
37         {                                                                    \
38           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
39           fflush (stderr);                                                   \
40           abort ();                                                          \
41         }                                                                    \
42     }                                                                        \
43   while (0)
44
45 /* Create a bi-directional pipe to a test child, and validate that the
46    child program returns the expected output.  The child is the same
47    program as the parent ARGV0, but with different arguments.
48    STDERR_CLOSED is true if we have already closed fd 2.  */
49 static void
50 test_pipe (const char *argv0, bool stderr_closed)
51 {
52   int fd[2];
53   const char *argv[3];
54   pid_t pid;
55   char buffer[2] = { 'a', 'a' };
56
57   /* Set up child.  */
58   argv[0] = argv0;
59   argv[1] = stderr_closed ? "9" : "8";
60   argv[2] = NULL;
61   pid = create_pipe_bidi (argv0, argv0, (char **) argv,
62                           false, true, true, fd);
63   ASSERT (0 <= pid);
64   ASSERT (STDERR_FILENO < fd[0]);
65   ASSERT (STDERR_FILENO < fd[1]);
66
67   /* Push child's input.  */
68   ASSERT (write (fd[1], buffer, 1) == 1);
69
70   /* Get child's output.  */
71   ASSERT (read (fd[0], buffer, 2) == 1);
72
73   /* Wait for child.  */
74   ASSERT (wait_subprocess (pid, argv0, true, false, true, true, NULL) == 0);
75   ASSERT (close (fd[0]) == 0);
76   ASSERT (close (fd[1]) == 0);
77
78   /* Check the result.  */
79   ASSERT (buffer[0] == 'b');
80   ASSERT (buffer[1] == 'a');
81 }
82
83 int
84 main (int argc, const char *argv[])
85 {
86   int i;
87   int test;
88   ASSERT (argc == 2);
89   test = atoi (argv[1]);
90   switch (test)
91     {
92       /* Driver cases.  Selectively close various standard fds, to
93          ensure the child process is not impacted by this.  */
94     case 0:
95       break;
96     case 1:
97       close (0);
98       break;
99     case 2:
100       close (1);
101       break;
102     case 3:
103       close (0);
104       close (1);
105       break;
106     case 4:
107       close (2);
108       break;
109     case 5:
110       close (0);
111       close (2);
112       break;
113     case 6:
114       close (1);
115       close (2);
116       break;
117     case 7:
118       close (0);
119       close (1);
120       close (2);
121       break;
122
123       /* Slave cases.  Read one byte from fd 0, and write its value
124          plus one to fd 1.  fd 2 should be closed iff the argument is
125          9.  Check that no other fd's leaked.  */
126     case 8:
127     case 9:
128       {
129         char buffer[1];
130         ASSERT (read (STDIN_FILENO, buffer, 1) == 1);
131         buffer[0]++;
132         ASSERT (write (STDOUT_FILENO, buffer, 1) == 1);
133         errno = 0;
134 #ifdef F_GETFL
135         /* Try to keep stderr open for better diagnostics.  */
136         i = fcntl (STDERR_FILENO, F_GETFL);
137 #else
138         /* But allow compilation on mingw.  */
139         i = close (STDERR_FILENO);
140 #endif
141         if (test == 8)
142           ASSERT (0 <= i);
143         else
144           {
145             ASSERT (i < 0);
146             ASSERT (errno == EBADF);
147           }
148         for (i = 3; i < 7; i++)
149           {
150             errno = 0;
151             ASSERT (close (i) == -1);
152             ASSERT (errno == EBADF);
153           }
154         return 0;
155       }
156     default:
157       ASSERT (0);
158     }
159   /* All remaining code is for the driver.  Plug any leaks inherited
160      from outside world before starting, so that child has a clean
161      slate (at least for the fds that we might be manipulating).  */
162   for (i = 3; i < 7; i++)
163     close (i);
164   test_pipe (argv[0], 3 < test);
165   return 0;
166 }