Path: blob/main/tests/sys/kqueue/libkqueue/read.c
102327 views
/*1* Copyright (c) 2009 Mark Heily <[email protected]>2*3* Permission to use, copy, modify, and distribute this software for any4* purpose with or without fee is hereby granted, provided that the above5* copyright notice and this permission notice appear in all copies.6*7* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES8* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF9* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR10* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES11* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN12* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF13* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.14*/1516#include "common.h"1718static int sockfd[2];1920static void21kevent_socket_drain(void)22{23char buf[1];2425/* Drain the read buffer, then make sure there are no more events. */26puts("draining the read buffer");27if (read(sockfd[0], &buf[0], 1) < 1)28err(1, "read(2)");29}3031static void32kevent_socket_fill(void)33{34puts("filling the read buffer");35if (write(sockfd[1], ".", 1) < 1)36err(1, "write(2)");37}383940static void41test_kevent_socket_add(void)42{43const char *test_id = "kevent(EVFILT_READ, EV_ADD)";44struct kevent kev;4546test_begin(test_id);47EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);48if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)49err(1, "%s", test_id);5051success();52}5354static void55test_kevent_socket_get(void)56{57const char *test_id = "kevent(EVFILT_READ) wait";58struct kevent kev;5960test_begin(test_id);6162EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);63if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)64err(1, "%s", test_id);6566kevent_socket_fill();6768kev.data = 1;69kevent_cmp(&kev, kevent_get(kqfd));7071kevent_socket_drain();72test_no_kevents();7374kev.flags = EV_DELETE;75if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)76err(1, "%s", test_id);7778success();79}8081static void82test_kevent_socket_clear(void)83{84const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)";85struct kevent kev;8687test_begin(test_id);8889test_no_kevents();9091EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]);92if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)93err(1, "%s", test_id);9495kevent_socket_fill();96kevent_socket_fill();9798kev.data = 2;99kevent_cmp(&kev, kevent_get(kqfd));100101/* We filled twice, but drain once. Edge-triggered would not generate102additional events.103*/104kevent_socket_drain();105test_no_kevents();106107kevent_socket_drain();108EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);109if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)110err(1, "%s", test_id);111112success();113}114115static void116test_kevent_socket_disable_and_enable(void)117{118const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)";119struct kevent kev;120121test_begin(test_id);122123/*124* Write to the socket before adding the event. This way we can verify that125* enabling a triggered kevent causes the event to be returned immediately.126*/127kevent_socket_fill();128129/* Add a disabled event. */130EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISABLE, 0, 0, &sockfd[0]);131if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)132err(1, "%s", test_id);133134test_no_kevents();135136/* Re-enable the knote, then see if an event is generated */137kev.flags = EV_ENABLE;138if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)139err(1, "%s", test_id);140kev.flags = EV_ADD;141kev.data = 1;142kevent_cmp(&kev, kevent_get(kqfd));143144kevent_socket_drain();145146kev.flags = EV_DELETE;147if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)148err(1, "%s", test_id);149150success();151}152153static void154test_kevent_socket_del(void)155{156const char *test_id = "kevent(EVFILT_READ, EV_DELETE)";157struct kevent kev;158159test_begin(test_id);160161EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);162if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)163err(1, "%s", test_id);164165kevent_socket_fill();166test_no_kevents();167kevent_socket_drain();168169success();170}171172static void173test_kevent_socket_oneshot(void)174{175const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)";176struct kevent kev;177178test_begin(test_id);179180/* Re-add the watch and make sure no events are pending */181puts("-- re-adding knote");182EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]);183if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)184err(1, "%s", test_id);185test_no_kevents();186187puts("-- getting one event");188kevent_socket_fill();189kev.data = 1;190kevent_cmp(&kev, kevent_get(kqfd));191192puts("-- checking knote disabled");193test_no_kevents();194195/* Try to delete the knote, it should already be deleted */196EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);197if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0)198err(1, "%s", test_id);199200kevent_socket_drain();201202success();203}204205206#if HAVE_EV_DISPATCH207static void208test_kevent_socket_dispatch(void)209{210const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)";211212test_begin(test_id);213214struct kevent kev;215216/* Re-add the watch and make sure no events are pending */217puts("-- re-adding knote");218EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]);219if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)220err(1, "%s", test_id);221test_no_kevents();222223/* The event will occur only once, even though EV_CLEAR is not224specified. */225kevent_socket_fill();226kev.data = 1;227kevent_cmp(&kev, kevent_get(kqfd));228test_no_kevents();229230/* Since the knote is disabled, the EV_DELETE operation succeeds. */231EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);232if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)233err(1, "%s", test_id);234235kevent_socket_drain();236237success();238}239#endif /* HAVE_EV_DISPATCH */240241#if BROKEN242static void243test_kevent_socket_lowat(void)244{245const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)";246struct kevent kev;247248test_begin(test_id);249250/* Re-add the watch and make sure no events are pending */251puts("-- re-adding knote, setting low watermark to 2 bytes");252EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]);253if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)254err(1, "%s", test_id);255test_no_kevents();256257puts("-- checking that one byte does not trigger an event..");258kevent_socket_fill();259test_no_kevents();260261puts("-- checking that two bytes triggers an event..");262kevent_socket_fill();263if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1)264err(1, "%s", test_id);265KEV_CMP(kev, sockfd[0], EVFILT_READ, 0);266test_no_kevents();267268kevent_socket_drain();269kevent_socket_drain();270271success();272}273#endif274275static void276test_kevent_socket_eof(void)277{278const char *test_id = "kevent(EVFILT_READ, EV_EOF)";279struct kevent kev;280281test_begin(test_id);282283/* Re-add the watch and make sure no events are pending */284EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);285if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)286err(1, "%s", test_id);287test_no_kevents();288289if (close(sockfd[1]) < 0)290err(1, "close(2)");291292kev.flags |= EV_EOF;293kevent_cmp(&kev, kevent_get(kqfd));294295/* Delete the watch */296EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]);297if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)298err(1, "%s", test_id);299300success();301}302303void304test_evfilt_read(void)305{306/* Create a connected pair of full-duplex sockets for testing socket events */307if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0)308abort();309310kqfd = kqueue();311test_kevent_socket_add();312test_kevent_socket_del();313test_kevent_socket_get();314test_kevent_socket_disable_and_enable();315test_kevent_socket_oneshot();316test_kevent_socket_clear();317#if HAVE_EV_DISPATCH318test_kevent_socket_dispatch();319#endif320test_kevent_socket_eof();321close(kqfd);322}323324325