~win-cross-dev/win-cross/gettext

« back to all changes in this revision

Viewing changes to gettext-tools/gnulib-tests/test-pipe.c

  • Committer: Nathan Osman
  • Date: 2012-08-11 05:06:52 UTC
  • Revision ID: admin@quickmediasolutions.com-20120811050652-ochkxjtonbw6kkve
Initial commit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Test of create_pipe_bidi/wait_subprocess.
 
2
   Copyright (C) 2009, 2010 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 <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
/* Code executed by the child process.  argv[1] = "child".  */
 
42
static int
 
43
child_main (int argc, char *argv[])
 
44
{
 
45
  char buffer[2] = { 's', 't' };
 
46
  int fd;
 
47
  int ret;
 
48
 
 
49
  ASSERT (argc == 3);
 
50
 
 
51
  /* Read one byte from fd 0, and write its value plus one to fd 1.
 
52
     fd 2 should be closed iff the argument is 1.  Check that no other file
 
53
     descriptors leaked.  */
 
54
 
 
55
  ASSERT (read (STDIN_FILENO, buffer, 2) == 1);
 
56
 
 
57
  buffer[0]++;
 
58
  ASSERT (write (STDOUT_FILENO, buffer, 1) == 1);
 
59
 
 
60
  errno = 0;
 
61
  ret = dup2 (STDERR_FILENO, STDERR_FILENO);
 
62
  switch (atoi (argv[2]))
 
63
    {
 
64
    case 0:
 
65
      /* Expect fd 2 is open.  */
 
66
      ASSERT (ret == STDERR_FILENO);
 
67
      break;
 
68
    case 1:
 
69
      /* Expect fd 2 is closed.  */
 
70
      ASSERT (ret == -1);
 
71
      ASSERT (errno == EBADF);
 
72
      break;
 
73
    default:
 
74
      ASSERT (false);
 
75
    }
 
76
 
 
77
  for (fd = 3; fd < 7; fd++)
 
78
    {
 
79
      errno = 0;
 
80
      ASSERT (close (fd) == -1);
 
81
      ASSERT (errno == EBADF);
 
82
    }
 
83
 
 
84
  return 0;
 
85
}
 
86
 
 
87
/* Create a bi-directional pipe to a test child, and validate that the
 
88
   child program returns the expected output.  The child is the same
 
89
   program as the parent ARGV0, but with different arguments.
 
90
   STDERR_CLOSED is true if we have already closed fd 2.  */
 
91
static void
 
92
test_pipe (const char *argv0, bool stderr_closed)
 
93
{
 
94
  int fd[2];
 
95
  char *argv[4];
 
96
  pid_t pid;
 
97
  char buffer[2] = { 'a', 't' };
 
98
 
 
99
  /* Set up child.  */
 
100
  argv[0] = (char *) argv0;
 
101
  argv[1] = (char *) "child";
 
102
  argv[2] = (char *) (stderr_closed ? "1" : "0");
 
103
  argv[3] = NULL;
 
104
  pid = create_pipe_bidi (argv0, argv0, argv, false, true, true, fd);
 
105
  ASSERT (0 <= pid);
 
106
  ASSERT (STDERR_FILENO < fd[0]);
 
107
  ASSERT (STDERR_FILENO < fd[1]);
 
108
 
 
109
  /* Push child's input.  */
 
110
  ASSERT (write (fd[1], buffer, 1) == 1);
 
111
  ASSERT (close (fd[1]) == 0);
 
112
 
 
113
  /* Get child's output.  */
 
114
  ASSERT (read (fd[0], buffer, 2) == 1);
 
115
 
 
116
  /* Wait for child.  */
 
117
  ASSERT (wait_subprocess (pid, argv0, true, false, true, true, NULL) == 0);
 
118
  ASSERT (close (fd[0]) == 0);
 
119
 
 
120
  /* Check the result.  */
 
121
  ASSERT (buffer[0] == 'b');
 
122
  ASSERT (buffer[1] == 't');
 
123
}
 
124
 
 
125
/* Code executed by the parent process.  */
 
126
static int
 
127
parent_main (int argc, char *argv[])
 
128
{
 
129
  int test;
 
130
  int fd;
 
131
 
 
132
  ASSERT (argc == 2);
 
133
 
 
134
  /* Selectively close various standard fds, to verify the child process is
 
135
     not impacted by this.  */
 
136
  test = atoi (argv[1]);
 
137
  switch (test)
 
138
    {
 
139
    case 0:
 
140
      break;
 
141
    case 1:
 
142
      close (0);
 
143
      break;
 
144
    case 2:
 
145
      close (1);
 
146
      break;
 
147
    case 3:
 
148
      close (0);
 
149
      close (1);
 
150
      break;
 
151
    case 4:
 
152
      close (2);
 
153
      break;
 
154
    case 5:
 
155
      close (0);
 
156
      close (2);
 
157
      break;
 
158
    case 6:
 
159
      close (1);
 
160
      close (2);
 
161
      break;
 
162
    case 7:
 
163
      close (0);
 
164
      close (1);
 
165
      close (2);
 
166
      break;
 
167
    default:
 
168
      ASSERT (false);
 
169
    }
 
170
 
 
171
  /* Plug any file descriptor leaks inherited from outside world before
 
172
     starting, so that child has a clean slate (at least for the fds that we
 
173
     might be manipulating).  */
 
174
  for (fd = 3; fd < 7; fd++)
 
175
    close (fd);
 
176
 
 
177
  test_pipe (argv[0], test >= 4);
 
178
 
 
179
  return 0;
 
180
}
 
181
 
 
182
int
 
183
main (int argc, char *argv[])
 
184
{
 
185
  if (argc < 2)
 
186
    {
 
187
      fprintf (stderr, "%s: need arguments\n", argv[0]);
 
188
      return 2;
 
189
    }
 
190
  if (strcmp (argv[1], "child") == 0)
 
191
    {
 
192
      /* fd 2 might be closed, but fd BACKUP_STDERR_FILENO is the original
 
193
         stderr.  */
 
194
      myerr = fdopen (BACKUP_STDERR_FILENO, "w");
 
195
      if (!myerr)
 
196
        return 2;
 
197
      return child_main (argc, argv);
 
198
    }
 
199
  /* We might close fd 2 later, so save it in fd 10.  */
 
200
  if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
 
201
      || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
 
202
    return 2;
 
203
  return parent_main (argc, argv);
 
204
}