xref: /freebsd/tests/sys/fifo/fifo_io.c (revision b3e76948)
1 /*-
2  * Copyright (c) 2005 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/event.h>
29 #include <sys/ioctl.h>
30 #include <sys/select.h>
31 #include <sys/stat.h>
32 #include <sys/time.h>
33 
34 #include <err.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <limits.h>
38 #include <poll.h>
39 #include <signal.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 
45 /*
46  * Regression test to exercise POSIX fifo I/O.
47  *
48  * We test a number of aspect of behavior, including:
49  *
50  * - If there's no data to read, then for blocking fifos, we block, and for
51  *   non-blocking, we return EAGAIN.
52  *
53  * - If we write ten bytes, ten bytes can be read, and they're the same
54  *   bytes, in the same order.
55  *
56  * - If we write two batches of five bytes, we can read the same ten bytes in
57  *   one read of ten bytes.
58  *
59  * - If we write ten bytes, we can read the same ten bytes in two reads of
60  *   five bytes each.
61  *
62  * - If we over-fill a buffer (by writing 512k, which we take to be a large
63  *   number above default buffer sizes), we block if there is no reader.
64  *
65  * - That once 512k (ish) is read from the other end, the blocked writer
66  *   wakes up.
67  *
68  * - When a fifo is empty, poll, select, kqueue, and fionread report it is
69  *   writable but not readable.
70  *
71  * - When a fifo has data in it, poll, select, and kqueue report that it is
72  *   writable.
73  *
74  * - XXX: blocked reader semantics?
75  *
76  * - XXX: event behavior on remote close?
77  *
78  * Although behavior of O_RDWR isn't defined for fifos by POSIX, we expect
79  * "reasonable" behavior, and run some additional tests relating to event
80  * management on O_RDWR fifo descriptors.
81  */
82 
83 #define	KQUEUE_MAX_EVENT	8
84 
85 /*
86  * All activity occurs within a temporary directory created early in the
87  * test.
88  */
89 static char	temp_dir[PATH_MAX];
90 
91 static void __unused
atexit_temp_dir(void)92 atexit_temp_dir(void)
93 {
94 
95 	rmdir(temp_dir);
96 }
97 
98 static void
makefifo(const char * fifoname,const char * testname)99 makefifo(const char *fifoname, const char *testname)
100 {
101 
102 	if (mkfifo(fifoname, 0700) < 0)
103 		err(-1, "%s: makefifo: mkfifo: %s", testname, fifoname);
104 }
105 
106 static void
cleanfifo2(const char * fifoname,int fd1,int fd2)107 cleanfifo2(const char *fifoname, int fd1, int fd2)
108 {
109 
110 	if (fd1 != -1)
111 		close(fd1);
112 	if (fd2 != -1)
113 		close(fd2);
114 	(void)unlink(fifoname);
115 }
116 
117 static void
cleanfifo3(const char * fifoname,int fd1,int fd2,int fd3)118 cleanfifo3(const char *fifoname, int fd1, int fd2, int fd3)
119 {
120 
121 	if (fd3 != -1)
122 		close(fd3);
123 	cleanfifo2(fifoname, fd1, fd2);
124 }
125 
126 /*
127  * Open two different file descriptors for a fifo: one read, one write.  Do
128  * so using non-blocking opens in order to avoid deadlocking the process.
129  */
130 static int
openfifo(const char * fifoname,int * reader_fdp,int * writer_fdp)131 openfifo(const char *fifoname, int *reader_fdp, int *writer_fdp)
132 {
133 	int error, fd1, fd2;
134 
135 	fd1 = open(fifoname, O_RDONLY | O_NONBLOCK);
136 	if (fd1 < 0)
137 		return (-1);
138 	fd2 = open(fifoname, O_WRONLY | O_NONBLOCK);
139 	if (fd2 < 0) {
140 		error = errno;
141 		close(fd1);
142 		errno = error;
143 		return (-1);
144 	}
145 	*reader_fdp = fd1;
146 	*writer_fdp = fd2;
147 
148 	return (0);
149 }
150 
151 /*
152  * Open one file descriptor for the fifo, supporting both read and write.
153  */
154 static int
openfifo_rw(const char * fifoname,int * fdp)155 openfifo_rw(const char *fifoname, int *fdp)
156 {
157 	int fd;
158 
159 	fd = open(fifoname, O_RDWR);
160 	if (fd < 0)
161 		return (-1);
162 	*fdp = fd;
163 
164 	return (0);
165 }
166 
167 static int
set_nonblocking(int fd,const char * testname)168 set_nonblocking(int fd, const char *testname)
169 {
170 	int flags;
171 
172 	flags = fcntl(fd, F_GETFL);
173 	if (flags < 0) {
174 		warn("%s: fcntl(fd, F_GETFL)", testname);
175 		return(-1);
176 	}
177 
178 	flags |= O_NONBLOCK;
179 
180 	if (fcntl(fd, F_SETFL, flags) < 0) {
181 		warn("%s: fcntl(fd, 0x%x)", testname, flags);
182 		return (-1);
183 	}
184 
185 	return (0);
186 }
187 
188 static int
set_blocking(int fd,const char * testname)189 set_blocking(int fd, const char *testname)
190 {
191 	int flags;
192 
193 	flags = fcntl(fd, F_GETFL);
194 	if (flags < 0) {
195 		warn("%s: fcntl(fd, F_GETFL)", testname);
196 		return(-1);
197 	}
198 
199 	flags &= ~O_NONBLOCK;
200 
201 	if (fcntl(fd, F_SETFL, flags) < 0) {
202 		warn("%s: fcntl(fd, 0x%x)", testname, flags);
203 		return (-1);
204 	}
205 
206 	return (0);
207 }
208 
209 /*
210  * Drain a file descriptor (fifo) of any readable data.  Note: resets the
211  * blocking state.
212  */
213 static int
drain_fd(int fd,const char * testname)214 drain_fd(int fd, const char *testname)
215 {
216 	ssize_t len;
217 	u_char ch;
218 
219 	if (set_nonblocking(fd, testname) < 0)
220 		return (-1);
221 
222 	while ((len = read(fd, &ch, sizeof(ch))) > 0);
223 	if (len < 0) {
224 		switch (errno) {
225 		case EAGAIN:
226 			return (0);
227 		default:
228 			warn("%s: drain_fd: read", testname);
229 			return (-1);
230 		}
231 	}
232 	warn("%s: drain_fd: read: returned 0 bytes", testname);
233 	return (-1);
234 }
235 
236 /*
237  * Simple I/O test: write ten integers, and make sure we get back the same
238  * integers in the same order.  This assumes a minimum fifo buffer > 10
239  * bytes in order to not block and deadlock.
240  */
241 static void
test_simpleio(void)242 test_simpleio(void)
243 {
244 	int i, reader_fd, writer_fd;
245 	u_char buffer[10];
246 	ssize_t len;
247 
248 	makefifo("testfifo", __func__);
249 	if (openfifo("testfifo", &reader_fd, &writer_fd)
250 	    < 0) {
251 		warn("test_simpleio: openfifo: testfifo");
252 		cleanfifo2("testfifo", -1, -1);
253 		exit(-1);
254 	}
255 
256 	for (i = 0; i < 10; i++)
257 		buffer[i] = i;
258 
259 	len = write(writer_fd, (char *)buffer, sizeof(buffer));
260 	if (len < 0) {
261 		warn("test_simpleio: write");
262 		cleanfifo2("testfifo", reader_fd, writer_fd);
263 		exit(-1);
264 	}
265 	if (len != sizeof(buffer)) {
266 		warnx("test_simplio: tried %zu but wrote %zd", sizeof(buffer),
267 		    len);
268 		cleanfifo2("testfifo", reader_fd, writer_fd);
269 		exit(-1);
270 	}
271 
272 	len = read(reader_fd, (char *)buffer, sizeof(buffer));
273 	if (len < 0) {
274 		warn("test_simpleio: read");
275 		cleanfifo2("testfifo", reader_fd, writer_fd);
276 		exit(-1);
277 	}
278 	if (len != sizeof(buffer)) {
279 		warnx("test_simpleio: tried %zu but read %zd", sizeof(buffer),
280 		    len);
281 		cleanfifo2("testfifo", reader_fd, writer_fd);
282 		exit(-1);
283 	}
284 	for (i = 0; i < 10; i++) {
285 		if (buffer[i] == i)
286 			continue;
287 		warnx("test_simpleio: write byte %d as 0x%02x, but read "
288 		    "0x%02x", i, i, buffer[i]);
289 		cleanfifo2("testfifo", reader_fd, writer_fd);
290 		exit(-1);
291 	}
292 
293 	cleanfifo2("testfifo", reader_fd, writer_fd);
294 }
295 
296 static volatile int alarm_fired;
297 /*
298  * Non-destructive SIGALRM handler.
299  */
300 static void
sigalarm(int signum __unused)301 sigalarm(int signum __unused)
302 {
303 
304 	alarm_fired = 1;
305 }
306 
307 /*
308  * Wrapper function for write, which uses a timer to interrupt any blocking.
309  * Because we can't reliably detect EINTR for blocking I/O, we also track
310  * whether or not our timeout fired.
311  */
312 static int __unused
timed_write(int fd,void * data,size_t len,ssize_t * written_lenp,int timeout,int * timedoutp,const char * testname)313 timed_write(int fd, void *data, size_t len, ssize_t *written_lenp,
314     int timeout, int *timedoutp, const char *testname)
315 {
316 	struct sigaction act, oact;
317 	ssize_t written_len;
318 	int error;
319 
320 	alarm_fired = 0;
321 	bzero(&act, sizeof(oact));
322 	act.sa_handler = sigalarm;
323 	if (sigaction(SIGALRM, &act, &oact) < 0) {
324 	 	warn("%s: timed_write: sigaction", testname);
325 		return (-1);
326 	}
327 	alarm(timeout);
328 	written_len = write(fd, data, len);
329 	error = errno;
330 	alarm(0);
331 	if (sigaction(SIGALRM, &oact, NULL) < 0) {
332 	 	warn("%s: timed_write: sigaction", testname);
333 		return (-1);
334 	}
335 	if (alarm_fired)
336 		*timedoutp = 1;
337 	else
338 		*timedoutp = 0;
339 
340 	errno = error;
341 	if (written_len < 0)
342 		return (-1);
343 	*written_lenp = written_len;
344 	return (0);
345 }
346 
347 /*
348  * Wrapper function for read, which uses a timer to interrupt any blocking.
349  * Because we can't reliably detect EINTR for blocking I/O, we also track
350  * whether or not our timeout fired.
351  */
352 static int
timed_read(int fd,void * data,size_t len,ssize_t * read_lenp,int timeout,int * timedoutp,const char * testname)353 timed_read(int fd, void *data, size_t len, ssize_t *read_lenp,
354     int timeout, int *timedoutp, const char *testname)
355 {
356 	struct sigaction act, oact;
357 	ssize_t read_len;
358 	int error;
359 
360 	alarm_fired = 0;
361 	bzero(&act, sizeof(oact));
362 	act.sa_handler = sigalarm;
363 	if (sigaction(SIGALRM, &act, &oact) < 0) {
364 	 	warn("%s: timed_write: sigaction", testname);
365 		return (-1);
366 	}
367 	alarm(timeout);
368 	read_len = read(fd, data, len);
369 	error = errno;
370 	alarm(0);
371 	if (sigaction(SIGALRM, &oact, NULL) < 0) {
372 	 	warn("%s: timed_write: sigaction", testname);
373 		return (-1);
374 	}
375 	if (alarm_fired)
376 		*timedoutp = 1;
377 	else
378 		*timedoutp = 0;
379 
380 	errno = error;
381 	if (read_len < 0)
382 		return (-1);
383 	*read_lenp = read_len;
384 	return (0);
385 }
386 
387 /*
388  * This test operates on blocking and non-blocking fifo file descriptors, in
389  * order to determine whether they block at good moments or not.  By good we
390  * mean: don't block for non-blocking sockets, and do block for blocking
391  * ones, assuming there isn't I/O buffer to satisfy the request.
392  *
393  * We use a timeout of 5 seconds, concluding that in 5 seconds either all I/O
394  * that can take place will, and that if we reach the end of the timeout,
395  * then blocking has occurred.
396  *
397  * We assume that the buffer size on a fifo is <512K, and as such, that
398  * writing that much data without an active reader will result in blocking.
399  */
400 static void
test_blocking_read_empty(void)401 test_blocking_read_empty(void)
402 {
403 	int reader_fd, ret, timedout, writer_fd;
404 	ssize_t len;
405 	u_char ch;
406 
407 	makefifo("testfifo", __func__);
408 	if (openfifo("testfifo", &reader_fd, &writer_fd)
409 	    < 0) {
410 		warn("test_blocking_read_empty: openfifo: testfifo");
411 		cleanfifo2("testfifo", -1, -1);
412 		exit(-1);
413 	}
414 
415 	/*
416 	 * Read one byte from an empty blocking fifo, block as there is no
417 	 * data.
418 	 */
419 	if (set_blocking(reader_fd, __func__) < 0) {
420 		cleanfifo2("testfifo", reader_fd, writer_fd);
421 		exit(-1);
422 	}
423 
424 	ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
425 	    __func__);
426 	if (ret != -1) {
427 		warnx("test_blocking_read_empty: timed_read: returned "
428 		    "success");
429 		cleanfifo2("testfifo", reader_fd, writer_fd);
430 		exit(-1);
431 	}
432 	if (errno != EINTR) {
433 		warn("test_blocking_read_empty: timed_read");
434 		cleanfifo2("testfifo", reader_fd, writer_fd);
435 		exit(-1);
436 	}
437 
438 	/*
439 	 * Read one byte from an empty non-blocking fifo, return EAGAIN as
440 	 * there is no data.
441 	 */
442 	if (set_nonblocking(reader_fd, __func__) < 0) {
443 		cleanfifo2("testfifo", reader_fd, writer_fd);
444 		exit(-1);
445 	}
446 
447 	ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
448 	    __func__);
449 	if (ret != -1) {
450 		warnx("test_blocking_read_empty: timed_read: returned "
451 		    "success");
452 		cleanfifo2("testfifo", reader_fd, writer_fd);
453 		exit(-1);
454 	}
455 	if (errno != EAGAIN) {
456 		warn("test_blocking_read_empty: timed_read");
457 		cleanfifo2("testfifo", reader_fd, writer_fd);
458 		exit(-1);
459 	}
460 
461 	cleanfifo2("testfifo", reader_fd, writer_fd);
462 }
463 
464 /*
465  * Write one byte to an empty fifo, then try to read one byte and make sure
466  * we don't block in either the write or the read.  This tests both for
467  * improper blocking in the send and receive code.
468  */
469 static void
test_blocking_one_byte(void)470 test_blocking_one_byte(void)
471 {
472 	int reader_fd, ret, timedout, writer_fd;
473 	ssize_t len;
474 	u_char ch;
475 
476 	makefifo("testfifo", __func__);
477 	if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
478 		warn("test_blocking: openfifo: testfifo");
479 		cleanfifo2("testfifo", -1, -1);
480 		exit(-1);
481 	}
482 
483 	if (set_blocking(writer_fd, __func__) < 0) {
484 		cleanfifo2("testfifo", reader_fd, writer_fd);
485 		exit(-1);
486 	}
487 	if (set_blocking(reader_fd, __func__) < 0) {
488 		cleanfifo2("testfifo", reader_fd, writer_fd);
489 		exit(-1);
490 	}
491 
492 	ch = 0xfe;
493 	ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout,
494 	    __func__);
495 	if (ret < 0) {
496 		warn("test_blocking_one_byte: timed_write");
497 		cleanfifo2("testfifo", reader_fd, writer_fd);
498 		exit(-1);
499 	}
500 	if (len != sizeof(ch)) {
501 		warnx("test_blocking_one_byte: timed_write: tried to write "
502 		    "%zu, wrote %zd", sizeof(ch), len);
503 		cleanfifo2("testfifo", reader_fd, writer_fd);
504 		exit(-1);
505 	}
506 
507 	ch = 0xab;
508 	ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
509 	    __func__);
510 	if (ret < 0) {
511 		warn("test_blocking_one_byte: timed_read");
512 		cleanfifo2("testfifo", reader_fd, writer_fd);
513 		exit(-1);
514 	}
515 	if (len != sizeof(ch)) {
516 		warnx("test_blocking_one_byte: timed_read: wanted %zu, "
517 		    "read %zd", sizeof(ch), len);
518 		cleanfifo2("testfifo", reader_fd, writer_fd);
519 		exit(-1);
520 	}
521 	if (ch != 0xfe) {
522 		warnx("test_blocking_one_byte: timed_read: expected to read "
523 		    "0x%02x, read 0x%02x", 0xfe, ch);
524 		cleanfifo2("testfifo", reader_fd, writer_fd);
525 		exit(-1);
526 	}
527 
528 	cleanfifo2("testfifo", reader_fd, writer_fd);
529 }
530 
531 /*
532  * Write one byte to an empty fifo, then try to read one byte and make sure
533  * we don't get back EAGAIN.
534  */
535 static void
test_nonblocking_one_byte(void)536 test_nonblocking_one_byte(void)
537 {
538 	int reader_fd, ret, timedout, writer_fd;
539 	ssize_t len;
540 	u_char ch;
541 
542 	makefifo("testfifo", __func__);
543 	if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
544 		warn("test_nonblocking: openfifo: testfifo");
545 		cleanfifo2("testfifo", -1, -1);
546 		exit(-1);
547 	}
548 
549 	if (set_nonblocking(reader_fd, __func__) < 0) {
550 		cleanfifo2("testfifo", reader_fd, writer_fd);
551 		exit(-1);
552 	}
553 
554 	ch = 0xfe;
555 	ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout,
556 	    __func__);
557 	if (ret < 0) {
558 		warn("test_nonblocking_one_byte: timed_write");
559 		cleanfifo2("testfifo", reader_fd, writer_fd);
560 		exit(-1);
561 	}
562 	if (len != sizeof(ch)) {
563 		warnx("test_nonblocking_one_byte: timed_write: tried to write "
564 		    "%zu, wrote %zd", sizeof(ch), len);
565 		cleanfifo2("testfifo", reader_fd, writer_fd);
566 		exit(-1);
567 	}
568 
569 	ch = 0xab;
570 	ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
571 	    __func__);
572 	if (ret < 0) {
573 		warn("test_nonblocking_one_byte: timed_read");
574 		cleanfifo2("testfifo", reader_fd, writer_fd);
575 		exit(-1);
576 	}
577 	if (len != sizeof(ch)) {
578 		warnx("test_nonblocking_one_byte: timed_read: wanted %zu, read "
579 		    "%zd", sizeof(ch), len);
580 		cleanfifo2("testfifo", reader_fd, writer_fd);
581 		exit(-1);
582 	}
583 	if (ch != 0xfe) {
584 		warnx("test_nonblocking_one_byte: timed_read: expected to read "
585 		    "0x%02x, read 0x%02x", 0xfe, ch);
586 		cleanfifo2("testfifo", reader_fd, writer_fd);
587 		exit(-1);
588 	}
589 
590 	cleanfifo2("testfifo", reader_fd, writer_fd);
591 }
592 
593 /*
594  * First of two test cases involving a 512K buffer: write the buffer into a
595  * blocking file descriptor.  We'd like to know it blocks, but the closest we
596  * can get is to see if SIGALRM fired during the I/O resulting in a partial
597  * write.
598  */
599 static void
test_blocking_partial_write(void)600 test_blocking_partial_write(void)
601 {
602 	int reader_fd, ret, timedout, writer_fd;
603 	u_char *buffer;
604 	ssize_t len;
605 
606 	makefifo("testfifo", __func__);
607 	if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
608 		warn("test_blocking_partial_write: openfifo: testfifo");
609 		cleanfifo2("testfifo", -1, -1);
610 		exit(-1);
611 	}
612 
613 	if (set_blocking(writer_fd, __func__) < 0) {
614 		cleanfifo2("testfifo", reader_fd, writer_fd);
615 		exit(-1);
616 	}
617 
618 	buffer = malloc(512*1024);
619 	if (buffer == NULL) {
620 		warn("test_blocking_partial_write: malloc");
621 		cleanfifo2("testfifo", reader_fd, writer_fd);
622 		exit(-1);
623 	}
624 	bzero(buffer, 512*1024);
625 
626 	ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout,
627 	    __func__);
628 	if (ret < 0) {
629 		warn("test_blocking_partial_write: timed_write");
630 		free(buffer);
631 		cleanfifo2("testfifo", reader_fd, writer_fd);
632 		exit(-1);
633 	}
634 
635 	if (!timedout) {
636 		warnx("test_blocking_partial_write: timed_write: blocking "
637 		    "socket didn't time out");
638 		free(buffer);
639 		cleanfifo2("testfifo", reader_fd, writer_fd);
640 		exit(-1);
641 	}
642 
643 	free(buffer);
644 
645 	if (drain_fd(reader_fd, __func__) < 0) {
646 		cleanfifo2("testfifo", reader_fd, writer_fd);
647 		exit(-1);
648 	}
649 
650 	cleanfifo2("testfifo", reader_fd, writer_fd);
651 }
652 
653 /*
654  * Write a 512K buffer to an empty fifo using a non-blocking file descriptor,
655  * and make sure it doesn't block.
656  */
657 static void
test_nonblocking_partial_write(void)658 test_nonblocking_partial_write(void)
659 {
660 	int reader_fd, ret, timedout, writer_fd;
661 	u_char *buffer;
662 	ssize_t len;
663 
664 	makefifo("testfifo", __func__);
665 	if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
666 		warn("test_blocking_partial_write: openfifo: testfifo");
667 		cleanfifo2("testfifo", -1, -1);
668 		exit(-1);
669 	}
670 
671 	if (set_nonblocking(writer_fd, __func__) < 0) {
672 		cleanfifo2("testfifo", reader_fd, writer_fd);
673 		exit(-1);
674 	}
675 
676 	buffer = malloc(512*1024);
677 	if (buffer == NULL) {
678 		warn("test_blocking_partial_write: malloc");
679 		cleanfifo2("testfifo", reader_fd, writer_fd);
680 		exit(-1);
681 	}
682 	bzero(buffer, 512*1024);
683 
684 	ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout,
685 	    __func__);
686 	if (ret < 0) {
687 		warn("test_blocking_partial_write: timed_write");
688 		free(buffer);
689 		cleanfifo2("testfifo", reader_fd, writer_fd);
690 		exit(-1);
691 	}
692 
693 	if (timedout) {
694 		warnx("test_blocking_partial_write: timed_write: "
695 		    "non-blocking socket timed out");
696 		free(buffer);
697 		cleanfifo2("testfifo", reader_fd, writer_fd);
698 		exit(-1);
699 	}
700 
701 	if (len == 0 || len >= 512*1024) {
702 		warnx("test_blocking_partial_write: timed_write: requested "
703 		    "%d, sent %zd", 512*1024, len);
704 		free(buffer);
705 		cleanfifo2("testfifo", reader_fd, writer_fd);
706 		exit(-1);
707 	}
708 
709 	free(buffer);
710 
711 	if (drain_fd(reader_fd, __func__) < 0) {
712 		cleanfifo2("testfifo", reader_fd, writer_fd);
713 		exit(-1);
714 	}
715 
716 	cleanfifo2("testfifo", reader_fd, writer_fd);
717 }
718 
719 /*
720  * test_coalesce_big_read() verifies that data mingles in the fifo across
721  * message boundaries by performing two small writes, then a bigger read
722  * that should return data from both writes.
723  */
724 static void
test_coalesce_big_read(void)725 test_coalesce_big_read(void)
726 {
727 	int i, reader_fd, writer_fd;
728 	u_char buffer[10];
729 	ssize_t len;
730 
731 	makefifo("testfifo", __func__);
732 	if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
733 		warn("test_coalesce_big_read: openfifo: testfifo");
734 		cleanfifo2("testfifo", -1, -1);
735 		exit(-1);
736 	}
737 
738 	/* Write five, write five, read ten. */
739 	for (i = 0; i < 10; i++)
740 		buffer[i] = i;
741 
742 	len = write(writer_fd, buffer, 5);
743 	if (len < 0) {
744 		warn("test_coalesce_big_read: write 5");
745 		cleanfifo2("testfifo", reader_fd, writer_fd);
746 		exit(-1);
747 	}
748 	if (len != 5) {
749 		warnx("test_coalesce_big_read: write 5 wrote %zd", len);
750 		cleanfifo2("testfifo", reader_fd, writer_fd);
751 		exit(-1);
752 	}
753 
754 	len = write(writer_fd, buffer + 5, 5);
755 	if (len < 0) {
756 		warn("test_coalesce_big_read: write 5");
757 		cleanfifo2("testfifo", reader_fd, writer_fd);
758 		exit(-1);
759 	}
760 	if (len != 5) {
761 		warnx("test_coalesce_big_read: write 5 wrote %zd", len);
762 		cleanfifo2("testfifo", reader_fd, writer_fd);
763 		exit(-1);
764 	}
765 
766 	len = read(reader_fd, buffer, 10);
767 	if (len < 0) {
768 		warn("test_coalesce_big_read: read 10");
769 		cleanfifo2("testfifo", reader_fd, writer_fd);
770 		exit(-1);
771 	}
772 	if (len != 10) {
773 		warnx("test_coalesce_big_read: read 10 read %zd", len);
774 		cleanfifo2("testfifo", reader_fd, writer_fd);
775 		exit(-1);
776 	}
777 
778 	for (i = 0; i < 10; i++) {
779 		if (buffer[i] == i)
780 			continue;
781 		warnx("test_coalesce_big_read: expected to read 0x%02x, "
782 		    "read 0x%02x", i, buffer[i]);
783 		cleanfifo2("testfifo", reader_fd, writer_fd);
784 		exit(-1);
785 	}
786 
787 	cleanfifo2("testfifo", -1, -1);
788 }
789 
790 /*
791  * test_coalesce_big_write() verifies that data mingles in the fifo across
792  * message boundaries by performing one big write, then two smaller reads
793  * that should return sequential elements of data from the write.
794  */
795 static void
test_coalesce_big_write(void)796 test_coalesce_big_write(void)
797 {
798 	int i, reader_fd, writer_fd;
799 	u_char buffer[10];
800 	ssize_t len;
801 
802 	makefifo("testfifo", __func__);
803 	if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
804 		warn("test_coalesce_big_write: openfifo: testfifo");
805 		cleanfifo2("testfifo", -1, -1);
806 		exit(-1);
807 	}
808 
809 	/* Write ten, read five, read five. */
810 	for (i = 0; i < 10; i++)
811 		buffer[i] = i;
812 
813 	len = write(writer_fd, buffer, 10);
814 	if (len < 0) {
815 		warn("test_coalesce_big_write: write 10");
816 		cleanfifo2("testfifo", reader_fd, writer_fd);
817 		exit(-1);
818 	}
819 	if (len != 10) {
820 		warnx("test_coalesce_big_write: write 10 wrote %zd", len);
821 		cleanfifo2("testfifo", reader_fd, writer_fd);
822 		exit(-1);
823 	}
824 
825 	len = read(reader_fd, buffer, 5);
826 	if (len < 0) {
827 		warn("test_coalesce_big_write: read 5");
828 		cleanfifo2("testfifo", reader_fd, writer_fd);
829 		exit(-1);
830 	}
831 	if (len != 5) {
832 		warnx("test_coalesce_big_write: read 5 read %zd", len);
833 		cleanfifo2("testfifo", reader_fd, writer_fd);
834 		exit(-1);
835 	}
836 
837 	len = read(reader_fd, buffer + 5, 5);
838 	if (len < 0) {
839 		warn("test_coalesce_big_write: read 5");
840 		cleanfifo2("testfifo", reader_fd, writer_fd);
841 		exit(-1);
842 	}
843 	if (len != 5) {
844 		warnx("test_coalesce_big_write: read 5 read %zd", len);
845 		cleanfifo2("testfifo", reader_fd, writer_fd);
846 		exit(-1);
847 	}
848 
849 	for (i = 0; i < 10; i++) {
850 		if (buffer[i] == i)
851 			continue;
852 		warnx("test_coalesce_big_write: expected to read 0x%02x, "
853 		    "read 0x%02x", i, buffer[i]);
854 		cleanfifo2("testfifo", reader_fd, writer_fd);
855 		exit(-1);
856 	}
857 
858 	cleanfifo2("testfifo", -1, -1);
859 }
860 
861 static int
poll_status(int fd,int * readable,int * writable,int * exception,const char * testname)862 poll_status(int fd, int *readable, int *writable, int *exception,
863     const char *testname)
864 {
865 	struct pollfd fds[1];
866 
867 	fds[0].fd = fd;
868 	fds[0].events = POLLIN | POLLOUT | POLLERR;
869 	fds[0].revents = 0;
870 
871 	if (poll(fds, 1, 0) < 0) {
872 		warn("%s: poll", testname);
873 		return (-1);
874 	}
875 	*readable = (fds[0].revents & POLLIN) ? 1 : 0;
876 	*writable = (fds[0].revents & POLLOUT) ? 1 : 0;
877 	*exception = (fds[0].revents & POLLERR) ? 1 : 0;
878 	return (0);
879 }
880 
881 static int
select_status(int fd,int * readable,int * writable,int * exception,const char * testname)882 select_status(int fd, int *readable, int *writable, int *exception,
883     const char *testname)
884 {
885 	struct fd_set readfds, writefds, exceptfds;
886 	struct timeval timeout;
887 
888 	FD_ZERO(&readfds);
889 	FD_ZERO(&writefds);
890 	FD_ZERO(&exceptfds);
891 	FD_SET(fd, &readfds);
892 	FD_SET(fd, &writefds);
893 	FD_SET(fd, &exceptfds);
894 	timeout.tv_sec = 0;
895 	timeout.tv_usec = 0;
896 	if (select(fd+1, &readfds, &writefds, &exceptfds, &timeout) < 0) {
897 		warn("%s: select", testname);
898 		return (-1);
899 	}
900 	*readable = FD_ISSET(fd, &readfds) ? 1 : 0;
901 	*writable = FD_ISSET(fd, &writefds) ? 1 : 0;
902 	*exception = FD_ISSET(fd, &exceptfds) ? 1 : 0;
903 	return (0);
904 }
905 
906 /*
907  * Given an existing kqueue, set up read and write event filters for the
908  * passed file descriptor.  Typically called once for the read endpoint, and
909  * once for the write endpoint.
910  */
911 static int
kqueue_setup(int kqueue_fd,int fd,const char * testname)912 kqueue_setup(int kqueue_fd, int fd, const char *testname)
913 {
914 	struct kevent kevent_changelist[2];
915 	struct kevent kevent_eventlist[KQUEUE_MAX_EVENT], *kp;
916 	struct timespec timeout;
917 	int i, ret;
918 
919 	timeout.tv_sec = 0;
920 	timeout.tv_nsec = 0;
921 
922 	bzero(&kevent_changelist, sizeof(kevent_changelist));
923 	EV_SET(&kevent_changelist[0], fd, EVFILT_READ, EV_ADD, 0, 0, 0);
924 	EV_SET(&kevent_changelist[1], fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
925 
926 	bzero(&kevent_eventlist, sizeof(kevent_eventlist));
927 	ret = kevent(kqueue_fd, kevent_changelist, 2, kevent_eventlist,
928 	    KQUEUE_MAX_EVENT, &timeout);
929 	if (ret < 0) {
930 		warn("%s:%s: kevent initial register", testname, __func__);
931 		return (-1);
932 	}
933 
934 	/*
935 	 * Verify that the events registered alright.
936 	 */
937 	for (i = 0; i < ret; i++) {
938 		kp = &kevent_eventlist[i];
939 		if (kp->flags != EV_ERROR)
940 			continue;
941 		errno = kp->data;
942 		warn("%s:%s: kevent register index %d", testname, __func__,
943 		    i);
944 		return (-1);
945 	}
946 
947 	return (0);
948 }
949 
950 static int
kqueue_status(int kqueue_fd,int fd,int * readable,int * writable,int * exception,const char * testname)951 kqueue_status(int kqueue_fd, int fd, int *readable, int *writable,
952     int *exception, const char *testname)
953 {
954 	struct kevent kevent_eventlist[KQUEUE_MAX_EVENT], *kp;
955 	struct timespec timeout;
956 	int i, ret;
957 
958 	timeout.tv_sec = 0;
959 	timeout.tv_nsec = 0;
960 
961 	ret = kevent(kqueue_fd, NULL, 0, kevent_eventlist, KQUEUE_MAX_EVENT,
962 	    &timeout);
963 	if (ret < 0) {
964 		warn("%s: %s: kevent", testname, __func__);
965 		return (-1);
966 	}
967 
968 	*readable = *writable = *exception = 0;
969 	for (i = 0; i < ret; i++) {
970 		kp = &kevent_eventlist[i];
971 		if (kp->ident != (u_int)fd)
972 			continue;
973 		if (kp->filter == EVFILT_READ)
974 			*readable = 1;
975 		if (kp->filter == EVFILT_WRITE)
976 			*writable = 1;
977 	}
978 
979 	return (0);
980 }
981 
982 static int
fionread_status(int fd,int * readable,const char * testname)983 fionread_status(int fd, int *readable, const char *testname)
984 {
985 	int i;
986 
987 	if (ioctl(fd, FIONREAD, &i) < 0) {
988 		warn("%s: ioctl(FIONREAD)", testname);
989 		return (-1);
990 	}
991 
992 	if (i > 0)
993 		*readable = 1;
994 	else
995 		*readable = 0;
996 	return (0);
997 }
998 
999 #define	READABLE	1
1000 #define	WRITABLE	1
1001 #define	EXCEPTION	1
1002 
1003 #define	NOT_READABLE	0
1004 #define	NOT_WRITABLE	0
1005 #define	NOT_EXCEPTION	0
1006 
1007 static int
assert_status(int fd,int kqueue_fd,int assert_readable,int assert_writable,int assert_exception,const char * testname,const char * conditionname,const char * fdname)1008 assert_status(int fd, int kqueue_fd, int assert_readable,
1009     int assert_writable, int assert_exception, const char *testname,
1010     const char *conditionname, const char *fdname)
1011 {
1012 	int readable, writable, exception;
1013 
1014 	if (poll_status(fd, &readable, &writable, &exception, testname) < 0)
1015 		return (-1);
1016 
1017 	if (readable != assert_readable || writable != assert_writable ||
1018 	    exception != assert_exception) {
1019 		warnx("%s: %s polls r:%d, w:%d, e:%d on %s", testname,
1020 		    fdname, readable, writable, exception, conditionname);
1021 		return (-1);
1022 	}
1023 
1024 	if (select_status(fd, &readable, &writable, &exception, testname) < 0)
1025 		return (-1);
1026 
1027 	if (readable != assert_readable || writable != assert_writable ||
1028 	    exception != assert_exception) {
1029 		warnx("%s: %s selects r:%d, w:%d, e:%d on %s", testname,
1030 		    fdname, readable, writable, exception, conditionname);
1031 		return (-1);
1032 	}
1033 
1034 	if (kqueue_status(kqueue_fd, fd, &readable, &writable, &exception,
1035 	    testname) < 0)
1036 		return (-1);
1037 
1038 	if (readable != assert_readable || writable != assert_writable ||
1039 	    exception != assert_exception) {
1040 		warnx("%s: %s kevent r:%d, w:%d, e:%d on %s", testname,
1041 		    fdname, readable, writable, exception, conditionname);
1042 		return (-1);
1043 	}
1044 
1045 	if (fionread_status(fd, &readable, __func__) < 0)
1046 		return (-1);
1047 
1048 	if (readable != assert_readable) {
1049 		warnx("%s: %s fionread r:%d on %s", testname, fdname,
1050 		    readable, conditionname);
1051 		return (-1);
1052 	}
1053 
1054 	return (0);
1055 }
1056 
1057 /*
1058  * test_events() uses poll(), select(), and kevent() to query the status of
1059  * fifo file descriptors and determine whether they match expected state
1060  * based on earlier semantic tests: specifically, whether or not poll/select/
1061  * kevent will correctly inform on readable/writable state following I/O.
1062  *
1063  * It would be nice to also test status changes as a result of closing of one
1064  * or another fifo endpoint.
1065  */
1066 static void
test_events_outofbox(void)1067 test_events_outofbox(void)
1068 {
1069 	int kqueue_fd, reader_fd, writer_fd;
1070 
1071 	makefifo("testfifo", __func__);
1072 	if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
1073 		warn("test_events_outofbox: openfifo: testfifo");
1074 		cleanfifo2("testfifo", -1, -1);
1075 		exit(-1);
1076 	}
1077 
1078 	kqueue_fd = kqueue();
1079 	if (kqueue_fd < 0) {
1080 		warn("%s: kqueue", __func__);
1081 		cleanfifo2("testfifo", reader_fd, writer_fd);
1082 		exit(-1);
1083 	}
1084 
1085 	if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) {
1086 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1087 		exit(-1);
1088 	}
1089 
1090 	if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) {
1091 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1092 		exit(-1);
1093 	}
1094 
1095 	/*
1096 	 * Make sure that fresh, out-of-the-box fifo file descriptors have
1097 	 * good initial states.  The reader_fd should have no active state,
1098 	 * since it will not be readable (no data in pipe), writable (it's
1099 	 * a read-only descriptor), and there's no reason for error yet.
1100 	 */
1101 	if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE,
1102 	    NOT_EXCEPTION, __func__, "create", "reader_fd") < 0) {
1103 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1104 		exit(-1);
1105 	}
1106 
1107 	/*
1108 	 * Make sure that fresh, out-of-the-box fifo file descriptors have
1109 	 * good initial states.  The writer_fd should be ready to write.
1110 	 */
1111 	if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
1112 	    NOT_EXCEPTION, __func__, "create", "writer_fd") < 0) {
1113 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1114 		exit(-1);
1115 	}
1116 
1117 	cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1118 }
1119 
1120 static void
test_events_write_read_byte(void)1121 test_events_write_read_byte(void)
1122 {
1123 	int kqueue_fd, reader_fd, writer_fd;
1124 	ssize_t len;
1125 	u_char ch;
1126 
1127 	makefifo("testfifo", __func__);
1128 	if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
1129 		warn("test_events_write_read_byte: openfifo: testfifo");
1130 		cleanfifo2("testfifo", -1, -1);
1131 		exit(-1);
1132 	}
1133 
1134 	kqueue_fd = kqueue();
1135 	if (kqueue_fd < 0) {
1136 		warn("%s: kqueue", __func__);
1137 		cleanfifo2("testfifo", reader_fd, writer_fd);
1138 		exit(-1);
1139 	}
1140 
1141 	if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) {
1142 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1143 		exit(-1);
1144 	}
1145 
1146 	if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) {
1147 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1148 		exit(-1);
1149 	}
1150 
1151 	/*
1152 	 * Write a byte to the fifo, and make sure that the read end becomes
1153 	 * readable, and that the write end remains writable (small write).
1154 	 */
1155 	ch = 0x00;
1156 	len = write(writer_fd, &ch, sizeof(ch));
1157 	if (len < 0) {
1158 		warn("%s: write", __func__);
1159 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1160 		exit(-1);
1161 	}
1162 
1163 	if (assert_status(reader_fd, kqueue_fd, READABLE, NOT_WRITABLE,
1164 	    NOT_EXCEPTION, __func__, "write", "reader_fd") < 0) {
1165 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1166 		exit(-1);
1167 	}
1168 
1169 	/*
1170 	 * the writer_fd should remain writable.
1171 	 */
1172 	if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
1173 	    NOT_EXCEPTION, __func__, "write", "writer_fd") < 0) {
1174 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1175 		exit(-1);
1176 	}
1177 
1178 	/*
1179 	 * Read the byte from the reader_fd, and now confirm that the fifo
1180 	 * becomes unreadable.
1181 	 */
1182 	len = read(reader_fd, &ch, sizeof(ch));
1183 	if (len < 0) {
1184 		warn("%s: read", __func__);
1185 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1186 		exit(-1);
1187 	}
1188 
1189 	if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE,
1190 	    NOT_EXCEPTION, __func__, "write+read", "reader_fd") < 0) {
1191 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1192 		exit(-1);
1193 	}
1194 
1195 	/*
1196 	 * The writer_fd should remain writable.
1197 	 */
1198 	if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
1199 	    NOT_EXCEPTION, __func__, "write+read", "writer_fd") < 0) {
1200 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1201 		exit(-1);
1202 	}
1203 
1204 	cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1205 }
1206 
1207 /*
1208  * Write a 512k buffer to the fifo in non-blocking mode, and make sure that
1209  * the write end becomes un-writable as a result of a partial write that
1210  * fills the fifo buffer.
1211  */
1212 static void
test_events_partial_write(void)1213 test_events_partial_write(void)
1214 {
1215 	int kqueue_fd, reader_fd, writer_fd;
1216 	u_char *buffer;
1217 	ssize_t len;
1218 
1219 	makefifo("testfifo", __func__);
1220 	if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
1221 		warn("test_events_partial_write: openfifo: testfifo");
1222 		cleanfifo2("testfifo", -1, -1);
1223 		exit(-1);
1224 	}
1225 
1226 	kqueue_fd = kqueue();
1227 	if (kqueue_fd < 0) {
1228 		warn("%s: kqueue", __func__);
1229 		cleanfifo2("testfifo", reader_fd, writer_fd);
1230 		exit(-1);
1231 	}
1232 
1233 	if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) {
1234 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1235 		exit(-1);
1236 	}
1237 
1238 	if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) {
1239 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1240 		exit(-1);
1241 	}
1242 
1243 	if (set_nonblocking(writer_fd, "test_events") < 0) {
1244 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1245 		exit(-1);
1246 	}
1247 
1248 	buffer = malloc(512*1024);
1249 	if (buffer == NULL) {
1250 		warn("test_events_partial_write: malloc");
1251 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1252 		exit(-1);
1253 	}
1254 	bzero(buffer, 512*1024);
1255 
1256 	len = write(writer_fd, buffer, 512*1024);
1257 	if (len < 0) {
1258 		warn("test_events_partial_write: write");
1259 		free(buffer);
1260 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1261 		exit(-1);
1262 	}
1263 
1264 	free(buffer);
1265 
1266 	if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE,
1267 	    NOT_EXCEPTION, __func__, "big write", "writer_fd") < 0) {
1268 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1269 		exit(-1);
1270 	}
1271 
1272 	if (drain_fd(reader_fd, "test_events") < 0) {
1273 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1274 		exit(-1);
1275 	}
1276 
1277 	/*
1278 	 * Test that the writer_fd has been restored to writable state after
1279 	 * draining.
1280 	 */
1281 	if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
1282 	    NOT_EXCEPTION, __func__, "big write + drain", "writer_fd") < 0) {
1283 		cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1284 		exit(-1);
1285 	}
1286 
1287 	cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1288 }
1289 
1290 /*
1291  * We don't comprehensively test O_RDWR file descriptors, but do run a couple
1292  * of event tests to make sure that the fifo implementation doesn't mixed up
1293  * status checks.  In particular, at least one past FreeBSD bug exists in
1294  * which the FIONREAD test was performed on the wrong socket implementing the
1295  * fifo, resulting in the fifo never returning readable.
1296  */
1297 static void
test_events_rdwr(void)1298 test_events_rdwr(void)
1299 {
1300 	int fd, kqueue_fd;
1301 	ssize_t len;
1302 	char ch;
1303 
1304 	makefifo("testfifo", __func__);
1305 	if (openfifo_rw("testfifo", &fd) < 0) {
1306 		warn("%s: openfifo_rw: testfifo", __func__);
1307 		cleanfifo2("testfifo", -1, -1);
1308 		exit(-1);
1309 	}
1310 
1311 	kqueue_fd = kqueue();
1312 	if (kqueue_fd < 0) {
1313 		warn("%s: kqueue", __func__);
1314 		cleanfifo2("testifo", fd, -1);
1315 		exit(-1);
1316 	}
1317 
1318 	if (kqueue_setup(kqueue_fd, fd, __func__) < 0) {
1319 		cleanfifo2("testfifo", fd, kqueue_fd);
1320 		exit(-1);
1321 	}
1322 
1323 	/*
1324 	 * On first creation, the O_RDWR descriptor should be writable but
1325 	 * not readable.
1326 	 */
1327 	if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE,
1328 	    NOT_EXCEPTION, __func__, "create", "fd") < 0) {
1329 		cleanfifo2("testfifo", fd, kqueue_fd);
1330 		exit(-1);
1331 	}
1332 
1333 	/*
1334 	 * Write a byte, which should cause the file descriptor to become
1335 	 * readable and writable.
1336 	 */
1337 	ch = 0x00;
1338 	len = write(fd, &ch, sizeof(ch));
1339 	if (len < 0) {
1340 		warn("%s: write", __func__);
1341 		cleanfifo2("testfifo", fd, kqueue_fd);
1342 		exit(-1);
1343 	}
1344 
1345 	if (assert_status(fd, kqueue_fd, READABLE, WRITABLE, NOT_EXCEPTION,
1346 	    __func__, "write", "fd") < 0) {
1347 		cleanfifo2("testfifo", fd, kqueue_fd);
1348 		exit(-1);
1349 	}
1350 
1351 	/*
1352 	 * Read a byte, which should cause the file descriptor to return to
1353 	 * simply being writable.
1354 	 */
1355 	len = read(fd, &ch, sizeof(ch));
1356 	if (len < 0) {
1357 		warn("%s: read", __func__);
1358 		cleanfifo2("testfifo", fd, kqueue_fd);
1359 		exit(-1);
1360 	}
1361 
1362 	if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE,
1363 	    NOT_EXCEPTION, __func__, "write+read", "fd") < 0) {
1364 		cleanfifo2("testfifo", fd, kqueue_fd);
1365 		exit(-1);
1366 	}
1367 
1368 	cleanfifo2("testfifo", fd, kqueue_fd);
1369 }
1370 
1371 int
main(void)1372 main(void)
1373 {
1374 
1375 	strcpy(temp_dir, "fifo_io.XXXXXXXXXXX");
1376 	if (mkdtemp(temp_dir) == NULL)
1377 		err(-1, "mkdtemp");
1378 	atexit(atexit_temp_dir);
1379 
1380 	if (chdir(temp_dir) < 0)
1381 		err(-1, "chdir %s", temp_dir);
1382 
1383 	test_simpleio();
1384 	test_blocking_read_empty();
1385 	test_blocking_one_byte();
1386 	test_nonblocking_one_byte();
1387 	test_blocking_partial_write();
1388 	test_nonblocking_partial_write();
1389 	test_coalesce_big_read();
1390 	test_coalesce_big_write();
1391 	test_events_outofbox();
1392 	test_events_write_read_byte();
1393 	test_events_partial_write();
1394 	test_events_rdwr();
1395 
1396 	return (0);
1397 }
1398