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