1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2020 Jan Kokem��ller
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/param.h>
29#include <sys/event.h>
30#include <sys/stat.h>
31
32#include <errno.h>
33#include <fcntl.h>
34#include <limits.h>
35#include <poll.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <time.h>
39#include <unistd.h>
40
41#include <atf-c.h>
42
43ATF_TC_WITHOUT_HEAD(pipe_kqueue__write_end);
44ATF_TC_BODY(pipe_kqueue__write_end, tc)
45{
46	int p[2] = { -1, -1 };
47
48	ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);
49	ATF_REQUIRE(p[0] >= 0);
50	ATF_REQUIRE(p[1] >= 0);
51
52	int kq = kqueue();
53	ATF_REQUIRE(kq >= 0);
54
55	struct kevent kev[32];
56	EV_SET(&kev[0], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, 0);
57
58	ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, NULL) == 0);
59
60	/* Test that EVFILT_WRITE behaves sensibly on the write end. */
61
62	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
63	    &(struct timespec) { 0, 0 }) == 1);
64	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
65	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
66	ATF_REQUIRE(kev[0].flags == EV_CLEAR);
67	ATF_REQUIRE(kev[0].fflags == 0);
68	ATF_REQUIRE(kev[0].data == 16384);
69	ATF_REQUIRE(kev[0].udata == 0);
70
71	/* Filling up the pipe should make the EVFILT_WRITE disappear. */
72
73	char c = 0;
74	ssize_t r;
75	while ((r = write(p[1], &c, 1)) == 1) {
76	}
77	ATF_REQUIRE(r < 0);
78	ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
79
80	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
81	    &(struct timespec) { 0, 0 }) == 0);
82
83	/* Reading (PIPE_BUF - 1) bytes will not trigger a EVFILT_WRITE yet. */
84
85	for (int i = 0; i < PIPE_BUF - 1; ++i) {
86		ATF_REQUIRE(read(p[0], &c, 1) == 1);
87	}
88
89	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
90	    &(struct timespec) { 0, 0 }) == 0);
91
92	/* Reading one additional byte triggers the EVFILT_WRITE. */
93
94	ATF_REQUIRE(read(p[0], &c, 1) == 1);
95
96	r = kevent(kq, NULL, 0, kev, nitems(kev), &(struct timespec) { 0, 0 });
97	ATF_REQUIRE(r == 1);
98	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
99	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
100	ATF_REQUIRE(kev[0].flags == EV_CLEAR);
101	ATF_REQUIRE(kev[0].fflags == 0);
102	ATF_REQUIRE(kev[0].data == PIPE_BUF);
103	ATF_REQUIRE(kev[0].udata == 0);
104
105	/*
106	 * Reading another byte triggers the EVFILT_WRITE again with a changed
107	 * 'data' field.
108	 */
109
110	ATF_REQUIRE(read(p[0], &c, 1) == 1);
111
112	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
113	    &(struct timespec) { 0, 0 }) == 1);
114	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
115	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
116	ATF_REQUIRE(kev[0].flags == EV_CLEAR);
117	ATF_REQUIRE(kev[0].fflags == 0);
118	ATF_REQUIRE(kev[0].data == PIPE_BUF + 1);
119	ATF_REQUIRE(kev[0].udata == 0);
120
121	/*
122	 * Closing the read end should make a EV_EOF appear but leave the 'data'
123	 * field unchanged.
124	 */
125
126	ATF_REQUIRE(close(p[0]) == 0);
127
128	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
129	    &(struct timespec) { 0, 0 }) == 1);
130	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
131	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
132	ATF_REQUIRE(kev[0].flags == (EV_CLEAR | EV_EOF | EV_ONESHOT));
133	ATF_REQUIRE(kev[0].fflags == 0);
134	ATF_REQUIRE(kev[0].data == PIPE_BUF + 1);
135	ATF_REQUIRE(kev[0].udata == 0);
136
137	ATF_REQUIRE(close(kq) == 0);
138	ATF_REQUIRE(close(p[1]) == 0);
139}
140
141ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_read_end);
142ATF_TC_BODY(pipe_kqueue__closed_read_end, tc)
143{
144	int p[2] = { -1, -1 };
145
146	ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);
147	ATF_REQUIRE(p[0] >= 0);
148	ATF_REQUIRE(p[1] >= 0);
149
150	ATF_REQUIRE(close(p[0]) == 0);
151
152	int kq = kqueue();
153	ATF_REQUIRE(kq >= 0);
154
155	struct kevent kev[32];
156	EV_SET(&kev[0], p[1], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/
157	    0, 0, 0);
158	EV_SET(&kev[1], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/
159	    0, 0, 0);
160
161	/*
162	 * Trying to register EVFILT_WRITE when the pipe is closed leads to an
163	 * EPIPE error.
164	 */
165
166	ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2);
167	ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0);
168	ATF_REQUIRE(kev[0].data == 0);
169	ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0);
170	ATF_REQUIRE(kev[1].data == EPIPE);
171
172	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
173	    &(struct timespec) { 0, 0 }) == 1);
174	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
175	ATF_REQUIRE(kev[0].filter == EVFILT_READ);
176	ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT));
177	ATF_REQUIRE(kev[0].fflags == 0);
178	ATF_REQUIRE(kev[0].data == 0);
179	ATF_REQUIRE(kev[0].udata == 0);
180
181	ATF_REQUIRE(close(kq) == 0);
182	ATF_REQUIRE(close(p[1]) == 0);
183}
184
185ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_read_end_register_before_close);
186ATF_TC_BODY(pipe_kqueue__closed_read_end_register_before_close, tc)
187{
188	int p[2] = { -1, -1 };
189
190	ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);
191	ATF_REQUIRE(p[0] >= 0);
192	ATF_REQUIRE(p[1] >= 0);
193
194	int kq = kqueue();
195	ATF_REQUIRE(kq >= 0);
196
197	struct kevent kev[32];
198	EV_SET(&kev[0], p[1], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/
199	    0, 0, 0);
200	EV_SET(&kev[1], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/
201	    0, 0, 0);
202
203	/*
204	 * Registering EVFILT_WRITE before the pipe is closed leads to a
205	 * EVFILT_WRITE event with EV_EOF set.
206	 */
207
208	ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2);
209	ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0);
210	ATF_REQUIRE(kev[0].data == 0);
211	ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0);
212	ATF_REQUIRE(kev[1].data == 0);
213
214	ATF_REQUIRE(close(p[0]) == 0);
215
216	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
217	    &(struct timespec) { 0, 0 }) == 2);
218	{
219		ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
220		ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
221		ATF_REQUIRE(kev[0].flags ==
222		    (EV_EOF | EV_CLEAR | EV_ONESHOT | EV_RECEIPT));
223		ATF_REQUIRE(kev[0].fflags == 0);
224		ATF_REQUIRE(kev[0].data == 16384);
225		ATF_REQUIRE(kev[0].udata == 0);
226	}
227	{
228		ATF_REQUIRE(kev[1].ident == (uintptr_t)p[1]);
229		ATF_REQUIRE(kev[1].filter == EVFILT_READ);
230		ATF_REQUIRE(kev[1].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT));
231		ATF_REQUIRE(kev[1].fflags == 0);
232		ATF_REQUIRE(kev[1].data == 0);
233		ATF_REQUIRE(kev[1].udata == 0);
234	}
235
236	ATF_REQUIRE(close(kq) == 0);
237	ATF_REQUIRE(close(p[1]) == 0);
238}
239
240ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_write_end);
241ATF_TC_BODY(pipe_kqueue__closed_write_end, tc)
242{
243	struct kevent kev[32];
244	ssize_t bytes, n;
245	int kq, p[2];
246	char c;
247
248	ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);
249	ATF_REQUIRE(p[0] >= 0);
250	ATF_REQUIRE(p[1] >= 0);
251
252	bytes = 0;
253	c = 0;
254	while ((n = write(p[1], &c, 1)) == 1)
255		bytes++;
256	ATF_REQUIRE(n < 0);
257	ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
258
259	ATF_REQUIRE(close(p[1]) == 0);
260
261	kq = kqueue();
262	ATF_REQUIRE(kq >= 0);
263
264	EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT,
265	    0, 0, 0);
266	EV_SET(&kev[1], p[0], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT,
267	    0, 0, 0);
268
269	/*
270	 * Trying to register EVFILT_WRITE when the pipe is closed leads to an
271	 * EPIPE error.
272	 */
273
274	ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2);
275	ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0);
276	ATF_REQUIRE(kev[0].data == 0);
277	ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0);
278	ATF_REQUIRE(kev[1].data == EPIPE);
279
280	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
281	    &(struct timespec) { 0, 0 }) == 1);
282	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]);
283	ATF_REQUIRE(kev[0].filter == EVFILT_READ);
284	ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT));
285	ATF_REQUIRE(kev[0].fflags == 0);
286	ATF_REQUIRE(kev[0].data == bytes);
287	ATF_REQUIRE(kev[0].udata == 0);
288
289	ATF_REQUIRE(close(kq) == 0);
290	ATF_REQUIRE(close(p[0]) == 0);
291}
292
293ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_write_end_register_before_close);
294ATF_TC_BODY(pipe_kqueue__closed_write_end_register_before_close, tc)
295{
296	struct kevent kev[32];
297	ssize_t bytes, n;
298	int kq, p[2];
299	char c;
300
301	ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);
302	ATF_REQUIRE(p[0] >= 0);
303	ATF_REQUIRE(p[1] >= 0);
304
305	kq = kqueue();
306	ATF_REQUIRE(kq >= 0);
307
308	EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT,
309	    0, 0, 0);
310	EV_SET(&kev[1], p[0], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT,
311	    0, 0, 0);
312
313	/*
314	 * Registering EVFILT_WRITE before the pipe is closed leads to a
315	 * EVFILT_WRITE event with EV_EOF set.
316	 */
317
318	ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2);
319	ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0);
320	ATF_REQUIRE(kev[0].data == 0);
321	ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0);
322	ATF_REQUIRE(kev[1].data == 0);
323
324	bytes = 0;
325	c = 0;
326	while ((n = write(p[1], &c, 1)) == 1)
327		bytes++;
328	ATF_REQUIRE(n < 0);
329	ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
330
331	ATF_REQUIRE(close(p[1]) == 0);
332
333	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
334	    &(struct timespec){ 0, 0 }) == 2);
335
336	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]);
337	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
338	ATF_REQUIRE(kev[0].flags ==
339	    (EV_EOF | EV_CLEAR | EV_ONESHOT | EV_RECEIPT));
340	ATF_REQUIRE(kev[0].fflags == 0);
341	ATF_REQUIRE(kev[0].data > 0);
342	ATF_REQUIRE(kev[0].udata == 0);
343
344	ATF_REQUIRE(kev[1].ident == (uintptr_t)p[0]);
345	ATF_REQUIRE(kev[1].filter == EVFILT_READ);
346	ATF_REQUIRE(kev[1].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT));
347	ATF_REQUIRE(kev[1].fflags == 0);
348	ATF_REQUIRE(kev[1].data == bytes);
349	ATF_REQUIRE(kev[1].udata == 0);
350
351	ATF_REQUIRE(close(kq) == 0);
352	ATF_REQUIRE(close(p[0]) == 0);
353}
354
355ATF_TP_ADD_TCS(tp)
356{
357	ATF_TP_ADD_TC(tp, pipe_kqueue__write_end);
358	ATF_TP_ADD_TC(tp, pipe_kqueue__closed_read_end);
359	ATF_TP_ADD_TC(tp, pipe_kqueue__closed_read_end_register_before_close);
360	ATF_TP_ADD_TC(tp, pipe_kqueue__closed_write_end);
361	ATF_TP_ADD_TC(tp, pipe_kqueue__closed_write_end_register_before_close);
362
363	return atf_no_error();
364}
365