1*cb5fe245SEnji Cooper /* 2*cb5fe245SEnji Cooper * Copyright (c) 2009 Mark Heily <mark@heily.com> 3*cb5fe245SEnji Cooper * 4*cb5fe245SEnji Cooper * Permission to use, copy, modify, and distribute this software for any 5*cb5fe245SEnji Cooper * purpose with or without fee is hereby granted, provided that the above 6*cb5fe245SEnji Cooper * copyright notice and this permission notice appear in all copies. 7*cb5fe245SEnji Cooper * 8*cb5fe245SEnji Cooper * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9*cb5fe245SEnji Cooper * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10*cb5fe245SEnji Cooper * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11*cb5fe245SEnji Cooper * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12*cb5fe245SEnji Cooper * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13*cb5fe245SEnji Cooper * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14*cb5fe245SEnji Cooper * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15*cb5fe245SEnji Cooper * 16*cb5fe245SEnji Cooper * $FreeBSD$ 17*cb5fe245SEnji Cooper */ 18*cb5fe245SEnji Cooper 19*cb5fe245SEnji Cooper #include "common.h" 20*cb5fe245SEnji Cooper 21*cb5fe245SEnji Cooper int kqfd; 22*cb5fe245SEnji Cooper int sockfd[2]; 23*cb5fe245SEnji Cooper 24*cb5fe245SEnji Cooper static void 25*cb5fe245SEnji Cooper kevent_socket_drain(void) 26*cb5fe245SEnji Cooper { 27*cb5fe245SEnji Cooper char buf[1]; 28*cb5fe245SEnji Cooper 29*cb5fe245SEnji Cooper /* Drain the read buffer, then make sure there are no more events. */ 30*cb5fe245SEnji Cooper puts("draining the read buffer"); 31*cb5fe245SEnji Cooper if (read(sockfd[0], &buf[0], 1) < 1) 32*cb5fe245SEnji Cooper err(1, "read(2)"); 33*cb5fe245SEnji Cooper } 34*cb5fe245SEnji Cooper 35*cb5fe245SEnji Cooper static void 36*cb5fe245SEnji Cooper kevent_socket_fill(void) 37*cb5fe245SEnji Cooper { 38*cb5fe245SEnji Cooper puts("filling the read buffer"); 39*cb5fe245SEnji Cooper if (write(sockfd[1], ".", 1) < 1) 40*cb5fe245SEnji Cooper err(1, "write(2)"); 41*cb5fe245SEnji Cooper } 42*cb5fe245SEnji Cooper 43*cb5fe245SEnji Cooper 44*cb5fe245SEnji Cooper void 45*cb5fe245SEnji Cooper test_kevent_socket_add(void) 46*cb5fe245SEnji Cooper { 47*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_ADD)"; 48*cb5fe245SEnji Cooper struct kevent kev; 49*cb5fe245SEnji Cooper 50*cb5fe245SEnji Cooper test_begin(test_id); 51*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 52*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 53*cb5fe245SEnji Cooper err(1, "%s", test_id); 54*cb5fe245SEnji Cooper 55*cb5fe245SEnji Cooper success(); 56*cb5fe245SEnji Cooper } 57*cb5fe245SEnji Cooper 58*cb5fe245SEnji Cooper void 59*cb5fe245SEnji Cooper test_kevent_socket_get(void) 60*cb5fe245SEnji Cooper { 61*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ) wait"; 62*cb5fe245SEnji Cooper struct kevent kev; 63*cb5fe245SEnji Cooper 64*cb5fe245SEnji Cooper test_begin(test_id); 65*cb5fe245SEnji Cooper 66*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 67*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 68*cb5fe245SEnji Cooper err(1, "%s", test_id); 69*cb5fe245SEnji Cooper 70*cb5fe245SEnji Cooper kevent_socket_fill(); 71*cb5fe245SEnji Cooper 72*cb5fe245SEnji Cooper kev.data = 1; 73*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd)); 74*cb5fe245SEnji Cooper 75*cb5fe245SEnji Cooper kevent_socket_drain(); 76*cb5fe245SEnji Cooper test_no_kevents(); 77*cb5fe245SEnji Cooper 78*cb5fe245SEnji Cooper kev.flags = EV_DELETE; 79*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 80*cb5fe245SEnji Cooper err(1, "%s", test_id); 81*cb5fe245SEnji Cooper 82*cb5fe245SEnji Cooper success(); 83*cb5fe245SEnji Cooper } 84*cb5fe245SEnji Cooper 85*cb5fe245SEnji Cooper void 86*cb5fe245SEnji Cooper test_kevent_socket_clear(void) 87*cb5fe245SEnji Cooper { 88*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; 89*cb5fe245SEnji Cooper struct kevent kev; 90*cb5fe245SEnji Cooper 91*cb5fe245SEnji Cooper test_begin(test_id); 92*cb5fe245SEnji Cooper 93*cb5fe245SEnji Cooper test_no_kevents(); 94*cb5fe245SEnji Cooper 95*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); 96*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 97*cb5fe245SEnji Cooper err(1, "%s", test_id); 98*cb5fe245SEnji Cooper 99*cb5fe245SEnji Cooper kevent_socket_fill(); 100*cb5fe245SEnji Cooper kevent_socket_fill(); 101*cb5fe245SEnji Cooper 102*cb5fe245SEnji Cooper kev.data = 2; 103*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd)); 104*cb5fe245SEnji Cooper 105*cb5fe245SEnji Cooper /* We filled twice, but drain once. Edge-triggered would not generate 106*cb5fe245SEnji Cooper additional events. 107*cb5fe245SEnji Cooper */ 108*cb5fe245SEnji Cooper kevent_socket_drain(); 109*cb5fe245SEnji Cooper test_no_kevents(); 110*cb5fe245SEnji Cooper 111*cb5fe245SEnji Cooper kevent_socket_drain(); 112*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 113*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 114*cb5fe245SEnji Cooper err(1, "%s", test_id); 115*cb5fe245SEnji Cooper 116*cb5fe245SEnji Cooper success(); 117*cb5fe245SEnji Cooper } 118*cb5fe245SEnji Cooper 119*cb5fe245SEnji Cooper void 120*cb5fe245SEnji Cooper test_kevent_socket_disable_and_enable(void) 121*cb5fe245SEnji Cooper { 122*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)"; 123*cb5fe245SEnji Cooper struct kevent kev; 124*cb5fe245SEnji Cooper 125*cb5fe245SEnji Cooper test_begin(test_id); 126*cb5fe245SEnji Cooper 127*cb5fe245SEnji Cooper /* 128*cb5fe245SEnji Cooper * Write to the socket before adding the event. This way we can verify that 129*cb5fe245SEnji Cooper * enabling a triggered kevent causes the event to be returned immediately. 130*cb5fe245SEnji Cooper */ 131*cb5fe245SEnji Cooper kevent_socket_fill(); 132*cb5fe245SEnji Cooper 133*cb5fe245SEnji Cooper /* Add a disabled event. */ 134*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISABLE, 0, 0, &sockfd[0]); 135*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 136*cb5fe245SEnji Cooper err(1, "%s", test_id); 137*cb5fe245SEnji Cooper 138*cb5fe245SEnji Cooper test_no_kevents(); 139*cb5fe245SEnji Cooper 140*cb5fe245SEnji Cooper /* Re-enable the knote, then see if an event is generated */ 141*cb5fe245SEnji Cooper kev.flags = EV_ENABLE; 142*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 143*cb5fe245SEnji Cooper err(1, "%s", test_id); 144*cb5fe245SEnji Cooper kev.flags = EV_ADD; 145*cb5fe245SEnji Cooper kev.data = 1; 146*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd)); 147*cb5fe245SEnji Cooper 148*cb5fe245SEnji Cooper kevent_socket_drain(); 149*cb5fe245SEnji Cooper 150*cb5fe245SEnji Cooper kev.flags = EV_DELETE; 151*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 152*cb5fe245SEnji Cooper err(1, "%s", test_id); 153*cb5fe245SEnji Cooper 154*cb5fe245SEnji Cooper success(); 155*cb5fe245SEnji Cooper } 156*cb5fe245SEnji Cooper 157*cb5fe245SEnji Cooper void 158*cb5fe245SEnji Cooper test_kevent_socket_del(void) 159*cb5fe245SEnji Cooper { 160*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; 161*cb5fe245SEnji Cooper struct kevent kev; 162*cb5fe245SEnji Cooper 163*cb5fe245SEnji Cooper test_begin(test_id); 164*cb5fe245SEnji Cooper 165*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 166*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 167*cb5fe245SEnji Cooper err(1, "%s", test_id); 168*cb5fe245SEnji Cooper 169*cb5fe245SEnji Cooper kevent_socket_fill(); 170*cb5fe245SEnji Cooper test_no_kevents(); 171*cb5fe245SEnji Cooper kevent_socket_drain(); 172*cb5fe245SEnji Cooper 173*cb5fe245SEnji Cooper success(); 174*cb5fe245SEnji Cooper } 175*cb5fe245SEnji Cooper 176*cb5fe245SEnji Cooper void 177*cb5fe245SEnji Cooper test_kevent_socket_oneshot(void) 178*cb5fe245SEnji Cooper { 179*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; 180*cb5fe245SEnji Cooper struct kevent kev; 181*cb5fe245SEnji Cooper 182*cb5fe245SEnji Cooper test_begin(test_id); 183*cb5fe245SEnji Cooper 184*cb5fe245SEnji Cooper /* Re-add the watch and make sure no events are pending */ 185*cb5fe245SEnji Cooper puts("-- re-adding knote"); 186*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); 187*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 188*cb5fe245SEnji Cooper err(1, "%s", test_id); 189*cb5fe245SEnji Cooper test_no_kevents(); 190*cb5fe245SEnji Cooper 191*cb5fe245SEnji Cooper puts("-- getting one event"); 192*cb5fe245SEnji Cooper kevent_socket_fill(); 193*cb5fe245SEnji Cooper kev.data = 1; 194*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd)); 195*cb5fe245SEnji Cooper 196*cb5fe245SEnji Cooper puts("-- checking knote disabled"); 197*cb5fe245SEnji Cooper test_no_kevents(); 198*cb5fe245SEnji Cooper 199*cb5fe245SEnji Cooper /* Try to delete the knote, it should already be deleted */ 200*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 201*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) 202*cb5fe245SEnji Cooper err(1, "%s", test_id); 203*cb5fe245SEnji Cooper 204*cb5fe245SEnji Cooper kevent_socket_drain(); 205*cb5fe245SEnji Cooper 206*cb5fe245SEnji Cooper success(); 207*cb5fe245SEnji Cooper } 208*cb5fe245SEnji Cooper 209*cb5fe245SEnji Cooper 210*cb5fe245SEnji Cooper #if HAVE_EV_DISPATCH 211*cb5fe245SEnji Cooper void 212*cb5fe245SEnji Cooper test_kevent_socket_dispatch(void) 213*cb5fe245SEnji Cooper { 214*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)"; 215*cb5fe245SEnji Cooper 216*cb5fe245SEnji Cooper test_begin(test_id); 217*cb5fe245SEnji Cooper 218*cb5fe245SEnji Cooper struct kevent kev; 219*cb5fe245SEnji Cooper 220*cb5fe245SEnji Cooper /* Re-add the watch and make sure no events are pending */ 221*cb5fe245SEnji Cooper puts("-- re-adding knote"); 222*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); 223*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 224*cb5fe245SEnji Cooper err(1, "%s", test_id); 225*cb5fe245SEnji Cooper test_no_kevents(); 226*cb5fe245SEnji Cooper 227*cb5fe245SEnji Cooper /* The event will occur only once, even though EV_CLEAR is not 228*cb5fe245SEnji Cooper specified. */ 229*cb5fe245SEnji Cooper kevent_socket_fill(); 230*cb5fe245SEnji Cooper kev.data = 1; 231*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd)); 232*cb5fe245SEnji Cooper test_no_kevents(); 233*cb5fe245SEnji Cooper 234*cb5fe245SEnji Cooper /* Since the knote is disabled, the EV_DELETE operation succeeds. */ 235*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 236*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 237*cb5fe245SEnji Cooper err(1, "%s", test_id); 238*cb5fe245SEnji Cooper 239*cb5fe245SEnji Cooper kevent_socket_drain(); 240*cb5fe245SEnji Cooper 241*cb5fe245SEnji Cooper success(); 242*cb5fe245SEnji Cooper } 243*cb5fe245SEnji Cooper #endif /* HAVE_EV_DISPATCH */ 244*cb5fe245SEnji Cooper 245*cb5fe245SEnji Cooper #if BROKEN 246*cb5fe245SEnji Cooper void 247*cb5fe245SEnji Cooper test_kevent_socket_lowat(void) 248*cb5fe245SEnji Cooper { 249*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)"; 250*cb5fe245SEnji Cooper struct kevent kev; 251*cb5fe245SEnji Cooper 252*cb5fe245SEnji Cooper test_begin(test_id); 253*cb5fe245SEnji Cooper 254*cb5fe245SEnji Cooper /* Re-add the watch and make sure no events are pending */ 255*cb5fe245SEnji Cooper puts("-- re-adding knote, setting low watermark to 2 bytes"); 256*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); 257*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 258*cb5fe245SEnji Cooper err(1, "%s", test_id); 259*cb5fe245SEnji Cooper test_no_kevents(); 260*cb5fe245SEnji Cooper 261*cb5fe245SEnji Cooper puts("-- checking that one byte does not trigger an event.."); 262*cb5fe245SEnji Cooper kevent_socket_fill(); 263*cb5fe245SEnji Cooper test_no_kevents(); 264*cb5fe245SEnji Cooper 265*cb5fe245SEnji Cooper puts("-- checking that two bytes triggers an event.."); 266*cb5fe245SEnji Cooper kevent_socket_fill(); 267*cb5fe245SEnji Cooper if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) 268*cb5fe245SEnji Cooper err(1, "%s", test_id); 269*cb5fe245SEnji Cooper KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); 270*cb5fe245SEnji Cooper test_no_kevents(); 271*cb5fe245SEnji Cooper 272*cb5fe245SEnji Cooper kevent_socket_drain(); 273*cb5fe245SEnji Cooper kevent_socket_drain(); 274*cb5fe245SEnji Cooper 275*cb5fe245SEnji Cooper success(); 276*cb5fe245SEnji Cooper } 277*cb5fe245SEnji Cooper #endif 278*cb5fe245SEnji Cooper 279*cb5fe245SEnji Cooper void 280*cb5fe245SEnji Cooper test_kevent_socket_eof(void) 281*cb5fe245SEnji Cooper { 282*cb5fe245SEnji Cooper const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; 283*cb5fe245SEnji Cooper struct kevent kev; 284*cb5fe245SEnji Cooper 285*cb5fe245SEnji Cooper test_begin(test_id); 286*cb5fe245SEnji Cooper 287*cb5fe245SEnji Cooper /* Re-add the watch and make sure no events are pending */ 288*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 289*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 290*cb5fe245SEnji Cooper err(1, "%s", test_id); 291*cb5fe245SEnji Cooper test_no_kevents(); 292*cb5fe245SEnji Cooper 293*cb5fe245SEnji Cooper if (close(sockfd[1]) < 0) 294*cb5fe245SEnji Cooper err(1, "close(2)"); 295*cb5fe245SEnji Cooper 296*cb5fe245SEnji Cooper kev.flags |= EV_EOF; 297*cb5fe245SEnji Cooper kevent_cmp(&kev, kevent_get(kqfd)); 298*cb5fe245SEnji Cooper 299*cb5fe245SEnji Cooper /* Delete the watch */ 300*cb5fe245SEnji Cooper EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 301*cb5fe245SEnji Cooper if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 302*cb5fe245SEnji Cooper err(1, "%s", test_id); 303*cb5fe245SEnji Cooper 304*cb5fe245SEnji Cooper success(); 305*cb5fe245SEnji Cooper } 306*cb5fe245SEnji Cooper 307*cb5fe245SEnji Cooper void 308*cb5fe245SEnji Cooper test_evfilt_read() 309*cb5fe245SEnji Cooper { 310*cb5fe245SEnji Cooper /* Create a connected pair of full-duplex sockets for testing socket events */ 311*cb5fe245SEnji Cooper if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) 312*cb5fe245SEnji Cooper abort(); 313*cb5fe245SEnji Cooper 314*cb5fe245SEnji Cooper kqfd = kqueue(); 315*cb5fe245SEnji Cooper test_kevent_socket_add(); 316*cb5fe245SEnji Cooper test_kevent_socket_del(); 317*cb5fe245SEnji Cooper test_kevent_socket_get(); 318*cb5fe245SEnji Cooper test_kevent_socket_disable_and_enable(); 319*cb5fe245SEnji Cooper test_kevent_socket_oneshot(); 320*cb5fe245SEnji Cooper test_kevent_socket_clear(); 321*cb5fe245SEnji Cooper #if HAVE_EV_DISPATCH 322*cb5fe245SEnji Cooper test_kevent_socket_dispatch(); 323*cb5fe245SEnji Cooper #endif 324*cb5fe245SEnji Cooper test_kevent_socket_eof(); 325*cb5fe245SEnji Cooper close(kqfd); 326*cb5fe245SEnji Cooper } 327