1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/test/regress_bufferevent.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,843 @@ 1.4 +/* 1.5 + * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 1.6 + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 1.7 + * 1.8 + * Redistribution and use in source and binary forms, with or without 1.9 + * modification, are permitted provided that the following conditions 1.10 + * are met: 1.11 + * 1. Redistributions of source code must retain the above copyright 1.12 + * notice, this list of conditions and the following disclaimer. 1.13 + * 2. Redistributions in binary form must reproduce the above copyright 1.14 + * notice, this list of conditions and the following disclaimer in the 1.15 + * documentation and/or other materials provided with the distribution. 1.16 + * 3. The name of the author may not be used to endorse or promote products 1.17 + * derived from this software without specific prior written permission. 1.18 + * 1.19 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.20 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.21 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.22 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1.23 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1.24 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.25 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.26 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.27 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.28 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.29 + */ 1.30 + 1.31 +/* The old tests here need assertions to work. */ 1.32 +#undef NDEBUG 1.33 + 1.34 +#ifdef WIN32 1.35 +#include <winsock2.h> 1.36 +#include <windows.h> 1.37 +#endif 1.38 + 1.39 +#include "event2/event-config.h" 1.40 + 1.41 +#include <sys/types.h> 1.42 +#include <sys/stat.h> 1.43 +#ifdef _EVENT_HAVE_SYS_TIME_H 1.44 +#include <sys/time.h> 1.45 +#endif 1.46 +#include <sys/queue.h> 1.47 +#ifndef WIN32 1.48 +#include <sys/socket.h> 1.49 +#include <sys/wait.h> 1.50 +#include <signal.h> 1.51 +#include <unistd.h> 1.52 +#include <netdb.h> 1.53 +#include <netinet/in.h> 1.54 +#endif 1.55 +#include <fcntl.h> 1.56 +#include <signal.h> 1.57 +#include <stdlib.h> 1.58 +#include <stdio.h> 1.59 +#include <string.h> 1.60 +#include <errno.h> 1.61 +#include <assert.h> 1.62 + 1.63 +#ifdef _EVENT_HAVE_ARPA_INET_H 1.64 +#include <arpa/inet.h> 1.65 +#endif 1.66 + 1.67 +#include "event2/event-config.h" 1.68 +#include "event2/event.h" 1.69 +#include "event2/event_struct.h" 1.70 +#include "event2/event_compat.h" 1.71 +#include "event2/tag.h" 1.72 +#include "event2/buffer.h" 1.73 +#include "event2/bufferevent.h" 1.74 +#include "event2/bufferevent_compat.h" 1.75 +#include "event2/bufferevent_struct.h" 1.76 +#include "event2/listener.h" 1.77 +#include "event2/util.h" 1.78 + 1.79 +#include "bufferevent-internal.h" 1.80 +#include "util-internal.h" 1.81 +#ifdef WIN32 1.82 +#include "iocp-internal.h" 1.83 +#endif 1.84 + 1.85 +#include "regress.h" 1.86 +#include "regress_testutils.h" 1.87 + 1.88 +/* 1.89 + * simple bufferevent test 1.90 + */ 1.91 + 1.92 +static void 1.93 +readcb(struct bufferevent *bev, void *arg) 1.94 +{ 1.95 + if (evbuffer_get_length(bev->input) == 8333) { 1.96 + struct evbuffer *evbuf = evbuffer_new(); 1.97 + assert(evbuf != NULL); 1.98 + 1.99 + /* gratuitous test of bufferevent_read_buffer */ 1.100 + bufferevent_read_buffer(bev, evbuf); 1.101 + 1.102 + bufferevent_disable(bev, EV_READ); 1.103 + 1.104 + if (evbuffer_get_length(evbuf) == 8333) { 1.105 + test_ok++; 1.106 + } 1.107 + 1.108 + evbuffer_free(evbuf); 1.109 + } 1.110 +} 1.111 + 1.112 +static void 1.113 +writecb(struct bufferevent *bev, void *arg) 1.114 +{ 1.115 + if (evbuffer_get_length(bev->output) == 0) { 1.116 + test_ok++; 1.117 + } 1.118 +} 1.119 + 1.120 +static void 1.121 +errorcb(struct bufferevent *bev, short what, void *arg) 1.122 +{ 1.123 + test_ok = -2; 1.124 +} 1.125 + 1.126 +static void 1.127 +test_bufferevent_impl(int use_pair) 1.128 +{ 1.129 + struct bufferevent *bev1 = NULL, *bev2 = NULL; 1.130 + char buffer[8333]; 1.131 + int i; 1.132 + 1.133 + if (use_pair) { 1.134 + struct bufferevent *pair[2]; 1.135 + tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 1.136 + bev1 = pair[0]; 1.137 + bev2 = pair[1]; 1.138 + bufferevent_setcb(bev1, readcb, writecb, errorcb, NULL); 1.139 + bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL); 1.140 + tt_int_op(bufferevent_getfd(bev1), ==, -1); 1.141 + tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); 1.142 + tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, bev2); 1.143 + tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, bev1); 1.144 + } else { 1.145 + bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL); 1.146 + bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL); 1.147 + tt_int_op(bufferevent_getfd(bev1), ==, pair[0]); 1.148 + tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); 1.149 + tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL); 1.150 + tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL); 1.151 + } 1.152 + 1.153 + bufferevent_disable(bev1, EV_READ); 1.154 + bufferevent_enable(bev2, EV_READ); 1.155 + 1.156 + tt_int_op(bufferevent_get_enabled(bev1), ==, EV_WRITE); 1.157 + tt_int_op(bufferevent_get_enabled(bev2), ==, EV_WRITE|EV_READ); 1.158 + 1.159 + for (i = 0; i < (int)sizeof(buffer); i++) 1.160 + buffer[i] = i; 1.161 + 1.162 + bufferevent_write(bev1, buffer, sizeof(buffer)); 1.163 + 1.164 + event_dispatch(); 1.165 + 1.166 + bufferevent_free(bev1); 1.167 + tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL); 1.168 + bufferevent_free(bev2); 1.169 + 1.170 + if (test_ok != 2) 1.171 + test_ok = 0; 1.172 +end: 1.173 + ; 1.174 +} 1.175 + 1.176 +static void 1.177 +test_bufferevent(void) 1.178 +{ 1.179 + test_bufferevent_impl(0); 1.180 +} 1.181 + 1.182 +static void 1.183 +test_bufferevent_pair(void) 1.184 +{ 1.185 + test_bufferevent_impl(1); 1.186 +} 1.187 + 1.188 +/* 1.189 + * test watermarks and bufferevent 1.190 + */ 1.191 + 1.192 +static void 1.193 +wm_readcb(struct bufferevent *bev, void *arg) 1.194 +{ 1.195 + struct evbuffer *evbuf = evbuffer_new(); 1.196 + int len = (int)evbuffer_get_length(bev->input); 1.197 + static int nread; 1.198 + 1.199 + assert(len >= 10 && len <= 20); 1.200 + 1.201 + assert(evbuf != NULL); 1.202 + 1.203 + /* gratuitous test of bufferevent_read_buffer */ 1.204 + bufferevent_read_buffer(bev, evbuf); 1.205 + 1.206 + nread += len; 1.207 + if (nread == 65000) { 1.208 + bufferevent_disable(bev, EV_READ); 1.209 + test_ok++; 1.210 + } 1.211 + 1.212 + evbuffer_free(evbuf); 1.213 +} 1.214 + 1.215 +static void 1.216 +wm_writecb(struct bufferevent *bev, void *arg) 1.217 +{ 1.218 + assert(evbuffer_get_length(bev->output) <= 100); 1.219 + if (evbuffer_get_length(bev->output) == 0) { 1.220 + evbuffer_drain(bev->output, evbuffer_get_length(bev->output)); 1.221 + test_ok++; 1.222 + } 1.223 +} 1.224 + 1.225 +static void 1.226 +wm_errorcb(struct bufferevent *bev, short what, void *arg) 1.227 +{ 1.228 + test_ok = -2; 1.229 +} 1.230 + 1.231 +static void 1.232 +test_bufferevent_watermarks_impl(int use_pair) 1.233 +{ 1.234 + struct bufferevent *bev1 = NULL, *bev2 = NULL; 1.235 + char buffer[65000]; 1.236 + int i; 1.237 + test_ok = 0; 1.238 + 1.239 + if (use_pair) { 1.240 + struct bufferevent *pair[2]; 1.241 + tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 1.242 + bev1 = pair[0]; 1.243 + bev2 = pair[1]; 1.244 + bufferevent_setcb(bev1, NULL, wm_writecb, errorcb, NULL); 1.245 + bufferevent_setcb(bev2, wm_readcb, NULL, errorcb, NULL); 1.246 + } else { 1.247 + bev1 = bufferevent_new(pair[0], NULL, wm_writecb, wm_errorcb, NULL); 1.248 + bev2 = bufferevent_new(pair[1], wm_readcb, NULL, wm_errorcb, NULL); 1.249 + } 1.250 + tt_assert(bev1); 1.251 + tt_assert(bev2); 1.252 + bufferevent_disable(bev1, EV_READ); 1.253 + bufferevent_enable(bev2, EV_READ); 1.254 + 1.255 + for (i = 0; i < (int)sizeof(buffer); i++) 1.256 + buffer[i] = (char)i; 1.257 + 1.258 + /* limit the reading on the receiving bufferevent */ 1.259 + bufferevent_setwatermark(bev2, EV_READ, 10, 20); 1.260 + 1.261 + /* Tell the sending bufferevent not to notify us till it's down to 1.262 + 100 bytes. */ 1.263 + bufferevent_setwatermark(bev1, EV_WRITE, 100, 2000); 1.264 + 1.265 + bufferevent_write(bev1, buffer, sizeof(buffer)); 1.266 + 1.267 + event_dispatch(); 1.268 + 1.269 + tt_int_op(test_ok, ==, 2); 1.270 + 1.271 + /* The write callback drained all the data from outbuf, so we 1.272 + * should have removed the write event... */ 1.273 + tt_assert(!event_pending(&bev2->ev_write, EV_WRITE, NULL)); 1.274 + 1.275 +end: 1.276 + if (bev1) 1.277 + bufferevent_free(bev1); 1.278 + if (bev2) 1.279 + bufferevent_free(bev2); 1.280 +} 1.281 + 1.282 +static void 1.283 +test_bufferevent_watermarks(void) 1.284 +{ 1.285 + test_bufferevent_watermarks_impl(0); 1.286 +} 1.287 + 1.288 +static void 1.289 +test_bufferevent_pair_watermarks(void) 1.290 +{ 1.291 + test_bufferevent_watermarks_impl(1); 1.292 +} 1.293 + 1.294 +/* 1.295 + * Test bufferevent filters 1.296 + */ 1.297 + 1.298 +/* strip an 'x' from each byte */ 1.299 + 1.300 +static enum bufferevent_filter_result 1.301 +bufferevent_input_filter(struct evbuffer *src, struct evbuffer *dst, 1.302 + ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 1.303 +{ 1.304 + const unsigned char *buffer; 1.305 + unsigned i; 1.306 + 1.307 + buffer = evbuffer_pullup(src, evbuffer_get_length(src)); 1.308 + for (i = 0; i < evbuffer_get_length(src); i += 2) { 1.309 + assert(buffer[i] == 'x'); 1.310 + evbuffer_add(dst, buffer + i + 1, 1); 1.311 + 1.312 + if (i + 2 > evbuffer_get_length(src)) 1.313 + break; 1.314 + } 1.315 + 1.316 + evbuffer_drain(src, i); 1.317 + return (BEV_OK); 1.318 +} 1.319 + 1.320 +/* add an 'x' before each byte */ 1.321 + 1.322 +static enum bufferevent_filter_result 1.323 +bufferevent_output_filter(struct evbuffer *src, struct evbuffer *dst, 1.324 + ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 1.325 +{ 1.326 + const unsigned char *buffer; 1.327 + unsigned i; 1.328 + 1.329 + buffer = evbuffer_pullup(src, evbuffer_get_length(src)); 1.330 + for (i = 0; i < evbuffer_get_length(src); ++i) { 1.331 + evbuffer_add(dst, "x", 1); 1.332 + evbuffer_add(dst, buffer + i, 1); 1.333 + } 1.334 + 1.335 + evbuffer_drain(src, evbuffer_get_length(src)); 1.336 + return (BEV_OK); 1.337 +} 1.338 + 1.339 +static void 1.340 +test_bufferevent_filters_impl(int use_pair) 1.341 +{ 1.342 + struct bufferevent *bev1 = NULL, *bev2 = NULL; 1.343 + struct bufferevent *bev1_base = NULL, *bev2_base = NULL; 1.344 + char buffer[8333]; 1.345 + int i; 1.346 + 1.347 + test_ok = 0; 1.348 + 1.349 + if (use_pair) { 1.350 + struct bufferevent *pair[2]; 1.351 + tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 1.352 + bev1 = pair[0]; 1.353 + bev2 = pair[1]; 1.354 + } else { 1.355 + bev1 = bufferevent_socket_new(NULL, pair[0], 0); 1.356 + bev2 = bufferevent_socket_new(NULL, pair[1], 0); 1.357 + } 1.358 + bev1_base = bev1; 1.359 + bev2_base = bev2; 1.360 + 1.361 + for (i = 0; i < (int)sizeof(buffer); i++) 1.362 + buffer[i] = i; 1.363 + 1.364 + bev1 = bufferevent_filter_new(bev1, NULL, bufferevent_output_filter, 1.365 + BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 1.366 + 1.367 + bev2 = bufferevent_filter_new(bev2, bufferevent_input_filter, 1.368 + NULL, BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 1.369 + bufferevent_setcb(bev1, NULL, writecb, errorcb, NULL); 1.370 + bufferevent_setcb(bev2, readcb, NULL, errorcb, NULL); 1.371 + 1.372 + tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev1_base); 1.373 + tt_ptr_op(bufferevent_get_underlying(bev2), ==, bev2_base); 1.374 + tt_int_op(bufferevent_getfd(bev1), ==, -1); 1.375 + tt_int_op(bufferevent_getfd(bev2), ==, -1); 1.376 + 1.377 + bufferevent_disable(bev1, EV_READ); 1.378 + bufferevent_enable(bev2, EV_READ); 1.379 + /* insert some filters */ 1.380 + bufferevent_write(bev1, buffer, sizeof(buffer)); 1.381 + 1.382 + event_dispatch(); 1.383 + 1.384 + if (test_ok != 2) 1.385 + test_ok = 0; 1.386 + 1.387 +end: 1.388 + if (bev1) 1.389 + bufferevent_free(bev1); 1.390 + if (bev2) 1.391 + bufferevent_free(bev2); 1.392 + 1.393 +} 1.394 + 1.395 +static void 1.396 +test_bufferevent_filters(void) 1.397 +{ 1.398 + test_bufferevent_filters_impl(0); 1.399 +} 1.400 + 1.401 +static void 1.402 +test_bufferevent_pair_filters(void) 1.403 +{ 1.404 + test_bufferevent_filters_impl(1); 1.405 +} 1.406 + 1.407 + 1.408 +static void 1.409 +sender_writecb(struct bufferevent *bev, void *ctx) 1.410 +{ 1.411 + if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) { 1.412 + bufferevent_disable(bev,EV_READ|EV_WRITE); 1.413 + bufferevent_free(bev); 1.414 + } 1.415 +} 1.416 + 1.417 +static void 1.418 +sender_errorcb(struct bufferevent *bev, short what, void *ctx) 1.419 +{ 1.420 + TT_FAIL(("Got sender error %d",(int)what)); 1.421 +} 1.422 + 1.423 +static int bufferevent_connect_test_flags = 0; 1.424 +static int n_strings_read = 0; 1.425 +static int n_reads_invoked = 0; 1.426 + 1.427 +#define TEST_STR "Now is the time for all good events to signal for " \ 1.428 + "the good of their protocol" 1.429 +static void 1.430 +listen_cb(struct evconnlistener *listener, evutil_socket_t fd, 1.431 + struct sockaddr *sa, int socklen, void *arg) 1.432 +{ 1.433 + struct event_base *base = arg; 1.434 + struct bufferevent *bev; 1.435 + const char s[] = TEST_STR; 1.436 + TT_BLATHER(("Got a request on socket %d", (int)fd )); 1.437 + bev = bufferevent_socket_new(base, fd, bufferevent_connect_test_flags); 1.438 + tt_assert(bev); 1.439 + bufferevent_setcb(bev, NULL, sender_writecb, sender_errorcb, NULL); 1.440 + bufferevent_write(bev, s, sizeof(s)); 1.441 +end: 1.442 + ; 1.443 +} 1.444 + 1.445 +static void 1.446 +reader_eventcb(struct bufferevent *bev, short what, void *ctx) 1.447 +{ 1.448 + struct event_base *base = ctx; 1.449 + if (what & BEV_EVENT_ERROR) { 1.450 + perror("foobar"); 1.451 + TT_FAIL(("got connector error %d", (int)what)); 1.452 + return; 1.453 + } 1.454 + if (what & BEV_EVENT_CONNECTED) { 1.455 + bufferevent_enable(bev, EV_READ); 1.456 + } 1.457 + if (what & BEV_EVENT_EOF) { 1.458 + char buf[512]; 1.459 + size_t n; 1.460 + n = bufferevent_read(bev, buf, sizeof(buf)-1); 1.461 + buf[n] = '\0'; 1.462 + tt_str_op(buf, ==, TEST_STR); 1.463 + if (++n_strings_read == 2) 1.464 + event_base_loopexit(base, NULL); 1.465 + } 1.466 +end: 1.467 + ; 1.468 +} 1.469 + 1.470 +static void 1.471 +reader_readcb(struct bufferevent *bev, void *ctx) 1.472 +{ 1.473 + n_reads_invoked++; 1.474 +} 1.475 + 1.476 +static void 1.477 +test_bufferevent_connect(void *arg) 1.478 +{ 1.479 + struct basic_test_data *data = arg; 1.480 + struct evconnlistener *lev=NULL; 1.481 + struct bufferevent *bev1=NULL, *bev2=NULL; 1.482 + struct sockaddr_in localhost; 1.483 + struct sockaddr_storage ss; 1.484 + struct sockaddr *sa; 1.485 + ev_socklen_t slen; 1.486 + 1.487 + int be_flags=BEV_OPT_CLOSE_ON_FREE; 1.488 + 1.489 + if (strstr((char*)data->setup_data, "defer")) { 1.490 + be_flags |= BEV_OPT_DEFER_CALLBACKS; 1.491 + } 1.492 + if (strstr((char*)data->setup_data, "unlocked")) { 1.493 + be_flags |= BEV_OPT_UNLOCK_CALLBACKS; 1.494 + } 1.495 + if (strstr((char*)data->setup_data, "lock")) { 1.496 + be_flags |= BEV_OPT_THREADSAFE; 1.497 + } 1.498 + bufferevent_connect_test_flags = be_flags; 1.499 +#ifdef WIN32 1.500 + if (!strcmp((char*)data->setup_data, "unset_connectex")) { 1.501 + struct win32_extension_fns *ext = 1.502 + (struct win32_extension_fns *) 1.503 + event_get_win32_extension_fns(); 1.504 + ext->ConnectEx = NULL; 1.505 + } 1.506 +#endif 1.507 + 1.508 + memset(&localhost, 0, sizeof(localhost)); 1.509 + 1.510 + localhost.sin_port = 0; /* pick-a-port */ 1.511 + localhost.sin_addr.s_addr = htonl(0x7f000001L); 1.512 + localhost.sin_family = AF_INET; 1.513 + sa = (struct sockaddr *)&localhost; 1.514 + lev = evconnlistener_new_bind(data->base, listen_cb, data->base, 1.515 + LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 1.516 + 16, sa, sizeof(localhost)); 1.517 + tt_assert(lev); 1.518 + 1.519 + sa = (struct sockaddr *)&ss; 1.520 + slen = sizeof(ss); 1.521 + if (regress_get_listener_addr(lev, sa, &slen) < 0) { 1.522 + tt_abort_perror("getsockname"); 1.523 + } 1.524 + 1.525 + tt_assert(!evconnlistener_enable(lev)); 1.526 + bev1 = bufferevent_socket_new(data->base, -1, be_flags); 1.527 + bev2 = bufferevent_socket_new(data->base, -1, be_flags); 1.528 + tt_assert(bev1); 1.529 + tt_assert(bev2); 1.530 + bufferevent_setcb(bev1, reader_readcb,NULL, reader_eventcb, data->base); 1.531 + bufferevent_setcb(bev2, reader_readcb,NULL, reader_eventcb, data->base); 1.532 + 1.533 + bufferevent_enable(bev1, EV_READ); 1.534 + bufferevent_enable(bev2, EV_READ); 1.535 + 1.536 + tt_want(!bufferevent_socket_connect(bev1, sa, sizeof(localhost))); 1.537 + tt_want(!bufferevent_socket_connect(bev2, sa, sizeof(localhost))); 1.538 + 1.539 + event_base_dispatch(data->base); 1.540 + 1.541 + tt_int_op(n_strings_read, ==, 2); 1.542 + tt_int_op(n_reads_invoked, >=, 2); 1.543 +end: 1.544 + if (lev) 1.545 + evconnlistener_free(lev); 1.546 + 1.547 + if (bev1) 1.548 + bufferevent_free(bev1); 1.549 + 1.550 + if (bev2) 1.551 + bufferevent_free(bev2); 1.552 +} 1.553 + 1.554 +static void 1.555 +want_fail_eventcb(struct bufferevent *bev, short what, void *ctx) 1.556 +{ 1.557 + struct event_base *base = ctx; 1.558 + const char *err; 1.559 + evutil_socket_t s; 1.560 + 1.561 + if (what & BEV_EVENT_ERROR) { 1.562 + s = bufferevent_getfd(bev); 1.563 + err = evutil_socket_error_to_string(evutil_socket_geterror(s)); 1.564 + TT_BLATHER(("connection failure on "EV_SOCK_FMT": %s", 1.565 + EV_SOCK_ARG(s), err)); 1.566 + test_ok = 1; 1.567 + } else { 1.568 + TT_FAIL(("didn't fail? what %hd", what)); 1.569 + } 1.570 + 1.571 + event_base_loopexit(base, NULL); 1.572 +} 1.573 + 1.574 +static void 1.575 +close_socket_cb(evutil_socket_t fd, short what, void *arg) 1.576 +{ 1.577 + evutil_socket_t *fdp = arg; 1.578 + if (*fdp >= 0) { 1.579 + evutil_closesocket(*fdp); 1.580 + *fdp = -1; 1.581 + } 1.582 +} 1.583 + 1.584 +static void 1.585 +test_bufferevent_connect_fail(void *arg) 1.586 +{ 1.587 + struct basic_test_data *data = arg; 1.588 + struct bufferevent *bev=NULL; 1.589 + struct sockaddr_in localhost; 1.590 + struct sockaddr *sa = (struct sockaddr*)&localhost; 1.591 + evutil_socket_t fake_listener = -1; 1.592 + ev_socklen_t slen = sizeof(localhost); 1.593 + struct event close_listener_event; 1.594 + int close_listener_event_added = 0; 1.595 + struct timeval one_second = { 1, 0 }; 1.596 + int r; 1.597 + 1.598 + test_ok = 0; 1.599 + 1.600 + memset(&localhost, 0, sizeof(localhost)); 1.601 + localhost.sin_port = 0; /* have the kernel pick a port */ 1.602 + localhost.sin_addr.s_addr = htonl(0x7f000001L); 1.603 + localhost.sin_family = AF_INET; 1.604 + 1.605 + /* bind, but don't listen or accept. should trigger 1.606 + "Connection refused" reliably on most platforms. */ 1.607 + fake_listener = socket(localhost.sin_family, SOCK_STREAM, 0); 1.608 + tt_assert(fake_listener >= 0); 1.609 + tt_assert(bind(fake_listener, sa, slen) == 0); 1.610 + tt_assert(getsockname(fake_listener, sa, &slen) == 0); 1.611 + bev = bufferevent_socket_new(data->base, -1, 1.612 + BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); 1.613 + tt_assert(bev); 1.614 + bufferevent_setcb(bev, NULL, NULL, want_fail_eventcb, data->base); 1.615 + 1.616 + r = bufferevent_socket_connect(bev, sa, slen); 1.617 + /* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells 1.618 + * detects the error immediately, which is not really wrong of it. */ 1.619 + tt_want(r == 0 || r == -1); 1.620 + 1.621 + /* Close the listener socket after a second. This should trigger 1.622 + "connection refused" on some other platforms, including OSX. */ 1.623 + evtimer_assign(&close_listener_event, data->base, close_socket_cb, 1.624 + &fake_listener); 1.625 + event_add(&close_listener_event, &one_second); 1.626 + close_listener_event_added = 1; 1.627 + 1.628 + event_base_dispatch(data->base); 1.629 + 1.630 + tt_int_op(test_ok, ==, 1); 1.631 + 1.632 +end: 1.633 + if (fake_listener >= 0) 1.634 + evutil_closesocket(fake_listener); 1.635 + 1.636 + if (bev) 1.637 + bufferevent_free(bev); 1.638 + 1.639 + if (close_listener_event_added) 1.640 + event_del(&close_listener_event); 1.641 +} 1.642 + 1.643 +struct timeout_cb_result { 1.644 + struct timeval read_timeout_at; 1.645 + struct timeval write_timeout_at; 1.646 + struct timeval last_wrote_at; 1.647 + int n_read_timeouts; 1.648 + int n_write_timeouts; 1.649 + int total_calls; 1.650 +}; 1.651 + 1.652 +static void 1.653 +bev_timeout_write_cb(struct bufferevent *bev, void *arg) 1.654 +{ 1.655 + struct timeout_cb_result *res = arg; 1.656 + evutil_gettimeofday(&res->last_wrote_at, NULL); 1.657 +} 1.658 + 1.659 +static void 1.660 +bev_timeout_event_cb(struct bufferevent *bev, short what, void *arg) 1.661 +{ 1.662 + struct timeout_cb_result *res = arg; 1.663 + ++res->total_calls; 1.664 + 1.665 + if ((what & (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) 1.666 + == (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) { 1.667 + evutil_gettimeofday(&res->read_timeout_at, NULL); 1.668 + ++res->n_read_timeouts; 1.669 + } 1.670 + if ((what & (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) 1.671 + == (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) { 1.672 + evutil_gettimeofday(&res->write_timeout_at, NULL); 1.673 + ++res->n_write_timeouts; 1.674 + } 1.675 +} 1.676 + 1.677 +static void 1.678 +test_bufferevent_timeouts(void *arg) 1.679 +{ 1.680 + /* "arg" is a string containing "pair" and/or "filter". */ 1.681 + struct bufferevent *bev1 = NULL, *bev2 = NULL; 1.682 + struct basic_test_data *data = arg; 1.683 + int use_pair = 0, use_filter = 0; 1.684 + struct timeval tv_w, tv_r, started_at; 1.685 + struct timeout_cb_result res1, res2; 1.686 + char buf[1024]; 1.687 + 1.688 + memset(&res1, 0, sizeof(res1)); 1.689 + memset(&res2, 0, sizeof(res2)); 1.690 + 1.691 + if (strstr((char*)data->setup_data, "pair")) 1.692 + use_pair = 1; 1.693 + if (strstr((char*)data->setup_data, "filter")) 1.694 + use_filter = 1; 1.695 + 1.696 + if (use_pair) { 1.697 + struct bufferevent *p[2]; 1.698 + tt_int_op(0, ==, bufferevent_pair_new(data->base, 0, p)); 1.699 + bev1 = p[0]; 1.700 + bev2 = p[1]; 1.701 + } else { 1.702 + bev1 = bufferevent_socket_new(data->base, data->pair[0], 0); 1.703 + bev2 = bufferevent_socket_new(data->base, data->pair[1], 0); 1.704 + } 1.705 + 1.706 + tt_assert(bev1); 1.707 + tt_assert(bev2); 1.708 + 1.709 + if (use_filter) { 1.710 + struct bufferevent *bevf1, *bevf2; 1.711 + bevf1 = bufferevent_filter_new(bev1, NULL, NULL, 1.712 + BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 1.713 + bevf2 = bufferevent_filter_new(bev2, NULL, NULL, 1.714 + BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 1.715 + tt_assert(bevf1); 1.716 + tt_assert(bevf2); 1.717 + bev1 = bevf1; 1.718 + bev2 = bevf2; 1.719 + } 1.720 + 1.721 + /* Do this nice and early. */ 1.722 + bufferevent_disable(bev2, EV_READ); 1.723 + 1.724 + /* bev1 will try to write and read. Both will time out. */ 1.725 + evutil_gettimeofday(&started_at, NULL); 1.726 + tv_w.tv_sec = tv_r.tv_sec = 0; 1.727 + tv_w.tv_usec = 100*1000; 1.728 + tv_r.tv_usec = 150*1000; 1.729 + bufferevent_setcb(bev1, NULL, bev_timeout_write_cb, 1.730 + bev_timeout_event_cb, &res1); 1.731 + bufferevent_setwatermark(bev1, EV_WRITE, 1024*1024+10, 0); 1.732 + bufferevent_set_timeouts(bev1, &tv_r, &tv_w); 1.733 + if (use_pair) { 1.734 + /* For a pair, the fact that the other side isn't reading 1.735 + * makes the writer stall */ 1.736 + bufferevent_write(bev1, "ABCDEFG", 7); 1.737 + } else { 1.738 + /* For a real socket, the kernel's TCP buffers can eat a 1.739 + * fair number of bytes; make sure that at some point we 1.740 + * have some bytes that will stall. */ 1.741 + struct evbuffer *output = bufferevent_get_output(bev1); 1.742 + int i; 1.743 + memset(buf, 0xbb, sizeof(buf)); 1.744 + for (i=0;i<1024;++i) { 1.745 + evbuffer_add_reference(output, buf, sizeof(buf), 1.746 + NULL, NULL); 1.747 + } 1.748 + } 1.749 + bufferevent_enable(bev1, EV_READ|EV_WRITE); 1.750 + 1.751 + /* bev2 has nothing to say, and isn't listening. */ 1.752 + bufferevent_setcb(bev2, NULL, bev_timeout_write_cb, 1.753 + bev_timeout_event_cb, &res2); 1.754 + tv_w.tv_sec = tv_r.tv_sec = 0; 1.755 + tv_w.tv_usec = 200*1000; 1.756 + tv_r.tv_usec = 100*1000; 1.757 + bufferevent_set_timeouts(bev2, &tv_r, &tv_w); 1.758 + bufferevent_enable(bev2, EV_WRITE); 1.759 + 1.760 + tv_r.tv_sec = 1; 1.761 + tv_r.tv_usec = 0; 1.762 + 1.763 + event_base_loopexit(data->base, &tv_r); 1.764 + event_base_dispatch(data->base); 1.765 + 1.766 + /* XXXX Test that actually reading or writing a little resets the 1.767 + * timeouts. */ 1.768 + 1.769 + /* Each buf1 timeout happens, and happens only once. */ 1.770 + tt_want(res1.n_read_timeouts); 1.771 + tt_want(res1.n_write_timeouts); 1.772 + tt_want(res1.n_read_timeouts == 1); 1.773 + tt_want(res1.n_write_timeouts == 1); 1.774 + 1.775 + test_timeval_diff_eq(&started_at, &res1.read_timeout_at, 150); 1.776 + test_timeval_diff_eq(&started_at, &res1.write_timeout_at, 100); 1.777 + 1.778 +end: 1.779 + if (bev1) 1.780 + bufferevent_free(bev1); 1.781 + if (bev2) 1.782 + bufferevent_free(bev2); 1.783 +} 1.784 + 1.785 +struct testcase_t bufferevent_testcases[] = { 1.786 + 1.787 + LEGACY(bufferevent, TT_ISOLATED), 1.788 + LEGACY(bufferevent_pair, TT_ISOLATED), 1.789 + LEGACY(bufferevent_watermarks, TT_ISOLATED), 1.790 + LEGACY(bufferevent_pair_watermarks, TT_ISOLATED), 1.791 + LEGACY(bufferevent_filters, TT_ISOLATED), 1.792 + LEGACY(bufferevent_pair_filters, TT_ISOLATED), 1.793 + { "bufferevent_connect", test_bufferevent_connect, TT_FORK|TT_NEED_BASE, 1.794 + &basic_setup, (void*)"" }, 1.795 + { "bufferevent_connect_defer", test_bufferevent_connect, 1.796 + TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"defer" }, 1.797 + { "bufferevent_connect_lock", test_bufferevent_connect, 1.798 + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, (void*)"lock" }, 1.799 + { "bufferevent_connect_lock_defer", test_bufferevent_connect, 1.800 + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1.801 + (void*)"defer lock" }, 1.802 + { "bufferevent_connect_unlocked_cbs", test_bufferevent_connect, 1.803 + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1.804 + (void*)"lock defer unlocked" }, 1.805 + { "bufferevent_connect_fail", test_bufferevent_connect_fail, 1.806 + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1.807 + { "bufferevent_timeout", test_bufferevent_timeouts, 1.808 + TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, (void*)"" }, 1.809 + { "bufferevent_timeout_pair", test_bufferevent_timeouts, 1.810 + TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"pair" }, 1.811 + { "bufferevent_timeout_filter", test_bufferevent_timeouts, 1.812 + TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter" }, 1.813 + { "bufferevent_timeout_filter_pair", test_bufferevent_timeouts, 1.814 + TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter pair" }, 1.815 +#ifdef _EVENT_HAVE_LIBZ 1.816 + LEGACY(bufferevent_zlib, TT_ISOLATED), 1.817 +#else 1.818 + { "bufferevent_zlib", NULL, TT_SKIP, NULL, NULL }, 1.819 +#endif 1.820 + 1.821 + END_OF_TESTCASES, 1.822 +}; 1.823 + 1.824 +struct testcase_t bufferevent_iocp_testcases[] = { 1.825 + 1.826 + LEGACY(bufferevent, TT_ISOLATED|TT_ENABLE_IOCP), 1.827 + LEGACY(bufferevent_watermarks, TT_ISOLATED|TT_ENABLE_IOCP), 1.828 + LEGACY(bufferevent_filters, TT_ISOLATED|TT_ENABLE_IOCP), 1.829 + { "bufferevent_connect", test_bufferevent_connect, 1.830 + TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"" }, 1.831 + { "bufferevent_connect_defer", test_bufferevent_connect, 1.832 + TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"defer" }, 1.833 + { "bufferevent_connect_lock", test_bufferevent_connect, 1.834 + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup, 1.835 + (void*)"lock" }, 1.836 + { "bufferevent_connect_lock_defer", test_bufferevent_connect, 1.837 + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup, 1.838 + (void*)"defer lock" }, 1.839 + { "bufferevent_connect_fail", test_bufferevent_connect_fail, 1.840 + TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL }, 1.841 + { "bufferevent_connect_nonblocking", test_bufferevent_connect, 1.842 + TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, 1.843 + (void*)"unset_connectex" }, 1.844 + 1.845 + END_OF_TESTCASES, 1.846 +};