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