1150022Srwatson/*- 2150022Srwatson * Copyright (c) 2005 Robert N. M. Watson 3150022Srwatson * All rights reserved. 4150022Srwatson * 5150022Srwatson * Redistribution and use in source and binary forms, with or without 6150022Srwatson * modification, are permitted provided that the following conditions 7150022Srwatson * are met: 8150022Srwatson * 1. Redistributions of source code must retain the above copyright 9150022Srwatson * notice, this list of conditions and the following disclaimer. 10150022Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11150022Srwatson * notice, this list of conditions and the following disclaimer in the 12150022Srwatson * documentation and/or other materials provided with the distribution. 13150022Srwatson * 14150022Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15150022Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16150022Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17150022Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18150022Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19150022Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20150022Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21150022Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22150022Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23150022Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24150022Srwatson * SUCH DAMAGE. 25150022Srwatson * 26150022Srwatson * $FreeBSD$ 27150022Srwatson */ 28150022Srwatson 29150059Srwatson#include <sys/types.h> 30150059Srwatson#include <sys/event.h> 31150091Srwatson#include <sys/ioctl.h> 32150022Srwatson#include <sys/select.h> 33150022Srwatson#include <sys/stat.h> 34150059Srwatson#include <sys/time.h> 35150022Srwatson 36150022Srwatson#include <err.h> 37150022Srwatson#include <errno.h> 38150022Srwatson#include <fcntl.h> 39150022Srwatson#include <limits.h> 40150022Srwatson#include <poll.h> 41150022Srwatson#include <signal.h> 42150022Srwatson#include <stdio.h> 43150022Srwatson#include <stdlib.h> 44150022Srwatson#include <string.h> 45150022Srwatson#include <unistd.h> 46150022Srwatson 47150022Srwatson/* 48150022Srwatson * Regression test to exercise POSIX fifo I/O. 49150022Srwatson * 50150022Srwatson * We test a number of aspect of behavior, including: 51150022Srwatson * 52150022Srwatson * - If there's no data to read, then for blocking fifos, we block, and for 53150022Srwatson * non-blocking, we return EAGAIN. 54150022Srwatson * 55150022Srwatson * - If we write ten bytes, ten bytes can be read, and they're the same 56150022Srwatson * bytes, in the same order. 57150022Srwatson * 58150022Srwatson * - If we write two batches of five bytes, we can read the same ten bytes in 59150022Srwatson * one read of ten bytes. 60150022Srwatson * 61150022Srwatson * - If we write ten bytes, we can read the same ten bytes in two reads of 62150022Srwatson * five bytes each. 63150022Srwatson * 64150022Srwatson * - If we over-fill a buffer (by writing 512k, which we take to be a large 65150022Srwatson * number above default buffer sizes), we block if there is no reader. 66150022Srwatson * 67150022Srwatson * - That once 512k (ish) is read from the other end, the blocked writer 68150022Srwatson * wakes up. 69150022Srwatson * 70150091Srwatson * - When a fifo is empty, poll, select, kqueue, and fionread report it is 71150091Srwatson * writable but not readable. 72150022Srwatson * 73150091Srwatson * - When a fifo has data in it, poll, select, and kqueue report that it is 74150091Srwatson * writable. 75150022Srwatson * 76150022Srwatson * - XXX: blocked reader semantics? 77150022Srwatson * 78150091Srwatson * - XXX: event behavior on remote close? 79150093Srwatson * 80150093Srwatson * Although behavior of O_RDWR isn't defined for fifos by POSIX, we expect 81150093Srwatson * "reasonable" behavior, and run some additional tests relating to event 82150093Srwatson * management on O_RDWR fifo descriptors. 83150022Srwatson */ 84150022Srwatson 85150093Srwatson#define KQUEUE_MAX_EVENT 8 86150093Srwatson 87150022Srwatson/* 88150022Srwatson * All activity occurs within a temporary directory created early in the 89150022Srwatson * test. 90150022Srwatson */ 91281450Sngiestatic char temp_dir[PATH_MAX]; 92150022Srwatson 93150022Srwatsonstatic void __unused 94150022Srwatsonatexit_temp_dir(void) 95150022Srwatson{ 96150022Srwatson 97150022Srwatson rmdir(temp_dir); 98150022Srwatson} 99150022Srwatson 100150022Srwatsonstatic void 101150022Srwatsonmakefifo(const char *fifoname, const char *testname) 102150022Srwatson{ 103150022Srwatson 104150022Srwatson if (mkfifo(fifoname, 0700) < 0) 105150022Srwatson err(-1, "%s: makefifo: mkfifo: %s", testname, fifoname); 106150022Srwatson} 107150022Srwatson 108150022Srwatsonstatic void 109150093Srwatsoncleanfifo2(const char *fifoname, int fd1, int fd2) 110150022Srwatson{ 111150022Srwatson 112150022Srwatson if (fd1 != -1) 113150022Srwatson close(fd1); 114150022Srwatson if (fd2 != -1) 115150022Srwatson close(fd2); 116150022Srwatson (void)unlink(fifoname); 117150022Srwatson} 118150022Srwatson 119150059Srwatsonstatic void 120150093Srwatsoncleanfifo3(const char *fifoname, int fd1, int fd2, int fd3) 121150059Srwatson{ 122150059Srwatson 123150059Srwatson if (fd3 != -1) 124150059Srwatson close(fd3); 125150093Srwatson cleanfifo2(fifoname, fd1, fd2); 126150059Srwatson} 127150059Srwatson 128150093Srwatson/* 129150093Srwatson * Open two different file descriptors for a fifo: one read, one write. Do 130150093Srwatson * so using non-blocking opens in order to avoid deadlocking the process. 131150093Srwatson */ 132150022Srwatsonstatic int 133281450Sngieopenfifo(const char *fifoname, int *reader_fdp, int *writer_fdp) 134150022Srwatson{ 135150022Srwatson int error, fd1, fd2; 136150022Srwatson 137150022Srwatson fd1 = open(fifoname, O_RDONLY | O_NONBLOCK); 138150022Srwatson if (fd1 < 0) 139150022Srwatson return (-1); 140150022Srwatson fd2 = open(fifoname, O_WRONLY | O_NONBLOCK); 141150022Srwatson if (fd2 < 0) { 142150022Srwatson error = errno; 143150022Srwatson close(fd1); 144150022Srwatson errno = error; 145150022Srwatson return (-1); 146150022Srwatson } 147150022Srwatson *reader_fdp = fd1; 148150022Srwatson *writer_fdp = fd2; 149150022Srwatson 150150022Srwatson return (0); 151150022Srwatson} 152150022Srwatson 153150093Srwatson/* 154150093Srwatson * Open one file descriptor for the fifo, supporting both read and write. 155150093Srwatson */ 156150022Srwatsonstatic int 157281450Sngieopenfifo_rw(const char *fifoname, int *fdp) 158150093Srwatson{ 159150093Srwatson int fd; 160150093Srwatson 161150093Srwatson fd = open(fifoname, O_RDWR); 162150093Srwatson if (fd < 0) 163150093Srwatson return (-1); 164150093Srwatson *fdp = fd; 165150093Srwatson 166150093Srwatson return (0); 167150093Srwatson} 168150093Srwatson 169150093Srwatsonstatic int 170150022Srwatsonset_nonblocking(int fd, const char *testname) 171150022Srwatson{ 172150022Srwatson int flags; 173150022Srwatson 174150022Srwatson flags = fcntl(fd, F_GETFL); 175150022Srwatson if (flags < 0) { 176150022Srwatson warn("%s: fcntl(fd, F_GETFL)", testname); 177150022Srwatson return(-1); 178150022Srwatson } 179150022Srwatson 180150022Srwatson flags |= O_NONBLOCK; 181150022Srwatson 182150022Srwatson if (fcntl(fd, F_SETFL, flags) < 0) { 183150022Srwatson warn("%s: fcntl(fd, 0x%x)", testname, flags); 184150022Srwatson return (-1); 185150022Srwatson } 186150022Srwatson 187150022Srwatson return (0); 188150022Srwatson} 189150022Srwatson 190150022Srwatsonstatic int 191150022Srwatsonset_blocking(int fd, const char *testname) 192150022Srwatson{ 193150022Srwatson int flags; 194150022Srwatson 195150022Srwatson flags = fcntl(fd, F_GETFL); 196150022Srwatson if (flags < 0) { 197150022Srwatson warn("%s: fcntl(fd, F_GETFL)", testname); 198150022Srwatson return(-1); 199150022Srwatson } 200150022Srwatson 201150022Srwatson flags &= ~O_NONBLOCK; 202150022Srwatson 203150022Srwatson if (fcntl(fd, F_SETFL, flags) < 0) { 204150022Srwatson warn("%s: fcntl(fd, 0x%x)", testname, flags); 205150022Srwatson return (-1); 206150022Srwatson } 207150022Srwatson 208150022Srwatson return (0); 209150022Srwatson} 210150022Srwatson 211150022Srwatson/* 212150022Srwatson * Drain a file descriptor (fifo) of any readable data. Note: resets the 213150022Srwatson * blocking state. 214150022Srwatson */ 215150022Srwatsonstatic int 216150022Srwatsondrain_fd(int fd, const char *testname) 217150022Srwatson{ 218150022Srwatson ssize_t len; 219150022Srwatson u_char ch; 220150022Srwatson 221150022Srwatson if (set_nonblocking(fd, testname) < 0) 222150022Srwatson return (-1); 223150022Srwatson 224150022Srwatson while ((len = read(fd, &ch, sizeof(ch))) > 0); 225150022Srwatson if (len < 0) { 226150022Srwatson switch (errno) { 227150022Srwatson case EAGAIN: 228150022Srwatson return (0); 229150022Srwatson default: 230150022Srwatson warn("%s: drain_fd: read", testname); 231150022Srwatson return (-1); 232150022Srwatson } 233150022Srwatson } 234150022Srwatson warn("%s: drain_fd: read: returned 0 bytes", testname); 235150022Srwatson return (-1); 236150022Srwatson} 237150022Srwatson 238150022Srwatson/* 239150022Srwatson * Simple I/O test: write ten integers, and make sure we get back the same 240150022Srwatson * integers in the same order. This assumes a minimum fifo buffer > 10 241150022Srwatson * bytes in order to not block and deadlock. 242150022Srwatson */ 243150022Srwatsonstatic void 244150022Srwatsontest_simpleio(void) 245150022Srwatson{ 246150022Srwatson int i, reader_fd, writer_fd; 247150022Srwatson u_char buffer[10]; 248150022Srwatson ssize_t len; 249150022Srwatson 250150022Srwatson makefifo("testfifo", __func__); 251281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) 252150022Srwatson < 0) { 253150022Srwatson warn("test_simpleio: openfifo: testfifo"); 254150093Srwatson cleanfifo2("testfifo", -1, -1); 255150022Srwatson exit(-1); 256150022Srwatson } 257150022Srwatson 258150022Srwatson for (i = 0; i < 10; i++) 259150022Srwatson buffer[i] = i; 260150022Srwatson 261150022Srwatson len = write(writer_fd, (char *)buffer, sizeof(buffer)); 262150022Srwatson if (len < 0) { 263150022Srwatson warn("test_simpleio: write"); 264150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 265150022Srwatson exit(-1); 266150022Srwatson } 267150022Srwatson if (len != sizeof(buffer)) { 268164083Sjkim warnx("test_simplio: tried %zu but wrote %zd", sizeof(buffer), 269150022Srwatson len); 270150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 271150022Srwatson exit(-1); 272150022Srwatson } 273150022Srwatson 274150022Srwatson len = read(reader_fd, (char *)buffer, sizeof(buffer)); 275150022Srwatson if (len < 0) { 276150022Srwatson warn("test_simpleio: read"); 277150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 278150022Srwatson exit(-1); 279150022Srwatson } 280150022Srwatson if (len != sizeof(buffer)) { 281164083Sjkim warnx("test_simpleio: tried %zu but read %zd", sizeof(buffer), 282150022Srwatson len); 283150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 284150022Srwatson exit(-1); 285150022Srwatson } 286150022Srwatson for (i = 0; i < 10; i++) { 287150022Srwatson if (buffer[i] == i) 288150022Srwatson continue; 289150022Srwatson warnx("test_simpleio: write byte %d as 0x%02x, but read " 290150022Srwatson "0x%02x", i, i, buffer[i]); 291150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 292150022Srwatson exit(-1); 293150022Srwatson } 294150022Srwatson 295150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 296150022Srwatson} 297150022Srwatson 298281450Sngiestatic volatile int alarm_fired; 299150022Srwatson/* 300150022Srwatson * Non-destructive SIGALRM handler. 301150022Srwatson */ 302150022Srwatsonstatic void 303281450Sngiesigalarm(int signum __unused) 304150022Srwatson{ 305150022Srwatson 306150022Srwatson alarm_fired = 1; 307150022Srwatson} 308150022Srwatson 309150022Srwatson/* 310150022Srwatson * Wrapper function for write, which uses a timer to interrupt any blocking. 311150022Srwatson * Because we can't reliably detect EINTR for blocking I/O, we also track 312150022Srwatson * whether or not our timeout fired. 313150022Srwatson */ 314150022Srwatsonstatic int __unused 315150022Srwatsontimed_write(int fd, void *data, size_t len, ssize_t *written_lenp, 316150022Srwatson int timeout, int *timedoutp, const char *testname) 317150022Srwatson{ 318150022Srwatson struct sigaction act, oact; 319150022Srwatson ssize_t written_len; 320150022Srwatson int error; 321150022Srwatson 322150022Srwatson alarm_fired = 0; 323150022Srwatson bzero(&act, sizeof(oact)); 324150022Srwatson act.sa_handler = sigalarm; 325150022Srwatson if (sigaction(SIGALRM, &act, &oact) < 0) { 326150022Srwatson warn("%s: timed_write: sigaction", testname); 327150022Srwatson return (-1); 328150022Srwatson } 329150022Srwatson alarm(timeout); 330150022Srwatson written_len = write(fd, data, len); 331150022Srwatson error = errno; 332150022Srwatson alarm(0); 333150022Srwatson if (sigaction(SIGALRM, &oact, NULL) < 0) { 334150022Srwatson warn("%s: timed_write: sigaction", testname); 335150022Srwatson return (-1); 336150022Srwatson } 337150022Srwatson if (alarm_fired) 338150022Srwatson *timedoutp = 1; 339150022Srwatson else 340150022Srwatson *timedoutp = 0; 341150022Srwatson 342150022Srwatson errno = error; 343150022Srwatson if (written_len < 0) 344150022Srwatson return (-1); 345150022Srwatson *written_lenp = written_len; 346150022Srwatson return (0); 347150022Srwatson} 348150022Srwatson 349150022Srwatson/* 350150022Srwatson * Wrapper function for read, which uses a timer to interrupt any blocking. 351150022Srwatson * Because we can't reliably detect EINTR for blocking I/O, we also track 352150022Srwatson * whether or not our timeout fired. 353150022Srwatson */ 354150022Srwatsonstatic int 355150022Srwatsontimed_read(int fd, void *data, size_t len, ssize_t *read_lenp, 356150022Srwatson int timeout, int *timedoutp, const char *testname) 357150022Srwatson{ 358150022Srwatson struct sigaction act, oact; 359150022Srwatson ssize_t read_len; 360150022Srwatson int error; 361150022Srwatson 362150022Srwatson alarm_fired = 0; 363150022Srwatson bzero(&act, sizeof(oact)); 364150022Srwatson act.sa_handler = sigalarm; 365150022Srwatson if (sigaction(SIGALRM, &act, &oact) < 0) { 366150022Srwatson warn("%s: timed_write: sigaction", testname); 367150022Srwatson return (-1); 368150022Srwatson } 369150022Srwatson alarm(timeout); 370150022Srwatson read_len = read(fd, data, len); 371150022Srwatson error = errno; 372150022Srwatson alarm(0); 373150022Srwatson if (sigaction(SIGALRM, &oact, NULL) < 0) { 374150022Srwatson warn("%s: timed_write: sigaction", testname); 375150022Srwatson return (-1); 376150022Srwatson } 377150022Srwatson if (alarm_fired) 378150022Srwatson *timedoutp = 1; 379150022Srwatson else 380150022Srwatson *timedoutp = 0; 381150022Srwatson 382150022Srwatson errno = error; 383150022Srwatson if (read_len < 0) 384150022Srwatson return (-1); 385150022Srwatson *read_lenp = read_len; 386150022Srwatson return (0); 387150022Srwatson} 388150022Srwatson 389150022Srwatson/* 390150022Srwatson * This test operates on blocking and non-blocking fifo file descriptors, in 391150022Srwatson * order to determine whether they block at good moments or not. By good we 392150022Srwatson * mean: don't block for non-blocking sockets, and do block for blocking 393150022Srwatson * ones, assuming there isn't I/O buffer to satisfy the request. 394150022Srwatson * 395150022Srwatson * We use a timeout of 5 seconds, concluding that in 5 seconds either all I/O 396150022Srwatson * that can take place will, and that if we reach the end of the timeout, 397228975Suqs * then blocking has occurred. 398150022Srwatson * 399150022Srwatson * We assume that the buffer size on a fifo is <512K, and as such, that 400150022Srwatson * writing that much data without an active reader will result in blocking. 401150022Srwatson */ 402150022Srwatsonstatic void 403150022Srwatsontest_blocking_read_empty(void) 404150022Srwatson{ 405150022Srwatson int reader_fd, ret, timedout, writer_fd; 406150022Srwatson ssize_t len; 407150022Srwatson u_char ch; 408150022Srwatson 409150022Srwatson makefifo("testfifo", __func__); 410281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) 411150022Srwatson < 0) { 412150022Srwatson warn("test_blocking_read_empty: openfifo: testfifo"); 413150093Srwatson cleanfifo2("testfifo", -1, -1); 414150022Srwatson exit(-1); 415150022Srwatson } 416150022Srwatson 417150022Srwatson /* 418150022Srwatson * Read one byte from an empty blocking fifo, block as there is no 419150022Srwatson * data. 420150022Srwatson */ 421150022Srwatson if (set_blocking(reader_fd, __func__) < 0) { 422150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 423150022Srwatson exit(-1); 424150022Srwatson } 425150022Srwatson 426150022Srwatson ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout, 427150022Srwatson __func__); 428150022Srwatson if (ret != -1) { 429150022Srwatson warnx("test_blocking_read_empty: timed_read: returned " 430150022Srwatson "success"); 431150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 432150022Srwatson exit(-1); 433150022Srwatson } 434150022Srwatson if (errno != EINTR) { 435150022Srwatson warn("test_blocking_read_empty: timed_read"); 436150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 437150022Srwatson exit(-1); 438150022Srwatson } 439150022Srwatson 440150022Srwatson /* 441150022Srwatson * Read one byte from an empty non-blocking fifo, return EAGAIN as 442150022Srwatson * there is no data. 443150022Srwatson */ 444150022Srwatson if (set_nonblocking(reader_fd, __func__) < 0) { 445150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 446150022Srwatson exit(-1); 447150022Srwatson } 448150022Srwatson 449150022Srwatson ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout, 450150022Srwatson __func__); 451150022Srwatson if (ret != -1) { 452150022Srwatson warnx("test_blocking_read_empty: timed_read: returned " 453150022Srwatson "success"); 454150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 455150022Srwatson exit(-1); 456150022Srwatson } 457150022Srwatson if (errno != EAGAIN) { 458150022Srwatson warn("test_blocking_read_empty: timed_read"); 459150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 460150022Srwatson exit(-1); 461150022Srwatson } 462150022Srwatson 463150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 464150022Srwatson} 465150022Srwatson 466150022Srwatson/* 467150022Srwatson * Write one byte to an empty fifo, then try to read one byte and make sure 468150022Srwatson * we don't block in either the write or the read. This tests both for 469150022Srwatson * improper blocking in the send and receive code. 470150022Srwatson */ 471150022Srwatsonstatic void 472150022Srwatsontest_blocking_one_byte(void) 473150022Srwatson{ 474150022Srwatson int reader_fd, ret, timedout, writer_fd; 475150022Srwatson ssize_t len; 476150022Srwatson u_char ch; 477150022Srwatson 478150022Srwatson makefifo("testfifo", __func__); 479281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { 480150022Srwatson warn("test_blocking: openfifo: testfifo"); 481150093Srwatson cleanfifo2("testfifo", -1, -1); 482150022Srwatson exit(-1); 483150022Srwatson } 484150022Srwatson 485150022Srwatson if (set_blocking(writer_fd, __func__) < 0) { 486150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 487150022Srwatson exit(-1); 488150022Srwatson } 489150022Srwatson if (set_blocking(reader_fd, __func__) < 0) { 490150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 491150022Srwatson exit(-1); 492150022Srwatson } 493150022Srwatson 494150022Srwatson ch = 0xfe; 495150022Srwatson ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout, 496150022Srwatson __func__); 497150022Srwatson if (ret < 0) { 498150022Srwatson warn("test_blocking_one_byte: timed_write"); 499150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 500150022Srwatson exit(-1); 501150022Srwatson } 502150022Srwatson if (len != sizeof(ch)) { 503150022Srwatson warnx("test_blocking_one_byte: timed_write: tried to write " 504164083Sjkim "%zu, wrote %zd", sizeof(ch), len); 505150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 506150022Srwatson exit(-1); 507150022Srwatson } 508150022Srwatson 509150022Srwatson ch = 0xab; 510150022Srwatson ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout, 511150022Srwatson __func__); 512150022Srwatson if (ret < 0) { 513150022Srwatson warn("test_blocking_one_byte: timed_read"); 514150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 515150022Srwatson exit(-1); 516150022Srwatson } 517150022Srwatson if (len != sizeof(ch)) { 518164083Sjkim warnx("test_blocking_one_byte: timed_read: wanted %zu, " 519164083Sjkim "read %zd", sizeof(ch), len); 520150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 521150022Srwatson exit(-1); 522150022Srwatson } 523150022Srwatson if (ch != 0xfe) { 524150022Srwatson warnx("test_blocking_one_byte: timed_read: expected to read " 525150022Srwatson "0x%02x, read 0x%02x", 0xfe, ch); 526150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 527150022Srwatson exit(-1); 528150022Srwatson } 529150022Srwatson 530150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 531150022Srwatson} 532150022Srwatson 533150022Srwatson/* 534150022Srwatson * Write one byte to an empty fifo, then try to read one byte and make sure 535150022Srwatson * we don't get back EAGAIN. 536150022Srwatson */ 537150022Srwatsonstatic void 538150022Srwatsontest_nonblocking_one_byte(void) 539150022Srwatson{ 540150022Srwatson int reader_fd, ret, timedout, writer_fd; 541150022Srwatson ssize_t len; 542150022Srwatson u_char ch; 543150022Srwatson 544150022Srwatson makefifo("testfifo", __func__); 545281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { 546150022Srwatson warn("test_nonblocking: openfifo: testfifo"); 547150093Srwatson cleanfifo2("testfifo", -1, -1); 548150022Srwatson exit(-1); 549150022Srwatson } 550150022Srwatson 551150022Srwatson if (set_nonblocking(reader_fd, __func__) < 0) { 552150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 553150022Srwatson exit(-1); 554150022Srwatson } 555150022Srwatson 556150022Srwatson ch = 0xfe; 557150022Srwatson ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout, 558150022Srwatson __func__); 559150022Srwatson if (ret < 0) { 560150022Srwatson warn("test_nonblocking_one_byte: timed_write"); 561150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 562150022Srwatson exit(-1); 563150022Srwatson } 564150022Srwatson if (len != sizeof(ch)) { 565150022Srwatson warnx("test_nonblocking_one_byte: timed_write: tried to write " 566164083Sjkim "%zu, wrote %zd", sizeof(ch), len); 567150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 568150022Srwatson exit(-1); 569150022Srwatson } 570150022Srwatson 571150022Srwatson ch = 0xab; 572150022Srwatson ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout, 573150022Srwatson __func__); 574150022Srwatson if (ret < 0) { 575150022Srwatson warn("test_nonblocking_one_byte: timed_read"); 576150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 577150022Srwatson exit(-1); 578150022Srwatson } 579150022Srwatson if (len != sizeof(ch)) { 580164083Sjkim warnx("test_nonblocking_one_byte: timed_read: wanted %zu, read " 581164083Sjkim "%zd", sizeof(ch), len); 582150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 583150022Srwatson exit(-1); 584150022Srwatson } 585150022Srwatson if (ch != 0xfe) { 586150022Srwatson warnx("test_nonblocking_one_byte: timed_read: expected to read " 587150022Srwatson "0x%02x, read 0x%02x", 0xfe, ch); 588150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 589150022Srwatson exit(-1); 590150022Srwatson } 591150022Srwatson 592150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 593150022Srwatson} 594150022Srwatson 595150022Srwatson/* 596150022Srwatson * First of two test cases involving a 512K buffer: write the buffer into a 597150022Srwatson * blocking file descriptor. We'd like to know it blocks, but the closest we 598150022Srwatson * can get is to see if SIGALRM fired during the I/O resulting in a partial 599150022Srwatson * write. 600150022Srwatson */ 601150022Srwatsonstatic void 602150022Srwatsontest_blocking_partial_write(void) 603150022Srwatson{ 604150022Srwatson int reader_fd, ret, timedout, writer_fd; 605150022Srwatson u_char *buffer; 606150022Srwatson ssize_t len; 607150022Srwatson 608150022Srwatson makefifo("testfifo", __func__); 609281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { 610150022Srwatson warn("test_blocking_partial_write: openfifo: testfifo"); 611150093Srwatson cleanfifo2("testfifo", -1, -1); 612150022Srwatson exit(-1); 613150022Srwatson } 614150022Srwatson 615150022Srwatson if (set_blocking(writer_fd, __func__) < 0) { 616150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 617150022Srwatson exit(-1); 618150022Srwatson } 619150022Srwatson 620150022Srwatson buffer = malloc(512*1024); 621150022Srwatson if (buffer == NULL) { 622150022Srwatson warn("test_blocking_partial_write: malloc"); 623150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 624150022Srwatson exit(-1); 625150022Srwatson } 626150022Srwatson bzero(buffer, 512*1024); 627150022Srwatson 628150022Srwatson ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout, 629150022Srwatson __func__); 630150022Srwatson if (ret < 0) { 631150022Srwatson warn("test_blocking_partial_write: timed_write"); 632150022Srwatson free(buffer); 633150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 634150022Srwatson exit(-1); 635150022Srwatson } 636150022Srwatson 637150022Srwatson if (!timedout) { 638150022Srwatson warnx("test_blocking_partial_write: timed_write: blocking " 639150022Srwatson "socket didn't time out"); 640150022Srwatson free(buffer); 641150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 642150022Srwatson exit(-1); 643150022Srwatson } 644150022Srwatson 645150022Srwatson free(buffer); 646150022Srwatson 647150022Srwatson if (drain_fd(reader_fd, __func__) < 0) { 648150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 649150022Srwatson exit(-1); 650150022Srwatson } 651150022Srwatson 652150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 653150022Srwatson} 654150022Srwatson 655150022Srwatson/* 656150022Srwatson * Write a 512K buffer to an empty fifo using a non-blocking file descriptor, 657150022Srwatson * and make sure it doesn't block. 658150022Srwatson */ 659150022Srwatsonstatic void 660150022Srwatsontest_nonblocking_partial_write(void) 661150022Srwatson{ 662150022Srwatson int reader_fd, ret, timedout, writer_fd; 663150022Srwatson u_char *buffer; 664150022Srwatson ssize_t len; 665150022Srwatson 666150022Srwatson makefifo("testfifo", __func__); 667281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { 668150022Srwatson warn("test_blocking_partial_write: openfifo: testfifo"); 669150093Srwatson cleanfifo2("testfifo", -1, -1); 670150022Srwatson exit(-1); 671150022Srwatson } 672150022Srwatson 673150022Srwatson if (set_nonblocking(writer_fd, __func__) < 0) { 674150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 675150022Srwatson exit(-1); 676150022Srwatson } 677150022Srwatson 678150022Srwatson buffer = malloc(512*1024); 679150022Srwatson if (buffer == NULL) { 680150022Srwatson warn("test_blocking_partial_write: malloc"); 681150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 682150022Srwatson exit(-1); 683150022Srwatson } 684150022Srwatson bzero(buffer, 512*1024); 685150022Srwatson 686150022Srwatson ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout, 687150022Srwatson __func__); 688150022Srwatson if (ret < 0) { 689150022Srwatson warn("test_blocking_partial_write: timed_write"); 690150022Srwatson free(buffer); 691150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 692150022Srwatson exit(-1); 693150022Srwatson } 694150022Srwatson 695150022Srwatson if (timedout) { 696150022Srwatson warnx("test_blocking_partial_write: timed_write: " 697150022Srwatson "non-blocking socket timed out"); 698150022Srwatson free(buffer); 699150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 700150022Srwatson exit(-1); 701150022Srwatson } 702150022Srwatson 703150022Srwatson if (len == 0 || len >= 512*1024) { 704150022Srwatson warnx("test_blocking_partial_write: timed_write: requested " 705164083Sjkim "%d, sent %zd", 512*1024, len); 706150022Srwatson free(buffer); 707150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 708150022Srwatson exit(-1); 709150022Srwatson } 710150022Srwatson 711150022Srwatson free(buffer); 712150022Srwatson 713150022Srwatson if (drain_fd(reader_fd, __func__) < 0) { 714150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 715150022Srwatson exit(-1); 716150022Srwatson } 717150022Srwatson 718150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 719150022Srwatson} 720150022Srwatson 721150022Srwatson/* 722150022Srwatson * test_coalesce_big_read() verifies that data mingles in the fifo across 723150022Srwatson * message boundaries by performing two small writes, then a bigger read 724150022Srwatson * that should return data from both writes. 725150022Srwatson */ 726150022Srwatsonstatic void 727150022Srwatsontest_coalesce_big_read(void) 728150022Srwatson{ 729150022Srwatson int i, reader_fd, writer_fd; 730150022Srwatson u_char buffer[10]; 731150022Srwatson ssize_t len; 732150022Srwatson 733150022Srwatson makefifo("testfifo", __func__); 734281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { 735150022Srwatson warn("test_coalesce_big_read: openfifo: testfifo"); 736150093Srwatson cleanfifo2("testfifo", -1, -1); 737150022Srwatson exit(-1); 738150022Srwatson } 739150022Srwatson 740150022Srwatson /* Write five, write five, read ten. */ 741150022Srwatson for (i = 0; i < 10; i++) 742150022Srwatson buffer[i] = i; 743150022Srwatson 744150022Srwatson len = write(writer_fd, buffer, 5); 745150022Srwatson if (len < 0) { 746150022Srwatson warn("test_coalesce_big_read: write 5"); 747150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 748150022Srwatson exit(-1); 749150022Srwatson } 750150022Srwatson if (len != 5) { 751164083Sjkim warnx("test_coalesce_big_read: write 5 wrote %zd", len); 752150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 753150022Srwatson exit(-1); 754150022Srwatson } 755150022Srwatson 756150022Srwatson len = write(writer_fd, buffer + 5, 5); 757150022Srwatson if (len < 0) { 758150022Srwatson warn("test_coalesce_big_read: write 5"); 759150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 760150022Srwatson exit(-1); 761150022Srwatson } 762150022Srwatson if (len != 5) { 763164083Sjkim warnx("test_coalesce_big_read: write 5 wrote %zd", len); 764150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 765150022Srwatson exit(-1); 766150022Srwatson } 767150022Srwatson 768150022Srwatson len = read(reader_fd, buffer, 10); 769150022Srwatson if (len < 0) { 770150022Srwatson warn("test_coalesce_big_read: read 10"); 771150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 772150022Srwatson exit(-1); 773150022Srwatson } 774150022Srwatson if (len != 10) { 775164083Sjkim warnx("test_coalesce_big_read: read 10 read %zd", len); 776150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 777150022Srwatson exit(-1); 778150022Srwatson } 779150022Srwatson 780150022Srwatson for (i = 0; i < 10; i++) { 781150022Srwatson if (buffer[i] == i) 782150022Srwatson continue; 783150022Srwatson warnx("test_coalesce_big_read: expected to read 0x%02x, " 784150022Srwatson "read 0x%02x", i, buffer[i]); 785150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 786150022Srwatson exit(-1); 787150022Srwatson } 788150022Srwatson 789150093Srwatson cleanfifo2("testfifo", -1, -1); 790150022Srwatson} 791150022Srwatson 792150022Srwatson/* 793150022Srwatson * test_coalesce_big_write() verifies that data mingles in the fifo across 794150022Srwatson * message boundaries by performing one big write, then two smaller reads 795150022Srwatson * that should return sequential elements of data from the write. 796150022Srwatson */ 797150022Srwatsonstatic void 798150022Srwatsontest_coalesce_big_write(void) 799150022Srwatson{ 800150022Srwatson int i, reader_fd, writer_fd; 801150022Srwatson u_char buffer[10]; 802150022Srwatson ssize_t len; 803150022Srwatson 804150022Srwatson makefifo("testfifo", __func__); 805281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { 806150022Srwatson warn("test_coalesce_big_write: openfifo: testfifo"); 807150093Srwatson cleanfifo2("testfifo", -1, -1); 808150022Srwatson exit(-1); 809150022Srwatson } 810150022Srwatson 811150022Srwatson /* Write ten, read five, read five. */ 812150022Srwatson for (i = 0; i < 10; i++) 813150022Srwatson buffer[i] = i; 814150022Srwatson 815150022Srwatson len = write(writer_fd, buffer, 10); 816150022Srwatson if (len < 0) { 817150022Srwatson warn("test_coalesce_big_write: write 10"); 818150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 819150022Srwatson exit(-1); 820150022Srwatson } 821150022Srwatson if (len != 10) { 822164083Sjkim warnx("test_coalesce_big_write: write 10 wrote %zd", len); 823150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 824150022Srwatson exit(-1); 825150022Srwatson } 826150022Srwatson 827150022Srwatson len = read(reader_fd, buffer, 5); 828150022Srwatson if (len < 0) { 829150022Srwatson warn("test_coalesce_big_write: read 5"); 830150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 831150022Srwatson exit(-1); 832150022Srwatson } 833150022Srwatson if (len != 5) { 834164083Sjkim warnx("test_coalesce_big_write: read 5 read %zd", len); 835150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 836150022Srwatson exit(-1); 837150022Srwatson } 838150022Srwatson 839150022Srwatson len = read(reader_fd, buffer + 5, 5); 840150022Srwatson if (len < 0) { 841150022Srwatson warn("test_coalesce_big_write: read 5"); 842150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 843150022Srwatson exit(-1); 844150022Srwatson } 845150022Srwatson if (len != 5) { 846164083Sjkim warnx("test_coalesce_big_write: read 5 read %zd", len); 847150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 848150022Srwatson exit(-1); 849150022Srwatson } 850150022Srwatson 851150022Srwatson for (i = 0; i < 10; i++) { 852150022Srwatson if (buffer[i] == i) 853150022Srwatson continue; 854150022Srwatson warnx("test_coalesce_big_write: expected to read 0x%02x, " 855150022Srwatson "read 0x%02x", i, buffer[i]); 856150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 857150022Srwatson exit(-1); 858150022Srwatson } 859150022Srwatson 860150093Srwatson cleanfifo2("testfifo", -1, -1); 861150022Srwatson} 862150022Srwatson 863150022Srwatsonstatic int 864150022Srwatsonpoll_status(int fd, int *readable, int *writable, int *exception, 865150022Srwatson const char *testname) 866150022Srwatson{ 867150022Srwatson struct pollfd fds[1]; 868150022Srwatson 869150022Srwatson fds[0].fd = fd; 870150022Srwatson fds[0].events = POLLIN | POLLOUT | POLLERR; 871150022Srwatson fds[0].revents = 0; 872150022Srwatson 873150022Srwatson if (poll(fds, 1, 0) < 0) { 874150022Srwatson warn("%s: poll", testname); 875150022Srwatson return (-1); 876150022Srwatson } 877150022Srwatson *readable = (fds[0].revents & POLLIN) ? 1 : 0; 878150022Srwatson *writable = (fds[0].revents & POLLOUT) ? 1 : 0; 879150022Srwatson *exception = (fds[0].revents & POLLERR) ? 1 : 0; 880150022Srwatson return (0); 881150022Srwatson} 882150022Srwatson 883150022Srwatsonstatic int 884150022Srwatsonselect_status(int fd, int *readable, int *writable, int *exception, 885150022Srwatson const char *testname) 886150022Srwatson{ 887150022Srwatson struct fd_set readfds, writefds, exceptfds; 888150022Srwatson struct timeval timeout; 889150022Srwatson 890150022Srwatson FD_ZERO(&readfds); 891150022Srwatson FD_ZERO(&writefds); 892150022Srwatson FD_ZERO(&exceptfds); 893150022Srwatson FD_SET(fd, &readfds); 894150022Srwatson FD_SET(fd, &writefds); 895150022Srwatson FD_SET(fd, &exceptfds); 896150022Srwatson timeout.tv_sec = 0; 897150022Srwatson timeout.tv_usec = 0; 898150059Srwatson if (select(fd+1, &readfds, &writefds, &exceptfds, &timeout) < 0) { 899150022Srwatson warn("%s: select", testname); 900150022Srwatson return (-1); 901150022Srwatson } 902150022Srwatson *readable = FD_ISSET(fd, &readfds) ? 1 : 0; 903150022Srwatson *writable = FD_ISSET(fd, &writefds) ? 1 : 0; 904150022Srwatson *exception = FD_ISSET(fd, &exceptfds) ? 1 : 0; 905150022Srwatson return (0); 906150022Srwatson} 907150022Srwatson 908150093Srwatson/* 909150093Srwatson * Given an existing kqueue, set up read and write event filters for the 910150093Srwatson * passed file descriptor. Typically called once for the read endpoint, and 911150093Srwatson * once for the write endpoint. 912150093Srwatson */ 913150059Srwatsonstatic int 914150093Srwatsonkqueue_setup(int kqueue_fd, int fd, const char *testname) 915150059Srwatson{ 916150093Srwatson struct kevent kevent_changelist[2]; 917150093Srwatson struct kevent kevent_eventlist[KQUEUE_MAX_EVENT], *kp; 918150059Srwatson struct timespec timeout; 919150093Srwatson int i, ret; 920150059Srwatson 921150059Srwatson timeout.tv_sec = 0; 922150059Srwatson timeout.tv_nsec = 0; 923150059Srwatson 924150059Srwatson bzero(&kevent_changelist, sizeof(kevent_changelist)); 925150093Srwatson EV_SET(&kevent_changelist[0], fd, EVFILT_READ, EV_ADD, 0, 0, 0); 926150093Srwatson EV_SET(&kevent_changelist[1], fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); 927150059Srwatson 928150059Srwatson bzero(&kevent_eventlist, sizeof(kevent_eventlist)); 929150093Srwatson ret = kevent(kqueue_fd, kevent_changelist, 2, kevent_eventlist, 930150093Srwatson KQUEUE_MAX_EVENT, &timeout); 931150059Srwatson if (ret < 0) { 932150093Srwatson warn("%s:%s: kevent initial register", testname, __func__); 933150093Srwatson return (-1); 934150059Srwatson } 935150059Srwatson 936150059Srwatson /* 937150093Srwatson * Verify that the events registered alright. 938150059Srwatson */ 939150059Srwatson for (i = 0; i < ret; i++) { 940150059Srwatson kp = &kevent_eventlist[i]; 941150059Srwatson if (kp->flags != EV_ERROR) 942150059Srwatson continue; 943150059Srwatson errno = kp->data; 944150093Srwatson warn("%s:%s: kevent register index %d", testname, __func__, 945150093Srwatson i); 946150093Srwatson return (-1); 947150059Srwatson } 948150059Srwatson 949150059Srwatson return (0); 950150059Srwatson} 951150059Srwatson 952150059Srwatsonstatic int 953150059Srwatsonkqueue_status(int kqueue_fd, int fd, int *readable, int *writable, 954150059Srwatson int *exception, const char *testname) 955150059Srwatson{ 956150093Srwatson struct kevent kevent_eventlist[KQUEUE_MAX_EVENT], *kp; 957150059Srwatson struct timespec timeout; 958150093Srwatson int i, ret; 959150059Srwatson 960150059Srwatson timeout.tv_sec = 0; 961150059Srwatson timeout.tv_nsec = 0; 962150059Srwatson 963150093Srwatson ret = kevent(kqueue_fd, NULL, 0, kevent_eventlist, KQUEUE_MAX_EVENT, 964150093Srwatson &timeout); 965150093Srwatson if (ret < 0) { 966150093Srwatson warn("%s: %s: kevent", testname, __func__); 967150059Srwatson return (-1); 968150059Srwatson } 969150059Srwatson 970150059Srwatson *readable = *writable = *exception = 0; 971150093Srwatson for (i = 0; i < ret; i++) { 972150059Srwatson kp = &kevent_eventlist[i]; 973150059Srwatson if (kp->ident != (u_int)fd) 974150059Srwatson continue; 975150059Srwatson if (kp->filter == EVFILT_READ) 976150059Srwatson *readable = 1; 977150059Srwatson if (kp->filter == EVFILT_WRITE) 978150059Srwatson *writable = 1; 979150059Srwatson } 980150059Srwatson 981150059Srwatson return (0); 982150059Srwatson} 983150059Srwatson 984150091Srwatsonstatic int 985150091Srwatsonfionread_status(int fd, int *readable, const char *testname) 986150091Srwatson{ 987150091Srwatson int i; 988150091Srwatson 989150091Srwatson if (ioctl(fd, FIONREAD, &i) < 0) { 990150091Srwatson warn("%s: ioctl(FIONREAD)", testname); 991150091Srwatson return (-1); 992150091Srwatson } 993150091Srwatson 994150091Srwatson if (i > 0) 995150091Srwatson *readable = 1; 996150091Srwatson else 997150091Srwatson *readable = 0; 998150091Srwatson return (0); 999150091Srwatson} 1000150091Srwatson 1001150093Srwatson#define READABLE 1 1002150093Srwatson#define WRITABLE 1 1003150093Srwatson#define EXCEPTION 1 1004150093Srwatson 1005150093Srwatson#define NOT_READABLE 0 1006150093Srwatson#define NOT_WRITABLE 0 1007150093Srwatson#define NOT_EXCEPTION 0 1008150093Srwatson 1009150093Srwatsonstatic int 1010150093Srwatsonassert_status(int fd, int kqueue_fd, int assert_readable, 1011150093Srwatson int assert_writable, int assert_exception, const char *testname, 1012150093Srwatson const char *conditionname, const char *fdname) 1013150093Srwatson{ 1014150093Srwatson int readable, writable, exception; 1015150093Srwatson 1016150093Srwatson if (poll_status(fd, &readable, &writable, &exception, testname) < 0) 1017150093Srwatson return (-1); 1018150093Srwatson 1019150093Srwatson if (readable != assert_readable || writable != assert_writable || 1020150093Srwatson exception != assert_exception) { 1021150093Srwatson warnx("%s: %s polls r:%d, w:%d, e:%d on %s", testname, 1022150093Srwatson fdname, readable, writable, exception, conditionname); 1023150093Srwatson return (-1); 1024150093Srwatson } 1025150093Srwatson 1026150093Srwatson if (select_status(fd, &readable, &writable, &exception, testname) < 0) 1027150093Srwatson return (-1); 1028150093Srwatson 1029150093Srwatson if (readable != assert_readable || writable != assert_writable || 1030150093Srwatson exception != assert_exception) { 1031150093Srwatson warnx("%s: %s selects r:%d, w:%d, e:%d on %s", testname, 1032150093Srwatson fdname, readable, writable, exception, conditionname); 1033150093Srwatson return (-1); 1034150093Srwatson } 1035150093Srwatson 1036150093Srwatson if (kqueue_status(kqueue_fd, fd, &readable, &writable, &exception, 1037150093Srwatson testname) < 0) 1038150093Srwatson return (-1); 1039150093Srwatson 1040150093Srwatson if (readable != assert_readable || writable != assert_writable || 1041150093Srwatson exception != assert_exception) { 1042150093Srwatson warnx("%s: %s kevent r:%d, w:%d, e:%d on %s", testname, 1043150093Srwatson fdname, readable, writable, exception, conditionname); 1044150093Srwatson return (-1); 1045150093Srwatson } 1046150093Srwatson 1047150093Srwatson if (fionread_status(fd, &readable, __func__) < 0) 1048150093Srwatson return (-1); 1049150093Srwatson 1050150093Srwatson if (readable != assert_readable) { 1051150093Srwatson warnx("%s: %s fionread r:%d on %s", testname, fdname, 1052150093Srwatson readable, conditionname); 1053150093Srwatson return (-1); 1054150093Srwatson } 1055150093Srwatson 1056150093Srwatson return (0); 1057150093Srwatson} 1058150093Srwatson 1059150022Srwatson/* 1060150059Srwatson * test_events() uses poll(), select(), and kevent() to query the status of 1061150059Srwatson * fifo file descriptors and determine whether they match expected state 1062150059Srwatson * based on earlier semantic tests: specifically, whether or not poll/select/ 1063150059Srwatson * kevent will correctly inform on readable/writable state following I/O. 1064150022Srwatson * 1065150059Srwatson * It would be nice to also test status changes as a result of closing of one 1066150059Srwatson * or another fifo endpoint. 1067150022Srwatson */ 1068150022Srwatsonstatic void 1069150022Srwatsontest_events_outofbox(void) 1070150022Srwatson{ 1071150059Srwatson int kqueue_fd, reader_fd, writer_fd; 1072150022Srwatson 1073150022Srwatson makefifo("testfifo", __func__); 1074281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { 1075150022Srwatson warn("test_events_outofbox: openfifo: testfifo"); 1076150093Srwatson cleanfifo2("testfifo", -1, -1); 1077150022Srwatson exit(-1); 1078150022Srwatson } 1079150022Srwatson 1080150093Srwatson kqueue_fd = kqueue(); 1081150093Srwatson if (kqueue_fd < 0) { 1082150093Srwatson warn("%s: kqueue", __func__); 1083150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 1084150059Srwatson exit(-1); 1085150059Srwatson } 1086150059Srwatson 1087150093Srwatson if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) { 1088150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1089150093Srwatson exit(-1); 1090150093Srwatson } 1091150093Srwatson 1092150093Srwatson if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) { 1093150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1094150093Srwatson exit(-1); 1095150093Srwatson } 1096150093Srwatson 1097150022Srwatson /* 1098150022Srwatson * Make sure that fresh, out-of-the-box fifo file descriptors have 1099150022Srwatson * good initial states. The reader_fd should have no active state, 1100150022Srwatson * since it will not be readable (no data in pipe), writable (it's 1101150022Srwatson * a read-only descriptor), and there's no reason for error yet. 1102150022Srwatson */ 1103150093Srwatson if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE, 1104150093Srwatson NOT_EXCEPTION, __func__, "create", "reader_fd") < 0) { 1105150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1106150022Srwatson exit(-1); 1107150022Srwatson } 1108150022Srwatson 1109150022Srwatson /* 1110150022Srwatson * Make sure that fresh, out-of-the-box fifo file descriptors have 1111150022Srwatson * good initial states. The writer_fd should be ready to write. 1112150022Srwatson */ 1113150093Srwatson if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE, 1114150093Srwatson NOT_EXCEPTION, __func__, "create", "writer_fd") < 0) { 1115150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1116150022Srwatson exit(-1); 1117150022Srwatson } 1118150022Srwatson 1119150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1120150022Srwatson} 1121150022Srwatson 1122150022Srwatsonstatic void 1123150022Srwatsontest_events_write_read_byte(void) 1124150022Srwatson{ 1125150059Srwatson int kqueue_fd, reader_fd, writer_fd; 1126150022Srwatson ssize_t len; 1127150022Srwatson u_char ch; 1128150022Srwatson 1129150022Srwatson makefifo("testfifo", __func__); 1130281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { 1131150022Srwatson warn("test_events_write_read_byte: openfifo: testfifo"); 1132150093Srwatson cleanfifo2("testfifo", -1, -1); 1133150022Srwatson exit(-1); 1134150022Srwatson } 1135150022Srwatson 1136150093Srwatson kqueue_fd = kqueue(); 1137150093Srwatson if (kqueue_fd < 0) { 1138150093Srwatson warn("%s: kqueue", __func__); 1139150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 1140150059Srwatson exit(-1); 1141150059Srwatson } 1142150059Srwatson 1143150093Srwatson if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) { 1144150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1145150093Srwatson exit(-1); 1146150093Srwatson } 1147150093Srwatson 1148150093Srwatson if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) { 1149150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1150150093Srwatson exit(-1); 1151150093Srwatson } 1152150093Srwatson 1153150022Srwatson /* 1154150022Srwatson * Write a byte to the fifo, and make sure that the read end becomes 1155150022Srwatson * readable, and that the write end remains writable (small write). 1156150022Srwatson */ 1157150022Srwatson ch = 0x00; 1158150022Srwatson len = write(writer_fd, &ch, sizeof(ch)); 1159150022Srwatson if (len < 0) { 1160150093Srwatson warn("%s: write", __func__); 1161150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1162150022Srwatson exit(-1); 1163150022Srwatson } 1164150022Srwatson 1165150093Srwatson if (assert_status(reader_fd, kqueue_fd, READABLE, NOT_WRITABLE, 1166150093Srwatson NOT_EXCEPTION, __func__, "write", "reader_fd") < 0) { 1167150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1168150022Srwatson exit(-1); 1169150022Srwatson } 1170150022Srwatson 1171150022Srwatson /* 1172150093Srwatson * the writer_fd should remain writable. 1173150022Srwatson */ 1174150093Srwatson if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE, 1175150093Srwatson NOT_EXCEPTION, __func__, "write", "writer_fd") < 0) { 1176150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1177150022Srwatson exit(-1); 1178150022Srwatson } 1179150022Srwatson 1180150022Srwatson /* 1181150022Srwatson * Read the byte from the reader_fd, and now confirm that that fifo 1182150022Srwatson * becomes unreadable. 1183150022Srwatson */ 1184150022Srwatson len = read(reader_fd, &ch, sizeof(ch)); 1185150022Srwatson if (len < 0) { 1186150093Srwatson warn("%s: read", __func__); 1187150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1188150022Srwatson exit(-1); 1189150022Srwatson } 1190150022Srwatson 1191150093Srwatson if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE, 1192150093Srwatson NOT_EXCEPTION, __func__, "write+read", "reader_fd") < 0) { 1193150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1194150022Srwatson exit(-1); 1195150022Srwatson } 1196150022Srwatson 1197150022Srwatson /* 1198150093Srwatson * The writer_fd should remain writable. 1199150022Srwatson */ 1200150093Srwatson if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE, 1201150093Srwatson NOT_EXCEPTION, __func__, "write+read", "writer_fd") < 0) { 1202150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1203150022Srwatson exit(-1); 1204150022Srwatson } 1205150022Srwatson 1206150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1207150022Srwatson} 1208150022Srwatson 1209150059Srwatson/* 1210150059Srwatson * Write a 512k buffer to the fifo in non-blocking mode, and make sure that 1211150059Srwatson * the write end becomes un-writable as a result of a partial write that 1212150059Srwatson * fills the fifo buffer. 1213150059Srwatson */ 1214150022Srwatsonstatic void 1215150022Srwatsontest_events_partial_write(void) 1216150022Srwatson{ 1217150059Srwatson int kqueue_fd, reader_fd, writer_fd; 1218150022Srwatson u_char *buffer; 1219150022Srwatson ssize_t len; 1220150022Srwatson 1221150022Srwatson makefifo("testfifo", __func__); 1222281450Sngie if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { 1223150022Srwatson warn("test_events_partial_write: openfifo: testfifo"); 1224150093Srwatson cleanfifo2("testfifo", -1, -1); 1225150022Srwatson exit(-1); 1226150022Srwatson } 1227150022Srwatson 1228150093Srwatson kqueue_fd = kqueue(); 1229150093Srwatson if (kqueue_fd < 0) { 1230150093Srwatson warn("%s: kqueue", __func__); 1231150093Srwatson cleanfifo2("testfifo", reader_fd, writer_fd); 1232150022Srwatson exit(-1); 1233150022Srwatson } 1234150022Srwatson 1235150093Srwatson if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) { 1236150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1237150093Srwatson exit(-1); 1238150093Srwatson } 1239150093Srwatson 1240150093Srwatson if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) { 1241150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1242150093Srwatson exit(-1); 1243150093Srwatson } 1244150093Srwatson 1245150059Srwatson if (set_nonblocking(writer_fd, "test_events") < 0) { 1246150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1247150059Srwatson exit(-1); 1248150059Srwatson } 1249150059Srwatson 1250150022Srwatson buffer = malloc(512*1024); 1251150022Srwatson if (buffer == NULL) { 1252150022Srwatson warn("test_events_partial_write: malloc"); 1253150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1254150022Srwatson exit(-1); 1255150022Srwatson } 1256150022Srwatson bzero(buffer, 512*1024); 1257150022Srwatson 1258150022Srwatson len = write(writer_fd, buffer, 512*1024); 1259150022Srwatson if (len < 0) { 1260150022Srwatson warn("test_events_partial_write: write"); 1261150022Srwatson free(buffer); 1262150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1263150022Srwatson exit(-1); 1264150022Srwatson } 1265150022Srwatson 1266150022Srwatson free(buffer); 1267150022Srwatson 1268150093Srwatson if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE, 1269150093Srwatson NOT_EXCEPTION, __func__, "big write", "writer_fd") < 0) { 1270150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1271150022Srwatson exit(-1); 1272150022Srwatson } 1273150022Srwatson 1274150093Srwatson if (drain_fd(reader_fd, "test_events") < 0) { 1275150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1276150022Srwatson exit(-1); 1277150022Srwatson } 1278150022Srwatson 1279150093Srwatson /* 1280150093Srwatson * Test that the writer_fd has been restored to writable state after 1281150093Srwatson * draining. 1282150093Srwatson */ 1283150093Srwatson if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE, 1284150093Srwatson NOT_EXCEPTION, __func__, "big write + drain", "writer_fd") < 0) { 1285150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1286150022Srwatson exit(-1); 1287150022Srwatson } 1288150022Srwatson 1289150093Srwatson cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); 1290150093Srwatson} 1291150022Srwatson 1292150093Srwatson/* 1293150093Srwatson * We don't comprehensively test O_RDWR file descriptors, but do run a couple 1294150093Srwatson * of event tests to make sure that the fifo implementation doesn't mixed up 1295150093Srwatson * status checks. In particular, at least one past FreeBSD bug exists in 1296150093Srwatson * which the FIONREAD test was performed on the wrong socket implementing the 1297150093Srwatson * fifo, resulting in the fifo never returning readable. 1298150093Srwatson */ 1299150093Srwatsonstatic void 1300150093Srwatsontest_events_rdwr(void) 1301150093Srwatson{ 1302150093Srwatson int fd, kqueue_fd; 1303150093Srwatson ssize_t len; 1304150093Srwatson char ch; 1305150093Srwatson 1306150093Srwatson makefifo("testfifo", __func__); 1307281450Sngie if (openfifo_rw("testfifo", &fd) < 0) { 1308150093Srwatson warn("%s: openfifo_rw: testfifo", __func__); 1309150093Srwatson cleanfifo2("testfifo", -1, -1); 1310150059Srwatson exit(-1); 1311150059Srwatson } 1312150059Srwatson 1313150093Srwatson kqueue_fd = kqueue(); 1314150093Srwatson if (kqueue_fd < 0) { 1315150093Srwatson warn("%s: kqueue", __func__); 1316150093Srwatson cleanfifo2("testifo", fd, -1); 1317150059Srwatson exit(-1); 1318150059Srwatson } 1319150059Srwatson 1320150093Srwatson if (kqueue_setup(kqueue_fd, fd, __func__) < 0) { 1321150093Srwatson cleanfifo2("testfifo", fd, kqueue_fd); 1322150022Srwatson exit(-1); 1323150022Srwatson } 1324150022Srwatson 1325150022Srwatson /* 1326150093Srwatson * On first creation, the O_RDWR descriptor should be writable but 1327150093Srwatson * not readable. 1328150022Srwatson */ 1329150093Srwatson if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE, 1330150093Srwatson NOT_EXCEPTION, __func__, "create", "fd") < 0) { 1331150093Srwatson cleanfifo2("testfifo", fd, kqueue_fd); 1332150022Srwatson exit(-1); 1333150022Srwatson } 1334150022Srwatson 1335150093Srwatson /* 1336150093Srwatson * Write a byte, which should cause the file descriptor to become 1337150093Srwatson * readable and writable. 1338150093Srwatson */ 1339150093Srwatson ch = 0x00; 1340150093Srwatson len = write(fd, &ch, sizeof(ch)); 1341150093Srwatson if (len < 0) { 1342150093Srwatson warn("%s: write", __func__); 1343150093Srwatson cleanfifo2("testfifo", fd, kqueue_fd); 1344150022Srwatson exit(-1); 1345150022Srwatson } 1346150022Srwatson 1347150093Srwatson if (assert_status(fd, kqueue_fd, READABLE, WRITABLE, NOT_EXCEPTION, 1348150093Srwatson __func__, "write", "fd") < 0) { 1349150093Srwatson cleanfifo2("testfifo", fd, kqueue_fd); 1350150022Srwatson exit(-1); 1351150022Srwatson } 1352150022Srwatson 1353150093Srwatson /* 1354150093Srwatson * Read a byte, which should cause the file descriptor to return to 1355150093Srwatson * simply being writable. 1356150093Srwatson */ 1357150093Srwatson len = read(fd, &ch, sizeof(ch)); 1358150093Srwatson if (len < 0) { 1359150093Srwatson warn("%s: read", __func__); 1360150093Srwatson cleanfifo2("testfifo", fd, kqueue_fd); 1361150022Srwatson exit(-1); 1362150022Srwatson } 1363150059Srwatson 1364150093Srwatson if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE, 1365150093Srwatson NOT_EXCEPTION, __func__, "write+read", "fd") < 0) { 1366150093Srwatson cleanfifo2("testfifo", fd, kqueue_fd); 1367150059Srwatson exit(-1); 1368150059Srwatson } 1369150059Srwatson 1370150093Srwatson cleanfifo2("testfifo", fd, kqueue_fd); 1371150022Srwatson} 1372150059Srwatson 1373150022Srwatsonint 1374281450Sngiemain(void) 1375150022Srwatson{ 1376150022Srwatson 1377281450Sngie strcpy(temp_dir, "fifo_io.XXXXXXXXXXX"); 1378150022Srwatson if (mkdtemp(temp_dir) == NULL) 1379150022Srwatson err(-1, "mkdtemp"); 1380150022Srwatson atexit(atexit_temp_dir); 1381150022Srwatson 1382150022Srwatson if (chdir(temp_dir) < 0) 1383150022Srwatson err(-1, "chdir %s", temp_dir); 1384150022Srwatson 1385150022Srwatson test_simpleio(); 1386150022Srwatson test_blocking_read_empty(); 1387150022Srwatson test_blocking_one_byte(); 1388150022Srwatson test_nonblocking_one_byte(); 1389150022Srwatson test_blocking_partial_write(); 1390150022Srwatson test_nonblocking_partial_write(); 1391150022Srwatson test_coalesce_big_read(); 1392150022Srwatson test_coalesce_big_write(); 1393150022Srwatson test_events_outofbox(); 1394150022Srwatson test_events_write_read_byte(); 1395150022Srwatson test_events_partial_write(); 1396150093Srwatson test_events_rdwr(); 1397150022Srwatson 1398150022Srwatson return (0); 1399150022Srwatson} 1400