xref: /netbsd-src/tests/lib/libc/sys/t_wait_noproc.c (revision deb6f0161a9109e7de9b519dc8dfb9478668dcdd)
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
45 ATF_TC(wait);
46 ATF_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 
52 ATF_TC_BODY(wait, tc)
53 {
54 	ATF_REQUIRE_ERRNO(ECHILD, wait(NULL) == -1);
55 }
56 #endif
57 
58 ATF_TC(waitpid);
59 ATF_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 
66 ATF_TC_BODY(waitpid, tc)
67 {
68 	ATF_REQUIRE_ERRNO(ECHILD, waitpid(WAIT_ANY, NULL, TWAIT_OPTION) == -1);
69 }
70 
71 ATF_TC(waitid);
72 ATF_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 
79 ATF_TC_BODY(waitid, tc)
80 {
81 	ATF_REQUIRE_ERRNO(ECHILD,
82 	    waitid(P_ALL, 0, NULL,
83 	        WTRAPPED | WEXITED | TWAIT_OPTION) == -1);
84 }
85 
86 ATF_TC(wait3);
87 ATF_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 
93 ATF_TC_BODY(wait3, tc)
94 {
95 	ATF_REQUIRE_ERRNO(ECHILD, wait3(NULL, TWAIT_OPTION, NULL) == -1);
96 }
97 
98 ATF_TC(wait4);
99 ATF_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 
106 ATF_TC_BODY(wait4, tc)
107 {
108 	ATF_REQUIRE_ERRNO(ECHILD,
109 	    wait4(WAIT_ANY, NULL, TWAIT_OPTION, NULL) == -1);
110 }
111 
112 ATF_TC(wait6);
113 ATF_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 
120 ATF_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  */
131 static int
132 get_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  */
172 static int
173 get_options4(size_t pos)
174 {
175 	int rv = 0;
176 	size_t n;
177 
178 	const int special[] = {
179 		0,
180 		WALLSIG,
181 		WALTSIG,
182 		__WALL,		/* Linux compatibility, equal to WALLSIG */
183 		__WCLONE	/* Linux compatibility, equal to WALTSIG */
184 	};
185 
186 	const int matrix[] = {
187 		WNOWAIT,
188 		WEXITED,
189 		WUNTRACED,
190 		WSTOPPED,	/* SUS compatibility, equal to WUNTRACED */
191 		WTRAPPED,
192 		WCONTINUED
193 	};
194 
195 	const size_t M = (1 << __arraycount(special)) - 1;
196 
197 	if (pos < __arraycount(special))
198 		return special[pos];
199 
200 	pos -= __arraycount(special);
201 
202 	++pos; /* Don't start with empty mask */
203 
204 	if (pos > M)
205 		return -1;
206 
207 	for (n = 0; n < __arraycount(special); n++) {
208 		if (pos & __BIT(n))
209 			rv |= matrix[n];
210 	}
211 
212 	return rv;
213 }
214 
215 ATF_TC(waitpid_options);
216 ATF_TC_HEAD(waitpid_options, tc)
217 {
218 	atf_tc_set_md_var(tc, "descr",
219 	    "Test that waitpid(2) returns ECHILD for WAIT_ANY and valid "
220 	    "combination of options with%s WNOHANG",
221 	    TWAIT_OPTION == 0 ? "out" : "");
222 }
223 
224 ATF_TC_BODY(waitpid_options, tc)
225 {
226 	size_t i = 0;
227 	int o;
228 
229 	while((o = get_options4(i++)) != -1) {
230 		printf("Testing waitpid(2) with options %x\n", o);
231 
232 		ATF_REQUIRE_ERRNO(ECHILD,
233 		    waitpid(WAIT_ANY, NULL, o | TWAIT_OPTION) == -1);
234 	}
235 }
236 
237 ATF_TC(waitid_options);
238 ATF_TC_HEAD(waitid_options, tc)
239 {
240 	atf_tc_set_md_var(tc, "descr",
241 	    "Test that waitid(2) returns ECHILD for P_ALL and valid "
242 	    "combination of options with%s WNOHANG",
243 	    TWAIT_OPTION == 0 ? "out" : "");
244 }
245 
246 ATF_TC_BODY(waitid_options, tc)
247 {
248 	size_t i = 0;
249 	int o;
250 
251 	while((o = get_options6(i++)) != -1) {
252 		printf("Testing waitid(2) with options %x\n", o);
253 
254 		ATF_REQUIRE_ERRNO(ECHILD,
255 		    waitid(P_ALL, 0, NULL, o | TWAIT_OPTION) == -1);
256 	}
257 }
258 
259 ATF_TC(wait3_options);
260 ATF_TC_HEAD(wait3_options, tc)
261 {
262 	atf_tc_set_md_var(tc, "descr",
263 	    "Test that wait3(2) returns ECHILD for no child");
264 }
265 
266 ATF_TC_BODY(wait3_options, tc)
267 {
268 	size_t i = 0;
269 	int o;
270 
271 	while((o = get_options4(i++)) != -1) {
272 		printf("Testing wait3(2) with options %x\n", o);
273 
274 		ATF_REQUIRE_ERRNO(ECHILD,
275 		    wait3(NULL, o | TWAIT_OPTION, NULL) == -1);
276 	}
277 }
278 
279 ATF_TC(wait4_options);
280 ATF_TC_HEAD(wait4_options, tc)
281 {
282 	atf_tc_set_md_var(tc, "descr",
283 	    "Test that wait4(2) returns ECHILD for WAIT_ANY and option %s",
284 	    ___STRING(TWAIT_OPTION));
285 }
286 
287 ATF_TC_BODY(wait4_options, tc)
288 {
289 	size_t i = 0;
290 	int o;
291 
292 	while((o = get_options4(i++)) != -1) {
293 		printf("Testing wait4(2) with options %x\n", o);
294 
295 		ATF_REQUIRE_ERRNO(ECHILD,
296 		    wait4(WAIT_ANY, NULL, o | TWAIT_OPTION, NULL) == -1);
297 	}
298 }
299 
300 ATF_TC(wait6_options);
301 ATF_TC_HEAD(wait6_options, tc)
302 {
303 	atf_tc_set_md_var(tc, "descr",
304 	    "Test that wait6(2) returns ECHILD for P_ALL and option %s",
305 	    ___STRING(TWAIT_OPTION));
306 }
307 
308 ATF_TC_BODY(wait6_options, tc)
309 {
310 	size_t i = 0;
311 	int o;
312 
313 	while((o = get_options6(i++)) != -1) {
314 		printf("Testing wait6(2) with options %x\n", o);
315 
316 		ATF_REQUIRE_ERRNO(ECHILD,
317 		    wait6(P_ALL, 0, NULL, o | TWAIT_OPTION, NULL, NULL) == -1);
318 	}
319 }
320 
321 ATF_TP_ADD_TCS(tp)
322 {
323 
324 #if TWAIT_OPTION == 0
325 	ATF_TP_ADD_TC(tp, wait);
326 #endif
327 	ATF_TP_ADD_TC(tp, waitpid);
328 	ATF_TP_ADD_TC(tp, waitid);
329 	ATF_TP_ADD_TC(tp, wait3);
330 	ATF_TP_ADD_TC(tp, wait4);
331 	ATF_TP_ADD_TC(tp, wait6);
332 
333 	ATF_TP_ADD_TC(tp, waitpid_options);
334 	ATF_TP_ADD_TC(tp, waitid_options);
335 	ATF_TP_ADD_TC(tp, wait3_options);
336 	ATF_TP_ADD_TC(tp, wait4_options);
337 	ATF_TP_ADD_TC(tp, wait6_options);
338 
339 	return atf_no_error();
340 }
341