1 /* $NetBSD: t_wait_noproc.c,v 1.6 2020/06/15 13:57:45 christos 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.6 2020/06/15 13:57:45 christos 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);
ATF_TC_HEAD(wait,tc)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
ATF_TC_BODY(wait,tc)52 ATF_TC_BODY(wait, tc)
53 {
54 ATF_REQUIRE_ERRNO(ECHILD, wait(NULL) == -1);
55 }
56 #endif
57
58 ATF_TC(waitpid);
ATF_TC_HEAD(waitpid,tc)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
ATF_TC_BODY(waitpid,tc)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);
ATF_TC_HEAD(waitid,tc)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
ATF_TC_BODY(waitid,tc)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);
ATF_TC_HEAD(wait3,tc)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
ATF_TC_BODY(wait3,tc)93 ATF_TC_BODY(wait3, tc)
94 {
95 ATF_REQUIRE_ERRNO(ECHILD, wait3(NULL, TWAIT_OPTION, NULL) == -1);
96 }
97
98 ATF_TC(wait4);
ATF_TC_HEAD(wait4,tc)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
ATF_TC_BODY(wait4,tc)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);
ATF_TC_HEAD(wait6,tc)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
ATF_TC_BODY(wait6,tc)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
get_options6(size_t pos)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 exclude 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
get_options4(size_t pos)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);
ATF_TC_HEAD(waitpid_options,tc)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
ATF_TC_BODY(waitpid_options,tc)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);
ATF_TC_HEAD(waitid_options,tc)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
ATF_TC_BODY(waitid_options,tc)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);
ATF_TC_HEAD(wait3_options,tc)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
ATF_TC_BODY(wait3_options,tc)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);
ATF_TC_HEAD(wait4_options,tc)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
ATF_TC_BODY(wait4_options,tc)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);
ATF_TC_HEAD(wait6_options,tc)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
ATF_TC_BODY(wait6_options,tc)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
ATF_TP_ADD_TCS(tp)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