t_wait_noproc.c revision 313535
1/* $NetBSD: t_wait_noproc.c,v 1.5 2016/11/09 17:50:19 kamil Exp $ */
2
3/*-
4 * Copyright (c) 2016 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__RCSID("$NetBSD: t_wait_noproc.c,v 1.5 2016/11/09 17:50:19 kamil Exp $");
31
32#ifdef __FreeBSD__
33#include <sys/param.h> /* For NBBY -- it's in sys/types.h on NetBSD */
34#endif
35#include <sys/wait.h>
36#include <sys/resource.h>
37
38#include <errno.h>
39#include <stdio.h>
40
41#include <atf-c.h>
42
43#ifndef TWAIT_OPTION
44#define TWAIT_OPTION 0
45#endif
46
47#if TWAIT_OPTION == 0
48ATF_TC(wait);
49ATF_TC_HEAD(wait, tc)
50{
51	atf_tc_set_md_var(tc, "descr",
52	    "Test that wait(2) returns ECHILD for no child");
53}
54
55ATF_TC_BODY(wait, tc)
56{
57	ATF_REQUIRE_ERRNO(ECHILD, wait(NULL) == -1);
58}
59#endif
60
61ATF_TC(waitpid);
62ATF_TC_HEAD(waitpid, tc)
63{
64	atf_tc_set_md_var(tc, "descr",
65	    "Test that waitpid(2) returns ECHILD for WAIT_ANY and option %s",
66	    ___STRING(TWAIT_OPTION));
67}
68
69ATF_TC_BODY(waitpid, tc)
70{
71	ATF_REQUIRE_ERRNO(ECHILD, waitpid(WAIT_ANY, NULL, TWAIT_OPTION) == -1);
72}
73
74ATF_TC(waitid);
75ATF_TC_HEAD(waitid, tc)
76{
77	atf_tc_set_md_var(tc, "descr",
78	    "Test that waitid(2) returns ECHILD for P_ALL and option %s",
79	    ___STRING(TWAIT_OPTION));
80}
81
82ATF_TC_BODY(waitid, tc)
83{
84	ATF_REQUIRE_ERRNO(ECHILD,
85	    waitid(P_ALL, 0, NULL,
86	        WTRAPPED | WEXITED | TWAIT_OPTION) == -1);
87}
88
89ATF_TC(wait3);
90ATF_TC_HEAD(wait3, tc)
91{
92	atf_tc_set_md_var(tc, "descr",
93	    "Test that wait3(2) returns ECHILD for no child");
94}
95
96ATF_TC_BODY(wait3, tc)
97{
98	ATF_REQUIRE_ERRNO(ECHILD, wait3(NULL, TWAIT_OPTION, NULL) == -1);
99}
100
101ATF_TC(wait4);
102ATF_TC_HEAD(wait4, tc)
103{
104	atf_tc_set_md_var(tc, "descr",
105	    "Test that wait4(2) returns ECHILD for WAIT_ANY and option %s",
106	    ___STRING(TWAIT_OPTION));
107}
108
109ATF_TC_BODY(wait4, tc)
110{
111	ATF_REQUIRE_ERRNO(ECHILD,
112	    wait4(WAIT_ANY, NULL, TWAIT_OPTION, NULL) == -1);
113}
114
115ATF_TC(wait6);
116ATF_TC_HEAD(wait6, tc)
117{
118	atf_tc_set_md_var(tc, "descr",
119	    "Test that wait6(2) returns ECHILD for P_ALL and option %s",
120	    ___STRING(TWAIT_OPTION));
121}
122
123ATF_TC_BODY(wait6, tc)
124{
125	ATF_REQUIRE_ERRNO(ECHILD,
126	    wait6(P_ALL, 0, NULL,
127	        WTRAPPED | WEXITED | TWAIT_OPTION, NULL, NULL) == -1);
128}
129
130/*
131 * Generator of valid combinations of options
132 * Usage: i = 0; while ((o = get_options_wait6(i++)) != -1) {}
133 */
134static int
135get_options6(size_t pos)
136{
137	int rv = 0;
138	size_t n;
139
140	/*
141	 * waitid(2) must specify at least one of WEXITED, WUNTRACED,
142	 * WSTOPPED, WTRAPPED or WCONTINUED. Single option WNOWAIT
143	 * isn't valid.
144	 */
145
146	const int matrix[] = {
147		WNOWAIT,	/* First in order to blacklist it easily */
148		WEXITED,
149		WUNTRACED,
150		WSTOPPED,	/* SUS compatibility, equal to WUNTRACED */
151		WTRAPPED,
152		WCONTINUED
153	};
154
155	const size_t M = (1 << __arraycount(matrix)) - 1;
156
157	/* Skip empty and sole WNOWAIT option */
158	pos+=2;
159
160	if (pos > M)
161		return -1;
162
163	for (n = 0; n < __arraycount(matrix); n++) {
164		if (pos & __BIT(n))
165			rv |= matrix[n];
166	}
167
168	return rv;
169}
170
171/*
172 * Generator of valid combinations of options
173 * Usage: i = 0; while ((o = get_options_wait4(i++)) != -1) {}
174 */
175static int
176get_options4(size_t pos)
177{
178	int rv = 0;
179	size_t n;
180
181	const int special[] = {
182		0,
183#ifdef	__NetBSD__
184		WALLSIG,
185		WALTSIG,
186		__WALL,		/* Linux compatibility, equal to WALLSIG */
187		__WCLONE	/* Linux compatibility, equal to WALTSIG */
188#endif
189	};
190
191	const int matrix[] = {
192		WNOWAIT,
193		WEXITED,
194		WUNTRACED,
195		WSTOPPED,	/* SUS compatibility, equal to WUNTRACED */
196		WTRAPPED,
197		WCONTINUED
198	};
199
200	const size_t M = (1 << __arraycount(special)) - 1;
201
202	if (pos < __arraycount(special))
203		return special[pos];
204
205	pos -= __arraycount(special);
206
207	++pos; /* Don't start with empty mask */
208
209	if (pos > M)
210		return -1;
211
212	for (n = 0; n < __arraycount(special); n++) {
213		if (pos & __BIT(n))
214			rv |= matrix[n];
215	}
216
217	return rv;
218}
219
220ATF_TC(waitpid_options);
221ATF_TC_HEAD(waitpid_options, tc)
222{
223	atf_tc_set_md_var(tc, "descr",
224	    "Test that waitpid(2) returns ECHILD for WAIT_ANY and valid "
225	    "combination of options with%s WNOHANG",
226	    TWAIT_OPTION == 0 ? "out" : "");
227}
228
229ATF_TC_BODY(waitpid_options, tc)
230{
231	size_t i = 0;
232	int o;
233
234	while((o = get_options4(i++)) != -1) {
235		printf("Testing waitpid(2) with options %x\n", o);
236
237		ATF_REQUIRE_ERRNO(ECHILD,
238		    waitpid(WAIT_ANY, NULL, o | TWAIT_OPTION) == -1);
239	}
240}
241
242ATF_TC(waitid_options);
243ATF_TC_HEAD(waitid_options, tc)
244{
245	atf_tc_set_md_var(tc, "descr",
246	    "Test that waitid(2) returns ECHILD for P_ALL and valid "
247	    "combination of options with%s WNOHANG",
248	    TWAIT_OPTION == 0 ? "out" : "");
249}
250
251ATF_TC_BODY(waitid_options, tc)
252{
253	size_t i = 0;
254	int o;
255
256	while((o = get_options6(i++)) != -1) {
257		printf("Testing waitid(2) with options %x\n", o);
258
259		ATF_REQUIRE_ERRNO(ECHILD,
260		    waitid(P_ALL, 0, NULL, o | TWAIT_OPTION) == -1);
261	}
262}
263
264ATF_TC(wait3_options);
265ATF_TC_HEAD(wait3_options, tc)
266{
267	atf_tc_set_md_var(tc, "descr",
268	    "Test that wait3(2) returns ECHILD for no child");
269}
270
271ATF_TC_BODY(wait3_options, tc)
272{
273	size_t i = 0;
274	int o;
275
276	while((o = get_options4(i++)) != -1) {
277		printf("Testing wait3(2) with options %x\n", o);
278
279		ATF_REQUIRE_ERRNO(ECHILD,
280		    wait3(NULL, o | TWAIT_OPTION, NULL) == -1);
281	}
282}
283
284ATF_TC(wait4_options);
285ATF_TC_HEAD(wait4_options, tc)
286{
287	atf_tc_set_md_var(tc, "descr",
288	    "Test that wait4(2) returns ECHILD for WAIT_ANY and option %s",
289	    ___STRING(TWAIT_OPTION));
290}
291
292ATF_TC_BODY(wait4_options, tc)
293{
294	size_t i = 0;
295	int o;
296
297	while((o = get_options4(i++)) != -1) {
298		printf("Testing wait4(2) with options %x\n", o);
299
300		ATF_REQUIRE_ERRNO(ECHILD,
301		    wait4(WAIT_ANY, NULL, o | TWAIT_OPTION, NULL) == -1);
302	}
303}
304
305ATF_TC(wait6_options);
306ATF_TC_HEAD(wait6_options, tc)
307{
308	atf_tc_set_md_var(tc, "descr",
309	    "Test that wait6(2) returns ECHILD for P_ALL and option %s",
310	    ___STRING(TWAIT_OPTION));
311}
312
313ATF_TC_BODY(wait6_options, tc)
314{
315	size_t i = 0;
316	int o;
317
318	while((o = get_options6(i++)) != -1) {
319		printf("Testing wait6(2) with options %x\n", o);
320
321		ATF_REQUIRE_ERRNO(ECHILD,
322		    wait6(P_ALL, 0, NULL, o | TWAIT_OPTION, NULL, NULL) == -1);
323	}
324}
325
326ATF_TP_ADD_TCS(tp)
327{
328
329#if TWAIT_OPTION == 0
330	ATF_TP_ADD_TC(tp, wait);
331#endif
332	ATF_TP_ADD_TC(tp, waitpid);
333	ATF_TP_ADD_TC(tp, waitid);
334	ATF_TP_ADD_TC(tp, wait3);
335	ATF_TP_ADD_TC(tp, wait4);
336	ATF_TP_ADD_TC(tp, wait6);
337
338	ATF_TP_ADD_TC(tp, waitpid_options);
339	ATF_TP_ADD_TC(tp, waitid_options);
340	ATF_TP_ADD_TC(tp, wait3_options);
341	ATF_TP_ADD_TC(tp, wait4_options);
342	ATF_TP_ADD_TC(tp, wait6_options);
343
344	return atf_no_error();
345}
346