regress_bufferevent.c revision 282408
1184251Smarcel/* 2184251Smarcel * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 3184251Smarcel * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 4184251Smarcel * 5184251Smarcel * Redistribution and use in source and binary forms, with or without 6184251Smarcel * modification, are permitted provided that the following conditions 7184251Smarcel * are met: 8184251Smarcel * 1. Redistributions of source code must retain the above copyright 9184251Smarcel * notice, this list of conditions and the following disclaimer. 10184251Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11184251Smarcel * notice, this list of conditions and the following disclaimer in the 12184251Smarcel * documentation and/or other materials provided with the distribution. 13184251Smarcel * 3. The name of the author may not be used to endorse or promote products 14184251Smarcel * derived from this software without specific prior written permission. 15184251Smarcel * 16184251Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17184251Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18184251Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19184251Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20184251Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21184251Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22184251Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23184251Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24184251Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25184251Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26184251Smarcel */ 27184251Smarcel#include "util-internal.h" 28184251Smarcel 29184251Smarcel/* The old tests here need assertions to work. */ 30184251Smarcel#undef NDEBUG 31184251Smarcel 32184251Smarcel#ifdef _WIN32 33188156Ssam#include <winsock2.h> 34188156Ssam#include <windows.h> 35184251Smarcel#endif 36184251Smarcel 37184251Smarcel#include "event2/event-config.h" 38184251Smarcel 39184251Smarcel#include <sys/types.h> 40184251Smarcel#include <sys/stat.h> 41184251Smarcel#ifdef EVENT__HAVE_SYS_TIME_H 42184251Smarcel#include <sys/time.h> 43184251Smarcel#endif 44184251Smarcel#include <sys/queue.h> 45184251Smarcel#ifndef _WIN32 46184251Smarcel#include <sys/socket.h> 47184251Smarcel#include <sys/wait.h> 48184251Smarcel#include <signal.h> 49184251Smarcel#include <unistd.h> 50184251Smarcel#include <netdb.h> 51184251Smarcel#include <netinet/in.h> 52184251Smarcel#endif 53184251Smarcel#include <fcntl.h> 54184251Smarcel#include <signal.h> 55184251Smarcel#include <stdlib.h> 56184251Smarcel#include <stdio.h> 57184251Smarcel#include <string.h> 58184251Smarcel#include <errno.h> 59184251Smarcel#include <assert.h> 60184251Smarcel 61184251Smarcel#ifdef EVENT__HAVE_ARPA_INET_H 62184251Smarcel#include <arpa/inet.h> 63184251Smarcel#endif 64184251Smarcel 65184251Smarcel#include "event2/event-config.h" 66184251Smarcel#include "event2/event.h" 67184251Smarcel#include "event2/event_struct.h" 68184251Smarcel#include "event2/event_compat.h" 69184251Smarcel#include "event2/tag.h" 70184251Smarcel#include "event2/buffer.h" 71184251Smarcel#include "event2/bufferevent.h" 72184251Smarcel#include "event2/bufferevent_compat.h" 73184251Smarcel#include "event2/bufferevent_struct.h" 74184251Smarcel#include "event2/listener.h" 75184251Smarcel#include "event2/util.h" 76184251Smarcel 77184251Smarcel#include "bufferevent-internal.h" 78184251Smarcel#include "evthread-internal.h" 79184251Smarcel#include "util-internal.h" 80184251Smarcel#ifdef _WIN32 81184251Smarcel#include "iocp-internal.h" 82184251Smarcel#endif 83184251Smarcel 84184251Smarcel#include "regress.h" 85184251Smarcel#include "regress_testutils.h" 86184251Smarcel 87184251Smarcel/* 88184251Smarcel * simple bufferevent test 89184251Smarcel */ 90184251Smarcel 91184251Smarcelstatic void 92184251Smarcelreadcb(struct bufferevent *bev, void *arg) 93184251Smarcel{ 94184251Smarcel if (evbuffer_get_length(bev->input) == 8333) { 95184251Smarcel struct evbuffer *evbuf = evbuffer_new(); 96184251Smarcel assert(evbuf != NULL); 97184251Smarcel 98184251Smarcel /* gratuitous test of bufferevent_read_buffer */ 99184251Smarcel bufferevent_read_buffer(bev, evbuf); 100184251Smarcel 101184251Smarcel bufferevent_disable(bev, EV_READ); 102184251Smarcel 103184251Smarcel if (evbuffer_get_length(evbuf) == 8333) { 104184251Smarcel test_ok++; 105184251Smarcel } 106184251Smarcel 107184251Smarcel evbuffer_free(evbuf); 108184251Smarcel } 109184251Smarcel} 110184251Smarcel 111184251Smarcelstatic void 112184251Smarcelwritecb(struct bufferevent *bev, void *arg) 113184251Smarcel{ 114184251Smarcel if (evbuffer_get_length(bev->output) == 0) { 115184251Smarcel test_ok++; 116184251Smarcel } 117184251Smarcel} 118184251Smarcel 119184251Smarcelstatic void 120184251Smarcelerrorcb(struct bufferevent *bev, short what, void *arg) 121184251Smarcel{ 122184251Smarcel test_ok = -2; 123184251Smarcel} 124184251Smarcel 125184251Smarcelstatic void 126184251Smarceltest_bufferevent_impl(int use_pair) 127184251Smarcel{ 128184251Smarcel struct bufferevent *bev1 = NULL, *bev2 = NULL; 129184251Smarcel char buffer[8333]; 130184251Smarcel int i; 131184251Smarcel 132184251Smarcel if (use_pair) { 133184251Smarcel struct bufferevent *pair[2]; 134184251Smarcel tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 135184251Smarcel bev1 = pair[0]; 136184251Smarcel bev2 = pair[1]; 137184251Smarcel bufferevent_setcb(bev1, readcb, writecb, errorcb, bev1); 138184251Smarcel bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL); 139184251Smarcel tt_int_op(bufferevent_getfd(bev1), ==, -1); 140184251Smarcel tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); 141184251Smarcel tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, bev2); 142184251Smarcel tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, bev1); 143184251Smarcel } else { 144184251Smarcel bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL); 145184251Smarcel bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL); 146184251Smarcel tt_int_op(bufferevent_getfd(bev1), ==, pair[0]); 147184251Smarcel tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); 148184251Smarcel tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL); 149184251Smarcel tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL); 150184251Smarcel } 151184251Smarcel 152184251Smarcel { 153184251Smarcel /* Test getcb. */ 154188087Ssam bufferevent_data_cb r, w; 155188087Ssam bufferevent_event_cb e; 156188087Ssam void *a; 157188087Ssam bufferevent_getcb(bev1, &r, &w, &e, &a); 158188087Ssam tt_ptr_op(r, ==, readcb); 159188087Ssam tt_ptr_op(w, ==, writecb); 160188087Ssam tt_ptr_op(e, ==, errorcb); 161188087Ssam tt_ptr_op(a, ==, use_pair ? bev1 : NULL); 162188087Ssam } 163188087Ssam 164184251Smarcel bufferevent_disable(bev1, EV_READ); 165184251Smarcel bufferevent_enable(bev2, EV_READ); 166184251Smarcel 167184251Smarcel tt_int_op(bufferevent_get_enabled(bev1), ==, EV_WRITE); 168184251Smarcel tt_int_op(bufferevent_get_enabled(bev2), ==, EV_WRITE|EV_READ); 169184251Smarcel 170184251Smarcel for (i = 0; i < (int)sizeof(buffer); i++) 171184251Smarcel buffer[i] = i; 172184251Smarcel 173184251Smarcel bufferevent_write(bev1, buffer, sizeof(buffer)); 174184251Smarcel 175184251Smarcel event_dispatch(); 176184251Smarcel 177184251Smarcel bufferevent_free(bev2); 178184251Smarcel tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL); 179184251Smarcel bufferevent_free(bev1); 180184251Smarcel 181184251Smarcel if (test_ok != 2) 182184251Smarcel test_ok = 0; 183184251Smarcelend: 184184251Smarcel ; 185184251Smarcel} 186184251Smarcel 187184251Smarcelstatic void 188184251Smarceltest_bufferevent(void) 189184251Smarcel{ 190184251Smarcel test_bufferevent_impl(0); 191184251Smarcel} 192184251Smarcel 193184251Smarcelstatic void 194184251Smarceltest_bufferevent_pair(void) 195184251Smarcel{ 196184251Smarcel test_bufferevent_impl(1); 197184251Smarcel} 198184251Smarcel 199184251Smarcel#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) 200184251Smarcel/** 201184251Smarcel * Trace lock/unlock/alloc/free for locks. 202184251Smarcel * (More heavier then evthread_debug*) 203184251Smarcel */ 204184251Smarceltypedef struct 205184251Smarcel{ 206184251Smarcel void *lock; 207184251Smarcel enum { 208184251Smarcel ALLOC, FREE, 209184251Smarcel } status; 210184251Smarcel size_t locked /** allow recursive locking */; 211184251Smarcel} lock_wrapper; 212184251Smarcelstruct lock_unlock_base 213184251Smarcel{ 214184251Smarcel /* Original callbacks */ 215184251Smarcel struct evthread_lock_callbacks cbs; 216184251Smarcel /* Map of locks */ 217184251Smarcel lock_wrapper *locks; 218184251Smarcel size_t nr_locks; 219184251Smarcel} lu_base = { 220184251Smarcel .locks = NULL, 221184251Smarcel}; 222184251Smarcel 223184251Smarcelstatic lock_wrapper *lu_find(void *lock_) 224184251Smarcel{ 225184251Smarcel size_t i; 226184251Smarcel for (i = 0; i < lu_base.nr_locks; ++i) { 227184251Smarcel lock_wrapper *lock = &lu_base.locks[i]; 228184251Smarcel if (lock->lock == lock_) 229184251Smarcel return lock; 230184251Smarcel } 231184251Smarcel return NULL; 232184251Smarcel} 233184251Smarcel 234184251Smarcelstatic void *trace_lock_alloc(unsigned locktype) 235184251Smarcel{ 236184251Smarcel ++lu_base.nr_locks; 237184251Smarcel lu_base.locks = realloc(lu_base.locks, 238184251Smarcel sizeof(lock_wrapper) * lu_base.nr_locks); 239184251Smarcel void *lock = lu_base.cbs.alloc(locktype); 240184251Smarcel lu_base.locks[lu_base.nr_locks - 1] = (lock_wrapper){ lock, ALLOC, 0 }; 241184251Smarcel return lock; 242184251Smarcel} 243184251Smarcelstatic void trace_lock_free(void *lock_, unsigned locktype) 244184251Smarcel{ 245184251Smarcel lock_wrapper *lock = lu_find(lock_); 246184251Smarcel if (!lock || lock->status == FREE || lock->locked) { 247184251Smarcel __asm__("int3"); 248184251Smarcel TT_FAIL(("lock: free error")); 249184251Smarcel } else { 250184251Smarcel lock->status = FREE; 251184251Smarcel lu_base.cbs.free(lock_, locktype); 252184251Smarcel } 253184251Smarcel} 254184251Smarcelstatic int trace_lock_lock(unsigned mode, void *lock_) 255184251Smarcel{ 256184251Smarcel lock_wrapper *lock = lu_find(lock_); 257184251Smarcel if (!lock || lock->status == FREE) { 258184251Smarcel TT_FAIL(("lock: lock error")); 259184251Smarcel return -1; 260184251Smarcel } else { 261184251Smarcel ++lock->locked; 262184251Smarcel return lu_base.cbs.lock(mode, lock_); 263184251Smarcel } 264184251Smarcel} 265184251Smarcelstatic int trace_lock_unlock(unsigned mode, void *lock_) 266184251Smarcel{ 267184251Smarcel lock_wrapper *lock = lu_find(lock_); 268184251Smarcel if (!lock || lock->status == FREE || !lock->locked) { 269184251Smarcel TT_FAIL(("lock: unlock error")); 270184251Smarcel return -1; 271184251Smarcel } else { 272184251Smarcel --lock->locked; 273184251Smarcel return lu_base.cbs.unlock(mode, lock_); 274184251Smarcel } 275184251Smarcel} 276184251Smarcelstatic void lock_unlock_free_thread_cbs() 277184251Smarcel{ 278184251Smarcel event_base_free(NULL); 279184251Smarcel 280184251Smarcel /** drop immutable flag */ 281184251Smarcel evthread_set_lock_callbacks(NULL); 282184251Smarcel /** avoid calling of event_global_setup_locks_() for new cbs */ 283184251Smarcel libevent_global_shutdown(); 284184251Smarcel /** drop immutable flag for non-debug ops (since called after shutdown) */ 285184251Smarcel evthread_set_lock_callbacks(NULL); 286184251Smarcel} 287184251Smarcel 288184251Smarcelstatic int use_lock_unlock_profiler(void) 289184251Smarcel{ 290184251Smarcel struct evthread_lock_callbacks cbs = { 291184251Smarcel EVTHREAD_LOCK_API_VERSION, 292184251Smarcel EVTHREAD_LOCKTYPE_RECURSIVE, 293184251Smarcel trace_lock_alloc, 294184251Smarcel trace_lock_free, 295184251Smarcel trace_lock_lock, 296184251Smarcel trace_lock_unlock, 297184251Smarcel }; 298184251Smarcel memcpy(&lu_base.cbs, evthread_get_lock_callbacks(), 299184251Smarcel sizeof(lu_base.cbs)); 300184251Smarcel { 301184251Smarcel lock_unlock_free_thread_cbs(); 302184251Smarcel 303184251Smarcel evthread_set_lock_callbacks(&cbs); 304188156Ssam /** re-create debug locks correctly */ 305184251Smarcel evthread_enable_lock_debugging(); 306184251Smarcel 307188156Ssam event_init(); 308184251Smarcel } 309184251Smarcel return 0; 310184251Smarcel} 311184251Smarcelstatic void free_lock_unlock_profiler(struct basic_test_data *data) 312184251Smarcel{ 313184251Smarcel lock_unlock_free_thread_cbs(); 314184251Smarcel free(lu_base.locks); 315184251Smarcel data->base = NULL; 316184251Smarcel} 317184251Smarcel 318184251Smarcelstatic void test_bufferevent_pair_release_lock(void *arg) 319188156Ssam{ 320188156Ssam struct basic_test_data *data = arg; 321184251Smarcel use_lock_unlock_profiler(); 322188156Ssam { 323188156Ssam struct bufferevent *pair[2]; 324188156Ssam if (!bufferevent_pair_new(NULL, BEV_OPT_THREADSAFE, pair)) { 325188156Ssam bufferevent_free(pair[0]); 326188156Ssam bufferevent_free(pair[1]); 327184251Smarcel } else 328188156Ssam tt_abort_perror("bufferevent_pair_new"); 329184251Smarcel } 330188156Ssam free_lock_unlock_profiler(data); 331184251Smarcelend: 332188156Ssam ; 333188156Ssam} 334184251Smarcel#endif 335184251Smarcel 336184251Smarcel/* 337184251Smarcel * test watermarks and bufferevent 338188156Ssam */ 339188156Ssam 340184251Smarcelstatic void 341184251Smarcelwm_readcb(struct bufferevent *bev, void *arg) 342184251Smarcel{ 343184251Smarcel struct evbuffer *evbuf = evbuffer_new(); 344184251Smarcel int len = (int)evbuffer_get_length(bev->input); 345184251Smarcel static int nread; 346184251Smarcel 347188156Ssam assert(len >= 10 && len <= 20); 348184251Smarcel 349184251Smarcel assert(evbuf != NULL); 350184251Smarcel 351184251Smarcel /* gratuitous test of bufferevent_read_buffer */ 352184251Smarcel bufferevent_read_buffer(bev, evbuf); 353184251Smarcel 354184251Smarcel nread += len; 355184251Smarcel if (nread == 65000) { 356184251Smarcel bufferevent_disable(bev, EV_READ); 357184251Smarcel test_ok++; 358184251Smarcel } 359184251Smarcel 360184251Smarcel evbuffer_free(evbuf); 361184251Smarcel} 362184251Smarcel 363184251Smarcelstatic void 364184251Smarcelwm_writecb(struct bufferevent *bev, void *arg) 365184251Smarcel{ 366184251Smarcel assert(evbuffer_get_length(bev->output) <= 100); 367184251Smarcel if (evbuffer_get_length(bev->output) == 0) { 368184251Smarcel evbuffer_drain(bev->output, evbuffer_get_length(bev->output)); 369184251Smarcel test_ok++; 370184251Smarcel } 371184251Smarcel} 372184251Smarcel 373184251Smarcelstatic void 374184251Smarcelwm_errorcb(struct bufferevent *bev, short what, void *arg) 375184251Smarcel{ 376184251Smarcel test_ok = -2; 377184251Smarcel} 378184251Smarcel 379188156Ssamstatic void 380184251Smarceltest_bufferevent_watermarks_impl(int use_pair) 381184251Smarcel{ 382184251Smarcel struct bufferevent *bev1 = NULL, *bev2 = NULL; 383184251Smarcel char buffer[65000]; 384184251Smarcel size_t low, high; 385184251Smarcel int i; 386184251Smarcel test_ok = 0; 387184251Smarcel 388184251Smarcel if (use_pair) { 389184251Smarcel struct bufferevent *pair[2]; 390184251Smarcel tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 391184251Smarcel bev1 = pair[0]; 392184251Smarcel bev2 = pair[1]; 393184251Smarcel bufferevent_setcb(bev1, NULL, wm_writecb, errorcb, NULL); 394184251Smarcel bufferevent_setcb(bev2, wm_readcb, NULL, errorcb, NULL); 395184251Smarcel } else { 396184251Smarcel bev1 = bufferevent_new(pair[0], NULL, wm_writecb, wm_errorcb, NULL); 397184251Smarcel bev2 = bufferevent_new(pair[1], wm_readcb, NULL, wm_errorcb, NULL); 398184251Smarcel } 399184251Smarcel tt_assert(bev1); 400184251Smarcel tt_assert(bev2); 401184251Smarcel bufferevent_disable(bev1, EV_READ); 402184251Smarcel bufferevent_enable(bev2, EV_READ); 403184251Smarcel 404184251Smarcel /* By default, low watermarks are set to 0 */ 405184251Smarcel bufferevent_getwatermark(bev1, EV_READ, &low, NULL); 406184251Smarcel tt_int_op(low, ==, 0); 407184251Smarcel bufferevent_getwatermark(bev2, EV_WRITE, &low, NULL); 408184251Smarcel tt_int_op(low, ==, 0); 409184251Smarcel 410184251Smarcel for (i = 0; i < (int)sizeof(buffer); i++) 411184251Smarcel buffer[i] = (char)i; 412184251Smarcel 413184251Smarcel /* limit the reading on the receiving bufferevent */ 414184251Smarcel bufferevent_setwatermark(bev2, EV_READ, 10, 20); 415184251Smarcel 416184251Smarcel bufferevent_getwatermark(bev2, EV_READ, &low, &high); 417184251Smarcel tt_int_op(low, ==, 10); 418184251Smarcel tt_int_op(high, ==, 20); 419184251Smarcel 420184251Smarcel /* Tell the sending bufferevent not to notify us till it's down to 421188156Ssam 100 bytes. */ 422184251Smarcel bufferevent_setwatermark(bev1, EV_WRITE, 100, 2000); 423184251Smarcel 424184251Smarcel bufferevent_getwatermark(bev1, EV_WRITE, &low, &high); 425184251Smarcel tt_int_op(low, ==, 100); 426184251Smarcel tt_int_op(high, ==, 2000); 427184251Smarcel 428184251Smarcel { 429184251Smarcel int r = bufferevent_getwatermark(bev1, EV_WRITE | EV_READ, &low, &high); 430184251Smarcel tt_int_op(r, !=, 0); 431184251Smarcel } 432188156Ssam 433188156Ssam bufferevent_write(bev1, buffer, sizeof(buffer)); 434188156Ssam 435188156Ssam event_dispatch(); 436188156Ssam 437188156Ssam tt_int_op(test_ok, ==, 2); 438188156Ssam 439188156Ssam /* The write callback drained all the data from outbuf, so we 440188156Ssam * should have removed the write event... */ 441188267Ssam tt_assert(!event_pending(&bev2->ev_write, EV_WRITE, NULL)); 442188267Ssam 443188267Ssamend: 444188156Ssam if (bev1) 445188156Ssam bufferevent_free(bev1); 446188156Ssam if (bev2) 447188156Ssam bufferevent_free(bev2); 448188156Ssam} 449188156Ssam 450188156Ssamstatic void 451188156Ssamtest_bufferevent_watermarks(void) 452188156Ssam{ 453188268Ssam test_bufferevent_watermarks_impl(0); 454188156Ssam} 455188156Ssam 456188156Ssamstatic void 457188156Ssamtest_bufferevent_pair_watermarks(void) 458188156Ssam{ 459188268Ssam test_bufferevent_watermarks_impl(1); 460188156Ssam} 461188156Ssam 462188156Ssam/* 463188156Ssam * Test bufferevent filters 464188156Ssam */ 465188156Ssam 466188156Ssam/* strip an 'x' from each byte */ 467188156Ssam 468188156Ssamstatic enum bufferevent_filter_result 469188156Ssambufferevent_input_filter(struct evbuffer *src, struct evbuffer *dst, 470188156Ssam ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 471188156Ssam{ 472188156Ssam const unsigned char *buffer; 473188156Ssam unsigned i; 474188156Ssam 475188156Ssam buffer = evbuffer_pullup(src, evbuffer_get_length(src)); 476188156Ssam for (i = 0; i < evbuffer_get_length(src); i += 2) { 477188156Ssam assert(buffer[i] == 'x'); 478188156Ssam evbuffer_add(dst, buffer + i + 1, 1); 479188156Ssam 480188156Ssam if (i + 2 > evbuffer_get_length(src)) 481188156Ssam break; 482188156Ssam } 483188156Ssam 484188156Ssam evbuffer_drain(src, i); 485188156Ssam return (BEV_OK); 486188156Ssam} 487188156Ssam 488188156Ssam/* add an 'x' before each byte */ 489188156Ssam 490188156Ssamstatic enum bufferevent_filter_result 491188156Ssambufferevent_output_filter(struct evbuffer *src, struct evbuffer *dst, 492188156Ssam ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 493188156Ssam{ 494188156Ssam const unsigned char *buffer; 495188156Ssam unsigned i; 496188156Ssam 497188156Ssam buffer = evbuffer_pullup(src, evbuffer_get_length(src)); 498188156Ssam for (i = 0; i < evbuffer_get_length(src); ++i) { 499188156Ssam evbuffer_add(dst, "x", 1); 500188156Ssam evbuffer_add(dst, buffer + i, 1); 501188267Ssam } 502188156Ssam 503188156Ssam evbuffer_drain(src, evbuffer_get_length(src)); 504188156Ssam return (BEV_OK); 505188156Ssam} 506188267Ssam 507188156Ssamstatic void 508188156Ssamtest_bufferevent_filters_impl(int use_pair) 509188267Ssam{ 510188156Ssam struct bufferevent *bev1 = NULL, *bev2 = NULL; 511188156Ssam struct bufferevent *bev1_base = NULL, *bev2_base = NULL; 512188156Ssam char buffer[8333]; 513188156Ssam int i; 514188156Ssam 515188267Ssam test_ok = 0; 516188156Ssam 517188156Ssam if (use_pair) { 518188156Ssam struct bufferevent *pair[2]; 519188156Ssam tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 520188156Ssam bev1 = pair[0]; 521188156Ssam bev2 = pair[1]; 522188156Ssam } else { 523188156Ssam bev1 = bufferevent_socket_new(NULL, pair[0], 0); 524188156Ssam bev2 = bufferevent_socket_new(NULL, pair[1], 0); 525188156Ssam } 526188156Ssam bev1_base = bev1; 527188156Ssam bev2_base = bev2; 528188267Ssam 529188267Ssam for (i = 0; i < (int)sizeof(buffer); i++) 530188267Ssam buffer[i] = i; 531188267Ssam 532188267Ssam bev1 = bufferevent_filter_new(bev1, NULL, bufferevent_output_filter, 533188156Ssam BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 534188156Ssam 535188156Ssam bev2 = bufferevent_filter_new(bev2, bufferevent_input_filter, 536188156Ssam NULL, BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 537188156Ssam bufferevent_setcb(bev1, NULL, writecb, errorcb, NULL); 538188156Ssam bufferevent_setcb(bev2, readcb, NULL, errorcb, NULL); 539188156Ssam 540188156Ssam tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev1_base); 541188156Ssam tt_ptr_op(bufferevent_get_underlying(bev2), ==, bev2_base); 542188156Ssam tt_int_op(bufferevent_getfd(bev1), ==, -1); 543188156Ssam tt_int_op(bufferevent_getfd(bev2), ==, -1); 544188156Ssam 545188156Ssam bufferevent_disable(bev1, EV_READ); 546188156Ssam bufferevent_enable(bev2, EV_READ); 547188156Ssam /* insert some filters */ 548188156Ssam bufferevent_write(bev1, buffer, sizeof(buffer)); 549188156Ssam 550188156Ssam event_dispatch(); 551188156Ssam 552188156Ssam if (test_ok != 2) 553188156Ssam test_ok = 0; 554188156Ssam 555188156Ssamend: 556188156Ssam if (bev1) 557188156Ssam bufferevent_free(bev1); 558188156Ssam if (bev2) 559188156Ssam bufferevent_free(bev2); 560188156Ssam 561188268Ssam} 562188156Ssam 563188156Ssamstatic void 564188156Ssamtest_bufferevent_filters(void) 565188156Ssam{ 566188156Ssam test_bufferevent_filters_impl(0); 567188156Ssam} 568188156Ssam 569188156Ssamstatic void 570188156Ssamtest_bufferevent_pair_filters(void) 571188156Ssam{ 572188156Ssam test_bufferevent_filters_impl(1); 573188156Ssam} 574188156Ssam 575188156Ssam 576188268Ssamstatic void 577188156Ssamsender_writecb(struct bufferevent *bev, void *ctx) 578188156Ssam{ 579188156Ssam if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) { 580188268Ssam bufferevent_disable(bev,EV_READ|EV_WRITE); 581188156Ssam TT_BLATHER(("Flushed %d: freeing it.", (int)bufferevent_getfd(bev))); 582188156Ssam bufferevent_free(bev); 583188156Ssam } 584} 585 586static void 587sender_errorcb(struct bufferevent *bev, short what, void *ctx) 588{ 589 TT_FAIL(("Got sender error %d",(int)what)); 590} 591 592static int bufferevent_connect_test_flags = 0; 593static int bufferevent_trigger_test_flags = 0; 594static int n_strings_read = 0; 595static int n_reads_invoked = 0; 596 597#define TEST_STR "Now is the time for all good events to signal for " \ 598 "the good of their protocol" 599static void 600listen_cb(struct evconnlistener *listener, evutil_socket_t fd, 601 struct sockaddr *sa, int socklen, void *arg) 602{ 603 struct event_base *base = arg; 604 struct bufferevent *bev; 605 const char s[] = TEST_STR; 606 TT_BLATHER(("Got a request on socket %d", (int)fd )); 607 bev = bufferevent_socket_new(base, fd, bufferevent_connect_test_flags); 608 tt_assert(bev); 609 bufferevent_setcb(bev, NULL, sender_writecb, sender_errorcb, NULL); 610 bufferevent_write(bev, s, sizeof(s)); 611end: 612 ; 613} 614 615static void 616reader_eventcb(struct bufferevent *bev, short what, void *ctx) 617{ 618 struct event_base *base = ctx; 619 if (what & BEV_EVENT_ERROR) { 620 perror("foobar"); 621 TT_FAIL(("got connector error %d", (int)what)); 622 return; 623 } 624 if (what & BEV_EVENT_CONNECTED) { 625 TT_BLATHER(("connected on %d", (int)bufferevent_getfd(bev))); 626 bufferevent_enable(bev, EV_READ); 627 } 628 if (what & BEV_EVENT_EOF) { 629 char buf[512]; 630 size_t n; 631 n = bufferevent_read(bev, buf, sizeof(buf)-1); 632 tt_int_op(n, >=, 0); 633 buf[n] = '\0'; 634 tt_str_op(buf, ==, TEST_STR); 635 if (++n_strings_read == 2) 636 event_base_loopexit(base, NULL); 637 TT_BLATHER(("EOF on %d: %d strings read.", 638 (int)bufferevent_getfd(bev), n_strings_read)); 639 } 640end: 641 ; 642} 643 644static void 645reader_readcb(struct bufferevent *bev, void *ctx) 646{ 647 TT_BLATHER(("Read invoked on %d.", (int)bufferevent_getfd(bev))); 648 n_reads_invoked++; 649} 650 651static void 652test_bufferevent_connect(void *arg) 653{ 654 struct basic_test_data *data = arg; 655 struct evconnlistener *lev=NULL; 656 struct bufferevent *bev1=NULL, *bev2=NULL; 657 struct sockaddr_in localhost; 658 struct sockaddr_storage ss; 659 struct sockaddr *sa; 660 ev_socklen_t slen; 661 662 int be_flags=BEV_OPT_CLOSE_ON_FREE; 663 664 if (strstr((char*)data->setup_data, "defer")) { 665 be_flags |= BEV_OPT_DEFER_CALLBACKS; 666 } 667 if (strstr((char*)data->setup_data, "unlocked")) { 668 be_flags |= BEV_OPT_UNLOCK_CALLBACKS; 669 } 670 if (strstr((char*)data->setup_data, "lock")) { 671 be_flags |= BEV_OPT_THREADSAFE; 672 } 673 bufferevent_connect_test_flags = be_flags; 674#ifdef _WIN32 675 if (!strcmp((char*)data->setup_data, "unset_connectex")) { 676 struct win32_extension_fns *ext = 677 (struct win32_extension_fns *) 678 event_get_win32_extension_fns_(); 679 ext->ConnectEx = NULL; 680 } 681#endif 682 683 memset(&localhost, 0, sizeof(localhost)); 684 685 localhost.sin_port = 0; /* pick-a-port */ 686 localhost.sin_addr.s_addr = htonl(0x7f000001L); 687 localhost.sin_family = AF_INET; 688 sa = (struct sockaddr *)&localhost; 689 lev = evconnlistener_new_bind(data->base, listen_cb, data->base, 690 LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 691 16, sa, sizeof(localhost)); 692 tt_assert(lev); 693 694 sa = (struct sockaddr *)&ss; 695 slen = sizeof(ss); 696 if (regress_get_listener_addr(lev, sa, &slen) < 0) { 697 tt_abort_perror("getsockname"); 698 } 699 700 tt_assert(!evconnlistener_enable(lev)); 701 bev1 = bufferevent_socket_new(data->base, -1, be_flags); 702 bev2 = bufferevent_socket_new(data->base, -1, be_flags); 703 tt_assert(bev1); 704 tt_assert(bev2); 705 bufferevent_setcb(bev1, reader_readcb,NULL, reader_eventcb, data->base); 706 bufferevent_setcb(bev2, reader_readcb,NULL, reader_eventcb, data->base); 707 708 bufferevent_enable(bev1, EV_READ); 709 bufferevent_enable(bev2, EV_READ); 710 711 tt_want(!bufferevent_socket_connect(bev1, sa, sizeof(localhost))); 712 tt_want(!bufferevent_socket_connect(bev2, sa, sizeof(localhost))); 713 714 event_base_dispatch(data->base); 715 716 tt_int_op(n_strings_read, ==, 2); 717 tt_int_op(n_reads_invoked, >=, 2); 718end: 719 if (lev) 720 evconnlistener_free(lev); 721 722 if (bev1) 723 bufferevent_free(bev1); 724 725 if (bev2) 726 bufferevent_free(bev2); 727} 728 729static void 730want_fail_eventcb(struct bufferevent *bev, short what, void *ctx) 731{ 732 struct event_base *base = ctx; 733 const char *err; 734 evutil_socket_t s; 735 736 if (what & BEV_EVENT_ERROR) { 737 s = bufferevent_getfd(bev); 738 err = evutil_socket_error_to_string(evutil_socket_geterror(s)); 739 TT_BLATHER(("connection failure on "EV_SOCK_FMT": %s", 740 EV_SOCK_ARG(s), err)); 741 test_ok = 1; 742 } else { 743 TT_FAIL(("didn't fail? what %hd", what)); 744 } 745 746 event_base_loopexit(base, NULL); 747} 748 749static void 750close_socket_cb(evutil_socket_t fd, short what, void *arg) 751{ 752 evutil_socket_t *fdp = arg; 753 if (*fdp >= 0) { 754 evutil_closesocket(*fdp); 755 *fdp = -1; 756 } 757} 758 759static void 760test_bufferevent_connect_fail(void *arg) 761{ 762 struct basic_test_data *data = (struct basic_test_data *)arg; 763 struct bufferevent *bev=NULL; 764 struct sockaddr_in localhost; 765 struct sockaddr *sa = (struct sockaddr*)&localhost; 766 evutil_socket_t fake_listener = -1; 767 ev_socklen_t slen = sizeof(localhost); 768 struct event close_listener_event; 769 int close_listener_event_added = 0; 770 struct timeval one_second = { 1, 0 }; 771 int r; 772 773 test_ok = 0; 774 775 memset(&localhost, 0, sizeof(localhost)); 776 localhost.sin_port = 0; /* have the kernel pick a port */ 777 localhost.sin_addr.s_addr = htonl(0x7f000001L); 778 localhost.sin_family = AF_INET; 779 780 /* bind, but don't listen or accept. should trigger 781 "Connection refused" reliably on most platforms. */ 782 fake_listener = socket(localhost.sin_family, SOCK_STREAM, 0); 783 tt_assert(fake_listener >= 0); 784 tt_assert(bind(fake_listener, sa, slen) == 0); 785 tt_assert(getsockname(fake_listener, sa, &slen) == 0); 786 bev = bufferevent_socket_new(data->base, -1, 787 BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); 788 tt_assert(bev); 789 bufferevent_setcb(bev, NULL, NULL, want_fail_eventcb, data->base); 790 791 r = bufferevent_socket_connect(bev, sa, slen); 792 /* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells 793 * detects the error immediately, which is not really wrong of it. */ 794 tt_want(r == 0 || r == -1); 795 796 /* Close the listener socket after a second. This should trigger 797 "connection refused" on some other platforms, including OSX. */ 798 evtimer_assign(&close_listener_event, data->base, close_socket_cb, 799 &fake_listener); 800 event_add(&close_listener_event, &one_second); 801 close_listener_event_added = 1; 802 803 event_base_dispatch(data->base); 804 805 tt_int_op(test_ok, ==, 1); 806 807end: 808 if (fake_listener >= 0) 809 evutil_closesocket(fake_listener); 810 811 if (bev) 812 bufferevent_free(bev); 813 814 if (close_listener_event_added) 815 event_del(&close_listener_event); 816} 817 818struct timeout_cb_result { 819 struct timeval read_timeout_at; 820 struct timeval write_timeout_at; 821 struct timeval last_wrote_at; 822 int n_read_timeouts; 823 int n_write_timeouts; 824 int total_calls; 825}; 826 827static void 828bev_timeout_write_cb(struct bufferevent *bev, void *arg) 829{ 830 struct timeout_cb_result *res = arg; 831 evutil_gettimeofday(&res->last_wrote_at, NULL); 832} 833 834static void 835bev_timeout_event_cb(struct bufferevent *bev, short what, void *arg) 836{ 837 struct timeout_cb_result *res = arg; 838 ++res->total_calls; 839 840 if ((what & (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) 841 == (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) { 842 evutil_gettimeofday(&res->read_timeout_at, NULL); 843 ++res->n_read_timeouts; 844 } 845 if ((what & (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) 846 == (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) { 847 evutil_gettimeofday(&res->write_timeout_at, NULL); 848 ++res->n_write_timeouts; 849 } 850} 851 852static void 853test_bufferevent_timeouts(void *arg) 854{ 855 /* "arg" is a string containing "pair" and/or "filter". */ 856 struct bufferevent *bev1 = NULL, *bev2 = NULL; 857 struct basic_test_data *data = arg; 858 int use_pair = 0, use_filter = 0; 859 struct timeval tv_w, tv_r, started_at; 860 struct timeout_cb_result res1, res2; 861 char buf[1024]; 862 863 memset(&res1, 0, sizeof(res1)); 864 memset(&res2, 0, sizeof(res2)); 865 866 if (strstr((char*)data->setup_data, "pair")) 867 use_pair = 1; 868 if (strstr((char*)data->setup_data, "filter")) 869 use_filter = 1; 870 871 if (use_pair) { 872 struct bufferevent *p[2]; 873 tt_int_op(0, ==, bufferevent_pair_new(data->base, 0, p)); 874 bev1 = p[0]; 875 bev2 = p[1]; 876 } else { 877 bev1 = bufferevent_socket_new(data->base, data->pair[0], 0); 878 bev2 = bufferevent_socket_new(data->base, data->pair[1], 0); 879 } 880 881 tt_assert(bev1); 882 tt_assert(bev2); 883 884 if (use_filter) { 885 struct bufferevent *bevf1, *bevf2; 886 bevf1 = bufferevent_filter_new(bev1, NULL, NULL, 887 BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 888 bevf2 = bufferevent_filter_new(bev2, NULL, NULL, 889 BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 890 tt_assert(bevf1); 891 tt_assert(bevf2); 892 bev1 = bevf1; 893 bev2 = bevf2; 894 } 895 896 /* Do this nice and early. */ 897 bufferevent_disable(bev2, EV_READ); 898 899 /* bev1 will try to write and read. Both will time out. */ 900 evutil_gettimeofday(&started_at, NULL); 901 tv_w.tv_sec = tv_r.tv_sec = 0; 902 tv_w.tv_usec = 100*1000; 903 tv_r.tv_usec = 150*1000; 904 bufferevent_setcb(bev1, NULL, bev_timeout_write_cb, 905 bev_timeout_event_cb, &res1); 906 bufferevent_setwatermark(bev1, EV_WRITE, 1024*1024+10, 0); 907 bufferevent_set_timeouts(bev1, &tv_r, &tv_w); 908 if (use_pair) { 909 /* For a pair, the fact that the other side isn't reading 910 * makes the writer stall */ 911 bufferevent_write(bev1, "ABCDEFG", 7); 912 } else { 913 /* For a real socket, the kernel's TCP buffers can eat a 914 * fair number of bytes; make sure that at some point we 915 * have some bytes that will stall. */ 916 struct evbuffer *output = bufferevent_get_output(bev1); 917 int i; 918 memset(buf, 0xbb, sizeof(buf)); 919 for (i=0;i<1024;++i) { 920 evbuffer_add_reference(output, buf, sizeof(buf), 921 NULL, NULL); 922 } 923 } 924 bufferevent_enable(bev1, EV_READ|EV_WRITE); 925 926 /* bev2 has nothing to say, and isn't listening. */ 927 bufferevent_setcb(bev2, NULL, bev_timeout_write_cb, 928 bev_timeout_event_cb, &res2); 929 tv_w.tv_sec = tv_r.tv_sec = 0; 930 tv_w.tv_usec = 200*1000; 931 tv_r.tv_usec = 100*1000; 932 bufferevent_set_timeouts(bev2, &tv_r, &tv_w); 933 bufferevent_enable(bev2, EV_WRITE); 934 935 tv_r.tv_sec = 0; 936 tv_r.tv_usec = 350000; 937 938 event_base_loopexit(data->base, &tv_r); 939 event_base_dispatch(data->base); 940 941 /* XXXX Test that actually reading or writing a little resets the 942 * timeouts. */ 943 944 /* Each buf1 timeout happens, and happens only once. */ 945 tt_want(res1.n_read_timeouts); 946 tt_want(res1.n_write_timeouts); 947 tt_want(res1.n_read_timeouts == 1); 948 tt_want(res1.n_write_timeouts == 1); 949 950 test_timeval_diff_eq(&started_at, &res1.read_timeout_at, 150); 951 test_timeval_diff_eq(&started_at, &res1.write_timeout_at, 100); 952 953end: 954 if (bev1) 955 bufferevent_free(bev1); 956 if (bev2) 957 bufferevent_free(bev2); 958} 959 960static void 961trigger_failure_cb(evutil_socket_t fd, short what, void *ctx) 962{ 963 TT_FAIL(("The triggered callback did not fire or the machine is really slow (try increasing timeout).")); 964} 965 966static void 967trigger_eventcb(struct bufferevent *bev, short what, void *ctx) 968{ 969 struct event_base *base = ctx; 970 if (what == ~0) { 971 TT_BLATHER(("Event successfully triggered.")); 972 event_base_loopexit(base, NULL); 973 return; 974 } 975 reader_eventcb(bev, what, ctx); 976} 977 978static void 979trigger_readcb_triggered(struct bufferevent *bev, void *ctx) 980{ 981 TT_BLATHER(("Read successfully triggered.")); 982 n_reads_invoked++; 983 bufferevent_trigger_event(bev, ~0, bufferevent_trigger_test_flags); 984} 985 986static void 987trigger_readcb(struct bufferevent *bev, void *ctx) 988{ 989 struct timeval timeout = { 30, 0 }; 990 struct event_base *base = ctx; 991 size_t low, high, len; 992 int expected_reads; 993 994 TT_BLATHER(("Read invoked on %d.", (int)bufferevent_getfd(bev))); 995 expected_reads = ++n_reads_invoked; 996 997 bufferevent_setcb(bev, trigger_readcb_triggered, NULL, trigger_eventcb, ctx); 998 999 bufferevent_getwatermark(bev, EV_READ, &low, &high); 1000 len = evbuffer_get_length(bufferevent_get_input(bev)); 1001 1002 bufferevent_setwatermark(bev, EV_READ, len + 1, 0); 1003 bufferevent_trigger(bev, EV_READ, bufferevent_trigger_test_flags); 1004 /* no callback expected */ 1005 tt_int_op(n_reads_invoked, ==, expected_reads); 1006 1007 if ((bufferevent_trigger_test_flags & BEV_TRIG_DEFER_CALLBACKS) || 1008 (bufferevent_connect_test_flags & BEV_OPT_DEFER_CALLBACKS)) { 1009 /* will be deferred */ 1010 } else { 1011 expected_reads++; 1012 } 1013 1014 event_base_once(base, -1, EV_TIMEOUT, trigger_failure_cb, NULL, &timeout); 1015 1016 bufferevent_trigger(bev, EV_READ, 1017 bufferevent_trigger_test_flags | BEV_TRIG_IGNORE_WATERMARKS); 1018 tt_int_op(n_reads_invoked, ==, expected_reads); 1019 1020 bufferevent_setwatermark(bev, EV_READ, low, high); 1021end: 1022 ; 1023} 1024 1025static void 1026test_bufferevent_trigger(void *arg) 1027{ 1028 struct basic_test_data *data = arg; 1029 struct evconnlistener *lev=NULL; 1030 struct bufferevent *bev=NULL; 1031 struct sockaddr_in localhost; 1032 struct sockaddr_storage ss; 1033 struct sockaddr *sa; 1034 ev_socklen_t slen; 1035 1036 int be_flags=BEV_OPT_CLOSE_ON_FREE; 1037 int trig_flags=0; 1038 1039 if (strstr((char*)data->setup_data, "defer")) { 1040 be_flags |= BEV_OPT_DEFER_CALLBACKS; 1041 } 1042 bufferevent_connect_test_flags = be_flags; 1043 1044 if (strstr((char*)data->setup_data, "postpone")) { 1045 trig_flags |= BEV_TRIG_DEFER_CALLBACKS; 1046 } 1047 bufferevent_trigger_test_flags = trig_flags; 1048 1049 memset(&localhost, 0, sizeof(localhost)); 1050 1051 localhost.sin_port = 0; /* pick-a-port */ 1052 localhost.sin_addr.s_addr = htonl(0x7f000001L); 1053 localhost.sin_family = AF_INET; 1054 sa = (struct sockaddr *)&localhost; 1055 lev = evconnlistener_new_bind(data->base, listen_cb, data->base, 1056 LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 1057 16, sa, sizeof(localhost)); 1058 tt_assert(lev); 1059 1060 sa = (struct sockaddr *)&ss; 1061 slen = sizeof(ss); 1062 if (regress_get_listener_addr(lev, sa, &slen) < 0) { 1063 tt_abort_perror("getsockname"); 1064 } 1065 1066 tt_assert(!evconnlistener_enable(lev)); 1067 bev = bufferevent_socket_new(data->base, -1, be_flags); 1068 tt_assert(bev); 1069 bufferevent_setcb(bev, trigger_readcb, NULL, trigger_eventcb, data->base); 1070 1071 bufferevent_enable(bev, EV_READ); 1072 1073 tt_want(!bufferevent_socket_connect(bev, sa, sizeof(localhost))); 1074 1075 event_base_dispatch(data->base); 1076 1077 tt_int_op(n_reads_invoked, ==, 2); 1078end: 1079 if (lev) 1080 evconnlistener_free(lev); 1081 1082 if (bev) 1083 bufferevent_free(bev); 1084} 1085 1086struct testcase_t bufferevent_testcases[] = { 1087 1088 LEGACY(bufferevent, TT_ISOLATED), 1089 LEGACY(bufferevent_pair, TT_ISOLATED), 1090#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) 1091 { "bufferevent_pair_release_lock", test_bufferevent_pair_release_lock, 1092 TT_FORK|TT_ISOLATED|TT_NEED_THREADS|TT_NEED_BASE|TT_LEGACY, 1093 &basic_setup, NULL }, 1094#endif 1095 LEGACY(bufferevent_watermarks, TT_ISOLATED), 1096 LEGACY(bufferevent_pair_watermarks, TT_ISOLATED), 1097 LEGACY(bufferevent_filters, TT_ISOLATED), 1098 LEGACY(bufferevent_pair_filters, TT_ISOLATED), 1099 { "bufferevent_connect", test_bufferevent_connect, TT_FORK|TT_NEED_BASE, 1100 &basic_setup, (void*)"" }, 1101 { "bufferevent_connect_defer", test_bufferevent_connect, 1102 TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"defer" }, 1103 { "bufferevent_connect_lock", test_bufferevent_connect, 1104 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, (void*)"lock" }, 1105 { "bufferevent_connect_lock_defer", test_bufferevent_connect, 1106 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1107 (void*)"defer lock" }, 1108 { "bufferevent_connect_unlocked_cbs", test_bufferevent_connect, 1109 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1110 (void*)"lock defer unlocked" }, 1111 { "bufferevent_connect_fail", test_bufferevent_connect_fail, 1112 TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1113 { "bufferevent_timeout", test_bufferevent_timeouts, 1114 TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, (void*)"" }, 1115 { "bufferevent_timeout_pair", test_bufferevent_timeouts, 1116 TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"pair" }, 1117 { "bufferevent_timeout_filter", test_bufferevent_timeouts, 1118 TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter" }, 1119 { "bufferevent_timeout_filter_pair", test_bufferevent_timeouts, 1120 TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter pair" }, 1121 { "bufferevent_trigger", test_bufferevent_trigger, TT_FORK|TT_NEED_BASE, 1122 &basic_setup, (void*)"" }, 1123 { "bufferevent_trigger_defer", test_bufferevent_trigger, 1124 TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"defer" }, 1125 { "bufferevent_trigger_postpone", test_bufferevent_trigger, 1126 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1127 (void*)"postpone" }, 1128 { "bufferevent_trigger_defer_postpone", test_bufferevent_trigger, 1129 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1130 (void*)"defer postpone" }, 1131#ifdef EVENT__HAVE_LIBZ 1132 LEGACY(bufferevent_zlib, TT_ISOLATED), 1133#else 1134 { "bufferevent_zlib", NULL, TT_SKIP, NULL, NULL }, 1135#endif 1136 1137 END_OF_TESTCASES, 1138}; 1139 1140struct testcase_t bufferevent_iocp_testcases[] = { 1141 1142 LEGACY(bufferevent, TT_ISOLATED|TT_ENABLE_IOCP), 1143 LEGACY(bufferevent_watermarks, TT_ISOLATED|TT_ENABLE_IOCP), 1144 LEGACY(bufferevent_filters, TT_ISOLATED|TT_ENABLE_IOCP), 1145 { "bufferevent_connect", test_bufferevent_connect, 1146 TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"" }, 1147 { "bufferevent_connect_defer", test_bufferevent_connect, 1148 TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"defer" }, 1149 { "bufferevent_connect_lock", test_bufferevent_connect, 1150 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup, 1151 (void*)"lock" }, 1152 { "bufferevent_connect_lock_defer", test_bufferevent_connect, 1153 TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup, 1154 (void*)"defer lock" }, 1155 { "bufferevent_connect_fail", test_bufferevent_connect_fail, 1156 TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL }, 1157 { "bufferevent_connect_nonblocking", test_bufferevent_connect, 1158 TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, 1159 (void*)"unset_connectex" }, 1160 1161 END_OF_TESTCASES, 1162}; 1163