Module Name: src Committed By: thorpej Date: Sat Oct 2 18:21:05 UTC 2021
Modified Files: src/tests/kernel/kqueue/read: t_fifo.c Log Message: New EVFILT_READ test case for FIFOs; validates readability threshold and EV_EOF behavior. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/tests/kernel/kqueue/read/t_fifo.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/kernel/kqueue/read/t_fifo.c diff -u src/tests/kernel/kqueue/read/t_fifo.c:1.4 src/tests/kernel/kqueue/read/t_fifo.c:1.5 --- src/tests/kernel/kqueue/read/t_fifo.c:1.4 Fri Jan 13 21:30:41 2017 +++ src/tests/kernel/kqueue/read/t_fifo.c Sat Oct 2 18:21:05 2021 @@ -1,11 +1,11 @@ -/* $NetBSD: t_fifo.c,v 1.4 2017/01/13 21:30:41 christos Exp $ */ +/* $NetBSD: t_fifo.c,v 1.5 2021/10/02 18:21:05 thorpej Exp $ */ /*- - * Copyright (c) 2008 The NetBSD Foundation, Inc. + * Copyright (c) 2021 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Luke Mewburn and Jaromir Dolecek. + * by Jason R. Thorpe. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,13 +30,14 @@ */ #include <sys/cdefs.h> -__COPYRIGHT("@(#) Copyright (c) 2008\ +__COPYRIGHT("@(#) Copyright (c) 2021\ The NetBSD Foundation, inc. All rights reserved."); -__RCSID("$NetBSD: t_fifo.c,v 1.4 2017/01/13 21:30:41 christos Exp $"); +__RCSID("$NetBSD: t_fifo.c,v 1.5 2021/10/02 18:21:05 thorpej Exp $"); #include <sys/event.h> #include <sys/stat.h> +#include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> @@ -46,48 +47,94 @@ __RCSID("$NetBSD: t_fifo.c,v 1.4 2017/01 #include <atf-c.h> -#include "h_macros.h" +static const char fifo_path[] = "fifo"; -#define FIFONAME "fifo" +static void +fifo_support(void) +{ + errno = 0; + if (mkfifo(fifo_path, 0600) == 0) { + ATF_REQUIRE(unlink(fifo_path) == 0); + return; + } + + if (errno == EOPNOTSUPP) { + atf_tc_skip("the kernel does not support FIFOs"); + } else { + atf_tc_fail("mkfifo(2) failed"); + } +} -ATF_TC(fifo); +ATF_TC_WITH_CLEANUP(fifo); ATF_TC_HEAD(fifo, tc) { atf_tc_set_md_var(tc, "descr", "Checks EVFILT_READ on fifo"); } ATF_TC_BODY(fifo, tc) { - int kq, n, fd; + const struct timespec to = { 0, 0 }; struct kevent event[1]; - char buffer[128]; - - RL(mkfifo(FIFONAME, 0644)); - RL(fd = open(FIFONAME, O_RDWR, 0644)); - - RL(kq = kqueue()); - - EV_SET(&event[0], fd, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0); - RL(kevent(kq, event, 1, NULL, 0, NULL)); - - /* make sure there is something in the fifo */ - RL(write(fd, "foo", 3)); - (void)printf("fifo: wrote 'foo'\n"); - - (void)memset(event, 0, sizeof(event)); - - RL(n = kevent(kq, NULL, 0, event, 1, NULL)); - - (void)printf("kevent num %d filt %d flags: %#x, fflags: %#x, " - "data: %" PRId64 "\n", n, event[0].filter, event[0].flags, - event[0].fflags, event[0].data); - - ATF_REQUIRE_EQ(event[0].filter, EVFILT_READ); - - RL(n = read(fd, buffer, event[0].data)); - buffer[n] = '\0'; - (void)printf("fifo: read '%s'\n", buffer); + char *buf; + int rfd, wfd, kq; + long pipe_buf; + + fifo_support(); + + ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0); + ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0); + ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY | O_NONBLOCK)) >= 0); + ATF_REQUIRE((kq = kqueue()) >= 0); + + /* Get the maximum atomic pipe write size. */ + pipe_buf = fpathconf(wfd, _PC_PIPE_BUF); + ATF_REQUIRE(pipe_buf > 1); + + buf = malloc(pipe_buf); + ATF_REQUIRE(buf != NULL); + + EV_SET(&event[0], rfd, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0); + ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0); + + /* We expect the FIFO to not be readable. */ + ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &to) == 0); + + /* Write a single byte of data into the FIFO. */ + ATF_REQUIRE(write(wfd, buf, 1) == 1); + + /* We expect the FIFO to be readable. */ + ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &to) == 1); + ATF_REQUIRE(event[0].ident == (uintptr_t)rfd); + ATF_REQUIRE(event[0].filter == EVFILT_READ); + ATF_REQUIRE((event[0].flags & EV_EOF) == 0); + + /* Read that single byte back out. */ + ATF_REQUIRE(read(rfd, buf, 1) == 1); + + /* We expect the FIFO to not be readable. */ + ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &to) == 0); + + /* Close the writer. We expect to get EV_EOF. */ + (void)close(wfd); + ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &to) == 1); + ATF_REQUIRE(event[0].ident == (uintptr_t)rfd); + ATF_REQUIRE(event[0].filter == EVFILT_READ); + ATF_REQUIRE((event[0].flags & EV_EOF) != 0); + + /* + * Reconect the writer. We expect EV_EOF to be cleared and + * for the FIFO to no longer be readable once again. + */ + ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY | O_NONBLOCK)) >= 0); + ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &to) == 0); + + (void)close(wfd); + (void)close(rfd); + (void)close(kq); +} - RL(close(fd)); +ATF_TC_CLEANUP(fifo, tc) +{ + (void)unlink(fifo_path); } ATF_TP_ADD_TCS(tp)