xref: /freebsd-src/contrib/atf/atf-c/detail/process_test.c (revision c243e4902be8df1e643c76b5f18b68bb77cc5268)
1*c243e490SMarcel Moolenaar /*
2*c243e490SMarcel Moolenaar  * Automated Testing Framework (atf)
3*c243e490SMarcel Moolenaar  *
4*c243e490SMarcel Moolenaar  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5*c243e490SMarcel Moolenaar  * All rights reserved.
6*c243e490SMarcel Moolenaar  *
7*c243e490SMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
8*c243e490SMarcel Moolenaar  * modification, are permitted provided that the following conditions
9*c243e490SMarcel Moolenaar  * are met:
10*c243e490SMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
11*c243e490SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer.
12*c243e490SMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
13*c243e490SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
14*c243e490SMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
15*c243e490SMarcel Moolenaar  *
16*c243e490SMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*c243e490SMarcel Moolenaar  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*c243e490SMarcel Moolenaar  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*c243e490SMarcel Moolenaar  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*c243e490SMarcel Moolenaar  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*c243e490SMarcel Moolenaar  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*c243e490SMarcel Moolenaar  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*c243e490SMarcel Moolenaar  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*c243e490SMarcel Moolenaar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*c243e490SMarcel Moolenaar  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*c243e490SMarcel Moolenaar  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*c243e490SMarcel Moolenaar  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*c243e490SMarcel Moolenaar  */
29*c243e490SMarcel Moolenaar 
30*c243e490SMarcel Moolenaar #include <sys/types.h>
31*c243e490SMarcel Moolenaar #include <sys/time.h>
32*c243e490SMarcel Moolenaar #include <sys/resource.h>
33*c243e490SMarcel Moolenaar #include <sys/wait.h>
34*c243e490SMarcel Moolenaar 
35*c243e490SMarcel Moolenaar #include <errno.h>
36*c243e490SMarcel Moolenaar #include <fcntl.h>
37*c243e490SMarcel Moolenaar #include <signal.h>
38*c243e490SMarcel Moolenaar #include <stdio.h>
39*c243e490SMarcel Moolenaar #include <stdlib.h>
40*c243e490SMarcel Moolenaar #include <string.h>
41*c243e490SMarcel Moolenaar #include <unistd.h>
42*c243e490SMarcel Moolenaar 
43*c243e490SMarcel Moolenaar #include <atf-c.h>
44*c243e490SMarcel Moolenaar 
45*c243e490SMarcel Moolenaar #include "atf-c/defs.h"
46*c243e490SMarcel Moolenaar 
47*c243e490SMarcel Moolenaar #include "process.h"
48*c243e490SMarcel Moolenaar #include "sanity.h"
49*c243e490SMarcel Moolenaar #include "test_helpers.h"
50*c243e490SMarcel Moolenaar 
51*c243e490SMarcel Moolenaar atf_error_t atf_process_status_init(atf_process_status_t *, int);
52*c243e490SMarcel Moolenaar 
53*c243e490SMarcel Moolenaar /* ---------------------------------------------------------------------
54*c243e490SMarcel Moolenaar  * Auxiliary functions for testing of 'atf_process_fork'.
55*c243e490SMarcel Moolenaar  * --------------------------------------------------------------------- */
56*c243e490SMarcel Moolenaar 
57*c243e490SMarcel Moolenaar /*
58*c243e490SMarcel Moolenaar  * Testing of atf_process_fork is quite messy.  We want to be able to test
59*c243e490SMarcel Moolenaar  * all the possible combinations of stdout and stderr behavior to ensure
60*c243e490SMarcel Moolenaar  * that the streams are manipulated correctly.
61*c243e490SMarcel Moolenaar  *
62*c243e490SMarcel Moolenaar  * To do this, the do_fork function is a wrapper for atf_process_fork that
63*c243e490SMarcel Moolenaar  * issues stream-specific hooks before fork, while the child is running and
64*c243e490SMarcel Moolenaar  * after the child terminates.  We then provide test cases that just call
65*c243e490SMarcel Moolenaar  * do_fork with different hooks.
66*c243e490SMarcel Moolenaar  *
67*c243e490SMarcel Moolenaar  * The hooks are described by base_stream, and we then have one *_stream
68*c243e490SMarcel Moolenaar  * type for ever possible stream behavior.
69*c243e490SMarcel Moolenaar  */
70*c243e490SMarcel Moolenaar 
71*c243e490SMarcel Moolenaar enum out_type { stdout_type, stderr_type };
72*c243e490SMarcel Moolenaar 
73*c243e490SMarcel Moolenaar struct base_stream {
74*c243e490SMarcel Moolenaar     void (*init)(void *);
75*c243e490SMarcel Moolenaar     void (*process)(void *, atf_process_child_t *);
76*c243e490SMarcel Moolenaar     void (*fini)(void *);
77*c243e490SMarcel Moolenaar 
78*c243e490SMarcel Moolenaar     /* m_sb is initialized by subclasses that need it, but all consumers
79*c243e490SMarcel Moolenaar      * must use m_sb_ptr, which may or may not point to m_sb.  This allows
80*c243e490SMarcel Moolenaar      * us to test the interface with a NULL value, which triggers a
81*c243e490SMarcel Moolenaar      * default behavior. */
82*c243e490SMarcel Moolenaar     atf_process_stream_t m_sb;
83*c243e490SMarcel Moolenaar     atf_process_stream_t *m_sb_ptr;
84*c243e490SMarcel Moolenaar     enum out_type m_type;
85*c243e490SMarcel Moolenaar };
86*c243e490SMarcel Moolenaar #define BASE_STREAM(ihook, phook, fhook, type) \
87*c243e490SMarcel Moolenaar     { .init = ihook, \
88*c243e490SMarcel Moolenaar       .process = phook, \
89*c243e490SMarcel Moolenaar       .fini = fhook, \
90*c243e490SMarcel Moolenaar       .m_type = type }
91*c243e490SMarcel Moolenaar 
92*c243e490SMarcel Moolenaar static
93*c243e490SMarcel Moolenaar void
94*c243e490SMarcel Moolenaar check_file(const enum out_type type)
95*c243e490SMarcel Moolenaar {
96*c243e490SMarcel Moolenaar     switch (type) {
97*c243e490SMarcel Moolenaar     case stdout_type:
98*c243e490SMarcel Moolenaar         ATF_CHECK(grep_file("stdout", "stdout: msg"));
99*c243e490SMarcel Moolenaar         ATF_CHECK(!grep_file("stdout", "stderr: msg"));
100*c243e490SMarcel Moolenaar         break;
101*c243e490SMarcel Moolenaar     case stderr_type:
102*c243e490SMarcel Moolenaar         ATF_CHECK(grep_file("stderr", "stderr: msg"));
103*c243e490SMarcel Moolenaar         ATF_CHECK(!grep_file("stderr", "stdout: msg"));
104*c243e490SMarcel Moolenaar         break;
105*c243e490SMarcel Moolenaar     default:
106*c243e490SMarcel Moolenaar         UNREACHABLE;
107*c243e490SMarcel Moolenaar     }
108*c243e490SMarcel Moolenaar }
109*c243e490SMarcel Moolenaar 
110*c243e490SMarcel Moolenaar struct capture_stream {
111*c243e490SMarcel Moolenaar     struct base_stream m_base;
112*c243e490SMarcel Moolenaar 
113*c243e490SMarcel Moolenaar     atf_dynstr_t m_msg;
114*c243e490SMarcel Moolenaar };
115*c243e490SMarcel Moolenaar #define CAPTURE_STREAM(type) \
116*c243e490SMarcel Moolenaar     { .m_base = BASE_STREAM(capture_stream_init, \
117*c243e490SMarcel Moolenaar                             capture_stream_process, \
118*c243e490SMarcel Moolenaar                             capture_stream_fini, \
119*c243e490SMarcel Moolenaar                             type) }
120*c243e490SMarcel Moolenaar 
121*c243e490SMarcel Moolenaar static
122*c243e490SMarcel Moolenaar void
123*c243e490SMarcel Moolenaar capture_stream_init(void *v)
124*c243e490SMarcel Moolenaar {
125*c243e490SMarcel Moolenaar     struct capture_stream *s = v;
126*c243e490SMarcel Moolenaar 
127*c243e490SMarcel Moolenaar     s->m_base.m_sb_ptr = &s->m_base.m_sb;
128*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_capture(&s->m_base.m_sb));
129*c243e490SMarcel Moolenaar     RE(atf_dynstr_init(&s->m_msg));
130*c243e490SMarcel Moolenaar }
131*c243e490SMarcel Moolenaar 
132*c243e490SMarcel Moolenaar static
133*c243e490SMarcel Moolenaar void
134*c243e490SMarcel Moolenaar capture_stream_process(void *v, atf_process_child_t *c)
135*c243e490SMarcel Moolenaar {
136*c243e490SMarcel Moolenaar     struct capture_stream *s = v;
137*c243e490SMarcel Moolenaar 
138*c243e490SMarcel Moolenaar     switch (s->m_base.m_type) {
139*c243e490SMarcel Moolenaar     case stdout_type:
140*c243e490SMarcel Moolenaar         (void)read_line(atf_process_child_stdout(c), &s->m_msg);
141*c243e490SMarcel Moolenaar         break;
142*c243e490SMarcel Moolenaar     case stderr_type:
143*c243e490SMarcel Moolenaar         (void)read_line(atf_process_child_stderr(c), &s->m_msg);
144*c243e490SMarcel Moolenaar         break;
145*c243e490SMarcel Moolenaar     default:
146*c243e490SMarcel Moolenaar         UNREACHABLE;
147*c243e490SMarcel Moolenaar     }
148*c243e490SMarcel Moolenaar }
149*c243e490SMarcel Moolenaar 
150*c243e490SMarcel Moolenaar static
151*c243e490SMarcel Moolenaar void
152*c243e490SMarcel Moolenaar capture_stream_fini(void *v)
153*c243e490SMarcel Moolenaar {
154*c243e490SMarcel Moolenaar     struct capture_stream *s = v;
155*c243e490SMarcel Moolenaar 
156*c243e490SMarcel Moolenaar     switch (s->m_base.m_type) {
157*c243e490SMarcel Moolenaar     case stdout_type:
158*c243e490SMarcel Moolenaar         ATF_CHECK(grep_string(&s->m_msg, "stdout: msg"));
159*c243e490SMarcel Moolenaar         ATF_CHECK(!grep_string(&s->m_msg, "stderr: msg"));
160*c243e490SMarcel Moolenaar         break;
161*c243e490SMarcel Moolenaar     case stderr_type:
162*c243e490SMarcel Moolenaar         ATF_CHECK(!grep_string(&s->m_msg, "stdout: msg"));
163*c243e490SMarcel Moolenaar         ATF_CHECK(grep_string(&s->m_msg, "stderr: msg"));
164*c243e490SMarcel Moolenaar         break;
165*c243e490SMarcel Moolenaar     default:
166*c243e490SMarcel Moolenaar         UNREACHABLE;
167*c243e490SMarcel Moolenaar     }
168*c243e490SMarcel Moolenaar 
169*c243e490SMarcel Moolenaar     atf_dynstr_fini(&s->m_msg);
170*c243e490SMarcel Moolenaar     atf_process_stream_fini(&s->m_base.m_sb);
171*c243e490SMarcel Moolenaar }
172*c243e490SMarcel Moolenaar 
173*c243e490SMarcel Moolenaar struct connect_stream {
174*c243e490SMarcel Moolenaar     struct base_stream m_base;
175*c243e490SMarcel Moolenaar 
176*c243e490SMarcel Moolenaar     int m_fd;
177*c243e490SMarcel Moolenaar };
178*c243e490SMarcel Moolenaar #define CONNECT_STREAM(type) \
179*c243e490SMarcel Moolenaar     { .m_base = BASE_STREAM(connect_stream_init, \
180*c243e490SMarcel Moolenaar                             NULL, \
181*c243e490SMarcel Moolenaar                             connect_stream_fini, \
182*c243e490SMarcel Moolenaar                             type) }
183*c243e490SMarcel Moolenaar 
184*c243e490SMarcel Moolenaar static
185*c243e490SMarcel Moolenaar void
186*c243e490SMarcel Moolenaar connect_stream_init(void *v)
187*c243e490SMarcel Moolenaar {
188*c243e490SMarcel Moolenaar     struct connect_stream *s = v;
189*c243e490SMarcel Moolenaar     int src_fd;
190*c243e490SMarcel Moolenaar 
191*c243e490SMarcel Moolenaar     switch (s->m_base.m_type) {
192*c243e490SMarcel Moolenaar     case stdout_type:
193*c243e490SMarcel Moolenaar         src_fd = STDOUT_FILENO;
194*c243e490SMarcel Moolenaar         s->m_fd = open("stdout", O_WRONLY | O_CREAT | O_TRUNC, 0644);
195*c243e490SMarcel Moolenaar         break;
196*c243e490SMarcel Moolenaar     case stderr_type:
197*c243e490SMarcel Moolenaar         src_fd = STDERR_FILENO;
198*c243e490SMarcel Moolenaar         s->m_fd = open("stderr", O_WRONLY | O_CREAT | O_TRUNC, 0644);
199*c243e490SMarcel Moolenaar         break;
200*c243e490SMarcel Moolenaar     default:
201*c243e490SMarcel Moolenaar         UNREACHABLE;
202*c243e490SMarcel Moolenaar         src_fd = -1;
203*c243e490SMarcel Moolenaar     }
204*c243e490SMarcel Moolenaar     ATF_REQUIRE(s->m_fd != -1);
205*c243e490SMarcel Moolenaar 
206*c243e490SMarcel Moolenaar     s->m_base.m_sb_ptr = &s->m_base.m_sb;
207*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_connect(&s->m_base.m_sb, src_fd, s->m_fd));
208*c243e490SMarcel Moolenaar }
209*c243e490SMarcel Moolenaar 
210*c243e490SMarcel Moolenaar static
211*c243e490SMarcel Moolenaar void
212*c243e490SMarcel Moolenaar connect_stream_fini(void *v)
213*c243e490SMarcel Moolenaar {
214*c243e490SMarcel Moolenaar     struct connect_stream *s = v;
215*c243e490SMarcel Moolenaar 
216*c243e490SMarcel Moolenaar     ATF_REQUIRE(close(s->m_fd) != -1);
217*c243e490SMarcel Moolenaar 
218*c243e490SMarcel Moolenaar     atf_process_stream_fini(&s->m_base.m_sb);
219*c243e490SMarcel Moolenaar 
220*c243e490SMarcel Moolenaar     check_file(s->m_base.m_type);
221*c243e490SMarcel Moolenaar }
222*c243e490SMarcel Moolenaar 
223*c243e490SMarcel Moolenaar struct inherit_stream {
224*c243e490SMarcel Moolenaar     struct base_stream m_base;
225*c243e490SMarcel Moolenaar     int m_fd;
226*c243e490SMarcel Moolenaar 
227*c243e490SMarcel Moolenaar     int m_old_fd;
228*c243e490SMarcel Moolenaar };
229*c243e490SMarcel Moolenaar #define INHERIT_STREAM(type) \
230*c243e490SMarcel Moolenaar     { .m_base = BASE_STREAM(inherit_stream_init, \
231*c243e490SMarcel Moolenaar                             NULL, \
232*c243e490SMarcel Moolenaar                             inherit_stream_fini, \
233*c243e490SMarcel Moolenaar                             type) }
234*c243e490SMarcel Moolenaar 
235*c243e490SMarcel Moolenaar static
236*c243e490SMarcel Moolenaar void
237*c243e490SMarcel Moolenaar inherit_stream_init(void *v)
238*c243e490SMarcel Moolenaar {
239*c243e490SMarcel Moolenaar     struct inherit_stream *s = v;
240*c243e490SMarcel Moolenaar     const char *name;
241*c243e490SMarcel Moolenaar 
242*c243e490SMarcel Moolenaar     s->m_base.m_sb_ptr = &s->m_base.m_sb;
243*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_inherit(&s->m_base.m_sb));
244*c243e490SMarcel Moolenaar 
245*c243e490SMarcel Moolenaar     switch (s->m_base.m_type) {
246*c243e490SMarcel Moolenaar     case stdout_type:
247*c243e490SMarcel Moolenaar         s->m_fd = STDOUT_FILENO;
248*c243e490SMarcel Moolenaar         name = "stdout";
249*c243e490SMarcel Moolenaar         break;
250*c243e490SMarcel Moolenaar     case stderr_type:
251*c243e490SMarcel Moolenaar         s->m_fd = STDERR_FILENO;
252*c243e490SMarcel Moolenaar         name = "stderr";
253*c243e490SMarcel Moolenaar         break;
254*c243e490SMarcel Moolenaar     default:
255*c243e490SMarcel Moolenaar         UNREACHABLE;
256*c243e490SMarcel Moolenaar         name = NULL;
257*c243e490SMarcel Moolenaar     }
258*c243e490SMarcel Moolenaar 
259*c243e490SMarcel Moolenaar     s->m_old_fd = dup(s->m_fd);
260*c243e490SMarcel Moolenaar     ATF_REQUIRE(s->m_old_fd != -1);
261*c243e490SMarcel Moolenaar     ATF_REQUIRE(close(s->m_fd) != -1);
262*c243e490SMarcel Moolenaar     ATF_REQUIRE_EQ(open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644),
263*c243e490SMarcel Moolenaar                    s->m_fd);
264*c243e490SMarcel Moolenaar }
265*c243e490SMarcel Moolenaar 
266*c243e490SMarcel Moolenaar static
267*c243e490SMarcel Moolenaar void
268*c243e490SMarcel Moolenaar inherit_stream_fini(void *v)
269*c243e490SMarcel Moolenaar {
270*c243e490SMarcel Moolenaar     struct inherit_stream *s = v;
271*c243e490SMarcel Moolenaar 
272*c243e490SMarcel Moolenaar     ATF_REQUIRE(dup2(s->m_old_fd, s->m_fd) != -1);
273*c243e490SMarcel Moolenaar     ATF_REQUIRE(close(s->m_old_fd) != -1);
274*c243e490SMarcel Moolenaar 
275*c243e490SMarcel Moolenaar     atf_process_stream_fini(&s->m_base.m_sb);
276*c243e490SMarcel Moolenaar 
277*c243e490SMarcel Moolenaar     check_file(s->m_base.m_type);
278*c243e490SMarcel Moolenaar }
279*c243e490SMarcel Moolenaar 
280*c243e490SMarcel Moolenaar #define default_stream inherit_stream
281*c243e490SMarcel Moolenaar #define DEFAULT_STREAM(type) \
282*c243e490SMarcel Moolenaar     { .m_base = BASE_STREAM(default_stream_init, \
283*c243e490SMarcel Moolenaar                             NULL, \
284*c243e490SMarcel Moolenaar                             default_stream_fini, \
285*c243e490SMarcel Moolenaar                             type) }
286*c243e490SMarcel Moolenaar 
287*c243e490SMarcel Moolenaar static
288*c243e490SMarcel Moolenaar void
289*c243e490SMarcel Moolenaar default_stream_init(void *v)
290*c243e490SMarcel Moolenaar {
291*c243e490SMarcel Moolenaar     struct inherit_stream *s = v;
292*c243e490SMarcel Moolenaar 
293*c243e490SMarcel Moolenaar     inherit_stream_init(v);
294*c243e490SMarcel Moolenaar     s->m_base.m_sb_ptr = NULL;
295*c243e490SMarcel Moolenaar }
296*c243e490SMarcel Moolenaar 
297*c243e490SMarcel Moolenaar static
298*c243e490SMarcel Moolenaar void
299*c243e490SMarcel Moolenaar default_stream_fini(void *v)
300*c243e490SMarcel Moolenaar {
301*c243e490SMarcel Moolenaar     inherit_stream_fini(v);
302*c243e490SMarcel Moolenaar }
303*c243e490SMarcel Moolenaar 
304*c243e490SMarcel Moolenaar struct redirect_fd_stream {
305*c243e490SMarcel Moolenaar     struct base_stream m_base;
306*c243e490SMarcel Moolenaar 
307*c243e490SMarcel Moolenaar     int m_fd;
308*c243e490SMarcel Moolenaar };
309*c243e490SMarcel Moolenaar #define REDIRECT_FD_STREAM(type) \
310*c243e490SMarcel Moolenaar     { .m_base = BASE_STREAM(redirect_fd_stream_init, \
311*c243e490SMarcel Moolenaar                             NULL, \
312*c243e490SMarcel Moolenaar                             redirect_fd_stream_fini, \
313*c243e490SMarcel Moolenaar                             type) }
314*c243e490SMarcel Moolenaar 
315*c243e490SMarcel Moolenaar static
316*c243e490SMarcel Moolenaar void
317*c243e490SMarcel Moolenaar redirect_fd_stream_init(void *v)
318*c243e490SMarcel Moolenaar {
319*c243e490SMarcel Moolenaar     struct redirect_fd_stream *s = v;
320*c243e490SMarcel Moolenaar 
321*c243e490SMarcel Moolenaar     switch (s->m_base.m_type) {
322*c243e490SMarcel Moolenaar     case stdout_type:
323*c243e490SMarcel Moolenaar         s->m_fd = open("stdout", O_WRONLY | O_CREAT | O_TRUNC, 0644);
324*c243e490SMarcel Moolenaar         break;
325*c243e490SMarcel Moolenaar     case stderr_type:
326*c243e490SMarcel Moolenaar         s->m_fd = open("stderr", O_WRONLY | O_CREAT | O_TRUNC, 0644);
327*c243e490SMarcel Moolenaar         break;
328*c243e490SMarcel Moolenaar     default:
329*c243e490SMarcel Moolenaar         UNREACHABLE;
330*c243e490SMarcel Moolenaar     }
331*c243e490SMarcel Moolenaar     ATF_REQUIRE(s->m_fd != -1);
332*c243e490SMarcel Moolenaar 
333*c243e490SMarcel Moolenaar     s->m_base.m_sb_ptr = &s->m_base.m_sb;
334*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_redirect_fd(&s->m_base.m_sb, s->m_fd));
335*c243e490SMarcel Moolenaar }
336*c243e490SMarcel Moolenaar 
337*c243e490SMarcel Moolenaar static
338*c243e490SMarcel Moolenaar void
339*c243e490SMarcel Moolenaar redirect_fd_stream_fini(void *v)
340*c243e490SMarcel Moolenaar {
341*c243e490SMarcel Moolenaar     struct redirect_fd_stream *s = v;
342*c243e490SMarcel Moolenaar 
343*c243e490SMarcel Moolenaar     ATF_REQUIRE(close(s->m_fd) != -1);
344*c243e490SMarcel Moolenaar 
345*c243e490SMarcel Moolenaar     atf_process_stream_fini(&s->m_base.m_sb);
346*c243e490SMarcel Moolenaar 
347*c243e490SMarcel Moolenaar     check_file(s->m_base.m_type);
348*c243e490SMarcel Moolenaar }
349*c243e490SMarcel Moolenaar 
350*c243e490SMarcel Moolenaar struct redirect_path_stream {
351*c243e490SMarcel Moolenaar     struct base_stream m_base;
352*c243e490SMarcel Moolenaar 
353*c243e490SMarcel Moolenaar     atf_fs_path_t m_path;
354*c243e490SMarcel Moolenaar };
355*c243e490SMarcel Moolenaar #define REDIRECT_PATH_STREAM(type) \
356*c243e490SMarcel Moolenaar     { .m_base = BASE_STREAM(redirect_path_stream_init, \
357*c243e490SMarcel Moolenaar                             NULL, \
358*c243e490SMarcel Moolenaar                             redirect_path_stream_fini, \
359*c243e490SMarcel Moolenaar                             type) }
360*c243e490SMarcel Moolenaar 
361*c243e490SMarcel Moolenaar static
362*c243e490SMarcel Moolenaar void
363*c243e490SMarcel Moolenaar redirect_path_stream_init(void *v)
364*c243e490SMarcel Moolenaar {
365*c243e490SMarcel Moolenaar     struct redirect_path_stream *s = v;
366*c243e490SMarcel Moolenaar 
367*c243e490SMarcel Moolenaar     switch (s->m_base.m_type) {
368*c243e490SMarcel Moolenaar     case stdout_type:
369*c243e490SMarcel Moolenaar         RE(atf_fs_path_init_fmt(&s->m_path, "stdout"));
370*c243e490SMarcel Moolenaar         break;
371*c243e490SMarcel Moolenaar     case stderr_type:
372*c243e490SMarcel Moolenaar         RE(atf_fs_path_init_fmt(&s->m_path, "stderr"));
373*c243e490SMarcel Moolenaar         break;
374*c243e490SMarcel Moolenaar     default:
375*c243e490SMarcel Moolenaar         UNREACHABLE;
376*c243e490SMarcel Moolenaar     }
377*c243e490SMarcel Moolenaar 
378*c243e490SMarcel Moolenaar     s->m_base.m_sb_ptr = &s->m_base.m_sb;
379*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_redirect_path(&s->m_base.m_sb, &s->m_path));
380*c243e490SMarcel Moolenaar }
381*c243e490SMarcel Moolenaar 
382*c243e490SMarcel Moolenaar static
383*c243e490SMarcel Moolenaar void
384*c243e490SMarcel Moolenaar redirect_path_stream_fini(void *v)
385*c243e490SMarcel Moolenaar {
386*c243e490SMarcel Moolenaar     struct redirect_path_stream *s = v;
387*c243e490SMarcel Moolenaar 
388*c243e490SMarcel Moolenaar     atf_process_stream_fini(&s->m_base.m_sb);
389*c243e490SMarcel Moolenaar 
390*c243e490SMarcel Moolenaar     atf_fs_path_fini(&s->m_path);
391*c243e490SMarcel Moolenaar 
392*c243e490SMarcel Moolenaar     check_file(s->m_base.m_type);
393*c243e490SMarcel Moolenaar }
394*c243e490SMarcel Moolenaar 
395*c243e490SMarcel Moolenaar static void child_print(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
396*c243e490SMarcel Moolenaar 
397*c243e490SMarcel Moolenaar struct child_print_data {
398*c243e490SMarcel Moolenaar     const char *m_msg;
399*c243e490SMarcel Moolenaar };
400*c243e490SMarcel Moolenaar 
401*c243e490SMarcel Moolenaar static
402*c243e490SMarcel Moolenaar void
403*c243e490SMarcel Moolenaar child_print(void *v)
404*c243e490SMarcel Moolenaar {
405*c243e490SMarcel Moolenaar     struct child_print_data *cpd = v;
406*c243e490SMarcel Moolenaar 
407*c243e490SMarcel Moolenaar     fprintf(stdout, "stdout: %s\n", cpd->m_msg);
408*c243e490SMarcel Moolenaar     fprintf(stderr, "stderr: %s\n", cpd->m_msg);
409*c243e490SMarcel Moolenaar 
410*c243e490SMarcel Moolenaar     exit(EXIT_SUCCESS);
411*c243e490SMarcel Moolenaar }
412*c243e490SMarcel Moolenaar 
413*c243e490SMarcel Moolenaar static
414*c243e490SMarcel Moolenaar void
415*c243e490SMarcel Moolenaar do_fork(const struct base_stream *outfs, void *out,
416*c243e490SMarcel Moolenaar         const struct base_stream *errfs, void *err)
417*c243e490SMarcel Moolenaar {
418*c243e490SMarcel Moolenaar     atf_process_child_t child;
419*c243e490SMarcel Moolenaar     atf_process_status_t status;
420*c243e490SMarcel Moolenaar     struct child_print_data cpd = { "msg" };
421*c243e490SMarcel Moolenaar 
422*c243e490SMarcel Moolenaar     outfs->init(out);
423*c243e490SMarcel Moolenaar     errfs->init(err);
424*c243e490SMarcel Moolenaar 
425*c243e490SMarcel Moolenaar     RE(atf_process_fork(&child, child_print, outfs->m_sb_ptr,
426*c243e490SMarcel Moolenaar                         errfs->m_sb_ptr, &cpd));
427*c243e490SMarcel Moolenaar     if (outfs->process != NULL)
428*c243e490SMarcel Moolenaar         outfs->process(out, &child);
429*c243e490SMarcel Moolenaar     if (errfs->process != NULL)
430*c243e490SMarcel Moolenaar         errfs->process(err, &child);
431*c243e490SMarcel Moolenaar     RE(atf_process_child_wait(&child, &status));
432*c243e490SMarcel Moolenaar 
433*c243e490SMarcel Moolenaar     outfs->fini(out);
434*c243e490SMarcel Moolenaar     errfs->fini(err);
435*c243e490SMarcel Moolenaar 
436*c243e490SMarcel Moolenaar     atf_process_status_fini(&status);
437*c243e490SMarcel Moolenaar }
438*c243e490SMarcel Moolenaar 
439*c243e490SMarcel Moolenaar /* ---------------------------------------------------------------------
440*c243e490SMarcel Moolenaar  * Test cases for the "stream" type.
441*c243e490SMarcel Moolenaar  * --------------------------------------------------------------------- */
442*c243e490SMarcel Moolenaar 
443*c243e490SMarcel Moolenaar ATF_TC(stream_init_capture);
444*c243e490SMarcel Moolenaar ATF_TC_HEAD(stream_init_capture, tc)
445*c243e490SMarcel Moolenaar {
446*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the "
447*c243e490SMarcel Moolenaar                       "atf_process_stream_init_capture function");
448*c243e490SMarcel Moolenaar }
449*c243e490SMarcel Moolenaar ATF_TC_BODY(stream_init_capture, tc)
450*c243e490SMarcel Moolenaar {
451*c243e490SMarcel Moolenaar     atf_process_stream_t sb;
452*c243e490SMarcel Moolenaar 
453*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_capture(&sb));
454*c243e490SMarcel Moolenaar 
455*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_stream_type(&sb),
456*c243e490SMarcel Moolenaar                  atf_process_stream_type_capture);
457*c243e490SMarcel Moolenaar 
458*c243e490SMarcel Moolenaar     atf_process_stream_fini(&sb);
459*c243e490SMarcel Moolenaar }
460*c243e490SMarcel Moolenaar 
461*c243e490SMarcel Moolenaar ATF_TC(stream_init_connect);
462*c243e490SMarcel Moolenaar ATF_TC_HEAD(stream_init_connect, tc)
463*c243e490SMarcel Moolenaar {
464*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the "
465*c243e490SMarcel Moolenaar                       "atf_process_stream_init_connect function");
466*c243e490SMarcel Moolenaar }
467*c243e490SMarcel Moolenaar ATF_TC_BODY(stream_init_connect, tc)
468*c243e490SMarcel Moolenaar {
469*c243e490SMarcel Moolenaar     atf_process_stream_t sb;
470*c243e490SMarcel Moolenaar 
471*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_connect(&sb, 1, 2));
472*c243e490SMarcel Moolenaar 
473*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_stream_type(&sb),
474*c243e490SMarcel Moolenaar                  atf_process_stream_type_connect);
475*c243e490SMarcel Moolenaar 
476*c243e490SMarcel Moolenaar     atf_process_stream_fini(&sb);
477*c243e490SMarcel Moolenaar }
478*c243e490SMarcel Moolenaar 
479*c243e490SMarcel Moolenaar ATF_TC(stream_init_inherit);
480*c243e490SMarcel Moolenaar ATF_TC_HEAD(stream_init_inherit, tc)
481*c243e490SMarcel Moolenaar {
482*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the "
483*c243e490SMarcel Moolenaar                       "atf_process_stream_init_inherit function");
484*c243e490SMarcel Moolenaar }
485*c243e490SMarcel Moolenaar ATF_TC_BODY(stream_init_inherit, tc)
486*c243e490SMarcel Moolenaar {
487*c243e490SMarcel Moolenaar     atf_process_stream_t sb;
488*c243e490SMarcel Moolenaar 
489*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_inherit(&sb));
490*c243e490SMarcel Moolenaar 
491*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_stream_type(&sb),
492*c243e490SMarcel Moolenaar                  atf_process_stream_type_inherit);
493*c243e490SMarcel Moolenaar 
494*c243e490SMarcel Moolenaar     atf_process_stream_fini(&sb);
495*c243e490SMarcel Moolenaar }
496*c243e490SMarcel Moolenaar 
497*c243e490SMarcel Moolenaar ATF_TC(stream_init_redirect_fd);
498*c243e490SMarcel Moolenaar ATF_TC_HEAD(stream_init_redirect_fd, tc)
499*c243e490SMarcel Moolenaar {
500*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the "
501*c243e490SMarcel Moolenaar                       "atf_process_stream_init_redirect_fd function");
502*c243e490SMarcel Moolenaar }
503*c243e490SMarcel Moolenaar ATF_TC_BODY(stream_init_redirect_fd, tc)
504*c243e490SMarcel Moolenaar {
505*c243e490SMarcel Moolenaar     atf_process_stream_t sb;
506*c243e490SMarcel Moolenaar 
507*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_redirect_fd(&sb, 1));
508*c243e490SMarcel Moolenaar 
509*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_stream_type(&sb),
510*c243e490SMarcel Moolenaar                  atf_process_stream_type_redirect_fd);
511*c243e490SMarcel Moolenaar 
512*c243e490SMarcel Moolenaar     atf_process_stream_fini(&sb);
513*c243e490SMarcel Moolenaar }
514*c243e490SMarcel Moolenaar 
515*c243e490SMarcel Moolenaar ATF_TC(stream_init_redirect_path);
516*c243e490SMarcel Moolenaar ATF_TC_HEAD(stream_init_redirect_path, tc)
517*c243e490SMarcel Moolenaar {
518*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the "
519*c243e490SMarcel Moolenaar                       "atf_process_stream_init_redirect_path function");
520*c243e490SMarcel Moolenaar }
521*c243e490SMarcel Moolenaar ATF_TC_BODY(stream_init_redirect_path, tc)
522*c243e490SMarcel Moolenaar {
523*c243e490SMarcel Moolenaar     atf_process_stream_t sb;
524*c243e490SMarcel Moolenaar     atf_fs_path_t path;
525*c243e490SMarcel Moolenaar 
526*c243e490SMarcel Moolenaar     RE(atf_fs_path_init_fmt(&path, "foo"));
527*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_redirect_path(&sb, &path));
528*c243e490SMarcel Moolenaar 
529*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_stream_type(&sb),
530*c243e490SMarcel Moolenaar                  atf_process_stream_type_redirect_path);
531*c243e490SMarcel Moolenaar 
532*c243e490SMarcel Moolenaar     atf_process_stream_fini(&sb);
533*c243e490SMarcel Moolenaar     atf_fs_path_fini(&path);
534*c243e490SMarcel Moolenaar }
535*c243e490SMarcel Moolenaar 
536*c243e490SMarcel Moolenaar /* ---------------------------------------------------------------------
537*c243e490SMarcel Moolenaar  * Test cases for the "status" type.
538*c243e490SMarcel Moolenaar  * --------------------------------------------------------------------- */
539*c243e490SMarcel Moolenaar 
540*c243e490SMarcel Moolenaar static void child_exit_success(void) ATF_DEFS_ATTRIBUTE_NORETURN;
541*c243e490SMarcel Moolenaar static void child_exit_failure(void) ATF_DEFS_ATTRIBUTE_NORETURN;
542*c243e490SMarcel Moolenaar static void child_sigkill(void) ATF_DEFS_ATTRIBUTE_NORETURN;
543*c243e490SMarcel Moolenaar static void child_sigquit(void) ATF_DEFS_ATTRIBUTE_NORETURN;
544*c243e490SMarcel Moolenaar static void child_sigterm(void) ATF_DEFS_ATTRIBUTE_NORETURN;
545*c243e490SMarcel Moolenaar 
546*c243e490SMarcel Moolenaar void
547*c243e490SMarcel Moolenaar child_exit_success(void)
548*c243e490SMarcel Moolenaar {
549*c243e490SMarcel Moolenaar     exit(EXIT_SUCCESS);
550*c243e490SMarcel Moolenaar }
551*c243e490SMarcel Moolenaar 
552*c243e490SMarcel Moolenaar void
553*c243e490SMarcel Moolenaar child_exit_failure(void)
554*c243e490SMarcel Moolenaar {
555*c243e490SMarcel Moolenaar     exit(EXIT_FAILURE);
556*c243e490SMarcel Moolenaar }
557*c243e490SMarcel Moolenaar 
558*c243e490SMarcel Moolenaar void
559*c243e490SMarcel Moolenaar child_sigkill(void)
560*c243e490SMarcel Moolenaar {
561*c243e490SMarcel Moolenaar     kill(getpid(), SIGKILL);
562*c243e490SMarcel Moolenaar     abort();
563*c243e490SMarcel Moolenaar }
564*c243e490SMarcel Moolenaar 
565*c243e490SMarcel Moolenaar void
566*c243e490SMarcel Moolenaar child_sigquit(void)
567*c243e490SMarcel Moolenaar {
568*c243e490SMarcel Moolenaar     kill(getpid(), SIGQUIT);
569*c243e490SMarcel Moolenaar     abort();
570*c243e490SMarcel Moolenaar }
571*c243e490SMarcel Moolenaar 
572*c243e490SMarcel Moolenaar void
573*c243e490SMarcel Moolenaar child_sigterm(void)
574*c243e490SMarcel Moolenaar {
575*c243e490SMarcel Moolenaar     kill(getpid(), SIGTERM);
576*c243e490SMarcel Moolenaar     abort();
577*c243e490SMarcel Moolenaar }
578*c243e490SMarcel Moolenaar 
579*c243e490SMarcel Moolenaar static
580*c243e490SMarcel Moolenaar int
581*c243e490SMarcel Moolenaar fork_and_wait_child(void (*child_func)(void))
582*c243e490SMarcel Moolenaar {
583*c243e490SMarcel Moolenaar     pid_t pid;
584*c243e490SMarcel Moolenaar     int status;
585*c243e490SMarcel Moolenaar 
586*c243e490SMarcel Moolenaar     pid = fork();
587*c243e490SMarcel Moolenaar     ATF_REQUIRE(pid != -1);
588*c243e490SMarcel Moolenaar     if (pid == 0) {
589*c243e490SMarcel Moolenaar         status = 0; /* Silence compiler warnings */
590*c243e490SMarcel Moolenaar         child_func();
591*c243e490SMarcel Moolenaar         UNREACHABLE;
592*c243e490SMarcel Moolenaar     } else {
593*c243e490SMarcel Moolenaar         ATF_REQUIRE(waitpid(pid, &status, 0) != 0);
594*c243e490SMarcel Moolenaar     }
595*c243e490SMarcel Moolenaar 
596*c243e490SMarcel Moolenaar     return status;
597*c243e490SMarcel Moolenaar }
598*c243e490SMarcel Moolenaar 
599*c243e490SMarcel Moolenaar ATF_TC(status_exited);
600*c243e490SMarcel Moolenaar ATF_TC_HEAD(status_exited, tc)
601*c243e490SMarcel Moolenaar {
602*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the status type for processes "
603*c243e490SMarcel Moolenaar                       "that exit cleanly");
604*c243e490SMarcel Moolenaar }
605*c243e490SMarcel Moolenaar ATF_TC_BODY(status_exited, tc)
606*c243e490SMarcel Moolenaar {
607*c243e490SMarcel Moolenaar     {
608*c243e490SMarcel Moolenaar         const int rawstatus = fork_and_wait_child(child_exit_success);
609*c243e490SMarcel Moolenaar         atf_process_status_t s;
610*c243e490SMarcel Moolenaar         RE(atf_process_status_init(&s, rawstatus));
611*c243e490SMarcel Moolenaar         ATF_CHECK(atf_process_status_exited(&s));
612*c243e490SMarcel Moolenaar         ATF_CHECK_EQ(atf_process_status_exitstatus(&s), EXIT_SUCCESS);
613*c243e490SMarcel Moolenaar         ATF_CHECK(!atf_process_status_signaled(&s));
614*c243e490SMarcel Moolenaar         atf_process_status_fini(&s);
615*c243e490SMarcel Moolenaar     }
616*c243e490SMarcel Moolenaar 
617*c243e490SMarcel Moolenaar     {
618*c243e490SMarcel Moolenaar         const int rawstatus = fork_and_wait_child(child_exit_failure);
619*c243e490SMarcel Moolenaar         atf_process_status_t s;
620*c243e490SMarcel Moolenaar         RE(atf_process_status_init(&s, rawstatus));
621*c243e490SMarcel Moolenaar         ATF_CHECK(atf_process_status_exited(&s));
622*c243e490SMarcel Moolenaar         ATF_CHECK_EQ(atf_process_status_exitstatus(&s), EXIT_FAILURE);
623*c243e490SMarcel Moolenaar         ATF_CHECK(!atf_process_status_signaled(&s));
624*c243e490SMarcel Moolenaar         atf_process_status_fini(&s);
625*c243e490SMarcel Moolenaar     }
626*c243e490SMarcel Moolenaar }
627*c243e490SMarcel Moolenaar 
628*c243e490SMarcel Moolenaar ATF_TC(status_signaled);
629*c243e490SMarcel Moolenaar ATF_TC_HEAD(status_signaled, tc)
630*c243e490SMarcel Moolenaar {
631*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the status type for processes "
632*c243e490SMarcel Moolenaar                       "that end due to a signal");
633*c243e490SMarcel Moolenaar }
634*c243e490SMarcel Moolenaar ATF_TC_BODY(status_signaled, tc)
635*c243e490SMarcel Moolenaar {
636*c243e490SMarcel Moolenaar     {
637*c243e490SMarcel Moolenaar         const int rawstatus = fork_and_wait_child(child_sigkill);
638*c243e490SMarcel Moolenaar         atf_process_status_t s;
639*c243e490SMarcel Moolenaar         RE(atf_process_status_init(&s, rawstatus));
640*c243e490SMarcel Moolenaar         ATF_CHECK(!atf_process_status_exited(&s));
641*c243e490SMarcel Moolenaar         ATF_CHECK(atf_process_status_signaled(&s));
642*c243e490SMarcel Moolenaar         ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGKILL);
643*c243e490SMarcel Moolenaar         ATF_CHECK(!atf_process_status_coredump(&s));
644*c243e490SMarcel Moolenaar         atf_process_status_fini(&s);
645*c243e490SMarcel Moolenaar     }
646*c243e490SMarcel Moolenaar 
647*c243e490SMarcel Moolenaar     {
648*c243e490SMarcel Moolenaar         const int rawstatus = fork_and_wait_child(child_sigterm);
649*c243e490SMarcel Moolenaar         atf_process_status_t s;
650*c243e490SMarcel Moolenaar         RE(atf_process_status_init(&s, rawstatus));
651*c243e490SMarcel Moolenaar         ATF_CHECK(!atf_process_status_exited(&s));
652*c243e490SMarcel Moolenaar         ATF_CHECK(atf_process_status_signaled(&s));
653*c243e490SMarcel Moolenaar         ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGTERM);
654*c243e490SMarcel Moolenaar         ATF_CHECK(!atf_process_status_coredump(&s));
655*c243e490SMarcel Moolenaar         atf_process_status_fini(&s);
656*c243e490SMarcel Moolenaar     }
657*c243e490SMarcel Moolenaar }
658*c243e490SMarcel Moolenaar 
659*c243e490SMarcel Moolenaar ATF_TC(status_coredump);
660*c243e490SMarcel Moolenaar ATF_TC_HEAD(status_coredump, tc)
661*c243e490SMarcel Moolenaar {
662*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the status type for processes "
663*c243e490SMarcel Moolenaar                       "that crash");
664*c243e490SMarcel Moolenaar }
665*c243e490SMarcel Moolenaar ATF_TC_BODY(status_coredump, tc)
666*c243e490SMarcel Moolenaar {
667*c243e490SMarcel Moolenaar     struct rlimit rl;
668*c243e490SMarcel Moolenaar     rl.rlim_cur = RLIM_INFINITY;
669*c243e490SMarcel Moolenaar     rl.rlim_max = RLIM_INFINITY;
670*c243e490SMarcel Moolenaar     if (setrlimit(RLIMIT_CORE, &rl) == -1)
671*c243e490SMarcel Moolenaar         atf_tc_skip("Cannot unlimit the core file size; check limits "
672*c243e490SMarcel Moolenaar                     "manually");
673*c243e490SMarcel Moolenaar 
674*c243e490SMarcel Moolenaar     const int rawstatus = fork_and_wait_child(child_sigquit);
675*c243e490SMarcel Moolenaar     atf_process_status_t s;
676*c243e490SMarcel Moolenaar     RE(atf_process_status_init(&s, rawstatus));
677*c243e490SMarcel Moolenaar     ATF_CHECK(!atf_process_status_exited(&s));
678*c243e490SMarcel Moolenaar     ATF_CHECK(atf_process_status_signaled(&s));
679*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGQUIT);
680*c243e490SMarcel Moolenaar     ATF_CHECK(atf_process_status_coredump(&s));
681*c243e490SMarcel Moolenaar     atf_process_status_fini(&s);
682*c243e490SMarcel Moolenaar }
683*c243e490SMarcel Moolenaar 
684*c243e490SMarcel Moolenaar /* ---------------------------------------------------------------------
685*c243e490SMarcel Moolenaar  * Test cases for the "child" type.
686*c243e490SMarcel Moolenaar  * --------------------------------------------------------------------- */
687*c243e490SMarcel Moolenaar 
688*c243e490SMarcel Moolenaar static void child_report_pid(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
689*c243e490SMarcel Moolenaar 
690*c243e490SMarcel Moolenaar static
691*c243e490SMarcel Moolenaar void
692*c243e490SMarcel Moolenaar child_report_pid(void *v ATF_DEFS_ATTRIBUTE_UNUSED)
693*c243e490SMarcel Moolenaar {
694*c243e490SMarcel Moolenaar     const pid_t pid = getpid();
695*c243e490SMarcel Moolenaar     if (write(STDOUT_FILENO, &pid, sizeof(pid)) != sizeof(pid))
696*c243e490SMarcel Moolenaar         abort();
697*c243e490SMarcel Moolenaar     fprintf(stderr, "Reporting %d to parent\n", (int)getpid());
698*c243e490SMarcel Moolenaar     exit(EXIT_SUCCESS);
699*c243e490SMarcel Moolenaar }
700*c243e490SMarcel Moolenaar 
701*c243e490SMarcel Moolenaar ATF_TC(child_pid);
702*c243e490SMarcel Moolenaar ATF_TC_HEAD(child_pid, tc)
703*c243e490SMarcel Moolenaar {
704*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the correctness of the pid "
705*c243e490SMarcel Moolenaar                       "stored in the child type");
706*c243e490SMarcel Moolenaar }
707*c243e490SMarcel Moolenaar ATF_TC_BODY(child_pid, tc)
708*c243e490SMarcel Moolenaar {
709*c243e490SMarcel Moolenaar     atf_process_stream_t outsb, errsb;
710*c243e490SMarcel Moolenaar     atf_process_child_t child;
711*c243e490SMarcel Moolenaar     atf_process_status_t status;
712*c243e490SMarcel Moolenaar     pid_t pid;
713*c243e490SMarcel Moolenaar 
714*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_capture(&outsb));
715*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_inherit(&errsb));
716*c243e490SMarcel Moolenaar 
717*c243e490SMarcel Moolenaar     RE(atf_process_fork(&child, child_report_pid, &outsb, &errsb, NULL));
718*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(read(atf_process_child_stdout(&child), &pid, sizeof(pid)),
719*c243e490SMarcel Moolenaar                  sizeof(pid));
720*c243e490SMarcel Moolenaar     printf("Expected PID: %d\n", (int)atf_process_child_pid(&child));
721*c243e490SMarcel Moolenaar     printf("Actual PID: %d\n", (int)pid);
722*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_child_pid(&child), pid);
723*c243e490SMarcel Moolenaar 
724*c243e490SMarcel Moolenaar     RE(atf_process_child_wait(&child, &status));
725*c243e490SMarcel Moolenaar     atf_process_status_fini(&status);
726*c243e490SMarcel Moolenaar 
727*c243e490SMarcel Moolenaar     atf_process_stream_fini(&outsb);
728*c243e490SMarcel Moolenaar     atf_process_stream_fini(&errsb);
729*c243e490SMarcel Moolenaar }
730*c243e490SMarcel Moolenaar 
731*c243e490SMarcel Moolenaar static
732*c243e490SMarcel Moolenaar void
733*c243e490SMarcel Moolenaar child_loop(void *v ATF_DEFS_ATTRIBUTE_UNUSED)
734*c243e490SMarcel Moolenaar {
735*c243e490SMarcel Moolenaar     for (;;)
736*c243e490SMarcel Moolenaar         sleep(1);
737*c243e490SMarcel Moolenaar }
738*c243e490SMarcel Moolenaar 
739*c243e490SMarcel Moolenaar static
740*c243e490SMarcel Moolenaar void
741*c243e490SMarcel Moolenaar nop_signal(int sig ATF_DEFS_ATTRIBUTE_UNUSED)
742*c243e490SMarcel Moolenaar {
743*c243e490SMarcel Moolenaar }
744*c243e490SMarcel Moolenaar 
745*c243e490SMarcel Moolenaar static
746*c243e490SMarcel Moolenaar void
747*c243e490SMarcel Moolenaar child_spawn_loop_and_wait_eintr(void *v ATF_DEFS_ATTRIBUTE_UNUSED)
748*c243e490SMarcel Moolenaar {
749*c243e490SMarcel Moolenaar     atf_process_child_t child;
750*c243e490SMarcel Moolenaar     atf_process_status_t status;
751*c243e490SMarcel Moolenaar     struct sigaction sighup, old_sighup;
752*c243e490SMarcel Moolenaar 
753*c243e490SMarcel Moolenaar #define RE_ABORT(expr) \
754*c243e490SMarcel Moolenaar     do { \
755*c243e490SMarcel Moolenaar         atf_error_t _aux_err = expr; \
756*c243e490SMarcel Moolenaar         if (atf_is_error(_aux_err)) { \
757*c243e490SMarcel Moolenaar             atf_error_free(_aux_err); \
758*c243e490SMarcel Moolenaar             abort(); \
759*c243e490SMarcel Moolenaar         } \
760*c243e490SMarcel Moolenaar     } while (0)
761*c243e490SMarcel Moolenaar 
762*c243e490SMarcel Moolenaar     {
763*c243e490SMarcel Moolenaar         atf_process_stream_t outsb, errsb;
764*c243e490SMarcel Moolenaar 
765*c243e490SMarcel Moolenaar         RE_ABORT(atf_process_stream_init_capture(&outsb));
766*c243e490SMarcel Moolenaar         RE_ABORT(atf_process_stream_init_inherit(&errsb));
767*c243e490SMarcel Moolenaar         RE_ABORT(atf_process_fork(&child, child_loop, &outsb, &errsb, NULL));
768*c243e490SMarcel Moolenaar         atf_process_stream_fini(&outsb);
769*c243e490SMarcel Moolenaar         atf_process_stream_fini(&errsb);
770*c243e490SMarcel Moolenaar     }
771*c243e490SMarcel Moolenaar 
772*c243e490SMarcel Moolenaar     sighup.sa_handler = nop_signal;
773*c243e490SMarcel Moolenaar     sigemptyset(&sighup.sa_mask);
774*c243e490SMarcel Moolenaar     sighup.sa_flags = 0;
775*c243e490SMarcel Moolenaar     if (sigaction(SIGHUP, &sighup, &old_sighup) == -1)
776*c243e490SMarcel Moolenaar         abort();
777*c243e490SMarcel Moolenaar 
778*c243e490SMarcel Moolenaar     printf("waiting\n");
779*c243e490SMarcel Moolenaar     fflush(stdout);
780*c243e490SMarcel Moolenaar 
781*c243e490SMarcel Moolenaar     fprintf(stderr, "Child entering wait(2)\n");
782*c243e490SMarcel Moolenaar     atf_error_t err = atf_process_child_wait(&child, &status);
783*c243e490SMarcel Moolenaar     fprintf(stderr, "Child's wait(2) terminated\n");
784*c243e490SMarcel Moolenaar     if (!atf_is_error(err)) {
785*c243e490SMarcel Moolenaar         fprintf(stderr, "wait completed successfully (not interrupted)\n");
786*c243e490SMarcel Moolenaar         abort();
787*c243e490SMarcel Moolenaar     }
788*c243e490SMarcel Moolenaar     if (!atf_error_is(err, "libc")) {
789*c243e490SMarcel Moolenaar         fprintf(stderr, "wait did not raise libc_error\n");
790*c243e490SMarcel Moolenaar         abort();
791*c243e490SMarcel Moolenaar     }
792*c243e490SMarcel Moolenaar     if (atf_libc_error_code(err) != EINTR) {
793*c243e490SMarcel Moolenaar         fprintf(stderr, "libc_error is not EINTR\n");
794*c243e490SMarcel Moolenaar         abort();
795*c243e490SMarcel Moolenaar     }
796*c243e490SMarcel Moolenaar     atf_error_free(err);
797*c243e490SMarcel Moolenaar 
798*c243e490SMarcel Moolenaar     sigaction(SIGHUP, &old_sighup, NULL);
799*c243e490SMarcel Moolenaar 
800*c243e490SMarcel Moolenaar     fprintf(stderr, "Child is killing subchild\n");
801*c243e490SMarcel Moolenaar     kill(atf_process_child_pid(&child), SIGTERM);
802*c243e490SMarcel Moolenaar 
803*c243e490SMarcel Moolenaar     RE_ABORT(atf_process_child_wait(&child, &status));
804*c243e490SMarcel Moolenaar     atf_process_status_fini(&status);
805*c243e490SMarcel Moolenaar 
806*c243e490SMarcel Moolenaar #undef RE_ABORT
807*c243e490SMarcel Moolenaar 
808*c243e490SMarcel Moolenaar     exit(EXIT_SUCCESS);
809*c243e490SMarcel Moolenaar }
810*c243e490SMarcel Moolenaar 
811*c243e490SMarcel Moolenaar ATF_TC(child_wait_eintr);
812*c243e490SMarcel Moolenaar ATF_TC_HEAD(child_wait_eintr, tc)
813*c243e490SMarcel Moolenaar {
814*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests the interruption of the wait "
815*c243e490SMarcel Moolenaar                       "method by an external signal, and the return of "
816*c243e490SMarcel Moolenaar                       "an EINTR error");
817*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "timeout", "30");
818*c243e490SMarcel Moolenaar }
819*c243e490SMarcel Moolenaar ATF_TC_BODY(child_wait_eintr, tc)
820*c243e490SMarcel Moolenaar {
821*c243e490SMarcel Moolenaar     atf_process_child_t child;
822*c243e490SMarcel Moolenaar     atf_process_status_t status;
823*c243e490SMarcel Moolenaar 
824*c243e490SMarcel Moolenaar     {
825*c243e490SMarcel Moolenaar         atf_process_stream_t outsb, errsb;
826*c243e490SMarcel Moolenaar 
827*c243e490SMarcel Moolenaar         RE(atf_process_stream_init_capture(&outsb));
828*c243e490SMarcel Moolenaar         RE(atf_process_stream_init_inherit(&errsb));
829*c243e490SMarcel Moolenaar         RE(atf_process_fork(&child, child_spawn_loop_and_wait_eintr,
830*c243e490SMarcel Moolenaar                             &outsb, &errsb, NULL));
831*c243e490SMarcel Moolenaar         atf_process_stream_fini(&outsb);
832*c243e490SMarcel Moolenaar         atf_process_stream_fini(&errsb);
833*c243e490SMarcel Moolenaar     }
834*c243e490SMarcel Moolenaar 
835*c243e490SMarcel Moolenaar     {
836*c243e490SMarcel Moolenaar         /* Wait until the child process performs the wait call.  This is
837*c243e490SMarcel Moolenaar          * racy, because the message we get from it is sent *before*
838*c243e490SMarcel Moolenaar          * doing the real system call... but I can't figure any other way
839*c243e490SMarcel Moolenaar          * to do this. */
840*c243e490SMarcel Moolenaar         char buf[16];
841*c243e490SMarcel Moolenaar         printf("Waiting for child to issue wait(2)\n");
842*c243e490SMarcel Moolenaar         ATF_REQUIRE(read(atf_process_child_stdout(&child), buf,
843*c243e490SMarcel Moolenaar                          sizeof(buf)) > 0);
844*c243e490SMarcel Moolenaar         sleep(1);
845*c243e490SMarcel Moolenaar     }
846*c243e490SMarcel Moolenaar 
847*c243e490SMarcel Moolenaar     printf("Interrupting child's wait(2) call\n");
848*c243e490SMarcel Moolenaar     kill(atf_process_child_pid(&child), SIGHUP);
849*c243e490SMarcel Moolenaar 
850*c243e490SMarcel Moolenaar     printf("Waiting for child's completion\n");
851*c243e490SMarcel Moolenaar     RE(atf_process_child_wait(&child, &status));
852*c243e490SMarcel Moolenaar     ATF_REQUIRE(atf_process_status_exited(&status));
853*c243e490SMarcel Moolenaar     ATF_REQUIRE_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS);
854*c243e490SMarcel Moolenaar     atf_process_status_fini(&status);
855*c243e490SMarcel Moolenaar }
856*c243e490SMarcel Moolenaar 
857*c243e490SMarcel Moolenaar /* ---------------------------------------------------------------------
858*c243e490SMarcel Moolenaar  * Tests cases for the free functions.
859*c243e490SMarcel Moolenaar  * --------------------------------------------------------------------- */
860*c243e490SMarcel Moolenaar 
861*c243e490SMarcel Moolenaar static
862*c243e490SMarcel Moolenaar void
863*c243e490SMarcel Moolenaar do_exec(const atf_tc_t *tc, const char *helper_name, atf_process_status_t *s,
864*c243e490SMarcel Moolenaar         void (*prehook)(void))
865*c243e490SMarcel Moolenaar {
866*c243e490SMarcel Moolenaar     atf_fs_path_t process_helpers;
867*c243e490SMarcel Moolenaar     const char *argv[3];
868*c243e490SMarcel Moolenaar 
869*c243e490SMarcel Moolenaar     get_process_helpers_path(tc, true, &process_helpers);
870*c243e490SMarcel Moolenaar 
871*c243e490SMarcel Moolenaar     argv[0] = atf_fs_path_cstring(&process_helpers);
872*c243e490SMarcel Moolenaar     argv[1] = helper_name;
873*c243e490SMarcel Moolenaar     argv[2] = NULL;
874*c243e490SMarcel Moolenaar     printf("Executing %s %s\n", argv[0], argv[1]);
875*c243e490SMarcel Moolenaar 
876*c243e490SMarcel Moolenaar     RE(atf_process_exec_array(s, &process_helpers, argv, NULL, NULL, prehook));
877*c243e490SMarcel Moolenaar     atf_fs_path_fini(&process_helpers);
878*c243e490SMarcel Moolenaar }
879*c243e490SMarcel Moolenaar 
880*c243e490SMarcel Moolenaar static
881*c243e490SMarcel Moolenaar void
882*c243e490SMarcel Moolenaar check_line(int fd, const char *exp)
883*c243e490SMarcel Moolenaar {
884*c243e490SMarcel Moolenaar     atf_dynstr_t line;
885*c243e490SMarcel Moolenaar     bool eof;
886*c243e490SMarcel Moolenaar 
887*c243e490SMarcel Moolenaar     atf_dynstr_init(&line);
888*c243e490SMarcel Moolenaar     eof = read_line(fd, &line);
889*c243e490SMarcel Moolenaar     ATF_CHECK(!eof);
890*c243e490SMarcel Moolenaar     ATF_CHECK_MSG(atf_equal_dynstr_cstring(&line, exp),
891*c243e490SMarcel Moolenaar                   "read: '%s', expected: '%s'",
892*c243e490SMarcel Moolenaar                   atf_dynstr_cstring(&line), exp);
893*c243e490SMarcel Moolenaar     atf_dynstr_fini(&line);
894*c243e490SMarcel Moolenaar }
895*c243e490SMarcel Moolenaar 
896*c243e490SMarcel Moolenaar ATF_TC(exec_failure);
897*c243e490SMarcel Moolenaar ATF_TC_HEAD(exec_failure, tc)
898*c243e490SMarcel Moolenaar {
899*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests execing a command");
900*c243e490SMarcel Moolenaar }
901*c243e490SMarcel Moolenaar ATF_TC_BODY(exec_failure, tc)
902*c243e490SMarcel Moolenaar {
903*c243e490SMarcel Moolenaar     atf_process_status_t status;
904*c243e490SMarcel Moolenaar 
905*c243e490SMarcel Moolenaar     do_exec(tc, "exit-failure", &status, NULL);
906*c243e490SMarcel Moolenaar     ATF_CHECK(atf_process_status_exited(&status));
907*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_FAILURE);
908*c243e490SMarcel Moolenaar     atf_process_status_fini(&status);
909*c243e490SMarcel Moolenaar }
910*c243e490SMarcel Moolenaar 
911*c243e490SMarcel Moolenaar ATF_TC(exec_list);
912*c243e490SMarcel Moolenaar ATF_TC_HEAD(exec_list, tc)
913*c243e490SMarcel Moolenaar {
914*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests execing a command");
915*c243e490SMarcel Moolenaar }
916*c243e490SMarcel Moolenaar ATF_TC_BODY(exec_list, tc)
917*c243e490SMarcel Moolenaar {
918*c243e490SMarcel Moolenaar     atf_fs_path_t process_helpers;
919*c243e490SMarcel Moolenaar     atf_list_t argv;
920*c243e490SMarcel Moolenaar     atf_process_status_t status;
921*c243e490SMarcel Moolenaar 
922*c243e490SMarcel Moolenaar     RE(atf_list_init(&argv));
923*c243e490SMarcel Moolenaar 
924*c243e490SMarcel Moolenaar     get_process_helpers_path(tc, true, &process_helpers);
925*c243e490SMarcel Moolenaar     atf_list_append(&argv, strdup(atf_fs_path_cstring(&process_helpers)), true);
926*c243e490SMarcel Moolenaar     atf_list_append(&argv, strdup("echo"), true);
927*c243e490SMarcel Moolenaar     atf_list_append(&argv, strdup("test-message"), true);
928*c243e490SMarcel Moolenaar     {
929*c243e490SMarcel Moolenaar         atf_fs_path_t outpath;
930*c243e490SMarcel Moolenaar         atf_process_stream_t outsb;
931*c243e490SMarcel Moolenaar 
932*c243e490SMarcel Moolenaar         RE(atf_fs_path_init_fmt(&outpath, "stdout"));
933*c243e490SMarcel Moolenaar         RE(atf_process_stream_init_redirect_path(&outsb, &outpath));
934*c243e490SMarcel Moolenaar         RE(atf_process_exec_list(&status, &process_helpers, &argv, &outsb,
935*c243e490SMarcel Moolenaar                                  NULL, NULL));
936*c243e490SMarcel Moolenaar         atf_process_stream_fini(&outsb);
937*c243e490SMarcel Moolenaar         atf_fs_path_fini(&outpath);
938*c243e490SMarcel Moolenaar     }
939*c243e490SMarcel Moolenaar     atf_list_fini(&argv);
940*c243e490SMarcel Moolenaar 
941*c243e490SMarcel Moolenaar     ATF_CHECK(atf_process_status_exited(&status));
942*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS);
943*c243e490SMarcel Moolenaar 
944*c243e490SMarcel Moolenaar     {
945*c243e490SMarcel Moolenaar         int fd = open("stdout", O_RDONLY);
946*c243e490SMarcel Moolenaar         ATF_CHECK(fd != -1);
947*c243e490SMarcel Moolenaar         check_line(fd, "test-message");
948*c243e490SMarcel Moolenaar         close(fd);
949*c243e490SMarcel Moolenaar     }
950*c243e490SMarcel Moolenaar 
951*c243e490SMarcel Moolenaar     atf_process_status_fini(&status);
952*c243e490SMarcel Moolenaar     atf_fs_path_fini(&process_helpers);
953*c243e490SMarcel Moolenaar }
954*c243e490SMarcel Moolenaar 
955*c243e490SMarcel Moolenaar static void
956*c243e490SMarcel Moolenaar exit_early(void)
957*c243e490SMarcel Moolenaar {
958*c243e490SMarcel Moolenaar     exit(80);
959*c243e490SMarcel Moolenaar }
960*c243e490SMarcel Moolenaar 
961*c243e490SMarcel Moolenaar ATF_TC(exec_prehook);
962*c243e490SMarcel Moolenaar ATF_TC_HEAD(exec_prehook, tc)
963*c243e490SMarcel Moolenaar {
964*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests execing a command with a prehook");
965*c243e490SMarcel Moolenaar }
966*c243e490SMarcel Moolenaar ATF_TC_BODY(exec_prehook, tc)
967*c243e490SMarcel Moolenaar {
968*c243e490SMarcel Moolenaar     atf_process_status_t status;
969*c243e490SMarcel Moolenaar 
970*c243e490SMarcel Moolenaar     do_exec(tc, "exit-success", &status, exit_early);
971*c243e490SMarcel Moolenaar     ATF_CHECK(atf_process_status_exited(&status));
972*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_status_exitstatus(&status), 80);
973*c243e490SMarcel Moolenaar     atf_process_status_fini(&status);
974*c243e490SMarcel Moolenaar }
975*c243e490SMarcel Moolenaar 
976*c243e490SMarcel Moolenaar ATF_TC(exec_success);
977*c243e490SMarcel Moolenaar ATF_TC_HEAD(exec_success, tc)
978*c243e490SMarcel Moolenaar {
979*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests execing a command");
980*c243e490SMarcel Moolenaar }
981*c243e490SMarcel Moolenaar ATF_TC_BODY(exec_success, tc)
982*c243e490SMarcel Moolenaar {
983*c243e490SMarcel Moolenaar     atf_process_status_t status;
984*c243e490SMarcel Moolenaar 
985*c243e490SMarcel Moolenaar     do_exec(tc, "exit-success", &status, NULL);
986*c243e490SMarcel Moolenaar     ATF_CHECK(atf_process_status_exited(&status));
987*c243e490SMarcel Moolenaar     ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS);
988*c243e490SMarcel Moolenaar     atf_process_status_fini(&status);
989*c243e490SMarcel Moolenaar }
990*c243e490SMarcel Moolenaar 
991*c243e490SMarcel Moolenaar static const int exit_v_null = 1;
992*c243e490SMarcel Moolenaar static const int exit_v_notnull = 2;
993*c243e490SMarcel Moolenaar 
994*c243e490SMarcel Moolenaar static
995*c243e490SMarcel Moolenaar void
996*c243e490SMarcel Moolenaar child_cookie(void *v)
997*c243e490SMarcel Moolenaar {
998*c243e490SMarcel Moolenaar     if (v == NULL)
999*c243e490SMarcel Moolenaar         exit(exit_v_null);
1000*c243e490SMarcel Moolenaar     else
1001*c243e490SMarcel Moolenaar         exit(exit_v_notnull);
1002*c243e490SMarcel Moolenaar 
1003*c243e490SMarcel Moolenaar     UNREACHABLE;
1004*c243e490SMarcel Moolenaar }
1005*c243e490SMarcel Moolenaar 
1006*c243e490SMarcel Moolenaar ATF_TC(fork_cookie);
1007*c243e490SMarcel Moolenaar ATF_TC_HEAD(fork_cookie, tc)
1008*c243e490SMarcel Moolenaar {
1009*c243e490SMarcel Moolenaar     atf_tc_set_md_var(tc, "descr", "Tests forking a child, with "
1010*c243e490SMarcel Moolenaar                       "a null and non-null data cookie");
1011*c243e490SMarcel Moolenaar }
1012*c243e490SMarcel Moolenaar ATF_TC_BODY(fork_cookie, tc)
1013*c243e490SMarcel Moolenaar {
1014*c243e490SMarcel Moolenaar     atf_process_stream_t outsb, errsb;
1015*c243e490SMarcel Moolenaar 
1016*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_inherit(&outsb));
1017*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_inherit(&errsb));
1018*c243e490SMarcel Moolenaar 
1019*c243e490SMarcel Moolenaar     {
1020*c243e490SMarcel Moolenaar         atf_process_child_t child;
1021*c243e490SMarcel Moolenaar         atf_process_status_t status;
1022*c243e490SMarcel Moolenaar 
1023*c243e490SMarcel Moolenaar         RE(atf_process_fork(&child, child_cookie, &outsb, &errsb, NULL));
1024*c243e490SMarcel Moolenaar         RE(atf_process_child_wait(&child, &status));
1025*c243e490SMarcel Moolenaar 
1026*c243e490SMarcel Moolenaar         ATF_CHECK(atf_process_status_exited(&status));
1027*c243e490SMarcel Moolenaar         ATF_CHECK_EQ(atf_process_status_exitstatus(&status), exit_v_null);
1028*c243e490SMarcel Moolenaar 
1029*c243e490SMarcel Moolenaar         atf_process_status_fini(&status);
1030*c243e490SMarcel Moolenaar     }
1031*c243e490SMarcel Moolenaar 
1032*c243e490SMarcel Moolenaar     {
1033*c243e490SMarcel Moolenaar         atf_process_child_t child;
1034*c243e490SMarcel Moolenaar         atf_process_status_t status;
1035*c243e490SMarcel Moolenaar         int dummy_int;
1036*c243e490SMarcel Moolenaar 
1037*c243e490SMarcel Moolenaar         RE(atf_process_fork(&child, child_cookie, &outsb, &errsb, &dummy_int));
1038*c243e490SMarcel Moolenaar         RE(atf_process_child_wait(&child, &status));
1039*c243e490SMarcel Moolenaar 
1040*c243e490SMarcel Moolenaar         ATF_CHECK(atf_process_status_exited(&status));
1041*c243e490SMarcel Moolenaar         ATF_CHECK_EQ(atf_process_status_exitstatus(&status), exit_v_notnull);
1042*c243e490SMarcel Moolenaar 
1043*c243e490SMarcel Moolenaar         atf_process_status_fini(&status);
1044*c243e490SMarcel Moolenaar     }
1045*c243e490SMarcel Moolenaar 
1046*c243e490SMarcel Moolenaar     atf_process_stream_fini(&errsb);
1047*c243e490SMarcel Moolenaar     atf_process_stream_fini(&outsb);
1048*c243e490SMarcel Moolenaar }
1049*c243e490SMarcel Moolenaar 
1050*c243e490SMarcel Moolenaar #define TC_FORK_STREAMS(outlc, outuc, errlc, erruc) \
1051*c243e490SMarcel Moolenaar     ATF_TC(fork_out_ ## outlc ## _err_ ## errlc); \
1052*c243e490SMarcel Moolenaar     ATF_TC_HEAD(fork_out_ ## outlc ## _err_ ## errlc, tc) \
1053*c243e490SMarcel Moolenaar     { \
1054*c243e490SMarcel Moolenaar         atf_tc_set_md_var(tc, "descr", "Tests forking a child, with " \
1055*c243e490SMarcel Moolenaar                           "stdout " #outlc " and stderr " #errlc); \
1056*c243e490SMarcel Moolenaar     } \
1057*c243e490SMarcel Moolenaar     ATF_TC_BODY(fork_out_ ## outlc ## _err_ ## errlc, tc) \
1058*c243e490SMarcel Moolenaar     { \
1059*c243e490SMarcel Moolenaar         struct outlc ## _stream out = outuc ## _STREAM(stdout_type); \
1060*c243e490SMarcel Moolenaar         struct errlc ## _stream err = erruc ## _STREAM(stderr_type); \
1061*c243e490SMarcel Moolenaar         do_fork(&out.m_base, &out, &err.m_base, &err); \
1062*c243e490SMarcel Moolenaar     }
1063*c243e490SMarcel Moolenaar 
1064*c243e490SMarcel Moolenaar TC_FORK_STREAMS(capture, CAPTURE, capture, CAPTURE);
1065*c243e490SMarcel Moolenaar TC_FORK_STREAMS(capture, CAPTURE, connect, CONNECT);
1066*c243e490SMarcel Moolenaar TC_FORK_STREAMS(capture, CAPTURE, default, DEFAULT);
1067*c243e490SMarcel Moolenaar TC_FORK_STREAMS(capture, CAPTURE, inherit, INHERIT);
1068*c243e490SMarcel Moolenaar TC_FORK_STREAMS(capture, CAPTURE, redirect_fd, REDIRECT_FD);
1069*c243e490SMarcel Moolenaar TC_FORK_STREAMS(capture, CAPTURE, redirect_path, REDIRECT_PATH);
1070*c243e490SMarcel Moolenaar TC_FORK_STREAMS(connect, CONNECT, capture, CAPTURE);
1071*c243e490SMarcel Moolenaar TC_FORK_STREAMS(connect, CONNECT, connect, CONNECT);
1072*c243e490SMarcel Moolenaar TC_FORK_STREAMS(connect, CONNECT, default, DEFAULT);
1073*c243e490SMarcel Moolenaar TC_FORK_STREAMS(connect, CONNECT, inherit, INHERIT);
1074*c243e490SMarcel Moolenaar TC_FORK_STREAMS(connect, CONNECT, redirect_fd, REDIRECT_FD);
1075*c243e490SMarcel Moolenaar TC_FORK_STREAMS(connect, CONNECT, redirect_path, REDIRECT_PATH);
1076*c243e490SMarcel Moolenaar TC_FORK_STREAMS(default, DEFAULT, capture, CAPTURE);
1077*c243e490SMarcel Moolenaar TC_FORK_STREAMS(default, DEFAULT, connect, CONNECT);
1078*c243e490SMarcel Moolenaar TC_FORK_STREAMS(default, DEFAULT, default, DEFAULT);
1079*c243e490SMarcel Moolenaar TC_FORK_STREAMS(default, DEFAULT, inherit, INHERIT);
1080*c243e490SMarcel Moolenaar TC_FORK_STREAMS(default, DEFAULT, redirect_fd, REDIRECT_FD);
1081*c243e490SMarcel Moolenaar TC_FORK_STREAMS(default, DEFAULT, redirect_path, REDIRECT_PATH);
1082*c243e490SMarcel Moolenaar TC_FORK_STREAMS(inherit, INHERIT, capture, CAPTURE);
1083*c243e490SMarcel Moolenaar TC_FORK_STREAMS(inherit, INHERIT, connect, CONNECT);
1084*c243e490SMarcel Moolenaar TC_FORK_STREAMS(inherit, INHERIT, default, DEFAULT);
1085*c243e490SMarcel Moolenaar TC_FORK_STREAMS(inherit, INHERIT, inherit, INHERIT);
1086*c243e490SMarcel Moolenaar TC_FORK_STREAMS(inherit, INHERIT, redirect_fd, REDIRECT_FD);
1087*c243e490SMarcel Moolenaar TC_FORK_STREAMS(inherit, INHERIT, redirect_path, REDIRECT_PATH);
1088*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, capture, CAPTURE);
1089*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, connect, CONNECT);
1090*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, default, DEFAULT);
1091*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, inherit, INHERIT);
1092*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, redirect_fd, REDIRECT_FD);
1093*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, redirect_path, REDIRECT_PATH);
1094*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, capture, CAPTURE);
1095*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, connect, CONNECT);
1096*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, default, DEFAULT);
1097*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, inherit, INHERIT);
1098*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, redirect_fd, REDIRECT_FD);
1099*c243e490SMarcel Moolenaar TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, redirect_path, REDIRECT_PATH);
1100*c243e490SMarcel Moolenaar 
1101*c243e490SMarcel Moolenaar #undef TC_FORK_STREAMS
1102*c243e490SMarcel Moolenaar 
1103*c243e490SMarcel Moolenaar /* ---------------------------------------------------------------------
1104*c243e490SMarcel Moolenaar  * Main.
1105*c243e490SMarcel Moolenaar  * --------------------------------------------------------------------- */
1106*c243e490SMarcel Moolenaar 
1107*c243e490SMarcel Moolenaar ATF_TP_ADD_TCS(tp)
1108*c243e490SMarcel Moolenaar {
1109*c243e490SMarcel Moolenaar     /* Add the tests for the "stream" type. */
1110*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, stream_init_capture);
1111*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, stream_init_connect);
1112*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, stream_init_inherit);
1113*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, stream_init_redirect_fd);
1114*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, stream_init_redirect_path);
1115*c243e490SMarcel Moolenaar 
1116*c243e490SMarcel Moolenaar     /* Add the tests for the "status" type. */
1117*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, status_exited);
1118*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, status_signaled);
1119*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, status_coredump);
1120*c243e490SMarcel Moolenaar 
1121*c243e490SMarcel Moolenaar     /* Add the tests for the "child" type. */
1122*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, child_pid);
1123*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, child_wait_eintr);
1124*c243e490SMarcel Moolenaar 
1125*c243e490SMarcel Moolenaar     /* Add the tests for the free functions. */
1126*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, exec_failure);
1127*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, exec_list);
1128*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, exec_prehook);
1129*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, exec_success);
1130*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_cookie);
1131*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_capture_err_capture);
1132*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_capture_err_connect);
1133*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_capture_err_default);
1134*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_capture_err_inherit);
1135*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_capture_err_redirect_fd);
1136*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_capture_err_redirect_path);
1137*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_connect_err_capture);
1138*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_connect_err_connect);
1139*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_connect_err_default);
1140*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_connect_err_inherit);
1141*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_connect_err_redirect_fd);
1142*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_connect_err_redirect_path);
1143*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_default_err_capture);
1144*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_default_err_connect);
1145*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_default_err_default);
1146*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_default_err_inherit);
1147*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_default_err_redirect_fd);
1148*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_default_err_redirect_path);
1149*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_inherit_err_capture);
1150*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_inherit_err_connect);
1151*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_inherit_err_default);
1152*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_inherit_err_inherit);
1153*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_inherit_err_redirect_fd);
1154*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_inherit_err_redirect_path);
1155*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_capture);
1156*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_connect);
1157*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_default);
1158*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_inherit);
1159*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_redirect_fd);
1160*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_redirect_path);
1161*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_capture);
1162*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_connect);
1163*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_default);
1164*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_inherit);
1165*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_redirect_fd);
1166*c243e490SMarcel Moolenaar     ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_redirect_path);
1167*c243e490SMarcel Moolenaar 
1168*c243e490SMarcel Moolenaar     return atf_no_error();
1169*c243e490SMarcel Moolenaar }
1170