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 int kqfd; 22 int sockfd[2]; 23 24 static void 25 kevent_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 35 static void 36 kevent_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 44 void 45 test_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 58 void 59 test_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 85 void 86 test_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 119 void 120 test_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 /* 128 * Write to the socket before adding the event. This way we can verify that 129 * enabling a triggered kevent causes the event to be returned immediately. 130 */ 131 kevent_socket_fill(); 132 133 /* Add a disabled event. */ 134 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISABLE, 0, 0, &sockfd[0]); 135 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 136 err(1, "%s", test_id); 137 138 test_no_kevents(); 139 140 /* Re-enable the knote, then see if an event is generated */ 141 kev.flags = EV_ENABLE; 142 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 143 err(1, "%s", test_id); 144 kev.flags = EV_ADD; 145 kev.data = 1; 146 kevent_cmp(&kev, kevent_get(kqfd)); 147 148 kevent_socket_drain(); 149 150 kev.flags = EV_DELETE; 151 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 152 err(1, "%s", test_id); 153 154 success(); 155 } 156 157 void 158 test_kevent_socket_del(void) 159 { 160 const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; 161 struct kevent kev; 162 163 test_begin(test_id); 164 165 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 166 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 167 err(1, "%s", test_id); 168 169 kevent_socket_fill(); 170 test_no_kevents(); 171 kevent_socket_drain(); 172 173 success(); 174 } 175 176 void 177 test_kevent_socket_oneshot(void) 178 { 179 const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; 180 struct kevent kev; 181 182 test_begin(test_id); 183 184 /* Re-add the watch and make sure no events are pending */ 185 puts("-- re-adding knote"); 186 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); 187 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 188 err(1, "%s", test_id); 189 test_no_kevents(); 190 191 puts("-- getting one event"); 192 kevent_socket_fill(); 193 kev.data = 1; 194 kevent_cmp(&kev, kevent_get(kqfd)); 195 196 puts("-- checking knote disabled"); 197 test_no_kevents(); 198 199 /* Try to delete the knote, it should already be deleted */ 200 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 201 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) 202 err(1, "%s", test_id); 203 204 kevent_socket_drain(); 205 206 success(); 207 } 208 209 210 #if HAVE_EV_DISPATCH 211 void 212 test_kevent_socket_dispatch(void) 213 { 214 const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)"; 215 216 test_begin(test_id); 217 218 struct kevent kev; 219 220 /* Re-add the watch and make sure no events are pending */ 221 puts("-- re-adding knote"); 222 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); 223 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 224 err(1, "%s", test_id); 225 test_no_kevents(); 226 227 /* The event will occur only once, even though EV_CLEAR is not 228 specified. */ 229 kevent_socket_fill(); 230 kev.data = 1; 231 kevent_cmp(&kev, kevent_get(kqfd)); 232 test_no_kevents(); 233 234 /* Since the knote is disabled, the EV_DELETE operation succeeds. */ 235 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 236 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 237 err(1, "%s", test_id); 238 239 kevent_socket_drain(); 240 241 success(); 242 } 243 #endif /* HAVE_EV_DISPATCH */ 244 245 #if BROKEN 246 void 247 test_kevent_socket_lowat(void) 248 { 249 const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)"; 250 struct kevent kev; 251 252 test_begin(test_id); 253 254 /* Re-add the watch and make sure no events are pending */ 255 puts("-- re-adding knote, setting low watermark to 2 bytes"); 256 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); 257 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 258 err(1, "%s", test_id); 259 test_no_kevents(); 260 261 puts("-- checking that one byte does not trigger an event.."); 262 kevent_socket_fill(); 263 test_no_kevents(); 264 265 puts("-- checking that two bytes triggers an event.."); 266 kevent_socket_fill(); 267 if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) 268 err(1, "%s", test_id); 269 KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); 270 test_no_kevents(); 271 272 kevent_socket_drain(); 273 kevent_socket_drain(); 274 275 success(); 276 } 277 #endif 278 279 void 280 test_kevent_socket_eof(void) 281 { 282 const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; 283 struct kevent kev; 284 285 test_begin(test_id); 286 287 /* Re-add the watch and make sure no events are pending */ 288 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); 289 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 290 err(1, "%s", test_id); 291 test_no_kevents(); 292 293 if (close(sockfd[1]) < 0) 294 err(1, "close(2)"); 295 296 kev.flags |= EV_EOF; 297 kevent_cmp(&kev, kevent_get(kqfd)); 298 299 /* Delete the watch */ 300 EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); 301 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 302 err(1, "%s", test_id); 303 304 success(); 305 } 306 307 void 308 test_evfilt_read() 309 { 310 /* Create a connected pair of full-duplex sockets for testing socket events */ 311 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) 312 abort(); 313 314 kqfd = kqueue(); 315 test_kevent_socket_add(); 316 test_kevent_socket_del(); 317 test_kevent_socket_get(); 318 test_kevent_socket_disable_and_enable(); 319 test_kevent_socket_oneshot(); 320 test_kevent_socket_clear(); 321 #if HAVE_EV_DISPATCH 322 test_kevent_socket_dispatch(); 323 #endif 324 test_kevent_socket_eof(); 325 close(kqfd); 326 } 327