t_wait_noproc.c revision 314817
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#include <sys/wait.h>
33#include <sys/resource.h>
34
35#include <errno.h>
36#include <stdio.h>
37
38#include <atf-c.h>
39
40#ifndef TWAIT_OPTION
41#define TWAIT_OPTION 0
42#endif
43
44#if TWAIT_OPTION == 0
45ATF_TC(wait);
46ATF_TC_HEAD(wait, tc)
47{
48	atf_tc_set_md_var(tc, "descr",
49	    "Test that wait(2) returns ECHILD for no child");
50}
51
52ATF_TC_BODY(wait, tc)
53{
54	ATF_REQUIRE_ERRNO(ECHILD, wait(NULL) == -1);
55}
56#endif
57
58ATF_TC(waitpid);
59ATF_TC_HEAD(waitpid, tc)
60{
61	atf_tc_set_md_var(tc, "descr",
62	    "Test that waitpid(2) returns ECHILD for WAIT_ANY and option %s",
63	    ___STRING(TWAIT_OPTION));
64}
65
66ATF_TC_BODY(waitpid, tc)
67{
68	ATF_REQUIRE_ERRNO(ECHILD, waitpid(WAIT_ANY, NULL, TWAIT_OPTION) == -1);
69}
70
71ATF_TC(waitid);
72ATF_TC_HEAD(waitid, tc)
73{
74	atf_tc_set_md_var(tc, "descr",
75	    "Test that waitid(2) returns ECHILD for P_ALL and option %s",
76	    ___STRING(TWAIT_OPTION));
77}
78
79ATF_TC_BODY(waitid, tc)
80{
81	ATF_REQUIRE_ERRNO(ECHILD,
82	    waitid(P_ALL, 0, NULL,
83	        WTRAPPED | WEXITED | TWAIT_OPTION) == -1);
84}
85
86ATF_TC(wait3);
87ATF_TC_HEAD(wait3, tc)
88{
89	atf_tc_set_md_var(tc, "descr",
90	    "Test that wait3(2) returns ECHILD for no child");
91}
92
93ATF_TC_BODY(wait3, tc)
94{
95	ATF_REQUIRE_ERRNO(ECHILD, wait3(NULL, TWAIT_OPTION, NULL) == -1);
96}
97
98ATF_TC(wait4);
99ATF_TC_HEAD(wait4, tc)
100{
101	atf_tc_set_md_var(tc, "descr",
102	    "Test that wait4(2) returns ECHILD for WAIT_ANY and option %s",
103	    ___STRING(TWAIT_OPTION));
104}
105
106ATF_TC_BODY(wait4, tc)
107{
108	ATF_REQUIRE_ERRNO(ECHILD,
109	    wait4(WAIT_ANY, NULL, TWAIT_OPTION, NULL) == -1);
110}
111
112ATF_TC(wait6);
113ATF_TC_HEAD(wait6, tc)
114{
115	atf_tc_set_md_var(tc, "descr",
116	    "Test that wait6(2) returns ECHILD for P_ALL and option %s",
117	    ___STRING(TWAIT_OPTION));
118}
119
120ATF_TC_BODY(wait6, tc)
121{
122	ATF_REQUIRE_ERRNO(ECHILD,
123	    wait6(P_ALL, 0, NULL,
124	        WTRAPPED | WEXITED | TWAIT_OPTION, NULL, NULL) == -1);
125}
126
127/*
128 * Generator of valid combinations of options
129 * Usage: i = 0; while ((o = get_options_wait6(i++)) != -1) {}
130 */
131static int
132get_options6(size_t pos)
133{
134	int rv = 0;
135	size_t n;
136
137	/*
138	 * waitid(2) must specify at least one of WEXITED, WUNTRACED,
139	 * WSTOPPED, WTRAPPED or WCONTINUED. Single option WNOWAIT
140	 * isn't valid.
141	 */
142
143	const int matrix[] = {
144		WNOWAIT,	/* First in order to blacklist it easily */
145		WEXITED,
146		WUNTRACED,
147		WSTOPPED,	/* SUS compatibility, equal to WUNTRACED */
148		WTRAPPED,
149		WCONTINUED
150	};
151
152	const size_t M = (1 << __arraycount(matrix)) - 1;
153
154	/* Skip empty and sole WNOWAIT option */
155	pos+=2;
156
157	if (pos > M)
158		return -1;
159
160	for (n = 0; n < __arraycount(matrix); n++) {
161		if (pos & __BIT(n))
162			rv |= matrix[n];
163	}
164
165	return rv;
166}
167
168/*
169 * Generator of valid combinations of options
170 * Usage: i = 0; while ((o = get_options_wait4(i++)) != -1) {}
171 */
172static int
173get_options4(size_t pos)
174{
175	int rv = 0;
176	size_t n;
177
178	const int special[] = {
179		0,
180#ifdef	__NetBSD__
181		WALLSIG,
182		WALTSIG,
183		__WALL,		/* Linux compatibility, equal to WALLSIG */
184		__WCLONE	/* Linux compatibility, equal to WALTSIG */
185#endif
186	};
187
188	const int matrix[] = {
189		WNOWAIT,
190		WEXITED,
191		WUNTRACED,
192		WSTOPPED,	/* SUS compatibility, equal to WUNTRACED */
193		WTRAPPED,
194		WCONTINUED
195	};
196
197	const size_t M = (1 << __arraycount(special)) - 1;
198
199	if (pos < __arraycount(special))
200		return special[pos];
201
202	pos -= __arraycount(special);
203
204	++pos; /* Don't start with empty mask */
205
206	if (pos > M)
207		return -1;
208
209	for (n = 0; n < __arraycount(special); n++) {
210		if (pos & __BIT(n))
211			rv |= matrix[n];
212	}
213
214	return rv;
215}
216
217ATF_TC(waitpid_options);
218ATF_TC_HEAD(waitpid_options, tc)
219{
220	atf_tc_set_md_var(tc, "descr",
221	    "Test that waitpid(2) returns ECHILD for WAIT_ANY and valid "
222	    "combination of options with%s WNOHANG",
223	    TWAIT_OPTION == 0 ? "out" : "");
224}
225
226ATF_TC_BODY(waitpid_options, tc)
227{
228	size_t i = 0;
229	int o;
230
231	while((o = get_options4(i++)) != -1) {
232		printf("Testing waitpid(2) with options %x\n", o);
233
234		ATF_REQUIRE_ERRNO(ECHILD,
235		    waitpid(WAIT_ANY, NULL, o | TWAIT_OPTION) == -1);
236	}
237}
238
239ATF_TC(waitid_options);
240ATF_TC_HEAD(waitid_options, tc)
241{
242	atf_tc_set_md_var(tc, "descr",
243	    "Test that waitid(2) returns ECHILD for P_ALL and valid "
244	    "combination of options with%s WNOHANG",
245	    TWAIT_OPTION == 0 ? "out" : "");
246}
247
248ATF_TC_BODY(waitid_options, tc)
249{
250	size_t i = 0;
251	int o;
252
253	while((o = get_options6(i++)) != -1) {
254		printf("Testing waitid(2) with options %x\n", o);
255
256		ATF_REQUIRE_ERRNO(ECHILD,
257		    waitid(P_ALL, 0, NULL, o | TWAIT_OPTION) == -1);
258	}
259}
260
261ATF_TC(wait3_options);
262ATF_TC_HEAD(wait3_options, tc)
263{
264	atf_tc_set_md_var(tc, "descr",
265	    "Test that wait3(2) returns ECHILD for no child");
266}
267
268ATF_TC_BODY(wait3_options, tc)
269{
270	size_t i = 0;
271	int o;
272
273	while((o = get_options4(i++)) != -1) {
274		printf("Testing wait3(2) with options %x\n", o);
275
276		ATF_REQUIRE_ERRNO(ECHILD,
277		    wait3(NULL, o | TWAIT_OPTION, NULL) == -1);
278	}
279}
280
281ATF_TC(wait4_options);
282ATF_TC_HEAD(wait4_options, tc)
283{
284	atf_tc_set_md_var(tc, "descr",
285	    "Test that wait4(2) returns ECHILD for WAIT_ANY and option %s",
286	    ___STRING(TWAIT_OPTION));
287}
288
289ATF_TC_BODY(wait4_options, tc)
290{
291	size_t i = 0;
292	int o;
293
294	while((o = get_options4(i++)) != -1) {
295		printf("Testing wait4(2) with options %x\n", o);
296
297		ATF_REQUIRE_ERRNO(ECHILD,
298		    wait4(WAIT_ANY, NULL, o | TWAIT_OPTION, NULL) == -1);
299	}
300}
301
302ATF_TC(wait6_options);
303ATF_TC_HEAD(wait6_options, tc)
304{
305	atf_tc_set_md_var(tc, "descr",
306	    "Test that wait6(2) returns ECHILD for P_ALL and option %s",
307	    ___STRING(TWAIT_OPTION));
308}
309
310ATF_TC_BODY(wait6_options, tc)
311{
312	size_t i = 0;
313	int o;
314
315	while((o = get_options6(i++)) != -1) {
316		printf("Testing wait6(2) with options %x\n", o);
317
318		ATF_REQUIRE_ERRNO(ECHILD,
319		    wait6(P_ALL, 0, NULL, o | TWAIT_OPTION, NULL, NULL) == -1);
320	}
321}
322
323ATF_TP_ADD_TCS(tp)
324{
325
326#if TWAIT_OPTION == 0
327	ATF_TP_ADD_TC(tp, wait);
328#endif
329	ATF_TP_ADD_TC(tp, waitpid);
330	ATF_TP_ADD_TC(tp, waitid);
331	ATF_TP_ADD_TC(tp, wait3);
332	ATF_TP_ADD_TC(tp, wait4);
333	ATF_TP_ADD_TC(tp, wait6);
334
335	ATF_TP_ADD_TC(tp, waitpid_options);
336	ATF_TP_ADD_TC(tp, waitid_options);
337	ATF_TP_ADD_TC(tp, wait3_options);
338	ATF_TP_ADD_TC(tp, wait4_options);
339	ATF_TP_ADD_TC(tp, wait6_options);
340
341	return atf_no_error();
342}
343