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