summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_poll.c
diff options
context:
space:
mode:
authorbluhm <>2019-11-19 19:57:04 +0000
committerbluhm <>2019-11-19 19:57:04 +0000
commit9185f840eda265016178aeb0dcdba964f8f6f3e2 (patch)
treeda100b3712514c566fe948116f7926ad7f725401 /src/regress/lib/libc/sys/t_poll.c
parent6a6fe688152b422f3d65c970dad56e7d9d28b1ee (diff)
downloadopenbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.gz
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.bz2
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.zip
Import NetBSD system call regression tests. They were written with
ATF (Automated Testing Framework), so we use a small wrapper to map it to our bsd.regress.mk framework. Only half of the 80 NetBSD tests have been taken, the others need more work to adapt. Of them 34 syscall tests pass. Moritz Buhl ported the tests to OpenBSD.
Diffstat (limited to 'src/regress/lib/libc/sys/t_poll.c')
-rw-r--r--src/regress/lib/libc/sys/t_poll.c398
1 files changed, 398 insertions, 0 deletions
diff --git a/src/regress/lib/libc/sys/t_poll.c b/src/regress/lib/libc/sys/t_poll.c
new file mode 100644
index 0000000000..bbb8dc2d14
--- /dev/null
+++ b/src/regress/lib/libc/sys/t_poll.c
@@ -0,0 +1,398 @@
1/* $OpenBSD: t_poll.c,v 1.1.1.1 2019/11/19 19:57:04 bluhm Exp $ */
2/* $NetBSD: t_poll.c,v 1.3 2012/03/18 07:00:52 jruoho Exp $ */
3
4/*-
5 * Copyright (c) 2011 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Matthias Scheler.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/time.h>
36#include <sys/wait.h>
37
38#include "atf-c.h"
39#include <errno.h>
40#include <fcntl.h>
41#include <paths.h>
42#include <poll.h>
43#include <stdio.h>
44#include <signal.h>
45#include <unistd.h>
46
47static int desc;
48
49static void
50child1(void)
51{
52 struct pollfd pfd;
53
54 pfd.fd = desc;
55 pfd.events = POLLIN | POLLHUP | POLLOUT;
56
57 (void)poll(&pfd, 1, 2000);
58 (void)printf("child1 exit\n");
59}
60
61static void
62child2(void)
63{
64 struct pollfd pfd;
65
66 pfd.fd = desc;
67 pfd.events = POLLIN | POLLHUP | POLLOUT;
68
69 (void)sleep(1);
70 (void)poll(&pfd, 1, INFTIM);
71 (void)printf("child2 exit\n");
72}
73
74static void
75child3(void)
76{
77 struct pollfd pfd;
78
79 (void)sleep(5);
80
81 pfd.fd = desc;
82 pfd.events = POLLIN | POLLHUP | POLLOUT;
83
84 (void)poll(&pfd, 1, INFTIM);
85 (void)printf("child3 exit\n");
86}
87
88ATF_TC(poll_3way);
89ATF_TC_HEAD(poll_3way, tc)
90{
91 atf_tc_set_md_var(tc, "timeout", "15");
92 atf_tc_set_md_var(tc, "descr",
93 "Check for 3-way collision for descriptor. First child comes "
94 "and polls on descriptor, second child comes and polls, first "
95 "child times out and exits, third child comes and polls. When "
96 "the wakeup event happens, the two remaining children should "
97 "both be awaken. (kern/17517)");
98}
99
100ATF_TC_BODY(poll_3way, tc)
101{
102 int pf[2];
103 int status, i;
104 pid_t pid;
105
106 pipe(pf);
107 desc = pf[0];
108
109 pid = fork();
110 ATF_REQUIRE(pid >= 0);
111
112 if (pid == 0) {
113 (void)close(pf[1]);
114 child1();
115 _exit(0);
116 /* NOTREACHED */
117 }
118
119 pid = fork();
120 ATF_REQUIRE(pid >= 0);
121
122 if (pid == 0) {
123 (void)close(pf[1]);
124 child2();
125 _exit(0);
126 /* NOTREACHED */
127 }
128
129 pid = fork();
130 ATF_REQUIRE( pid >= 0);
131
132 if (pid == 0) {
133 (void)close(pf[1]);
134 child3();
135 _exit(0);
136 /* NOTREACHED */
137 }
138
139 (void)sleep(10);
140
141 (void)printf("parent write\n");
142
143 ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6);
144
145 for(i = 0; i < 3; ++i)
146 (void)wait(&status);
147
148 (void)printf("parent terminated\n");
149}
150
151ATF_TC(poll_basic);
152ATF_TC_HEAD(poll_basic, tc)
153{
154 atf_tc_set_md_var(tc, "timeout", "10");
155 atf_tc_set_md_var(tc, "descr",
156 "Basis functionality test for poll(2)");
157}
158
159ATF_TC_BODY(poll_basic, tc)
160{
161 int fds[2];
162 struct pollfd pfds[2];
163 int ret;
164
165 ATF_REQUIRE_EQ(pipe(fds), 0);
166
167 pfds[0].fd = fds[0];
168 pfds[0].events = POLLIN;
169 pfds[1].fd = fds[1];
170 pfds[1].events = POLLOUT;
171
172 /*
173 * Check that we get a timeout waiting for data on the read end
174 * of our pipe.
175 */
176 pfds[0].revents = -1;
177 pfds[1].revents = -1;
178 ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0,
179 "got: %d", ret);
180 ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
181 ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
182
183 /* Check that the write end of the pipe as reported as ready. */
184 pfds[0].revents = -1;
185 pfds[1].revents = -1;
186 ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1,
187 "got: %d", ret);
188 ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
189 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
190 pfds[1].revents);
191
192 /* Check that only the write end of the pipe as reported as ready. */
193 pfds[0].revents = -1;
194 pfds[1].revents = -1;
195 ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1,
196 "got: %d", ret);
197 ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
198 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
199 pfds[1].revents);
200
201 /* Write data to our pipe. */
202 ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
203
204 /* Check that both ends of our pipe are reported as ready. */
205 pfds[0].revents = -1;
206 pfds[1].revents = -1;
207 ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2,
208 "got: %d", ret);
209 ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
210 pfds[0].revents);
211 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
212 pfds[1].revents);
213
214 ATF_REQUIRE_EQ(close(fds[0]), 0);
215 ATF_REQUIRE_EQ(close(fds[1]), 0);
216}
217
218ATF_TC(poll_err);
219ATF_TC_HEAD(poll_err, tc)
220{
221 atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
222}
223
224ATF_TC_BODY(poll_err, tc)
225{
226 struct pollfd pfd;
227 int fd = 0;
228
229 pfd.fd = fd;
230 pfd.events = POLLIN;
231
232 errno = 0;
233 ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
234
235 errno = 0;
236 ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
237}
238
239ATF_TC(pollts_basic);
240ATF_TC_HEAD(pollts_basic, tc)
241{
242 atf_tc_set_md_var(tc, "timeout", "10");
243 atf_tc_set_md_var(tc, "descr",
244 "Basis functionality test for pollts(2)");
245}
246
247ATF_TC_BODY(pollts_basic, tc)
248{
249 int fds[2];
250 struct pollfd pfds[2];
251 struct timespec timeout;
252 int ret;
253
254 ATF_REQUIRE_EQ(pipe(fds), 0);
255
256 pfds[0].fd = fds[0];
257 pfds[0].events = POLLIN;
258 pfds[1].fd = fds[1];
259 pfds[1].events = POLLOUT;
260
261 /* Use a timeout of 1 second. */
262 timeout.tv_sec = 1;
263 timeout.tv_nsec = 0;
264
265 /*
266 * Check that we get a timeout waiting for data on the read end
267 * of our pipe.
268 */
269 pfds[0].revents = -1;
270 pfds[1].revents = -1;
271 ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[0], 1, &timeout, NULL), 0,
272 "got: %d", ret);
273 ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
274 ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
275
276 /* Check that the write end of the pipe as reported as ready. */
277 pfds[0].revents = -1;
278 pfds[1].revents = -1;
279 ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[1], 1, &timeout, NULL), 1,
280 "got: %d", ret);
281 ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
282 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
283 pfds[1].revents);
284
285 /* Check that only the write end of the pipe as reported as ready. */
286 pfds[0].revents = -1;
287 pfds[1].revents = -1;
288 ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 1,
289 "got: %d", ret);
290 ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
291 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
292 pfds[1].revents);
293
294 /* Write data to our pipe. */
295 ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
296
297 /* Check that both ends of our pipe are reported as ready. */
298 pfds[0].revents = -1;
299 pfds[1].revents = -1;
300 ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 2,
301 "got: %d", ret);
302 ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
303 pfds[0].revents);
304 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
305 pfds[1].revents);
306
307 ATF_REQUIRE_EQ(close(fds[0]), 0);
308 ATF_REQUIRE_EQ(close(fds[1]), 0);
309}
310
311ATF_TC(pollts_err);
312ATF_TC_HEAD(pollts_err, tc)
313{
314 atf_tc_set_md_var(tc, "descr", "Check errors from pollts(2)");
315}
316
317ATF_TC_BODY(pollts_err, tc)
318{
319 struct timespec timeout;
320 struct pollfd pfd;
321 int fd = 0;
322
323 pfd.fd = fd;
324 pfd.events = POLLIN;
325
326 timeout.tv_sec = 1;
327 timeout.tv_nsec = 0;
328
329 errno = 0;
330 ATF_REQUIRE_ERRNO(EFAULT, pollts((void *)-1, 1, &timeout, NULL) == -1);
331
332 timeout.tv_sec = -1;
333 timeout.tv_nsec = -1;
334
335 errno = 0;
336 ATF_REQUIRE_ERRNO(EINVAL, pollts(&pfd, 1, &timeout, NULL) == -1);
337}
338
339ATF_TC(pollts_sigmask);
340ATF_TC_HEAD(pollts_sigmask, tc)
341{
342 atf_tc_set_md_var(tc, "timeout", "10");
343 atf_tc_set_md_var(tc, "descr",
344 "Check that pollts(2) restores the signal mask (PR kern/44986)");
345}
346
347ATF_TC_BODY(pollts_sigmask, tc)
348{
349 int fd;
350 struct pollfd pfd;
351 struct timespec timeout;
352 sigset_t mask;
353 int ret;
354
355 fd = open(_PATH_DEVNULL, O_RDONLY);
356 ATF_REQUIRE(fd >= 0);
357
358 pfd.fd = fd;
359 pfd.events = POLLIN;
360
361 /* Use a timeout of 1 second. */
362 timeout.tv_sec = 1;
363 timeout.tv_nsec = 0;
364
365 /* Unblock all signals. */
366 ATF_REQUIRE_EQ(sigfillset(&mask), 0);
367 ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0);
368
369 /*
370 * Check that pollts(2) immediately returns. We block *all*
371 * signals during pollts(2).
372 */
373 ATF_REQUIRE_EQ_MSG(ret = pollts(&pfd, 1, &timeout, &mask), 1,
374 "got: %d", ret);
375
376 /* Check that signals are now longer blocked. */
377 ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0);
378 ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0,
379 "signal mask was changed.");
380
381 ATF_REQUIRE_EQ(close(fd), 0);
382}
383
384ATF_TP_ADD_TCS(tp)
385{
386
387 ATF_TP_ADD_TC(tp, poll_3way);
388 ATF_TP_ADD_TC(tp, poll_basic);
389 ATF_TP_ADD_TC(tp, poll_err);
390 /*
391 * Adjusted for OpenBSD, not supported
392 * ATF_TP_ADD_TC(tp, pollts_basic);
393 * ATF_TP_ADD_TC(tp, pollts_err);
394 * ATF_TP_ADD_TC(tp, pollts_sigmask);
395 */
396
397 return atf_no_error();
398}