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