1200483Srwatson/* 2200483Srwatson * Copyright (c) 2009 Mark Heily <mark@heily.com> 3200483Srwatson * 4200483Srwatson * Permission to use, copy, modify, and distribute this software for any 5200483Srwatson * purpose with or without fee is hereby granted, provided that the above 6200483Srwatson * copyright notice and this permission notice appear in all copies. 7200483Srwatson * 8200483Srwatson * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9200483Srwatson * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10200483Srwatson * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11200483Srwatson * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12200483Srwatson * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13200483Srwatson * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14200483Srwatson * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15200483Srwatson * 16200483Srwatson * $FreeBSD$ 17200483Srwatson */ 18200483Srwatson 19200483Srwatson#include "common.h" 20200483Srwatson 21200483Srwatsonint kqfd; 22200483Srwatsonint sockfd[2]; 23200483Srwatson 24200483Srwatsonstatic void 25200483Srwatsonkevent_socket_drain(void) 26200483Srwatson{ 27200483Srwatson char buf[1]; 28200483Srwatson 29200483Srwatson /* Drain the read buffer, then make sure there are no more events. */ 30200483Srwatson puts("draining the read buffer"); 31200483Srwatson if (read(sockfd[0], &buf[0], 1) < 1) 32200483Srwatson err(1, "read(2)"); 33200483Srwatson} 34200483Srwatson 35200483Srwatsonstatic void 36200483Srwatsonkevent_socket_fill(void) 37200483Srwatson{ 38200483Srwatson puts("filling the read buffer"); 39200483Srwatson if (write(sockfd[1], ".", 1) < 1) 40200483Srwatson err(1, "write(2)"); 41200483Srwatson} 42200483Srwatson 43200483Srwatson 44200483Srwatsonvoid 45200483Srwatsontest_kevent_socket_add(void) 46200483Srwatson{ 47200483Srwatson const char *test_id = "kevent(EVFILT_READ, EV_ADD)"; 48200483Srwatson struct kevent kev; 49200483Srwatson 50200483Srwatson test_begin(test_id); 51200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 52200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 53200483Srwatson err(1, "%s", test_id); 54200483Srwatson 55200483Srwatson success(); 56200483Srwatson} 57200483Srwatson 58200483Srwatsonvoid 59200483Srwatsontest_kevent_socket_get(void) 60200483Srwatson{ 61200483Srwatson const char *test_id = "kevent(EVFILT_READ) wait"; 62200483Srwatson struct kevent kev; 63200483Srwatson 64200483Srwatson test_begin(test_id); 65200483Srwatson 66200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 67200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 68200483Srwatson err(1, "%s", test_id); 69200483Srwatson 70200483Srwatson kevent_socket_fill(); 71200483Srwatson 72200483Srwatson kev.data = 1; 73200483Srwatson kevent_cmp(&kev, kevent_get(kqfd)); 74200483Srwatson 75200483Srwatson kevent_socket_drain(); 76200483Srwatson test_no_kevents(); 77200483Srwatson 78200483Srwatson kev.flags = EV_DELETE; 79200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 80200483Srwatson err(1, "%s", test_id); 81200483Srwatson 82200483Srwatson success(); 83200483Srwatson} 84200483Srwatson 85200483Srwatsonvoid 86200483Srwatsontest_kevent_socket_clear(void) 87200483Srwatson{ 88200483Srwatson const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; 89200483Srwatson struct kevent kev; 90200483Srwatson 91200483Srwatson test_begin(test_id); 92200483Srwatson 93200483Srwatson test_no_kevents(); 94200483Srwatson 95200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); 96200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 97200483Srwatson err(1, "%s", test_id); 98200483Srwatson 99200483Srwatson kevent_socket_fill(); 100200483Srwatson kevent_socket_fill(); 101200483Srwatson 102200483Srwatson kev.data = 2; 103200483Srwatson kevent_cmp(&kev, kevent_get(kqfd)); 104200483Srwatson 105200483Srwatson /* We filled twice, but drain once. Edge-triggered would not generate 106200483Srwatson additional events. 107200483Srwatson */ 108200483Srwatson kevent_socket_drain(); 109200483Srwatson test_no_kevents(); 110200483Srwatson 111200483Srwatson kevent_socket_drain(); 112200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 113200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 114200483Srwatson err(1, "%s", test_id); 115200483Srwatson 116200483Srwatson success(); 117200483Srwatson} 118200483Srwatson 119200483Srwatsonvoid 120200483Srwatsontest_kevent_socket_disable_and_enable(void) 121200483Srwatson{ 122200483Srwatson const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)"; 123200483Srwatson struct kevent kev; 124200483Srwatson 125200483Srwatson test_begin(test_id); 126200483Srwatson 127200483Srwatson /* Add an event, then disable it. */ 128200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 129200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 130200483Srwatson err(1, "%s", test_id); 131200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); 132200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 133200483Srwatson err(1, "%s", test_id); 134200483Srwatson 135200483Srwatson kevent_socket_fill(); 136200483Srwatson test_no_kevents(); 137200483Srwatson 138200483Srwatson /* Re-enable the knote, then see if an event is generated */ 139200483Srwatson kev.flags = EV_ENABLE; 140200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 141200483Srwatson err(1, "%s", test_id); 142200483Srwatson kev.flags = EV_ADD; 143200483Srwatson kev.data = 1; 144200483Srwatson kevent_cmp(&kev, kevent_get(kqfd)); 145200483Srwatson 146200483Srwatson kevent_socket_drain(); 147200483Srwatson 148200483Srwatson kev.flags = EV_DELETE; 149200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 150200483Srwatson err(1, "%s", test_id); 151200483Srwatson 152200483Srwatson success(); 153200483Srwatson} 154200483Srwatson 155200483Srwatsonvoid 156200483Srwatsontest_kevent_socket_del(void) 157200483Srwatson{ 158200483Srwatson const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; 159200483Srwatson struct kevent kev; 160200483Srwatson 161200483Srwatson test_begin(test_id); 162200483Srwatson 163200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 164200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 165200483Srwatson err(1, "%s", test_id); 166200483Srwatson 167200483Srwatson kevent_socket_fill(); 168200483Srwatson test_no_kevents(); 169200483Srwatson kevent_socket_drain(); 170200483Srwatson 171200483Srwatson success(); 172200483Srwatson} 173200483Srwatson 174200483Srwatsonvoid 175200483Srwatsontest_kevent_socket_oneshot(void) 176200483Srwatson{ 177200483Srwatson const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; 178200483Srwatson struct kevent kev; 179200483Srwatson 180200483Srwatson test_begin(test_id); 181200483Srwatson 182200483Srwatson /* Re-add the watch and make sure no events are pending */ 183200483Srwatson puts("-- re-adding knote"); 184200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); 185200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 186200483Srwatson err(1, "%s", test_id); 187200483Srwatson test_no_kevents(); 188200483Srwatson 189200483Srwatson puts("-- getting one event"); 190200483Srwatson kevent_socket_fill(); 191200483Srwatson kev.data = 1; 192200483Srwatson kevent_cmp(&kev, kevent_get(kqfd)); 193200483Srwatson 194200483Srwatson puts("-- checking knote disabled"); 195200483Srwatson test_no_kevents(); 196200483Srwatson 197200483Srwatson /* Try to delete the knote, it should already be deleted */ 198200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 199200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) 200200483Srwatson err(1, "%s", test_id); 201200483Srwatson 202200483Srwatson kevent_socket_drain(); 203200483Srwatson 204200483Srwatson success(); 205200483Srwatson} 206200483Srwatson 207200483Srwatson 208200483Srwatson#if HAVE_EV_DISPATCH 209200483Srwatsonvoid 210200483Srwatsontest_kevent_socket_dispatch(void) 211200483Srwatson{ 212200483Srwatson const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)"; 213200483Srwatson 214200483Srwatson test_begin(test_id); 215200483Srwatson 216200483Srwatson struct kevent kev; 217200483Srwatson 218200483Srwatson /* Re-add the watch and make sure no events are pending */ 219200483Srwatson puts("-- re-adding knote"); 220200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); 221200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 222200483Srwatson err(1, "%s", test_id); 223200483Srwatson test_no_kevents(); 224200483Srwatson 225200483Srwatson /* The event will occur only once, even though EV_CLEAR is not 226200483Srwatson specified. */ 227200483Srwatson kevent_socket_fill(); 228200483Srwatson kev.data = 1; 229200483Srwatson kevent_cmp(&kev, kevent_get(kqfd)); 230200483Srwatson test_no_kevents(); 231200483Srwatson 232200483Srwatson /* Since the knote is disabled, the EV_DELETE operation succeeds. */ 233200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 234200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 235200483Srwatson err(1, "%s", test_id); 236200483Srwatson 237200483Srwatson kevent_socket_drain(); 238200483Srwatson 239200483Srwatson success(); 240200483Srwatson} 241200483Srwatson#endif /* HAVE_EV_DISPATCH */ 242200483Srwatson 243200483Srwatson#if BROKEN 244200483Srwatsonvoid 245200483Srwatsontest_kevent_socket_lowat(void) 246200483Srwatson{ 247200483Srwatson const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)"; 248200483Srwatson struct kevent kev; 249200483Srwatson 250200483Srwatson test_begin(test_id); 251200483Srwatson 252200483Srwatson /* Re-add the watch and make sure no events are pending */ 253200483Srwatson puts("-- re-adding knote, setting low watermark to 2 bytes"); 254200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); 255200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 256200483Srwatson err(1, "%s", test_id); 257200483Srwatson test_no_kevents(); 258200483Srwatson 259200483Srwatson puts("-- checking that one byte does not trigger an event.."); 260200483Srwatson kevent_socket_fill(); 261200483Srwatson test_no_kevents(); 262200483Srwatson 263200483Srwatson puts("-- checking that two bytes triggers an event.."); 264200483Srwatson kevent_socket_fill(); 265200483Srwatson if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) 266200483Srwatson err(1, "%s", test_id); 267200483Srwatson KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); 268200483Srwatson test_no_kevents(); 269200483Srwatson 270200483Srwatson kevent_socket_drain(); 271200483Srwatson kevent_socket_drain(); 272200483Srwatson 273200483Srwatson success(); 274200483Srwatson} 275200483Srwatson#endif 276200483Srwatson 277200483Srwatsonvoid 278200483Srwatsontest_kevent_socket_eof(void) 279200483Srwatson{ 280200483Srwatson const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; 281200483Srwatson struct kevent kev; 282200483Srwatson 283200483Srwatson test_begin(test_id); 284200483Srwatson 285200483Srwatson /* Re-add the watch and make sure no events are pending */ 286200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 287200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 288200483Srwatson err(1, "%s", test_id); 289200483Srwatson test_no_kevents(); 290200483Srwatson 291200483Srwatson if (close(sockfd[1]) < 0) 292200483Srwatson err(1, "close(2)"); 293200483Srwatson 294200483Srwatson kev.flags |= EV_EOF; 295200483Srwatson kevent_cmp(&kev, kevent_get(kqfd)); 296200483Srwatson 297200483Srwatson /* Delete the watch */ 298200483Srwatson EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 299200483Srwatson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 300200483Srwatson err(1, "%s", test_id); 301200483Srwatson 302200483Srwatson success(); 303200483Srwatson} 304200483Srwatson 305200483Srwatsonvoid 306200483Srwatsontest_evfilt_read() 307200483Srwatson{ 308200483Srwatson /* Create a connected pair of full-duplex sockets for testing socket events */ 309200483Srwatson if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) 310200483Srwatson abort(); 311200483Srwatson 312200483Srwatson kqfd = kqueue(); 313200483Srwatson test_kevent_socket_add(); 314200483Srwatson test_kevent_socket_del(); 315200483Srwatson test_kevent_socket_get(); 316200483Srwatson test_kevent_socket_disable_and_enable(); 317200483Srwatson test_kevent_socket_oneshot(); 318200483Srwatson test_kevent_socket_clear(); 319200483Srwatson#if HAVE_EV_DISPATCH 320200483Srwatson test_kevent_socket_dispatch(); 321200483Srwatson#endif 322200483Srwatson test_kevent_socket_eof(); 323200483Srwatson close(kqfd); 324200483Srwatson} 325