Example #1
0
/*
 * test_events() uses poll(), select(), and kevent() to query the status of
 * fifo file descriptors and determine whether they match expected state
 * based on earlier semantic tests: specifically, whether or not poll/select/
 * kevent will correctly inform on readable/writable state following I/O.
 *
 * It would be nice to also test status changes as a result of closing of one
 * or another fifo endpoint.
 */
static void
test_events_outofbox(void)
{
    int kqueue_fd, reader_fd, writer_fd;

    makefifo("testfifo", __func__);
    if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
        warn("test_events_outofbox: openfifo: testfifo");
        cleanfifo2("testfifo", -1, -1);
        exit(-1);
    }

    kqueue_fd = kqueue();
    if (kqueue_fd < 0) {
        warn("%s: kqueue", __func__);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    /*
     * Make sure that fresh, out-of-the-box fifo file descriptors have
     * good initial states.  The reader_fd should have no active state,
     * since it will not be readable (no data in pipe), writable (it's
     * a read-only descriptor), and there's no reason for error yet.
     */
    if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE,
                      NOT_EXCEPTION, __func__, "create", "reader_fd") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    /*
     * Make sure that fresh, out-of-the-box fifo file descriptors have
     * good initial states.  The writer_fd should be ready to write.
     */
    if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
                      NOT_EXCEPTION, __func__, "create", "writer_fd") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
}
Example #2
0
/*
 * Write one byte to an empty fifo, then try to read one byte and make sure
 * we don't get back EAGAIN.
 */
static void
test_nonblocking_one_byte(void)
{
	int reader_fd, ret, timedout, writer_fd;
	ssize_t len;
	u_char ch;

	makefifo("testfifo", __func__);
	if (openfifo("testfifo", __func__, &reader_fd, &writer_fd)
	    < 0) {
		warn("test_nonblocking: openfifo: testfifo");
		cleanfifo2("testfifo", -1, -1);
		exit(-1);
	}

	if (set_nonblocking(reader_fd, __func__) < 0) {
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	ch = 0xfe;
	ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout,
	    __func__);
	if (ret < 0) {
		warn("test_nonblocking_one_byte: timed_write");
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}
	if (len != sizeof(ch)) {
		warnx("test_nonblocking_one_byte: timed_write: tried to write "
		    "%zu, wrote %zd", sizeof(ch), len);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	ch = 0xab;
	ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
	    __func__);
	if (ret < 0) {
		warn("test_nonblocking_one_byte: timed_read");
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}
	if (len != sizeof(ch)) {
		warnx("test_nonblocking_one_byte: timed_read: wanted %zu, read "
		    "%zd", sizeof(ch), len);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}
	if (ch != 0xfe) {
		warnx("test_nonblocking_one_byte: timed_read: expected to read "
		    "0x%02x, read 0x%02x", 0xfe, ch);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	cleanfifo2("testfifo", reader_fd, writer_fd);
}
Example #3
0
static void
cleanfifo3(const char *fifoname, int fd1, int fd2, int fd3)
{

    if (fd3 != -1)
        close(fd3);
    cleanfifo2(fifoname, fd1, fd2);
}
Example #4
0
/*
 * Simple I/O test: write ten integers, and make sure we get back the same
 * integers in the same order.  This assumes a minimum fifo buffer > 10
 * bytes in order to not block and deadlock.
 */
static void
test_simpleio(void)
{
    int i, reader_fd, writer_fd;
    u_char buffer[10];
    ssize_t len;

    makefifo("testfifo", __func__);
    if (openfifo("testfifo", &reader_fd, &writer_fd)
            < 0) {
        warn("test_simpleio: openfifo: testfifo");
        cleanfifo2("testfifo", -1, -1);
        exit(-1);
    }

    for (i = 0; i < 10; i++)
        buffer[i] = i;

    len = write(writer_fd, (char *)buffer, sizeof(buffer));
    if (len < 0) {
        warn("test_simpleio: write");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    if (len != sizeof(buffer)) {
        warnx("test_simplio: tried %zu but wrote %zd", sizeof(buffer),
              len);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    len = read(reader_fd, (char *)buffer, sizeof(buffer));
    if (len < 0) {
        warn("test_simpleio: read");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    if (len != sizeof(buffer)) {
        warnx("test_simpleio: tried %zu but read %zd", sizeof(buffer),
              len);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    for (i = 0; i < 10; i++) {
        if (buffer[i] == i)
            continue;
        warnx("test_simpleio: write byte %d as 0x%02x, but read "
              "0x%02x", i, i, buffer[i]);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    cleanfifo2("testfifo", reader_fd, writer_fd);
}
Example #5
0
/*
 * First of two test cases involving a 512K buffer: write the buffer into a
 * blocking file descriptor.  We'd like to know it blocks, but the closest we
 * can get is to see if SIGALRM fired during the I/O resulting in a partial
 * write.
 */
static void
test_blocking_partial_write(void)
{
	int reader_fd, ret, timedout, writer_fd;
	u_char *buffer;
	ssize_t len;

	makefifo("testfifo", __func__);
	if (openfifo("testfifo", __func__, &reader_fd, &writer_fd)
	    < 0) {
		warn("test_blocking_partial_write: openfifo: testfifo");
		cleanfifo2("testfifo", -1, -1);
		exit(-1);
	}

	if (set_blocking(writer_fd, __func__) < 0) {
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	buffer = malloc(512*1024);
	if (buffer == NULL) {
		warn("test_blocking_partial_write: malloc");
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}
	bzero(buffer, 512*1024);

	ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout,
	    __func__);
	if (ret < 0) {
		warn("test_blocking_partial_write: timed_write");
		free(buffer);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	if (!timedout) {
		warnx("test_blocking_partial_write: timed_write: blocking "
		    "socket didn't time out");
		free(buffer);
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	free(buffer);

	if (drain_fd(reader_fd, __func__) < 0) {
		cleanfifo2("testfifo", reader_fd, writer_fd);
		exit(-1);
	}

	cleanfifo2("testfifo", reader_fd, writer_fd);
}
Example #6
0
/*
 * test_coalesce_big_write() verifies that data mingles in the fifo across
 * message boundaries by performing one big write, then two smaller reads
 * that should return sequential elements of data from the write.
 */
static void
test_coalesce_big_write(void)
{
    int i, reader_fd, writer_fd;
    u_char buffer[10];
    ssize_t len;

    makefifo("testfifo", __func__);
    if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
        warn("test_coalesce_big_write: openfifo: testfifo");
        cleanfifo2("testfifo", -1, -1);
        exit(-1);
    }

    /* Write ten, read five, read five. */
    for (i = 0; i < 10; i++)
        buffer[i] = i;

    len = write(writer_fd, buffer, 10);
    if (len < 0) {
        warn("test_coalesce_big_write: write 10");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    if (len != 10) {
        warnx("test_coalesce_big_write: write 10 wrote %zd", len);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    len = read(reader_fd, buffer, 5);
    if (len < 0) {
        warn("test_coalesce_big_write: read 5");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    if (len != 5) {
        warnx("test_coalesce_big_write: read 5 read %zd", len);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    len = read(reader_fd, buffer + 5, 5);
    if (len < 0) {
        warn("test_coalesce_big_write: read 5");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    if (len != 5) {
        warnx("test_coalesce_big_write: read 5 read %zd", len);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    for (i = 0; i < 10; i++) {
        if (buffer[i] == i)
            continue;
        warnx("test_coalesce_big_write: expected to read 0x%02x, "
              "read 0x%02x", i, buffer[i]);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    cleanfifo2("testfifo", -1, -1);
}
Example #7
0
/*
 * Write a 512K buffer to an empty fifo using a non-blocking file descriptor,
 * and make sure it doesn't block.
 */
static void
test_nonblocking_partial_write(void)
{
    int reader_fd, ret, timedout, writer_fd;
    u_char *buffer;
    ssize_t len;

    makefifo("testfifo", __func__);
    if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
        warn("test_blocking_partial_write: openfifo: testfifo");
        cleanfifo2("testfifo", -1, -1);
        exit(-1);
    }

    if (set_nonblocking(writer_fd, __func__) < 0) {
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    buffer = malloc(512*1024);
    if (buffer == NULL) {
        warn("test_blocking_partial_write: malloc");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    bzero(buffer, 512*1024);

    ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout,
                      __func__);
    if (ret < 0) {
        warn("test_blocking_partial_write: timed_write");
        free(buffer);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    if (timedout) {
        warnx("test_blocking_partial_write: timed_write: "
              "non-blocking socket timed out");
        free(buffer);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    if (len == 0 || len >= 512*1024) {
        warnx("test_blocking_partial_write: timed_write: requested "
              "%d, sent %zd", 512*1024, len);
        free(buffer);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    free(buffer);

    if (drain_fd(reader_fd, __func__) < 0) {
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    cleanfifo2("testfifo", reader_fd, writer_fd);
}
Example #8
0
/*
 * This test operates on blocking and non-blocking fifo file descriptors, in
 * order to determine whether they block at good moments or not.  By good we
 * mean: don't block for non-blocking sockets, and do block for blocking
 * ones, assuming there isn't I/O buffer to satisfy the request.
 *
 * We use a timeout of 5 seconds, concluding that in 5 seconds either all I/O
 * that can take place will, and that if we reach the end of the timeout,
 * then blocking has occurred.
 *
 * We assume that the buffer size on a fifo is <512K, and as such, that
 * writing that much data without an active reader will result in blocking.
 */
static void
test_blocking_read_empty(void)
{
    int reader_fd, ret, timedout, writer_fd;
    ssize_t len;
    u_char ch;

    makefifo("testfifo", __func__);
    if (openfifo("testfifo", &reader_fd, &writer_fd)
            < 0) {
        warn("test_blocking_read_empty: openfifo: testfifo");
        cleanfifo2("testfifo", -1, -1);
        exit(-1);
    }

    /*
     * Read one byte from an empty blocking fifo, block as there is no
     * data.
     */
    if (set_blocking(reader_fd, __func__) < 0) {
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
                     __func__);
    if (ret != -1) {
        warnx("test_blocking_read_empty: timed_read: returned "
              "success");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    if (errno != EINTR) {
        warn("test_blocking_read_empty: timed_read");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    /*
     * Read one byte from an empty non-blocking fifo, return EAGAIN as
     * there is no data.
     */
    if (set_nonblocking(reader_fd, __func__) < 0) {
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
                     __func__);
    if (ret != -1) {
        warnx("test_blocking_read_empty: timed_read: returned "
              "success");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }
    if (errno != EAGAIN) {
        warn("test_blocking_read_empty: timed_read");
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    cleanfifo2("testfifo", reader_fd, writer_fd);
}
Example #9
0
/*
 * We don't comprehensively test O_RDWR file descriptors, but do run a couple
 * of event tests to make sure that the fifo implementation doesn't mixed up
 * status checks.  In particular, at least one past FreeBSD bug exists in
 * which the FIONREAD test was performed on the wrong socket implementing the
 * fifo, resulting in the fifo never returning readable.
 */
static void
test_events_rdwr(void)
{
    int fd, kqueue_fd;
    ssize_t len;
    char ch;

    makefifo("testfifo", __func__);
    if (openfifo_rw("testfifo", &fd) < 0) {
        warn("%s: openfifo_rw: testfifo", __func__);
        cleanfifo2("testfifo", -1, -1);
        exit(-1);
    }

    kqueue_fd = kqueue();
    if (kqueue_fd < 0) {
        warn("%s: kqueue", __func__);
        cleanfifo2("testifo", fd, -1);
        exit(-1);
    }

    if (kqueue_setup(kqueue_fd, fd, __func__) < 0) {
        cleanfifo2("testfifo", fd, kqueue_fd);
        exit(-1);
    }

    /*
     * On first creation, the O_RDWR descriptor should be writable but
     * not readable.
     */
    if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE,
                      NOT_EXCEPTION, __func__, "create", "fd") < 0) {
        cleanfifo2("testfifo", fd, kqueue_fd);
        exit(-1);
    }

    /*
     * Write a byte, which should cause the file descriptor to become
     * readable and writable.
     */
    ch = 0x00;
    len = write(fd, &ch, sizeof(ch));
    if (len < 0) {
        warn("%s: write", __func__);
        cleanfifo2("testfifo", fd, kqueue_fd);
        exit(-1);
    }

    if (assert_status(fd, kqueue_fd, READABLE, WRITABLE, NOT_EXCEPTION,
                      __func__, "write", "fd") < 0) {
        cleanfifo2("testfifo", fd, kqueue_fd);
        exit(-1);
    }

    /*
     * Read a byte, which should cause the file descriptor to return to
     * simply being writable.
     */
    len = read(fd, &ch, sizeof(ch));
    if (len < 0) {
        warn("%s: read", __func__);
        cleanfifo2("testfifo", fd, kqueue_fd);
        exit(-1);
    }

    if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE,
                      NOT_EXCEPTION, __func__, "write+read", "fd") < 0) {
        cleanfifo2("testfifo", fd, kqueue_fd);
        exit(-1);
    }

    cleanfifo2("testfifo", fd, kqueue_fd);
}
Example #10
0
/*
 * Write a 512k buffer to the fifo in non-blocking mode, and make sure that
 * the write end becomes un-writable as a result of a partial write that
 * fills the fifo buffer.
 */
static void
test_events_partial_write(void)
{
    int kqueue_fd, reader_fd, writer_fd;
    u_char *buffer;
    ssize_t len;

    makefifo("testfifo", __func__);
    if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
        warn("test_events_partial_write: openfifo: testfifo");
        cleanfifo2("testfifo", -1, -1);
        exit(-1);
    }

    kqueue_fd = kqueue();
    if (kqueue_fd < 0) {
        warn("%s: kqueue", __func__);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    if (set_nonblocking(writer_fd, "test_events") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    buffer = malloc(512*1024);
    if (buffer == NULL) {
        warn("test_events_partial_write: malloc");
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }
    bzero(buffer, 512*1024);

    len = write(writer_fd, buffer, 512*1024);
    if (len < 0) {
        warn("test_events_partial_write: write");
        free(buffer);
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    free(buffer);

    if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE,
                      NOT_EXCEPTION, __func__, "big write", "writer_fd") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    if (drain_fd(reader_fd, "test_events") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    /*
     * Test that the writer_fd has been restored to writable state after
     * draining.
     */
    if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
                      NOT_EXCEPTION, __func__, "big write + drain", "writer_fd") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
}
Example #11
0
static void
test_events_write_read_byte(void)
{
    int kqueue_fd, reader_fd, writer_fd;
    ssize_t len;
    u_char ch;

    makefifo("testfifo", __func__);
    if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
        warn("test_events_write_read_byte: openfifo: testfifo");
        cleanfifo2("testfifo", -1, -1);
        exit(-1);
    }

    kqueue_fd = kqueue();
    if (kqueue_fd < 0) {
        warn("%s: kqueue", __func__);
        cleanfifo2("testfifo", reader_fd, writer_fd);
        exit(-1);
    }

    if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    /*
     * Write a byte to the fifo, and make sure that the read end becomes
     * readable, and that the write end remains writable (small write).
     */
    ch = 0x00;
    len = write(writer_fd, &ch, sizeof(ch));
    if (len < 0) {
        warn("%s: write", __func__);
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    if (assert_status(reader_fd, kqueue_fd, READABLE, NOT_WRITABLE,
                      NOT_EXCEPTION, __func__, "write", "reader_fd") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    /*
     * the writer_fd should remain writable.
     */
    if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
                      NOT_EXCEPTION, __func__, "write", "writer_fd") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    /*
     * Read the byte from the reader_fd, and now confirm that that fifo
     * becomes unreadable.
     */
    len = read(reader_fd, &ch, sizeof(ch));
    if (len < 0) {
        warn("%s: read", __func__);
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE,
                      NOT_EXCEPTION, __func__, "write+read", "reader_fd") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    /*
     * The writer_fd should remain writable.
     */
    if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
                      NOT_EXCEPTION, __func__, "write+read", "writer_fd") < 0) {
        cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
        exit(-1);
    }

    cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
}