xref: /netbsd-src/tests/lib/libc/sys/t_poll.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*	$NetBSD: t_poll.c,v 1.4 2020/07/17 15:34:16 kamil Exp $	*/
2 
3 /*-
4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Matthias Scheler.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/time.h>
33 #include <sys/wait.h>
34 
35 #include <atf-c.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <paths.h>
39 #include <poll.h>
40 #include <stdio.h>
41 #include <signal.h>
42 #include <unistd.h>
43 
44 static int desc;
45 
46 static void
47 child1(void)
48 {
49 	struct pollfd pfd;
50 
51 	pfd.fd = desc;
52 	pfd.events = POLLIN | POLLHUP | POLLOUT;
53 
54 	(void)poll(&pfd, 1, 2000);
55 	(void)printf("child1 exit\n");
56 }
57 
58 static void
59 child2(void)
60 {
61 	struct pollfd pfd;
62 
63 	pfd.fd = desc;
64 	pfd.events = POLLIN | POLLHUP | POLLOUT;
65 
66 	(void)sleep(1);
67 	(void)poll(&pfd, 1, INFTIM);
68 	(void)printf("child2 exit\n");
69 }
70 
71 static void
72 child3(void)
73 {
74 	struct pollfd pfd;
75 
76 	(void)sleep(5);
77 
78 	pfd.fd = desc;
79 	pfd.events = POLLIN | POLLHUP | POLLOUT;
80 
81 	(void)poll(&pfd, 1, INFTIM);
82 	(void)printf("child3 exit\n");
83 }
84 
85 ATF_TC(3way);
86 ATF_TC_HEAD(3way, tc)
87 {
88 	atf_tc_set_md_var(tc, "timeout", "15");
89 	atf_tc_set_md_var(tc, "descr",
90 	    "Check for 3-way collision for descriptor. First child comes "
91 	    "and polls on descriptor, second child comes and polls, first "
92 	    "child times out and exits, third child comes and polls. When "
93 	    "the wakeup event happens, the two remaining children should "
94 	    "both be awaken. (kern/17517)");
95 }
96 
97 ATF_TC_BODY(3way, tc)
98 {
99 	int pf[2];
100 	int status, i;
101 	pid_t pid;
102 
103 	pipe(pf);
104 	desc = pf[0];
105 
106 	pid = fork();
107 	ATF_REQUIRE(pid >= 0);
108 
109 	if (pid == 0) {
110 		(void)close(pf[1]);
111 		child1();
112 		_exit(0);
113 		/* NOTREACHED */
114 	}
115 
116 	pid = fork();
117 	ATF_REQUIRE(pid >= 0);
118 
119 	if (pid == 0) {
120 		(void)close(pf[1]);
121 		child2();
122 		_exit(0);
123 		/* NOTREACHED */
124 	}
125 
126 	pid = fork();
127 	ATF_REQUIRE( pid >= 0);
128 
129 	if (pid == 0) {
130 		(void)close(pf[1]);
131 		child3();
132 		_exit(0);
133 		/* NOTREACHED */
134 	}
135 
136 	(void)sleep(10);
137 
138 	(void)printf("parent write\n");
139 
140 	ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6);
141 
142 	for(i = 0; i < 3; ++i)
143 		(void)wait(&status);
144 
145 	(void)printf("parent terminated\n");
146 }
147 
148 ATF_TC(basic);
149 ATF_TC_HEAD(basic, tc)
150 {
151 	atf_tc_set_md_var(tc, "timeout", "10");
152 	atf_tc_set_md_var(tc, "descr",
153 	    "Basis functionality test for poll(2)");
154 }
155 
156 ATF_TC_BODY(basic, tc)
157 {
158 	int fds[2];
159 	struct pollfd pfds[2];
160 	int ret;
161 
162 	ATF_REQUIRE_EQ(pipe(fds), 0);
163 
164 	pfds[0].fd = fds[0];
165 	pfds[0].events = POLLIN;
166 	pfds[1].fd = fds[1];
167 	pfds[1].events = POLLOUT;
168 
169 	/*
170 	 * Check that we get a timeout waiting for data on the read end
171 	 * of our pipe.
172 	 */
173 	pfds[0].revents = -1;
174 	pfds[1].revents = -1;
175 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0,
176 	    "got: %d", ret);
177 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
178 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
179 
180 	/* Check that the write end of the pipe as reported as ready. */
181 	pfds[0].revents = -1;
182 	pfds[1].revents = -1;
183 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1,
184 	    "got: %d", ret);
185 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
186 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
187 	    pfds[1].revents);
188 
189 	/* Check that only the write end of the pipe as reported as ready. */
190 	pfds[0].revents = -1;
191 	pfds[1].revents = -1;
192 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1,
193 	    "got: %d", ret);
194 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
195 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
196 	    pfds[1].revents);
197 
198 	/* Write data to our pipe. */
199 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
200 
201 	/* Check that both ends of our pipe are reported as ready. */
202 	pfds[0].revents = -1;
203 	pfds[1].revents = -1;
204 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2,
205 	    "got: %d", ret);
206 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
207 	    pfds[0].revents);
208 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
209 	    pfds[1].revents);
210 
211 	ATF_REQUIRE_EQ(close(fds[0]), 0);
212 	ATF_REQUIRE_EQ(close(fds[1]), 0);
213 }
214 
215 ATF_TC(err);
216 ATF_TC_HEAD(err, tc)
217 {
218 	atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
219 }
220 
221 ATF_TC_BODY(err, tc)
222 {
223 	struct pollfd pfd;
224 	int fd = 0;
225 
226 	pfd.fd = fd;
227 	pfd.events = POLLIN;
228 
229 	errno = 0;
230 	ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
231 
232 	errno = 0;
233 	ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
234 }
235 
236 ATF_TP_ADD_TCS(tp)
237 {
238 
239 	ATF_TP_ADD_TC(tp, 3way);
240 	ATF_TP_ADD_TC(tp, basic);
241 	ATF_TP_ADD_TC(tp, err);
242 
243 	return atf_no_error();
244 }
245