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