Path: blob/main/tests/sys/kern/pipe/pipe_kqueue_test.c
39488 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2020 Jan Kokemüller4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include <sys/param.h>28#include <sys/event.h>29#include <sys/stat.h>3031#include <errno.h>32#include <fcntl.h>33#include <limits.h>34#include <poll.h>35#include <stdio.h>36#include <stdlib.h>37#include <time.h>38#include <unistd.h>3940#include <atf-c.h>4142ATF_TC_WITHOUT_HEAD(pipe_kqueue__write_end);43ATF_TC_BODY(pipe_kqueue__write_end, tc)44{45int p[2] = { -1, -1 };4647ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);48ATF_REQUIRE(p[0] >= 0);49ATF_REQUIRE(p[1] >= 0);5051int kq = kqueue();52ATF_REQUIRE(kq >= 0);5354struct kevent kev[32];55EV_SET(&kev[0], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, 0);5657ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, NULL) == 0);5859/* Test that EVFILT_WRITE behaves sensibly on the write end. */6061ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),62&(struct timespec) { 0, 0 }) == 1);63ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);64ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);65ATF_REQUIRE(kev[0].flags == EV_CLEAR);66ATF_REQUIRE(kev[0].fflags == 0);67ATF_REQUIRE(kev[0].data == 16384);68ATF_REQUIRE(kev[0].udata == 0);6970/* Filling up the pipe should make the EVFILT_WRITE disappear. */7172char c = 0;73ssize_t r;74while ((r = write(p[1], &c, 1)) == 1) {75}76ATF_REQUIRE(r < 0);77ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);7879ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),80&(struct timespec) { 0, 0 }) == 0);8182/* Reading (PIPE_BUF - 1) bytes will not trigger a EVFILT_WRITE yet. */8384for (int i = 0; i < PIPE_BUF - 1; ++i) {85ATF_REQUIRE(read(p[0], &c, 1) == 1);86}8788ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),89&(struct timespec) { 0, 0 }) == 0);9091/* Reading one additional byte triggers the EVFILT_WRITE. */9293ATF_REQUIRE(read(p[0], &c, 1) == 1);9495r = kevent(kq, NULL, 0, kev, nitems(kev), &(struct timespec) { 0, 0 });96ATF_REQUIRE(r == 1);97ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);98ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);99ATF_REQUIRE(kev[0].flags == EV_CLEAR);100ATF_REQUIRE(kev[0].fflags == 0);101ATF_REQUIRE(kev[0].data == PIPE_BUF);102ATF_REQUIRE(kev[0].udata == 0);103104/*105* Reading another byte triggers the EVFILT_WRITE again with a changed106* 'data' field.107*/108109ATF_REQUIRE(read(p[0], &c, 1) == 1);110111ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),112&(struct timespec) { 0, 0 }) == 1);113ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);114ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);115ATF_REQUIRE(kev[0].flags == EV_CLEAR);116ATF_REQUIRE(kev[0].fflags == 0);117ATF_REQUIRE(kev[0].data == PIPE_BUF + 1);118ATF_REQUIRE(kev[0].udata == 0);119120/*121* Closing the read end should make a EV_EOF appear but leave the 'data'122* field unchanged.123*/124125ATF_REQUIRE(close(p[0]) == 0);126127ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),128&(struct timespec) { 0, 0 }) == 1);129ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);130ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);131ATF_REQUIRE(kev[0].flags == (EV_CLEAR | EV_EOF | EV_ONESHOT));132ATF_REQUIRE(kev[0].fflags == 0);133ATF_REQUIRE(kev[0].data == PIPE_BUF + 1);134ATF_REQUIRE(kev[0].udata == 0);135136ATF_REQUIRE(close(kq) == 0);137ATF_REQUIRE(close(p[1]) == 0);138}139140ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_read_end);141ATF_TC_BODY(pipe_kqueue__closed_read_end, tc)142{143int p[2] = { -1, -1 };144145ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);146ATF_REQUIRE(p[0] >= 0);147ATF_REQUIRE(p[1] >= 0);148149ATF_REQUIRE(close(p[0]) == 0);150151int kq = kqueue();152ATF_REQUIRE(kq >= 0);153154struct kevent kev[32];155EV_SET(&kev[0], p[1], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/1560, 0, 0);157EV_SET(&kev[1], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/1580, 0, 0);159160/*161* Trying to register EVFILT_WRITE when the pipe is closed leads to an162* EPIPE error.163*/164165ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2);166ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0);167ATF_REQUIRE(kev[0].data == 0);168ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0);169ATF_REQUIRE(kev[1].data == EPIPE);170171ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),172&(struct timespec) { 0, 0 }) == 1);173ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);174ATF_REQUIRE(kev[0].filter == EVFILT_READ);175ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT));176ATF_REQUIRE(kev[0].fflags == 0);177ATF_REQUIRE(kev[0].data == 0);178ATF_REQUIRE(kev[0].udata == 0);179180ATF_REQUIRE(close(kq) == 0);181ATF_REQUIRE(close(p[1]) == 0);182}183184ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_read_end_register_before_close);185ATF_TC_BODY(pipe_kqueue__closed_read_end_register_before_close, tc)186{187int p[2] = { -1, -1 };188189ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);190ATF_REQUIRE(p[0] >= 0);191ATF_REQUIRE(p[1] >= 0);192193int kq = kqueue();194ATF_REQUIRE(kq >= 0);195196struct kevent kev[32];197EV_SET(&kev[0], p[1], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/1980, 0, 0);199EV_SET(&kev[1], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/2000, 0, 0);201202/*203* Registering EVFILT_WRITE before the pipe is closed leads to a204* EVFILT_WRITE event with EV_EOF set.205*/206207ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2);208ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0);209ATF_REQUIRE(kev[0].data == 0);210ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0);211ATF_REQUIRE(kev[1].data == 0);212213ATF_REQUIRE(close(p[0]) == 0);214215ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),216&(struct timespec) { 0, 0 }) == 2);217{218ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);219ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);220ATF_REQUIRE(kev[0].flags ==221(EV_EOF | EV_CLEAR | EV_ONESHOT | EV_RECEIPT));222ATF_REQUIRE(kev[0].fflags == 0);223ATF_REQUIRE(kev[0].data == 16384);224ATF_REQUIRE(kev[0].udata == 0);225}226{227ATF_REQUIRE(kev[1].ident == (uintptr_t)p[1]);228ATF_REQUIRE(kev[1].filter == EVFILT_READ);229ATF_REQUIRE(kev[1].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT));230ATF_REQUIRE(kev[1].fflags == 0);231ATF_REQUIRE(kev[1].data == 0);232ATF_REQUIRE(kev[1].udata == 0);233}234235ATF_REQUIRE(close(kq) == 0);236ATF_REQUIRE(close(p[1]) == 0);237}238239ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_write_end);240ATF_TC_BODY(pipe_kqueue__closed_write_end, tc)241{242struct kevent kev[32];243ssize_t bytes, n;244int kq, p[2];245char c;246247ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);248ATF_REQUIRE(p[0] >= 0);249ATF_REQUIRE(p[1] >= 0);250251bytes = 0;252c = 0;253while ((n = write(p[1], &c, 1)) == 1)254bytes++;255ATF_REQUIRE(n < 0);256ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);257258ATF_REQUIRE(close(p[1]) == 0);259260kq = kqueue();261ATF_REQUIRE(kq >= 0);262263EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT,2640, 0, 0);265EV_SET(&kev[1], p[0], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT,2660, 0, 0);267268/*269* Trying to register EVFILT_WRITE when the pipe is closed leads to an270* EPIPE error.271*/272273ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2);274ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0);275ATF_REQUIRE(kev[0].data == 0);276ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0);277ATF_REQUIRE(kev[1].data == EPIPE);278279ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),280&(struct timespec) { 0, 0 }) == 1);281ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]);282ATF_REQUIRE(kev[0].filter == EVFILT_READ);283ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT));284ATF_REQUIRE(kev[0].fflags == 0);285ATF_REQUIRE(kev[0].data == bytes);286ATF_REQUIRE(kev[0].udata == 0);287288ATF_REQUIRE(close(kq) == 0);289ATF_REQUIRE(close(p[0]) == 0);290}291292ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_write_end_register_before_close);293ATF_TC_BODY(pipe_kqueue__closed_write_end_register_before_close, tc)294{295struct kevent kev[32];296ssize_t bytes, n;297int kq, p[2];298char c;299300ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0);301ATF_REQUIRE(p[0] >= 0);302ATF_REQUIRE(p[1] >= 0);303304kq = kqueue();305ATF_REQUIRE(kq >= 0);306307EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT,3080, 0, 0);309EV_SET(&kev[1], p[0], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT,3100, 0, 0);311312/*313* Registering EVFILT_WRITE before the pipe is closed leads to a314* EVFILT_WRITE event with EV_EOF set.315*/316317ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2);318ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0);319ATF_REQUIRE(kev[0].data == 0);320ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0);321ATF_REQUIRE(kev[1].data == 0);322323bytes = 0;324c = 0;325while ((n = write(p[1], &c, 1)) == 1)326bytes++;327ATF_REQUIRE(n < 0);328ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);329330ATF_REQUIRE(close(p[1]) == 0);331332ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),333&(struct timespec){ 0, 0 }) == 2);334335ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]);336ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);337ATF_REQUIRE(kev[0].flags ==338(EV_EOF | EV_CLEAR | EV_ONESHOT | EV_RECEIPT));339ATF_REQUIRE(kev[0].fflags == 0);340ATF_REQUIRE(kev[0].data > 0);341ATF_REQUIRE(kev[0].udata == 0);342343ATF_REQUIRE(kev[1].ident == (uintptr_t)p[0]);344ATF_REQUIRE(kev[1].filter == EVFILT_READ);345ATF_REQUIRE(kev[1].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT));346ATF_REQUIRE(kev[1].fflags == 0);347ATF_REQUIRE(kev[1].data == bytes);348ATF_REQUIRE(kev[1].udata == 0);349350ATF_REQUIRE(close(kq) == 0);351ATF_REQUIRE(close(p[0]) == 0);352}353354ATF_TP_ADD_TCS(tp)355{356ATF_TP_ADD_TC(tp, pipe_kqueue__write_end);357ATF_TP_ADD_TC(tp, pipe_kqueue__closed_read_end);358ATF_TP_ADD_TC(tp, pipe_kqueue__closed_read_end_register_before_close);359ATF_TP_ADD_TC(tp, pipe_kqueue__closed_write_end);360ATF_TP_ADD_TC(tp, pipe_kqueue__closed_write_end_register_before_close);361362return atf_no_error();363}364365366