1 /* Test capturing output from a subprocess.
2 Copyright (C) 2017 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
23 #include <support/capture_subprocess.h>
24 #include <support/check.h>
25 #include <support/support.h>
29 /* Write one byte at *P to FD and advance *P. Do nothing if *P is
32 transfer (const unsigned char **p
, int fd
)
36 TEST_VERIFY (write (fd
, *p
, 1) == 1);
41 /* Determine the order in which stdout and stderr are written. */
42 enum write_mode
{ out_first
, err_first
, interleave
,
43 write_mode_last
= interleave
};
45 /* Describe what to write in the subprocess. */
50 enum write_mode write_mode
;
55 /* For use with support_capture_subprocess. */
57 callback (void *closure
)
59 const struct test
*test
= closure
;
61 switch (test
->write_mode
)
64 TEST_VERIFY (fputs (test
->out
, stdout
) >= 0);
65 TEST_VERIFY (fflush (stdout
) == 0);
66 TEST_VERIFY (fputs (test
->err
, stderr
) >= 0);
67 TEST_VERIFY (fflush (stderr
) == 0);
71 TEST_VERIFY (fputs (test
->err
, stderr
) >= 0);
72 TEST_VERIFY (fflush (stderr
) == 0);
73 TEST_VERIFY (fputs (test
->out
, stdout
) >= 0);
74 TEST_VERIFY (fflush (stdout
) == 0);
79 const unsigned char *pout
= (const unsigned char *) test
->out
;
80 const unsigned char *perr
= (const unsigned char *) test
->err
;
83 transfer (&pout
, STDOUT_FILENO
);
84 transfer (&perr
, STDERR_FILENO
);
86 while (*pout
!= '\0' || *perr
!= '\0');
91 TEST_VERIFY (mode_ok
);
93 if (test
->signal
!= 0)
98 /* Create a heap-allocated random string of letters. */
100 random_string (size_t length
)
102 char *result
= xmalloc (length
+ 1);
103 for (size_t i
= 0; i
< length
; ++i
)
104 result
[i
] = 'a' + (rand () % 26);
105 result
[length
] = '\0';
109 /* Check that the specific stream from the captured subprocess matches
112 check_stream (const char *what
, const struct xmemstream
*stream
,
113 const char *expected
)
115 if (strcmp (stream
->buffer
, expected
) != 0)
117 support_record_failure ();
118 printf ("error: captured %s data incorrect\n"
121 what
, expected
, stream
->buffer
);
123 if (stream
->length
!= strlen (expected
))
125 support_record_failure ();
126 printf ("error: captured %s data length incorrect\n"
129 what
, strlen (expected
), stream
->length
);
136 const int lengths
[] = {0, 1, 17, 512, 20000, -1};
138 /* Test multiple combinations of support_capture_subprocess.
140 length_idx_stdout: Index into the lengths array above,
141 controls how many bytes are written by the subprocess to
143 length_idx_stderr: Same for standard error.
144 write_mode: How standard output and standard error writes are
146 signal: Exit with no signal if zero, with SIGTERM if one.
147 status: Process exit status: 0 if zero, 3 if one. */
148 for (int length_idx_stdout
= 0; lengths
[length_idx_stdout
] >= 0;
150 for (int length_idx_stderr
= 0; lengths
[length_idx_stderr
] >= 0;
152 for (int write_mode
= 0; write_mode
< write_mode_last
; ++write_mode
)
153 for (int signal
= 0; signal
< 2; ++signal
)
154 for (int status
= 0; status
< 2; ++status
)
158 .out
= random_string (lengths
[length_idx_stdout
]),
159 .err
= random_string (lengths
[length_idx_stderr
]),
160 .write_mode
= write_mode
,
161 .signal
= signal
* SIGTERM
, /* 0 or SIGTERM. */
162 .status
= status
* 3, /* 0 or 3. */
164 TEST_VERIFY (strlen (test
.out
) == lengths
[length_idx_stdout
]);
165 TEST_VERIFY (strlen (test
.err
) == lengths
[length_idx_stderr
]);
167 struct support_capture_subprocess result
168 = support_capture_subprocess (callback
, &test
);
169 check_stream ("stdout", &result
.out
, test
.out
);
170 check_stream ("stderr", &result
.err
, test
.err
);
171 if (test
.signal
!= 0)
173 TEST_VERIFY (WIFSIGNALED (result
.status
));
174 TEST_VERIFY (WTERMSIG (result
.status
) == test
.signal
);
178 TEST_VERIFY (WIFEXITED (result
.status
));
179 TEST_VERIFY (WEXITSTATUS (result
.status
) == test
.status
);
181 support_capture_subprocess_free (&result
);
188 #include <support/test-driver.c>