1/* 2 * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 3 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28/* The old tests here need assertions to work. */ 29#undef NDEBUG 30 31#ifdef WIN32 32#include <winsock2.h> 33#include <windows.h> 34#endif 35 36#include "event2/event-config.h" 37 38#include <sys/types.h> 39#include <sys/stat.h> 40#ifdef _EVENT_HAVE_SYS_TIME_H 41#include <sys/time.h> 42#endif 43#include <sys/queue.h> 44#ifndef WIN32 45#include <sys/socket.h> 46#include <sys/wait.h> 47#include <signal.h> 48#include <unistd.h> 49#include <netdb.h> 50#include <netinet/in.h> 51#endif 52#include <fcntl.h> 53#include <signal.h> 54#include <stdlib.h> 55#include <stdio.h> 56#include <string.h> 57#include <errno.h> 58#include <assert.h> 59 60#ifdef _EVENT_HAVE_ARPA_INET_H 61#include <arpa/inet.h> 62#endif 63 64#include "event2/event-config.h" 65#include "event2/event.h" 66#include "event2/event_struct.h" 67#include "event2/event_compat.h" 68#include "event2/tag.h" 69#include "event2/buffer.h" 70#include "event2/bufferevent.h" 71#include "event2/bufferevent_compat.h" 72#include "event2/bufferevent_struct.h" 73#include "event2/listener.h" 74#include "event2/util.h" 75 76#include "bufferevent-internal.h" 77#ifdef WIN32 78#include "iocp-internal.h" 79#endif 80 81#include "regress.h" 82#include "regress_testutils.h" 83 84/* 85 * simple bufferevent test 86 */ 87 88static void 89readcb(struct bufferevent *bev, void *arg) 90{ 91 if (evbuffer_get_length(bev->input) == 8333) { 92 struct evbuffer *evbuf = evbuffer_new(); 93 assert(evbuf != NULL); 94 95 /* gratuitous test of bufferevent_read_buffer */ 96 bufferevent_read_buffer(bev, evbuf); 97 98 bufferevent_disable(bev, EV_READ); 99 100 if (evbuffer_get_length(evbuf) == 8333) { 101 test_ok++; 102 } 103 104 evbuffer_free(evbuf); 105 } 106} 107 108static void 109writecb(struct bufferevent *bev, void *arg) 110{ 111 if (evbuffer_get_length(bev->output) == 0) { 112 test_ok++; 113 } 114} 115 116static void 117errorcb(struct bufferevent *bev, short what, void *arg) 118{ 119 test_ok = -2; 120} 121 122static void 123test_bufferevent_impl(int use_pair) 124{ 125 struct bufferevent *bev1 = NULL, *bev2 = NULL; 126 char buffer[8333]; 127 int i; 128 129 if (use_pair) { 130 struct bufferevent *pair[2]; 131 tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 132 bev1 = pair[0]; 133 bev2 = pair[1]; 134 bufferevent_setcb(bev1, readcb, writecb, errorcb, NULL); 135 bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL); 136 tt_int_op(bufferevent_getfd(bev1), ==, -1); 137 tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); 138 tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, bev2); 139 tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, bev1); 140 } else { 141 bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL); 142 bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL); 143 tt_int_op(bufferevent_getfd(bev1), ==, pair[0]); 144 tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); 145 tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL); 146 tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL); 147 } 148 149 bufferevent_disable(bev1, EV_READ); 150 bufferevent_enable(bev2, EV_READ); 151 152 tt_int_op(bufferevent_get_enabled(bev1), ==, EV_WRITE); 153 tt_int_op(bufferevent_get_enabled(bev2), ==, EV_WRITE|EV_READ); 154 155 for (i = 0; i < (int)sizeof(buffer); i++) 156 buffer[i] = i; 157 158 bufferevent_write(bev1, buffer, sizeof(buffer)); 159 160 event_dispatch(); 161 162 bufferevent_free(bev1); 163 tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL); 164 bufferevent_free(bev2); 165 166 if (test_ok != 2) 167 test_ok = 0; 168end: 169 ; 170} 171 172static void 173test_bufferevent(void) 174{ 175 test_bufferevent_impl(0); 176} 177 178static void 179test_bufferevent_pair(void) 180{ 181 test_bufferevent_impl(1); 182} 183 184/* 185 * test watermarks and bufferevent 186 */ 187 188static void 189wm_readcb(struct bufferevent *bev, void *arg) 190{ 191 struct evbuffer *evbuf = evbuffer_new(); 192 int len = (int)evbuffer_get_length(bev->input); 193 static int nread; 194 195 assert(len >= 10 && len <= 20); 196 197 assert(evbuf != NULL); 198 199 /* gratuitous test of bufferevent_read_buffer */ 200 bufferevent_read_buffer(bev, evbuf); 201 202 nread += len; 203 if (nread == 65000) { 204 bufferevent_disable(bev, EV_READ); 205 test_ok++; 206 } 207 208 evbuffer_free(evbuf); 209} 210 211static void 212wm_writecb(struct bufferevent *bev, void *arg) 213{ 214 assert(evbuffer_get_length(bev->output) <= 100); 215 if (evbuffer_get_length(bev->output) == 0) { 216 evbuffer_drain(bev->output, evbuffer_get_length(bev->output)); 217 test_ok++; 218 } 219} 220 221static void 222wm_errorcb(struct bufferevent *bev, short what, void *arg) 223{ 224 test_ok = -2; 225} 226 227static void 228test_bufferevent_watermarks_impl(int use_pair) 229{ 230 struct bufferevent *bev1 = NULL, *bev2 = NULL; 231 char buffer[65000]; 232 int i; 233 test_ok = 0; 234 235 if (use_pair) { 236 struct bufferevent *pair[2]; 237 tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 238 bev1 = pair[0]; 239 bev2 = pair[1]; 240 bufferevent_setcb(bev1, NULL, wm_writecb, errorcb, NULL); 241 bufferevent_setcb(bev2, wm_readcb, NULL, errorcb, NULL); 242 } else { 243 bev1 = bufferevent_new(pair[0], NULL, wm_writecb, wm_errorcb, NULL); 244 bev2 = bufferevent_new(pair[1], wm_readcb, NULL, wm_errorcb, NULL); 245 } 246 tt_assert(bev1); 247 tt_assert(bev2); 248 bufferevent_disable(bev1, EV_READ); 249 bufferevent_enable(bev2, EV_READ); 250 251 for (i = 0; i < (int)sizeof(buffer); i++) 252 buffer[i] = (char)i; 253 254 /* limit the reading on the receiving bufferevent */ 255 bufferevent_setwatermark(bev2, EV_READ, 10, 20); 256 257 /* Tell the sending bufferevent not to notify us till it's down to 258 100 bytes. */ 259 bufferevent_setwatermark(bev1, EV_WRITE, 100, 2000); 260 261 bufferevent_write(bev1, buffer, sizeof(buffer)); 262 263 event_dispatch(); 264 265 tt_int_op(test_ok, ==, 2); 266 267 /* The write callback drained all the data from outbuf, so we 268 * should have removed the write event... */ 269 tt_assert(!event_pending(&bev2->ev_write, EV_WRITE, NULL)); 270 271end: 272 if (bev1) 273 bufferevent_free(bev1); 274 if (bev2) 275 bufferevent_free(bev2); 276} 277 278static void 279test_bufferevent_watermarks(void) 280{ 281 test_bufferevent_watermarks_impl(0); 282} 283 284static void 285test_bufferevent_pair_watermarks(void) 286{ 287 test_bufferevent_watermarks_impl(1); 288} 289 290/* 291 * Test bufferevent filters 292 */ 293 294/* strip an 'x' from each byte */ 295 296static enum bufferevent_filter_result 297bufferevent_input_filter(struct evbuffer *src, struct evbuffer *dst, 298 ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 299{ 300 const unsigned char *buffer; 301 unsigned i; 302 303 buffer = evbuffer_pullup(src, evbuffer_get_length(src)); 304 for (i = 0; i < evbuffer_get_length(src); i += 2) { 305 assert(buffer[i] == 'x'); 306 evbuffer_add(dst, buffer + i + 1, 1); 307 308 if (i + 2 > evbuffer_get_length(src)) 309 break; 310 } 311 312 evbuffer_drain(src, i); 313 return (BEV_OK); 314} 315 316/* add an 'x' before each byte */ 317 318static enum bufferevent_filter_result 319bufferevent_output_filter(struct evbuffer *src, struct evbuffer *dst, 320 ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 321{ 322 const unsigned char *buffer; 323 unsigned i; 324 325 buffer = evbuffer_pullup(src, evbuffer_get_length(src)); 326 for (i = 0; i < evbuffer_get_length(src); ++i) { 327 evbuffer_add(dst, "x", 1); 328 evbuffer_add(dst, buffer + i, 1); 329 } 330 331 evbuffer_drain(src, evbuffer_get_length(src)); 332 return (BEV_OK); 333} 334 335static void 336test_bufferevent_filters_impl(int use_pair) 337{ 338 struct bufferevent *bev1 = NULL, *bev2 = NULL; 339 struct bufferevent *bev1_base = NULL, *bev2_base = NULL; 340 char buffer[8333]; 341 int i; 342 343 test_ok = 0; 344 345 if (use_pair) { 346 struct bufferevent *pair[2]; 347 tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 348 bev1 = pair[0]; 349 bev2 = pair[1]; 350 } else { 351 bev1 = bufferevent_socket_new(NULL, pair[0], 0); 352 bev2 = bufferevent_socket_new(NULL, pair[1], 0); 353 } 354 bev1_base = bev1; 355 bev2_base = bev2; 356 357 for (i = 0; i < (int)sizeof(buffer); i++) 358 buffer[i] = i; 359 360 bev1 = bufferevent_filter_new(bev1, NULL, bufferevent_output_filter, 361 BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 362 363 bev2 = bufferevent_filter_new(bev2, bufferevent_input_filter, 364 NULL, BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 365 bufferevent_setcb(bev1, NULL, writecb, errorcb, NULL); 366 bufferevent_setcb(bev2, readcb, NULL, errorcb, NULL); 367 368 tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev1_base); 369 tt_ptr_op(bufferevent_get_underlying(bev2), ==, bev2_base); 370 tt_int_op(bufferevent_getfd(bev1), ==, -1); 371 tt_int_op(bufferevent_getfd(bev2), ==, -1); 372 373 bufferevent_disable(bev1, EV_READ); 374 bufferevent_enable(bev2, EV_READ); 375 /* insert some filters */ 376 bufferevent_write(bev1, buffer, sizeof(buffer)); 377 378 event_dispatch(); 379 380 if (test_ok != 2) 381 test_ok = 0; 382 383end: 384 if (bev1) 385 bufferevent_free(bev1); 386 if (bev2) 387 bufferevent_free(bev2); 388 389} 390 391static void 392test_bufferevent_filters(void) 393{ 394 test_bufferevent_filters_impl(0); 395} 396 397static void 398test_bufferevent_pair_filters(void) 399{ 400 test_bufferevent_filters_impl(1); 401} 402 403 404static void 405sender_writecb(struct bufferevent *bev, void *ctx) 406{ 407 if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) { 408 bufferevent_disable(bev,EV_READ|EV_WRITE); 409 bufferevent_free(bev); 410 } 411} 412 413static void 414sender_errorcb(struct bufferevent *bev, short what, void *ctx) 415{ 416 TT_FAIL(("Got sender error %d",(int)what)); 417} 418 419static int bufferevent_connect_test_flags = 0; 420static int n_strings_read = 0; 421static int n_reads_invoked = 0; 422 423#define TEST_STR "Now is the time for all good events to signal for " \ 424 "the good of their protocol" 425static void 426listen_cb(struct evconnlistener *listener, evutil_socket_t fd, 427 struct sockaddr *sa, int socklen, void *arg) 428{ 429 struct event_base *base = arg; 430 struct bufferevent *bev; 431 const char s[] = TEST_STR; 432 TT_BLATHER(("Got a request on socket %d", (int)fd )); 433 bev = bufferevent_socket_new(base, fd, bufferevent_connect_test_flags); 434 tt_assert(bev); 435 bufferevent_setcb(bev, NULL, sender_writecb, sender_errorcb, NULL); 436 bufferevent_write(bev, s, sizeof(s)); 437end: 438 ; 439} 440 441static void 442reader_eventcb(struct bufferevent *bev, short what, void *ctx) 443{ 444 struct event_base *base = ctx; 445 if (what & BEV_EVENT_ERROR) { 446 perror("foobar"); 447 TT_FAIL(("got connector error %d", (int)what)); 448 return; 449 } 450 if (what & BEV_EVENT_CONNECTED) { 451 bufferevent_enable(bev, EV_READ); 452 } 453 if (what & BEV_EVENT_EOF) { 454 char buf[512]; 455 size_t n; 456 n = bufferevent_read(bev, buf, sizeof(buf)-1); 457 buf[n] = '\0'; 458 tt_str_op(buf, ==, TEST_STR); 459 if (++n_strings_read == 2) 460 event_base_loopexit(base, NULL); 461 } 462end: 463 ; 464} 465 466static void 467reader_readcb(struct bufferevent *bev, void *ctx) 468{ 469 n_reads_invoked++; 470} 471 472static void 473test_bufferevent_connect(void *arg) 474{ 475 struct basic_test_data *data = arg; 476 struct evconnlistener *lev=NULL; 477 struct bufferevent *bev1=NULL, *bev2=NULL; 478 struct sockaddr_in localhost; 479 struct sockaddr_storage ss; 480 struct sockaddr *sa; 481 ev_socklen_t slen; 482 483 int be_flags=BEV_OPT_CLOSE_ON_FREE; 484 485 if (strstr((char*)data->setup_data, "defer")) { 486 be_flags |= BEV_OPT_DEFER_CALLBACKS; 487 } 488 if (strstr((char*)data->setup_data, "unlocked")) { 489 be_flags |= BEV_OPT_UNLOCK_CALLBACKS; 490 } 491 if (strstr((char*)data->setup_data, "lock")) { 492 be_flags |= BEV_OPT_THREADSAFE; 493 } 494 bufferevent_connect_test_flags = be_flags; 495#ifdef WIN32 496 if (!strcmp((char*)data->setup_data, "unset_connectex")) { 497 struct win32_extension_fns *ext = 498 (struct win32_extension_fns *) 499 event_get_win32_extension_fns(); 500 ext->ConnectEx = NULL; 501 } 502#endif 503 504 memset(&localhost, 0, sizeof(localhost)); 505 506 localhost.sin_port = 0; /* pick-a-port */ 507 localhost.sin_addr.s_addr = htonl(0x7f000001L); 508 localhost.sin_family = AF_INET; 509 sa = (struct sockaddr *)&localhost; 510 lev = evconnlistener_new_bind(data->base, listen_cb, data->base, 511 LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 512 16, sa, sizeof(localhost)); 513 tt_assert(lev); 514 515 sa = (struct sockaddr *)&ss; 516 slen = sizeof(ss); 517 if (regress_get_listener_addr(lev, sa, &slen) < 0) { 518 tt_abort_perror("getsockname"); 519 } 520 521 tt_assert(!evconnlistener_enable(lev)); 522 bev1 = bufferevent_socket_new(data->base, -1, be_flags); 523 bev2 = bufferevent_socket_new(data->base, -1, be_flags); 524 tt_assert(bev1); 525 tt_assert(bev2); 526 bufferevent_setcb(bev1, reader_readcb,NULL, reader_eventcb, data->base); 527 bufferevent_setcb(bev2, reader_readcb,NULL, reader_eventcb, data->base); 528 529 bufferevent_enable(bev1, EV_READ); 530 bufferevent_enable(bev2, EV_READ); 531 532 tt_want(!bufferevent_socket_connect(bev1, sa, sizeof(localhost))); 533 tt_want(!bufferevent_socket_connect(bev2, sa, sizeof(localhost))); 534 535 event_base_dispatch(data->base); 536 537 tt_int_op(n_strings_read, ==, 2); 538 tt_int_op(n_reads_invoked, >=, 2); 539end: 540 if (lev) 541 evconnlistener_free(lev); 542 543 if (bev1) 544 bufferevent_free(bev1); 545 546 if (bev2) 547 bufferevent_free(bev2); 548} 549 550static void 551want_fail_eventcb(struct bufferevent *bev, short what, void *ctx) 552{ 553 struct event_base *base = ctx; 554 const char *err; 555 evutil_socket_t s; 556 557 if (what & BEV_EVENT_ERROR) { 558 s = bufferevent_getfd(bev); 559 err = evutil_socket_error_to_string(evutil_socket_geterror(s)); 560 TT_BLATHER(("connection failure on %d: %s", s, err)); 561 test_ok = 1; 562 } else { 563 TT_FAIL(("didn't fail? what %hd", what)); 564 } 565 566 event_base_loopexit(base, NULL); 567} 568 569static void 570close_socket_cb(evutil_socket_t fd, short what, void *arg) 571{ 572 evutil_socket_t *fdp = arg; 573 if (*fdp >= 0) { 574 evutil_closesocket(*fdp); 575 *fdp = -1; 576 } 577} 578 579static void 580test_bufferevent_connect_fail(void *arg) 581{ 582 struct basic_test_data *data = arg; 583 struct bufferevent *bev=NULL; 584 struct sockaddr_in localhost; 585 struct sockaddr *sa = (struct sockaddr*)&localhost; 586 evutil_socket_t fake_listener = -1; 587 ev_socklen_t slen = sizeof(localhost); 588 struct event close_listener_event; 589 int close_listener_event_added = 0; 590 struct timeval one_second = { 1, 0 }; 591 int r; 592 593 test_ok = 0; 594 595 memset(&localhost, 0, sizeof(localhost)); 596 localhost.sin_port = 0; /* have the kernel pick a port */ 597 localhost.sin_addr.s_addr = htonl(0x7f000001L); 598 localhost.sin_family = AF_INET; 599 600 /* bind, but don't listen or accept. should trigger 601 "Connection refused" reliably on most platforms. */ 602 fake_listener = socket(localhost.sin_family, SOCK_STREAM, 0); 603 tt_assert(fake_listener >= 0); 604 tt_assert(bind(fake_listener, sa, slen) == 0); 605 tt_assert(getsockname(fake_listener, sa, &slen) == 0); 606 bev = bufferevent_socket_new(data->base, -1, 607 BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); 608 tt_assert(bev); 609 bufferevent_setcb(bev, NULL, NULL, want_fail_eventcb, data->base); 610 611 r = bufferevent_socket_connect(bev, sa, slen); 612 /* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells 613 * detects the error immediately, which is not really wrong of it. */ 614 tt_want(r == 0 || r == -1); 615 616 /* Close the listener socket after a second. This should trigger 617 "connection refused" on some other platforms, including OSX. */ 618 evtimer_assign(&close_listener_event, data->base, close_socket_cb, 619 &fake_listener); 620 event_add(&close_listener_event, &one_second); 621 close_listener_event_added = 1; 622 623 event_base_dispatch(data->base); 624 625 tt_int_op(test_ok, ==, 1); 626 627end: 628 if (fake_listener >= 0) 629 evutil_closesocket(fake_listener); 630 631 if (bev) 632 bufferevent_free(bev); 633 634 if (close_listener_event_added) 635 event_del(&close_listener_event); 636} 637 638struct timeout_cb_result { 639 struct timeval read_timeout_at; 640 struct timeval write_timeout_at; 641 struct timeval last_wrote_at; 642 int n_read_timeouts; 643 int n_write_timeouts; 644 int total_calls; 645}; 646 647static void 648bev_timeout_write_cb(struct bufferevent *bev, void *arg) 649{ 650 struct timeout_cb_result *res = arg; 651 evutil_gettimeofday(&res->last_wrote_at, NULL); 652} 653 654static void 655bev_timeout_event_cb(struct bufferevent *bev, short what, void *arg) 656{ 657 struct timeout_cb_result *res = arg; 658 ++res->total_calls; 659 660 if ((what & (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) 661 == (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) { 662 evutil_gettimeofday(&res->read_timeout_at, NULL); 663 ++res->n_read_timeouts; 664 } 665 if ((what & (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) 666 == (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) { 667 evutil_gettimeofday(&res->write_timeout_at, NULL); 668 ++res->n_write_timeouts; 669 } 670} 671 672static void 673test_bufferevent_timeouts(void *arg) 674{ 675 /* "arg" is a string containing "pair" and/or "filter". */ 676 struct bufferevent *bev1 = NULL, *bev2 = NULL; 677 struct basic_test_data *data = arg; 678 int use_pair = 0, use_filter = 0; 679 struct timeval tv_w, tv_r, started_at; 680 struct timeout_cb_result res1, res2; 681 char buf[1024]; 682 683 memset(&res1, 0, sizeof(res1)); 684 memset(&res2, 0, sizeof(res2)); 685 686 if (strstr((char*)data->setup_data, "pair")) 687 use_pair = 1; 688 if (strstr((char*)data->setup_data, "filter")) 689 use_filter = 1; 690 691 if (use_pair) { 692 struct bufferevent *p[2]; 693 tt_int_op(0, ==, bufferevent_pair_new(data->base, 0, p)); 694 bev1 = p[0]; 695 bev2 = p[1]; 696 } else { 697 bev1 = bufferevent_socket_new(data->base, data->pair[0], 0); 698 bev2 = bufferevent_socket_new(data->base, data->pair[1], 0); 699 } 700 701 tt_assert(bev1); 702 tt_assert(bev2); 703 704 if (use_filter) { 705 struct bufferevent *bevf1, *bevf2; 706 bevf1 = bufferevent_filter_new(bev1, NULL, NULL, 707 BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 708 bevf2 = bufferevent_filter_new(bev2, NULL, NULL, 709 BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 710 tt_assert(bevf1); 711 tt_assert(bevf2); 712 bev1 = bevf1; 713 bev2 = bevf2; 714 } 715 716 /* Do this nice and early. */ 717 bufferevent_disable(bev2, EV_READ); 718 719 /* bev1 will try to write and read. Both will time out. */ 720 evutil_gettimeofday(&started_at, NULL); 721 tv_w.tv_sec = tv_r.tv_sec = 0; 722 tv_w.tv_usec = 100*1000; 723 tv_r.tv_usec = 150*1000; 724 bufferevent_setcb(bev1, NULL, bev_timeout_write_cb, 725 bev_timeout_event_cb, &res1); 726 bufferevent_setwatermark(bev1, EV_WRITE, 1024*1024+10, 0); 727 bufferevent_set_timeouts(bev1, &tv_r, &tv_w); 728 if (use_pair) { 729 /* For a pair, the fact that the other side isn't reading 730 * makes the writer stall */ 731 bufferevent_write(bev1, "ABCDEFG", 7); 732 } else { 733 /* For a real socket, the kernel's TCP buffers can eat a 734 * fair number of bytes; make sure that at some point we 735 * have some bytes that will stall. */ 736 struct evbuffer *output = bufferevent_get_output(bev1); 737 int i; 738 memset(buf, 0xbb, sizeof(buf)); 739 for (i=0;i<1024;++i) { 740 evbuffer_add_reference(output, buf, sizeof(buf), 741 NULL, NULL); 742 } 743 } 744 bufferevent_enable(bev1, EV_READ|EV_WRITE); 745 746 /* bev2 has nothing to say, and isn't listening. */ 747 bufferevent_setcb(bev2, NULL, bev_timeout_write_cb, 748 bev_timeout_event_cb, &res2); 749 tv_w.tv_sec = tv_r.tv_sec = 0; 750 tv_w.tv_usec = 200*1000; 751 tv_r.tv_usec = 100*1000; 752 bufferevent_set_timeouts(bev2, &tv_r, &tv_w); 753 bufferevent_enable(bev2, EV_WRITE); 754 755 tv_r.tv_sec = 1; 756 tv_r.tv_usec = 0; 757 758 event_base_loopexit(data->base, &tv_r); 759 event_base_dispatch(data->base); 760 761 /* XXXX Test that actually reading or writing a little resets the 762 * timeouts. */ 763 764 /* Each buf1 timeout happens, and happens only once. */ 765 tt_want(res1.n_read_timeouts); 766 tt_want(res1.n_write_timeouts); 767 tt_want(res1.n_read_timeouts == 1); 768 tt_want(res1.n_write_timeouts == 1); 769 770 test_timeval_diff_eq(&started_at, &res1.read_timeout_at, 150); 771 test_timeval_diff_eq(&started_at, &res1.write_timeout_at, 100); 772 773end: 774 if (bev1) 775 bufferevent_free(bev1); 776 if (bev2) 777 bufferevent_free(bev2); 778} 779 780struct testcase_t bufferevent_testcases[] = { 781 782 LEGACY(bufferevent, TT_ISOLATED), 783 LEGACY(bufferevent_pair, TT_ISOLATED), 784 LEGACY(bufferevent_watermarks, TT_ISOLATED), 785 LEGACY(bufferevent_pair_watermarks, TT_ISOLATED), 786 LEGACY(bufferevent_filters, TT_ISOLATED), 787 LEGACY(bufferevent_pair_filters, TT_ISOLATED), 788 { "bufferevent_connect", test_bufferevent_connect, TT_FORK|TT_NEED_BASE, 789 &basic_setup, (void*)"" }, 790 { "bufferevent_connect_defer", test_bufferevent_connect, 791 TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"defer" }, 792 { "bufferevent_connect_lock", test_bufferevent_connect, 793 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, (void*)"lock" }, 794 { "bufferevent_connect_lock_defer", test_bufferevent_connect, 795 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 796 (void*)"defer lock" }, 797 { "bufferevent_connect_unlocked_cbs", test_bufferevent_connect, 798 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 799 (void*)"lock defer unlocked" }, 800 { "bufferevent_connect_fail", test_bufferevent_connect_fail, 801 TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 802 { "bufferevent_timeout", test_bufferevent_timeouts, 803 TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, (void*)"" }, 804 { "bufferevent_timeout_pair", test_bufferevent_timeouts, 805 TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"pair" }, 806 { "bufferevent_timeout_filter", test_bufferevent_timeouts, 807 TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter" }, 808 { "bufferevent_timeout_filter_pair", test_bufferevent_timeouts, 809 TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter pair" }, 810#ifdef _EVENT_HAVE_LIBZ 811 LEGACY(bufferevent_zlib, TT_ISOLATED), 812#else 813 { "bufferevent_zlib", NULL, TT_SKIP, NULL, NULL }, 814#endif 815 816 END_OF_TESTCASES, 817}; 818 819struct testcase_t bufferevent_iocp_testcases[] = { 820 821 LEGACY(bufferevent, TT_ISOLATED|TT_ENABLE_IOCP), 822 LEGACY(bufferevent_watermarks, TT_ISOLATED|TT_ENABLE_IOCP), 823 LEGACY(bufferevent_filters, TT_ISOLATED|TT_ENABLE_IOCP), 824 { "bufferevent_connect", test_bufferevent_connect, 825 TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"" }, 826 { "bufferevent_connect_defer", test_bufferevent_connect, 827 TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"defer" }, 828 { "bufferevent_connect_lock", test_bufferevent_connect, 829 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup, 830 (void*)"lock" }, 831 { "bufferevent_connect_lock_defer", test_bufferevent_connect, 832 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup, 833 (void*)"defer lock" }, 834 { "bufferevent_connect_fail", test_bufferevent_connect_fail, 835 TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL }, 836 { "bufferevent_connect_nonblocking", test_bufferevent_connect, 837 TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, 838 (void*)"unset_connectex" }, 839 840 END_OF_TESTCASES, 841}; 842