1 1.6 christos /* $NetBSD: regress_bufferevent.c,v 1.7 2024/08/18 20:47:23 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (c) 2003-2007 Niels Provos <provos (at) citi.umich.edu> 5 1.1 christos * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 6 1.1 christos * 7 1.1 christos * Redistribution and use in source and binary forms, with or without 8 1.1 christos * modification, are permitted provided that the following conditions 9 1.1 christos * are met: 10 1.1 christos * 1. Redistributions of source code must retain the above copyright 11 1.1 christos * notice, this list of conditions and the following disclaimer. 12 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 christos * notice, this list of conditions and the following disclaimer in the 14 1.1 christos * documentation and/or other materials provided with the distribution. 15 1.1 christos * 3. The name of the author may not be used to endorse or promote products 16 1.1 christos * derived from this software without specific prior written permission. 17 1.1 christos * 18 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.1 christos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 christos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.1 christos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 christos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.1 christos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 christos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 christos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 christos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.1 christos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 christos */ 29 1.1 christos #include "util-internal.h" 30 1.1 christos 31 1.1 christos /* The old tests here need assertions to work. */ 32 1.1 christos #undef NDEBUG 33 1.1 christos 34 1.7 christos /** 35 1.7 christos * - clang supports __has_feature 36 1.7 christos * - gcc supports __SANITIZE_ADDRESS__ 37 1.7 christos * 38 1.7 christos * Let's set __SANITIZE_ADDRESS__ if __has_feature(address_sanitizer) 39 1.7 christos */ 40 1.7 christos #ifndef __has_feature 41 1.7 christos #define __has_feature(x) 0 42 1.7 christos #endif 43 1.7 christos #if !defined(__SANITIZE_ADDRESS__) && __has_feature(address_sanitizer) 44 1.7 christos #define __SANITIZE_ADDRESS__ 45 1.7 christos #endif 46 1.7 christos 47 1.1 christos #ifdef _WIN32 48 1.1 christos #include <winsock2.h> 49 1.1 christos #include <windows.h> 50 1.1 christos #endif 51 1.1 christos 52 1.1 christos #include "event2/event-config.h" 53 1.1 christos 54 1.1 christos #include <sys/types.h> 55 1.1 christos #include <sys/stat.h> 56 1.1 christos #ifdef EVENT__HAVE_SYS_TIME_H 57 1.1 christos #include <sys/time.h> 58 1.1 christos #endif 59 1.1 christos #include <sys/queue.h> 60 1.1 christos #ifndef _WIN32 61 1.1 christos #include <sys/socket.h> 62 1.1 christos #include <sys/wait.h> 63 1.1 christos #include <signal.h> 64 1.1 christos #include <unistd.h> 65 1.1 christos #include <netdb.h> 66 1.1 christos #include <netinet/in.h> 67 1.1 christos #endif 68 1.1 christos #include <fcntl.h> 69 1.1 christos #include <signal.h> 70 1.1 christos #include <stdlib.h> 71 1.1 christos #include <stdio.h> 72 1.1 christos #include <string.h> 73 1.1 christos #include <errno.h> 74 1.1 christos #include <assert.h> 75 1.1 christos 76 1.1 christos #ifdef EVENT__HAVE_ARPA_INET_H 77 1.1 christos #include <arpa/inet.h> 78 1.1 christos #endif 79 1.1 christos 80 1.1 christos #include "event2/event-config.h" 81 1.1 christos #include "event2/event.h" 82 1.1 christos #include "event2/event_struct.h" 83 1.1 christos #include "event2/event_compat.h" 84 1.1 christos #include "event2/tag.h" 85 1.1 christos #include "event2/buffer.h" 86 1.1 christos #include "event2/bufferevent.h" 87 1.1 christos #include "event2/bufferevent_compat.h" 88 1.1 christos #include "event2/bufferevent_struct.h" 89 1.1 christos #include "event2/listener.h" 90 1.1 christos #include "event2/util.h" 91 1.1 christos 92 1.1 christos #include "bufferevent-internal.h" 93 1.3 christos #include "evthread-internal.h" 94 1.1 christos #include "util-internal.h" 95 1.1 christos #ifdef _WIN32 96 1.1 christos #include "iocp-internal.h" 97 1.1 christos #endif 98 1.1 christos 99 1.1 christos #include "regress.h" 100 1.1 christos #include "regress_testutils.h" 101 1.1 christos 102 1.1 christos /* 103 1.1 christos * simple bufferevent test 104 1.1 christos */ 105 1.1 christos 106 1.1 christos static void 107 1.1 christos readcb(struct bufferevent *bev, void *arg) 108 1.1 christos { 109 1.1 christos if (evbuffer_get_length(bev->input) == 8333) { 110 1.1 christos struct evbuffer *evbuf = evbuffer_new(); 111 1.1 christos assert(evbuf != NULL); 112 1.1 christos 113 1.1 christos /* gratuitous test of bufferevent_read_buffer */ 114 1.1 christos bufferevent_read_buffer(bev, evbuf); 115 1.1 christos 116 1.1 christos bufferevent_disable(bev, EV_READ); 117 1.1 christos 118 1.1 christos if (evbuffer_get_length(evbuf) == 8333) { 119 1.1 christos test_ok++; 120 1.1 christos } 121 1.1 christos 122 1.1 christos evbuffer_free(evbuf); 123 1.1 christos } 124 1.1 christos } 125 1.1 christos 126 1.1 christos static void 127 1.1 christos writecb(struct bufferevent *bev, void *arg) 128 1.1 christos { 129 1.1 christos if (evbuffer_get_length(bev->output) == 0) { 130 1.1 christos test_ok++; 131 1.1 christos } 132 1.1 christos } 133 1.1 christos 134 1.1 christos static void 135 1.1 christos errorcb(struct bufferevent *bev, short what, void *arg) 136 1.1 christos { 137 1.1 christos test_ok = -2; 138 1.1 christos } 139 1.1 christos 140 1.1 christos static void 141 1.7 christos test_bufferevent_impl(int use_pair, int flush) 142 1.1 christos { 143 1.1 christos struct bufferevent *bev1 = NULL, *bev2 = NULL; 144 1.1 christos char buffer[8333]; 145 1.1 christos int i; 146 1.7 christos int expected = 2; 147 1.1 christos 148 1.1 christos if (use_pair) { 149 1.1 christos struct bufferevent *pair[2]; 150 1.1 christos tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 151 1.1 christos bev1 = pair[0]; 152 1.1 christos bev2 = pair[1]; 153 1.1 christos bufferevent_setcb(bev1, readcb, writecb, errorcb, bev1); 154 1.1 christos bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL); 155 1.7 christos tt_fd_op(bufferevent_getfd(bev1), ==, EVUTIL_INVALID_SOCKET); 156 1.1 christos tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); 157 1.1 christos tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, bev2); 158 1.1 christos tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, bev1); 159 1.1 christos } else { 160 1.1 christos bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL); 161 1.1 christos bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL); 162 1.7 christos tt_fd_op(bufferevent_getfd(bev1), ==, pair[0]); 163 1.1 christos tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); 164 1.1 christos tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL); 165 1.1 christos tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL); 166 1.1 christos } 167 1.1 christos 168 1.1 christos { 169 1.1 christos /* Test getcb. */ 170 1.1 christos bufferevent_data_cb r, w; 171 1.1 christos bufferevent_event_cb e; 172 1.1 christos void *a; 173 1.1 christos bufferevent_getcb(bev1, &r, &w, &e, &a); 174 1.1 christos tt_ptr_op(r, ==, readcb); 175 1.1 christos tt_ptr_op(w, ==, writecb); 176 1.1 christos tt_ptr_op(e, ==, errorcb); 177 1.1 christos tt_ptr_op(a, ==, use_pair ? bev1 : NULL); 178 1.1 christos } 179 1.1 christos 180 1.1 christos bufferevent_disable(bev1, EV_READ); 181 1.1 christos bufferevent_enable(bev2, EV_READ); 182 1.1 christos 183 1.1 christos tt_int_op(bufferevent_get_enabled(bev1), ==, EV_WRITE); 184 1.1 christos tt_int_op(bufferevent_get_enabled(bev2), ==, EV_WRITE|EV_READ); 185 1.1 christos 186 1.1 christos for (i = 0; i < (int)sizeof(buffer); i++) 187 1.1 christos buffer[i] = i; 188 1.1 christos 189 1.1 christos bufferevent_write(bev1, buffer, sizeof(buffer)); 190 1.7 christos if (flush >= 0) { 191 1.7 christos tt_int_op(bufferevent_flush(bev1, EV_WRITE, flush), >=, 0); 192 1.7 christos } 193 1.1 christos 194 1.1 christos event_dispatch(); 195 1.1 christos 196 1.3 christos bufferevent_free(bev2); 197 1.3 christos tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL); 198 1.1 christos bufferevent_free(bev1); 199 1.1 christos 200 1.7 christos /** Only pair call errorcb for BEV_FINISHED */ 201 1.7 christos if (use_pair && flush == BEV_FINISHED) { 202 1.7 christos expected = -1; 203 1.7 christos } 204 1.7 christos if (test_ok != expected) 205 1.1 christos test_ok = 0; 206 1.1 christos end: 207 1.1 christos ; 208 1.1 christos } 209 1.1 christos 210 1.7 christos static void test_bufferevent(void) { test_bufferevent_impl(0, -1); } 211 1.7 christos static void test_bufferevent_pair(void) { test_bufferevent_impl(1, -1); } 212 1.1 christos 213 1.7 christos static void test_bufferevent_flush_normal(void) { test_bufferevent_impl(0, BEV_NORMAL); } 214 1.7 christos static void test_bufferevent_flush_flush(void) { test_bufferevent_impl(0, BEV_FLUSH); } 215 1.7 christos static void test_bufferevent_flush_finished(void) { test_bufferevent_impl(0, BEV_FINISHED); } 216 1.7 christos 217 1.7 christos static void test_bufferevent_pair_flush_normal(void) { test_bufferevent_impl(1, BEV_NORMAL); } 218 1.7 christos static void test_bufferevent_pair_flush_flush(void) { test_bufferevent_impl(1, BEV_FLUSH); } 219 1.7 christos static void test_bufferevent_pair_flush_finished(void) { test_bufferevent_impl(1, BEV_FINISHED); } 220 1.1 christos 221 1.7 christos #if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) && !defined(__SANITIZE_ADDRESS__) 222 1.3 christos /** 223 1.3 christos * Trace lock/unlock/alloc/free for locks. 224 1.3 christos * (More heavier then evthread_debug*) 225 1.3 christos */ 226 1.3 christos typedef struct 227 1.3 christos { 228 1.3 christos void *lock; 229 1.3 christos enum { 230 1.3 christos ALLOC, FREE, 231 1.3 christos } status; 232 1.3 christos size_t locked /** allow recursive locking */; 233 1.3 christos } lock_wrapper; 234 1.3 christos struct lock_unlock_base 235 1.3 christos { 236 1.3 christos /* Original callbacks */ 237 1.3 christos struct evthread_lock_callbacks cbs; 238 1.3 christos /* Map of locks */ 239 1.3 christos lock_wrapper *locks; 240 1.3 christos size_t nr_locks; 241 1.3 christos } lu_base = { 242 1.3 christos .locks = NULL, 243 1.3 christos }; 244 1.3 christos 245 1.3 christos static lock_wrapper *lu_find(void *lock_) 246 1.3 christos { 247 1.3 christos size_t i; 248 1.3 christos for (i = 0; i < lu_base.nr_locks; ++i) { 249 1.3 christos lock_wrapper *lock = &lu_base.locks[i]; 250 1.3 christos if (lock->lock == lock_) 251 1.3 christos return lock; 252 1.3 christos } 253 1.3 christos return NULL; 254 1.3 christos } 255 1.3 christos 256 1.3 christos static void *trace_lock_alloc(unsigned locktype) 257 1.3 christos { 258 1.7 christos void *lock; 259 1.3 christos ++lu_base.nr_locks; 260 1.3 christos lu_base.locks = realloc(lu_base.locks, 261 1.3 christos sizeof(lock_wrapper) * lu_base.nr_locks); 262 1.7 christos lock = lu_base.cbs.alloc(locktype); 263 1.3 christos lu_base.locks[lu_base.nr_locks - 1] = (lock_wrapper){ lock, ALLOC, 0 }; 264 1.3 christos return lock; 265 1.3 christos } 266 1.3 christos static void trace_lock_free(void *lock_, unsigned locktype) 267 1.3 christos { 268 1.3 christos lock_wrapper *lock = lu_find(lock_); 269 1.3 christos if (!lock || lock->status == FREE || lock->locked) { 270 1.3 christos TT_FAIL(("lock: free error")); 271 1.3 christos } else { 272 1.3 christos lock->status = FREE; 273 1.3 christos lu_base.cbs.free(lock_, locktype); 274 1.3 christos } 275 1.3 christos } 276 1.3 christos static int trace_lock_lock(unsigned mode, void *lock_) 277 1.3 christos { 278 1.3 christos lock_wrapper *lock = lu_find(lock_); 279 1.3 christos if (!lock || lock->status == FREE) { 280 1.3 christos TT_FAIL(("lock: lock error")); 281 1.3 christos return -1; 282 1.3 christos } else { 283 1.3 christos ++lock->locked; 284 1.3 christos return lu_base.cbs.lock(mode, lock_); 285 1.3 christos } 286 1.3 christos } 287 1.3 christos static int trace_lock_unlock(unsigned mode, void *lock_) 288 1.3 christos { 289 1.3 christos lock_wrapper *lock = lu_find(lock_); 290 1.3 christos if (!lock || lock->status == FREE || !lock->locked) { 291 1.3 christos TT_FAIL(("lock: unlock error")); 292 1.3 christos return -1; 293 1.3 christos } else { 294 1.3 christos --lock->locked; 295 1.3 christos return lu_base.cbs.unlock(mode, lock_); 296 1.3 christos } 297 1.3 christos } 298 1.7 christos static void lock_unlock_free_thread_cbs(void) 299 1.3 christos { 300 1.3 christos event_base_free(NULL); 301 1.3 christos 302 1.7 christos if (libevent_tests_running_in_debug_mode) 303 1.7 christos libevent_global_shutdown(); 304 1.7 christos 305 1.3 christos /** drop immutable flag */ 306 1.3 christos evthread_set_lock_callbacks(NULL); 307 1.3 christos /** avoid calling of event_global_setup_locks_() for new cbs */ 308 1.3 christos libevent_global_shutdown(); 309 1.3 christos /** drop immutable flag for non-debug ops (since called after shutdown) */ 310 1.3 christos evthread_set_lock_callbacks(NULL); 311 1.3 christos } 312 1.3 christos 313 1.3 christos static int use_lock_unlock_profiler(void) 314 1.3 christos { 315 1.3 christos struct evthread_lock_callbacks cbs = { 316 1.3 christos EVTHREAD_LOCK_API_VERSION, 317 1.3 christos EVTHREAD_LOCKTYPE_RECURSIVE, 318 1.3 christos trace_lock_alloc, 319 1.3 christos trace_lock_free, 320 1.3 christos trace_lock_lock, 321 1.3 christos trace_lock_unlock, 322 1.3 christos }; 323 1.3 christos memcpy(&lu_base.cbs, evthread_get_lock_callbacks(), 324 1.3 christos sizeof(lu_base.cbs)); 325 1.3 christos { 326 1.3 christos lock_unlock_free_thread_cbs(); 327 1.3 christos 328 1.3 christos evthread_set_lock_callbacks(&cbs); 329 1.3 christos /** re-create debug locks correctly */ 330 1.3 christos evthread_enable_lock_debugging(); 331 1.3 christos 332 1.3 christos event_init(); 333 1.3 christos } 334 1.3 christos return 0; 335 1.3 christos } 336 1.3 christos static void free_lock_unlock_profiler(struct basic_test_data *data) 337 1.3 christos { 338 1.7 christos /** fix "held_by" for kqueue */ 339 1.7 christos evthread_set_lock_callbacks(NULL); 340 1.7 christos 341 1.3 christos lock_unlock_free_thread_cbs(); 342 1.3 christos free(lu_base.locks); 343 1.3 christos data->base = NULL; 344 1.3 christos } 345 1.3 christos 346 1.3 christos static void test_bufferevent_pair_release_lock(void *arg) 347 1.3 christos { 348 1.3 christos struct basic_test_data *data = arg; 349 1.3 christos use_lock_unlock_profiler(); 350 1.3 christos { 351 1.3 christos struct bufferevent *pair[2]; 352 1.3 christos if (!bufferevent_pair_new(NULL, BEV_OPT_THREADSAFE, pair)) { 353 1.3 christos bufferevent_free(pair[0]); 354 1.3 christos bufferevent_free(pair[1]); 355 1.3 christos } else 356 1.3 christos tt_abort_perror("bufferevent_pair_new"); 357 1.3 christos } 358 1.3 christos free_lock_unlock_profiler(data); 359 1.3 christos end: 360 1.3 christos ; 361 1.3 christos } 362 1.3 christos #endif 363 1.3 christos 364 1.1 christos /* 365 1.1 christos * test watermarks and bufferevent 366 1.1 christos */ 367 1.1 christos 368 1.1 christos static void 369 1.1 christos wm_readcb(struct bufferevent *bev, void *arg) 370 1.1 christos { 371 1.1 christos struct evbuffer *evbuf = evbuffer_new(); 372 1.1 christos int len = (int)evbuffer_get_length(bev->input); 373 1.1 christos static int nread; 374 1.1 christos 375 1.1 christos assert(len >= 10 && len <= 20); 376 1.1 christos 377 1.1 christos assert(evbuf != NULL); 378 1.1 christos 379 1.1 christos /* gratuitous test of bufferevent_read_buffer */ 380 1.1 christos bufferevent_read_buffer(bev, evbuf); 381 1.1 christos 382 1.1 christos nread += len; 383 1.1 christos if (nread == 65000) { 384 1.1 christos bufferevent_disable(bev, EV_READ); 385 1.1 christos test_ok++; 386 1.1 christos } 387 1.1 christos 388 1.1 christos evbuffer_free(evbuf); 389 1.1 christos } 390 1.1 christos 391 1.1 christos static void 392 1.1 christos wm_writecb(struct bufferevent *bev, void *arg) 393 1.1 christos { 394 1.1 christos assert(evbuffer_get_length(bev->output) <= 100); 395 1.1 christos if (evbuffer_get_length(bev->output) == 0) { 396 1.1 christos evbuffer_drain(bev->output, evbuffer_get_length(bev->output)); 397 1.1 christos test_ok++; 398 1.1 christos } 399 1.1 christos } 400 1.1 christos 401 1.1 christos static void 402 1.1 christos wm_errorcb(struct bufferevent *bev, short what, void *arg) 403 1.1 christos { 404 1.1 christos test_ok = -2; 405 1.1 christos } 406 1.1 christos 407 1.1 christos static void 408 1.1 christos test_bufferevent_watermarks_impl(int use_pair) 409 1.1 christos { 410 1.1 christos struct bufferevent *bev1 = NULL, *bev2 = NULL; 411 1.1 christos char buffer[65000]; 412 1.2 christos size_t low, high; 413 1.1 christos int i; 414 1.1 christos test_ok = 0; 415 1.1 christos 416 1.1 christos if (use_pair) { 417 1.1 christos struct bufferevent *pair[2]; 418 1.1 christos tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 419 1.1 christos bev1 = pair[0]; 420 1.1 christos bev2 = pair[1]; 421 1.1 christos bufferevent_setcb(bev1, NULL, wm_writecb, errorcb, NULL); 422 1.1 christos bufferevent_setcb(bev2, wm_readcb, NULL, errorcb, NULL); 423 1.1 christos } else { 424 1.1 christos bev1 = bufferevent_new(pair[0], NULL, wm_writecb, wm_errorcb, NULL); 425 1.1 christos bev2 = bufferevent_new(pair[1], wm_readcb, NULL, wm_errorcb, NULL); 426 1.1 christos } 427 1.1 christos tt_assert(bev1); 428 1.1 christos tt_assert(bev2); 429 1.1 christos bufferevent_disable(bev1, EV_READ); 430 1.1 christos bufferevent_enable(bev2, EV_READ); 431 1.1 christos 432 1.2 christos /* By default, low watermarks are set to 0 */ 433 1.2 christos bufferevent_getwatermark(bev1, EV_READ, &low, NULL); 434 1.2 christos tt_int_op(low, ==, 0); 435 1.2 christos bufferevent_getwatermark(bev2, EV_WRITE, &low, NULL); 436 1.2 christos tt_int_op(low, ==, 0); 437 1.2 christos 438 1.1 christos for (i = 0; i < (int)sizeof(buffer); i++) 439 1.1 christos buffer[i] = (char)i; 440 1.1 christos 441 1.1 christos /* limit the reading on the receiving bufferevent */ 442 1.1 christos bufferevent_setwatermark(bev2, EV_READ, 10, 20); 443 1.1 christos 444 1.2 christos bufferevent_getwatermark(bev2, EV_READ, &low, &high); 445 1.2 christos tt_int_op(low, ==, 10); 446 1.2 christos tt_int_op(high, ==, 20); 447 1.2 christos 448 1.1 christos /* Tell the sending bufferevent not to notify us till it's down to 449 1.1 christos 100 bytes. */ 450 1.1 christos bufferevent_setwatermark(bev1, EV_WRITE, 100, 2000); 451 1.1 christos 452 1.2 christos bufferevent_getwatermark(bev1, EV_WRITE, &low, &high); 453 1.2 christos tt_int_op(low, ==, 100); 454 1.2 christos tt_int_op(high, ==, 2000); 455 1.2 christos 456 1.3 christos { 457 1.3 christos int r = bufferevent_getwatermark(bev1, EV_WRITE | EV_READ, &low, &high); 458 1.3 christos tt_int_op(r, !=, 0); 459 1.3 christos } 460 1.3 christos 461 1.1 christos bufferevent_write(bev1, buffer, sizeof(buffer)); 462 1.1 christos 463 1.1 christos event_dispatch(); 464 1.1 christos 465 1.1 christos tt_int_op(test_ok, ==, 2); 466 1.1 christos 467 1.1 christos /* The write callback drained all the data from outbuf, so we 468 1.1 christos * should have removed the write event... */ 469 1.1 christos tt_assert(!event_pending(&bev2->ev_write, EV_WRITE, NULL)); 470 1.1 christos 471 1.1 christos end: 472 1.1 christos if (bev1) 473 1.1 christos bufferevent_free(bev1); 474 1.1 christos if (bev2) 475 1.1 christos bufferevent_free(bev2); 476 1.1 christos } 477 1.1 christos 478 1.1 christos static void 479 1.1 christos test_bufferevent_watermarks(void) 480 1.1 christos { 481 1.1 christos test_bufferevent_watermarks_impl(0); 482 1.1 christos } 483 1.1 christos 484 1.1 christos static void 485 1.1 christos test_bufferevent_pair_watermarks(void) 486 1.1 christos { 487 1.1 christos test_bufferevent_watermarks_impl(1); 488 1.1 christos } 489 1.1 christos 490 1.1 christos /* 491 1.1 christos * Test bufferevent filters 492 1.1 christos */ 493 1.1 christos 494 1.1 christos /* strip an 'x' from each byte */ 495 1.1 christos 496 1.1 christos static enum bufferevent_filter_result 497 1.1 christos bufferevent_input_filter(struct evbuffer *src, struct evbuffer *dst, 498 1.1 christos ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 499 1.1 christos { 500 1.1 christos const unsigned char *buffer; 501 1.1 christos unsigned i; 502 1.1 christos 503 1.1 christos buffer = evbuffer_pullup(src, evbuffer_get_length(src)); 504 1.1 christos for (i = 0; i < evbuffer_get_length(src); i += 2) { 505 1.7 christos if (buffer[i] == '-') 506 1.7 christos continue; 507 1.7 christos 508 1.1 christos assert(buffer[i] == 'x'); 509 1.1 christos evbuffer_add(dst, buffer + i + 1, 1); 510 1.1 christos } 511 1.1 christos 512 1.1 christos evbuffer_drain(src, i); 513 1.1 christos return (BEV_OK); 514 1.1 christos } 515 1.1 christos 516 1.1 christos /* add an 'x' before each byte */ 517 1.1 christos 518 1.1 christos static enum bufferevent_filter_result 519 1.1 christos bufferevent_output_filter(struct evbuffer *src, struct evbuffer *dst, 520 1.1 christos ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) 521 1.1 christos { 522 1.1 christos const unsigned char *buffer; 523 1.1 christos unsigned i; 524 1.7 christos struct bufferevent **bevp = ctx; 525 1.1 christos 526 1.7 christos ++test_ok; 527 1.7 christos 528 1.7 christos if (test_ok == 1) { 529 1.7 christos buffer = evbuffer_pullup(src, evbuffer_get_length(src)); 530 1.7 christos for (i = 0; i < evbuffer_get_length(src); ++i) { 531 1.7 christos evbuffer_add(dst, "x", 1); 532 1.7 christos evbuffer_add(dst, buffer + i, 1); 533 1.7 christos } 534 1.7 christos evbuffer_drain(src, evbuffer_get_length(src)); 535 1.7 christos } else { 536 1.7 christos return BEV_ERROR; 537 1.7 christos } 538 1.7 christos 539 1.7 christos if (bevp && test_ok == 1) { 540 1.7 christos int prev = ++test_ok; 541 1.7 christos bufferevent_write(*bevp, "-", 1); 542 1.7 christos /* check that during this bufferevent_write() 543 1.7 christos * bufferevent_output_filter() will not be called again */ 544 1.7 christos assert(test_ok == prev); 545 1.7 christos --test_ok; 546 1.1 christos } 547 1.1 christos 548 1.1 christos return (BEV_OK); 549 1.1 christos } 550 1.1 christos 551 1.1 christos static void 552 1.7 christos test_bufferevent_filters_impl(int use_pair, int disable) 553 1.1 christos { 554 1.1 christos struct bufferevent *bev1 = NULL, *bev2 = NULL; 555 1.1 christos struct bufferevent *bev1_base = NULL, *bev2_base = NULL; 556 1.1 christos char buffer[8333]; 557 1.1 christos int i; 558 1.1 christos 559 1.1 christos test_ok = 0; 560 1.1 christos 561 1.1 christos if (use_pair) { 562 1.1 christos struct bufferevent *pair[2]; 563 1.1 christos tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); 564 1.1 christos bev1 = pair[0]; 565 1.1 christos bev2 = pair[1]; 566 1.1 christos } else { 567 1.1 christos bev1 = bufferevent_socket_new(NULL, pair[0], 0); 568 1.1 christos bev2 = bufferevent_socket_new(NULL, pair[1], 0); 569 1.1 christos } 570 1.1 christos bev1_base = bev1; 571 1.1 christos bev2_base = bev2; 572 1.1 christos 573 1.1 christos for (i = 0; i < (int)sizeof(buffer); i++) 574 1.1 christos buffer[i] = i; 575 1.1 christos 576 1.1 christos bev1 = bufferevent_filter_new(bev1, NULL, bufferevent_output_filter, 577 1.7 christos BEV_OPT_CLOSE_ON_FREE, NULL, 578 1.7 christos disable ? &bev1 : NULL); 579 1.1 christos 580 1.1 christos bev2 = bufferevent_filter_new(bev2, bufferevent_input_filter, 581 1.1 christos NULL, BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 582 1.1 christos bufferevent_setcb(bev1, NULL, writecb, errorcb, NULL); 583 1.1 christos bufferevent_setcb(bev2, readcb, NULL, errorcb, NULL); 584 1.1 christos 585 1.1 christos tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev1_base); 586 1.1 christos tt_ptr_op(bufferevent_get_underlying(bev2), ==, bev2_base); 587 1.7 christos tt_fd_op(bufferevent_getfd(bev1), ==, bufferevent_getfd(bev1_base)); 588 1.7 christos tt_fd_op(bufferevent_getfd(bev2), ==, bufferevent_getfd(bev2_base)); 589 1.1 christos 590 1.1 christos bufferevent_disable(bev1, EV_READ); 591 1.1 christos bufferevent_enable(bev2, EV_READ); 592 1.1 christos /* insert some filters */ 593 1.1 christos bufferevent_write(bev1, buffer, sizeof(buffer)); 594 1.1 christos 595 1.1 christos event_dispatch(); 596 1.1 christos 597 1.7 christos if (test_ok != 3 + !!disable) 598 1.1 christos test_ok = 0; 599 1.1 christos 600 1.1 christos end: 601 1.1 christos if (bev1) 602 1.1 christos bufferevent_free(bev1); 603 1.1 christos if (bev2) 604 1.1 christos bufferevent_free(bev2); 605 1.1 christos 606 1.1 christos } 607 1.1 christos 608 1.7 christos static void test_bufferevent_filters(void) 609 1.7 christos { test_bufferevent_filters_impl(0, 0); } 610 1.7 christos static void test_bufferevent_pair_filters(void) 611 1.7 christos { test_bufferevent_filters_impl(1, 0); } 612 1.7 christos static void test_bufferevent_filters_disable(void) 613 1.7 christos { test_bufferevent_filters_impl(0, 1); } 614 1.7 christos static void test_bufferevent_pair_filters_disable(void) 615 1.7 christos { test_bufferevent_filters_impl(1, 1); } 616 1.1 christos 617 1.1 christos 618 1.1 christos static void 619 1.1 christos sender_writecb(struct bufferevent *bev, void *ctx) 620 1.1 christos { 621 1.1 christos if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) { 622 1.1 christos bufferevent_disable(bev,EV_READ|EV_WRITE); 623 1.2 christos TT_BLATHER(("Flushed %d: freeing it.", (int)bufferevent_getfd(bev))); 624 1.1 christos bufferevent_free(bev); 625 1.1 christos } 626 1.1 christos } 627 1.1 christos 628 1.1 christos static void 629 1.1 christos sender_errorcb(struct bufferevent *bev, short what, void *ctx) 630 1.1 christos { 631 1.1 christos TT_FAIL(("Got sender error %d",(int)what)); 632 1.1 christos } 633 1.1 christos 634 1.1 christos static int bufferevent_connect_test_flags = 0; 635 1.2 christos static int bufferevent_trigger_test_flags = 0; 636 1.1 christos static int n_strings_read = 0; 637 1.1 christos static int n_reads_invoked = 0; 638 1.7 christos static int n_events_invoked = 0; 639 1.1 christos 640 1.1 christos #define TEST_STR "Now is the time for all good events to signal for " \ 641 1.1 christos "the good of their protocol" 642 1.1 christos static void 643 1.1 christos listen_cb(struct evconnlistener *listener, evutil_socket_t fd, 644 1.1 christos struct sockaddr *sa, int socklen, void *arg) 645 1.1 christos { 646 1.1 christos struct event_base *base = arg; 647 1.1 christos struct bufferevent *bev; 648 1.1 christos const char s[] = TEST_STR; 649 1.1 christos TT_BLATHER(("Got a request on socket %d", (int)fd )); 650 1.1 christos bev = bufferevent_socket_new(base, fd, bufferevent_connect_test_flags); 651 1.1 christos tt_assert(bev); 652 1.1 christos bufferevent_setcb(bev, NULL, sender_writecb, sender_errorcb, NULL); 653 1.1 christos bufferevent_write(bev, s, sizeof(s)); 654 1.1 christos end: 655 1.1 christos ; 656 1.1 christos } 657 1.1 christos 658 1.7 christos static evutil_socket_t 659 1.7 christos fake_listener_create(struct sockaddr_in *localhost) 660 1.7 christos { 661 1.7 christos struct sockaddr *sa = (struct sockaddr *)localhost; 662 1.7 christos evutil_socket_t fd = -1; 663 1.7 christos ev_socklen_t slen = sizeof(*localhost); 664 1.7 christos 665 1.7 christos memset(localhost, 0, sizeof(*localhost)); 666 1.7 christos localhost->sin_port = 0; /* have the kernel pick a port */ 667 1.7 christos localhost->sin_addr.s_addr = htonl(0x7f000001L); 668 1.7 christos localhost->sin_family = AF_INET; 669 1.7 christos 670 1.7 christos /* bind, but don't listen or accept. should trigger 671 1.7 christos "Connection refused" reliably on most platforms. */ 672 1.7 christos fd = socket(localhost->sin_family, SOCK_STREAM, 0); 673 1.7 christos tt_assert(fd >= 0); 674 1.7 christos tt_assert(bind(fd, sa, slen) == 0); 675 1.7 christos tt_assert(getsockname(fd, sa, &slen) == 0); 676 1.7 christos 677 1.7 christos return fd; 678 1.7 christos 679 1.7 christos end: 680 1.7 christos return -1; 681 1.7 christos } 682 1.7 christos 683 1.1 christos static void 684 1.1 christos reader_eventcb(struct bufferevent *bev, short what, void *ctx) 685 1.1 christos { 686 1.1 christos struct event_base *base = ctx; 687 1.1 christos if (what & BEV_EVENT_ERROR) { 688 1.1 christos perror("foobar"); 689 1.1 christos TT_FAIL(("got connector error %d", (int)what)); 690 1.1 christos return; 691 1.1 christos } 692 1.1 christos if (what & BEV_EVENT_CONNECTED) { 693 1.2 christos TT_BLATHER(("connected on %d", (int)bufferevent_getfd(bev))); 694 1.1 christos bufferevent_enable(bev, EV_READ); 695 1.1 christos } 696 1.1 christos if (what & BEV_EVENT_EOF) { 697 1.1 christos char buf[512]; 698 1.1 christos size_t n; 699 1.1 christos n = bufferevent_read(bev, buf, sizeof(buf)-1); 700 1.2 christos tt_int_op(n, >=, 0); 701 1.1 christos buf[n] = '\0'; 702 1.1 christos tt_str_op(buf, ==, TEST_STR); 703 1.1 christos if (++n_strings_read == 2) 704 1.1 christos event_base_loopexit(base, NULL); 705 1.2 christos TT_BLATHER(("EOF on %d: %d strings read.", 706 1.2 christos (int)bufferevent_getfd(bev), n_strings_read)); 707 1.1 christos } 708 1.1 christos end: 709 1.1 christos ; 710 1.1 christos } 711 1.1 christos 712 1.1 christos static void 713 1.7 christos reader_eventcb_simple(struct bufferevent *bev, short what, void *ctx) 714 1.7 christos { 715 1.7 christos TT_BLATHER(("Read eventcb simple invoked on %d.", 716 1.7 christos (int)bufferevent_getfd(bev))); 717 1.7 christos n_events_invoked++; 718 1.7 christos } 719 1.7 christos 720 1.7 christos static void 721 1.1 christos reader_readcb(struct bufferevent *bev, void *ctx) 722 1.1 christos { 723 1.2 christos TT_BLATHER(("Read invoked on %d.", (int)bufferevent_getfd(bev))); 724 1.1 christos n_reads_invoked++; 725 1.1 christos } 726 1.1 christos 727 1.1 christos static void 728 1.1 christos test_bufferevent_connect(void *arg) 729 1.1 christos { 730 1.1 christos struct basic_test_data *data = arg; 731 1.1 christos struct evconnlistener *lev=NULL; 732 1.1 christos struct bufferevent *bev1=NULL, *bev2=NULL; 733 1.1 christos struct sockaddr_in localhost; 734 1.1 christos struct sockaddr_storage ss; 735 1.1 christos struct sockaddr *sa; 736 1.1 christos ev_socklen_t slen; 737 1.1 christos 738 1.1 christos int be_flags=BEV_OPT_CLOSE_ON_FREE; 739 1.1 christos 740 1.1 christos if (strstr((char*)data->setup_data, "defer")) { 741 1.1 christos be_flags |= BEV_OPT_DEFER_CALLBACKS; 742 1.1 christos } 743 1.1 christos if (strstr((char*)data->setup_data, "unlocked")) { 744 1.1 christos be_flags |= BEV_OPT_UNLOCK_CALLBACKS; 745 1.1 christos } 746 1.1 christos if (strstr((char*)data->setup_data, "lock")) { 747 1.1 christos be_flags |= BEV_OPT_THREADSAFE; 748 1.1 christos } 749 1.1 christos bufferevent_connect_test_flags = be_flags; 750 1.1 christos #ifdef _WIN32 751 1.1 christos if (!strcmp((char*)data->setup_data, "unset_connectex")) { 752 1.1 christos struct win32_extension_fns *ext = 753 1.1 christos (struct win32_extension_fns *) 754 1.1 christos event_get_win32_extension_fns_(); 755 1.1 christos ext->ConnectEx = NULL; 756 1.1 christos } 757 1.1 christos #endif 758 1.1 christos 759 1.1 christos memset(&localhost, 0, sizeof(localhost)); 760 1.1 christos 761 1.1 christos localhost.sin_port = 0; /* pick-a-port */ 762 1.1 christos localhost.sin_addr.s_addr = htonl(0x7f000001L); 763 1.1 christos localhost.sin_family = AF_INET; 764 1.1 christos sa = (struct sockaddr *)&localhost; 765 1.1 christos lev = evconnlistener_new_bind(data->base, listen_cb, data->base, 766 1.1 christos LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 767 1.1 christos 16, sa, sizeof(localhost)); 768 1.1 christos tt_assert(lev); 769 1.1 christos 770 1.1 christos sa = (struct sockaddr *)&ss; 771 1.1 christos slen = sizeof(ss); 772 1.1 christos if (regress_get_listener_addr(lev, sa, &slen) < 0) { 773 1.1 christos tt_abort_perror("getsockname"); 774 1.1 christos } 775 1.1 christos 776 1.1 christos tt_assert(!evconnlistener_enable(lev)); 777 1.1 christos bev1 = bufferevent_socket_new(data->base, -1, be_flags); 778 1.1 christos bev2 = bufferevent_socket_new(data->base, -1, be_flags); 779 1.1 christos tt_assert(bev1); 780 1.1 christos tt_assert(bev2); 781 1.1 christos bufferevent_setcb(bev1, reader_readcb,NULL, reader_eventcb, data->base); 782 1.1 christos bufferevent_setcb(bev2, reader_readcb,NULL, reader_eventcb, data->base); 783 1.1 christos 784 1.1 christos bufferevent_enable(bev1, EV_READ); 785 1.1 christos bufferevent_enable(bev2, EV_READ); 786 1.1 christos 787 1.1 christos tt_want(!bufferevent_socket_connect(bev1, sa, sizeof(localhost))); 788 1.1 christos tt_want(!bufferevent_socket_connect(bev2, sa, sizeof(localhost))); 789 1.1 christos 790 1.1 christos event_base_dispatch(data->base); 791 1.1 christos 792 1.1 christos tt_int_op(n_strings_read, ==, 2); 793 1.1 christos tt_int_op(n_reads_invoked, >=, 2); 794 1.1 christos end: 795 1.1 christos if (lev) 796 1.1 christos evconnlistener_free(lev); 797 1.1 christos 798 1.1 christos if (bev1) 799 1.1 christos bufferevent_free(bev1); 800 1.1 christos 801 1.1 christos if (bev2) 802 1.1 christos bufferevent_free(bev2); 803 1.1 christos } 804 1.1 christos 805 1.1 christos static void 806 1.7 christos close_socket_cb(evutil_socket_t fd, short what, void *arg) 807 1.7 christos { 808 1.7 christos evutil_socket_t *fdp = arg; 809 1.7 christos if (*fdp >= 0) { 810 1.7 christos evutil_closesocket(*fdp); 811 1.7 christos *fdp = -1; 812 1.7 christos } 813 1.7 christos } 814 1.7 christos 815 1.7 christos static void 816 1.7 christos test_bufferevent_connect_fail_eventcb(void *arg) 817 1.7 christos { 818 1.7 christos struct basic_test_data *data = arg; 819 1.7 christos int flags = BEV_OPT_CLOSE_ON_FREE | (long)data->setup_data; 820 1.7 christos struct event close_listener_event; 821 1.7 christos struct bufferevent *bev = NULL; 822 1.7 christos struct evconnlistener *lev = NULL; 823 1.7 christos struct sockaddr_in localhost; 824 1.7 christos struct timeval close_timeout = { 0, 300000 }; 825 1.7 christos ev_socklen_t slen = sizeof(localhost); 826 1.7 christos evutil_socket_t fake_listener = -1; 827 1.7 christos int r; 828 1.7 christos 829 1.7 christos fake_listener = fake_listener_create(&localhost); 830 1.7 christos 831 1.7 christos tt_int_op(n_events_invoked, ==, 0); 832 1.7 christos 833 1.7 christos bev = bufferevent_socket_new(data->base, -1, flags); 834 1.7 christos tt_assert(bev); 835 1.7 christos bufferevent_setcb(bev, reader_readcb, reader_readcb, 836 1.7 christos reader_eventcb_simple, data->base); 837 1.7 christos bufferevent_enable(bev, EV_READ|EV_WRITE); 838 1.7 christos tt_int_op(n_events_invoked, ==, 0); 839 1.7 christos tt_int_op(n_reads_invoked, ==, 0); 840 1.7 christos 841 1.7 christos /** @see also test_bufferevent_connect_fail() */ 842 1.7 christos r = bufferevent_socket_connect(bev, (struct sockaddr *)&localhost, slen); 843 1.7 christos /* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells 844 1.7 christos * detects the error immediately, which is not really wrong of it. */ 845 1.7 christos tt_want(r == 0 || r == -1); 846 1.7 christos 847 1.7 christos tt_int_op(n_events_invoked, ==, 0); 848 1.7 christos tt_int_op(n_reads_invoked, ==, 0); 849 1.7 christos 850 1.7 christos /* Close the listener socket after a delay. This should trigger 851 1.7 christos "connection refused" on some other platforms, including OSX. */ 852 1.7 christos evtimer_assign(&close_listener_event, data->base, close_socket_cb, 853 1.7 christos &fake_listener); 854 1.7 christos event_add(&close_listener_event, &close_timeout); 855 1.7 christos 856 1.7 christos event_base_dispatch(data->base); 857 1.7 christos tt_int_op(n_events_invoked, ==, 1); 858 1.7 christos tt_int_op(n_reads_invoked, ==, 0); 859 1.7 christos 860 1.7 christos end: 861 1.7 christos if (lev) 862 1.7 christos evconnlistener_free(lev); 863 1.7 christos if (bev) 864 1.7 christos bufferevent_free(bev); 865 1.7 christos if (fake_listener >= 0) 866 1.7 christos evutil_closesocket(fake_listener); 867 1.7 christos } 868 1.7 christos 869 1.7 christos static void 870 1.1 christos want_fail_eventcb(struct bufferevent *bev, short what, void *ctx) 871 1.1 christos { 872 1.1 christos struct event_base *base = ctx; 873 1.1 christos const char *err; 874 1.1 christos evutil_socket_t s; 875 1.1 christos 876 1.1 christos if (what & BEV_EVENT_ERROR) { 877 1.1 christos s = bufferevent_getfd(bev); 878 1.1 christos err = evutil_socket_error_to_string(evutil_socket_geterror(s)); 879 1.1 christos TT_BLATHER(("connection failure on "EV_SOCK_FMT": %s", 880 1.1 christos EV_SOCK_ARG(s), err)); 881 1.1 christos test_ok = 1; 882 1.1 christos } else { 883 1.1 christos TT_FAIL(("didn't fail? what %hd", what)); 884 1.1 christos } 885 1.1 christos 886 1.1 christos event_base_loopexit(base, NULL); 887 1.1 christos } 888 1.1 christos 889 1.1 christos static void 890 1.1 christos test_bufferevent_connect_fail(void *arg) 891 1.1 christos { 892 1.2 christos struct basic_test_data *data = (struct basic_test_data *)arg; 893 1.1 christos struct bufferevent *bev=NULL; 894 1.7 christos struct event close_listener_event; 895 1.7 christos int close_listener_event_added = 0; 896 1.7 christos struct timeval close_timeout = { 0, 300000 }; 897 1.1 christos struct sockaddr_in localhost; 898 1.7 christos ev_socklen_t slen = sizeof(localhost); 899 1.1 christos evutil_socket_t fake_listener = -1; 900 1.1 christos int r; 901 1.1 christos 902 1.1 christos test_ok = 0; 903 1.1 christos 904 1.7 christos fake_listener = fake_listener_create(&localhost); 905 1.1 christos bev = bufferevent_socket_new(data->base, -1, 906 1.1 christos BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); 907 1.1 christos tt_assert(bev); 908 1.1 christos bufferevent_setcb(bev, NULL, NULL, want_fail_eventcb, data->base); 909 1.1 christos 910 1.7 christos r = bufferevent_socket_connect(bev, (struct sockaddr *)&localhost, slen); 911 1.1 christos /* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells 912 1.1 christos * detects the error immediately, which is not really wrong of it. */ 913 1.1 christos tt_want(r == 0 || r == -1); 914 1.1 christos 915 1.7 christos /* Close the listener socket after a delay. This should trigger 916 1.1 christos "connection refused" on some other platforms, including OSX. */ 917 1.1 christos evtimer_assign(&close_listener_event, data->base, close_socket_cb, 918 1.1 christos &fake_listener); 919 1.7 christos event_add(&close_listener_event, &close_timeout); 920 1.1 christos close_listener_event_added = 1; 921 1.1 christos 922 1.1 christos event_base_dispatch(data->base); 923 1.1 christos 924 1.1 christos tt_int_op(test_ok, ==, 1); 925 1.1 christos 926 1.1 christos end: 927 1.1 christos if (fake_listener >= 0) 928 1.1 christos evutil_closesocket(fake_listener); 929 1.1 christos 930 1.1 christos if (bev) 931 1.1 christos bufferevent_free(bev); 932 1.1 christos 933 1.1 christos if (close_listener_event_added) 934 1.1 christos event_del(&close_listener_event); 935 1.1 christos } 936 1.1 christos 937 1.1 christos struct timeout_cb_result { 938 1.1 christos struct timeval read_timeout_at; 939 1.1 christos struct timeval write_timeout_at; 940 1.1 christos struct timeval last_wrote_at; 941 1.7 christos struct timeval last_read_at; 942 1.1 christos int n_read_timeouts; 943 1.1 christos int n_write_timeouts; 944 1.1 christos int total_calls; 945 1.1 christos }; 946 1.1 christos 947 1.1 christos static void 948 1.7 christos bev_timeout_read_cb(struct bufferevent *bev, void *arg) 949 1.7 christos { 950 1.7 christos struct timeout_cb_result *res = arg; 951 1.7 christos evutil_gettimeofday(&res->last_read_at, NULL); 952 1.7 christos } 953 1.7 christos static void 954 1.1 christos bev_timeout_write_cb(struct bufferevent *bev, void *arg) 955 1.1 christos { 956 1.1 christos struct timeout_cb_result *res = arg; 957 1.1 christos evutil_gettimeofday(&res->last_wrote_at, NULL); 958 1.1 christos } 959 1.1 christos static void 960 1.1 christos bev_timeout_event_cb(struct bufferevent *bev, short what, void *arg) 961 1.1 christos { 962 1.1 christos struct timeout_cb_result *res = arg; 963 1.1 christos ++res->total_calls; 964 1.1 christos 965 1.1 christos if ((what & (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) 966 1.1 christos == (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) { 967 1.1 christos evutil_gettimeofday(&res->read_timeout_at, NULL); 968 1.1 christos ++res->n_read_timeouts; 969 1.1 christos } 970 1.1 christos if ((what & (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) 971 1.1 christos == (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) { 972 1.1 christos evutil_gettimeofday(&res->write_timeout_at, NULL); 973 1.1 christos ++res->n_write_timeouts; 974 1.1 christos } 975 1.1 christos } 976 1.1 christos 977 1.1 christos static void 978 1.1 christos test_bufferevent_timeouts(void *arg) 979 1.1 christos { 980 1.1 christos /* "arg" is a string containing "pair" and/or "filter". */ 981 1.1 christos struct bufferevent *bev1 = NULL, *bev2 = NULL; 982 1.1 christos struct basic_test_data *data = arg; 983 1.1 christos int use_pair = 0, use_filter = 0; 984 1.1 christos struct timeval tv_w, tv_r, started_at; 985 1.1 christos struct timeout_cb_result res1, res2; 986 1.1 christos 987 1.1 christos memset(&res1, 0, sizeof(res1)); 988 1.1 christos memset(&res2, 0, sizeof(res2)); 989 1.1 christos 990 1.1 christos if (strstr((char*)data->setup_data, "pair")) 991 1.1 christos use_pair = 1; 992 1.1 christos if (strstr((char*)data->setup_data, "filter")) 993 1.1 christos use_filter = 1; 994 1.1 christos 995 1.1 christos if (use_pair) { 996 1.1 christos struct bufferevent *p[2]; 997 1.1 christos tt_int_op(0, ==, bufferevent_pair_new(data->base, 0, p)); 998 1.1 christos bev1 = p[0]; 999 1.1 christos bev2 = p[1]; 1000 1.1 christos } else { 1001 1.1 christos bev1 = bufferevent_socket_new(data->base, data->pair[0], 0); 1002 1.1 christos bev2 = bufferevent_socket_new(data->base, data->pair[1], 0); 1003 1.1 christos } 1004 1.1 christos tt_assert(bev1); 1005 1.1 christos tt_assert(bev2); 1006 1.1 christos 1007 1.1 christos if (use_filter) { 1008 1.1 christos struct bufferevent *bevf1, *bevf2; 1009 1.1 christos bevf1 = bufferevent_filter_new(bev1, NULL, NULL, 1010 1.1 christos BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 1011 1.1 christos bevf2 = bufferevent_filter_new(bev2, NULL, NULL, 1012 1.1 christos BEV_OPT_CLOSE_ON_FREE, NULL, NULL); 1013 1.1 christos tt_assert(bevf1); 1014 1.1 christos tt_assert(bevf2); 1015 1.1 christos bev1 = bevf1; 1016 1.1 christos bev2 = bevf2; 1017 1.1 christos } 1018 1.1 christos 1019 1.1 christos /* Do this nice and early. */ 1020 1.1 christos bufferevent_disable(bev2, EV_READ); 1021 1.1 christos 1022 1.1 christos /* bev1 will try to write and read. Both will time out. */ 1023 1.1 christos evutil_gettimeofday(&started_at, NULL); 1024 1.1 christos tv_w.tv_sec = tv_r.tv_sec = 0; 1025 1.1 christos tv_w.tv_usec = 100*1000; 1026 1.1 christos tv_r.tv_usec = 150*1000; 1027 1.7 christos bufferevent_setcb(bev1, bev_timeout_read_cb, bev_timeout_write_cb, 1028 1.1 christos bev_timeout_event_cb, &res1); 1029 1.1 christos bufferevent_set_timeouts(bev1, &tv_r, &tv_w); 1030 1.7 christos bufferevent_write(bev1, "ABCDEFG", 7); 1031 1.1 christos bufferevent_enable(bev1, EV_READ|EV_WRITE); 1032 1.1 christos 1033 1.1 christos /* bev2 has nothing to say, and isn't listening. */ 1034 1.7 christos bufferevent_setcb(bev2, bev_timeout_read_cb, bev_timeout_write_cb, 1035 1.1 christos bev_timeout_event_cb, &res2); 1036 1.1 christos tv_w.tv_sec = tv_r.tv_sec = 0; 1037 1.1 christos tv_w.tv_usec = 200*1000; 1038 1.1 christos tv_r.tv_usec = 100*1000; 1039 1.1 christos bufferevent_set_timeouts(bev2, &tv_r, &tv_w); 1040 1.1 christos bufferevent_enable(bev2, EV_WRITE); 1041 1.1 christos 1042 1.1 christos tv_r.tv_sec = 0; 1043 1.1 christos tv_r.tv_usec = 350000; 1044 1.1 christos 1045 1.1 christos event_base_loopexit(data->base, &tv_r); 1046 1.1 christos event_base_dispatch(data->base); 1047 1.1 christos 1048 1.1 christos /* XXXX Test that actually reading or writing a little resets the 1049 1.1 christos * timeouts. */ 1050 1.1 christos 1051 1.7 christos tt_want(res1.total_calls == 2); 1052 1.1 christos tt_want(res1.n_read_timeouts == 1); 1053 1.1 christos tt_want(res1.n_write_timeouts == 1); 1054 1.7 christos tt_want(res2.total_calls == !(use_pair && !use_filter)); 1055 1.7 christos tt_want(res2.n_write_timeouts == !(use_pair && !use_filter)); 1056 1.7 christos tt_want(!res2.n_read_timeouts); 1057 1.1 christos 1058 1.1 christos test_timeval_diff_eq(&started_at, &res1.read_timeout_at, 150); 1059 1.1 christos test_timeval_diff_eq(&started_at, &res1.write_timeout_at, 100); 1060 1.1 christos 1061 1.7 christos #define tt_assert_timeval_empty(tv) do { \ 1062 1.7 christos tt_int_op((tv).tv_sec, ==, 0); \ 1063 1.7 christos tt_int_op((tv).tv_usec, ==, 0); \ 1064 1.7 christos } while(0) 1065 1.7 christos tt_assert_timeval_empty(res1.last_read_at); 1066 1.7 christos tt_assert_timeval_empty(res2.last_read_at); 1067 1.7 christos tt_assert_timeval_empty(res2.last_wrote_at); 1068 1.7 christos tt_assert_timeval_empty(res2.last_wrote_at); 1069 1.7 christos #undef tt_assert_timeval_empty 1070 1.7 christos 1071 1.1 christos end: 1072 1.1 christos if (bev1) 1073 1.1 christos bufferevent_free(bev1); 1074 1.1 christos if (bev2) 1075 1.1 christos bufferevent_free(bev2); 1076 1.1 christos } 1077 1.1 christos 1078 1.2 christos static void 1079 1.2 christos trigger_failure_cb(evutil_socket_t fd, short what, void *ctx) 1080 1.2 christos { 1081 1.2 christos TT_FAIL(("The triggered callback did not fire or the machine is really slow (try increasing timeout).")); 1082 1.2 christos } 1083 1.2 christos 1084 1.2 christos static void 1085 1.2 christos trigger_eventcb(struct bufferevent *bev, short what, void *ctx) 1086 1.2 christos { 1087 1.2 christos struct event_base *base = ctx; 1088 1.2 christos if (what == ~0) { 1089 1.2 christos TT_BLATHER(("Event successfully triggered.")); 1090 1.2 christos event_base_loopexit(base, NULL); 1091 1.2 christos return; 1092 1.2 christos } 1093 1.2 christos reader_eventcb(bev, what, ctx); 1094 1.2 christos } 1095 1.2 christos 1096 1.2 christos static void 1097 1.2 christos trigger_readcb_triggered(struct bufferevent *bev, void *ctx) 1098 1.2 christos { 1099 1.2 christos TT_BLATHER(("Read successfully triggered.")); 1100 1.2 christos n_reads_invoked++; 1101 1.2 christos bufferevent_trigger_event(bev, ~0, bufferevent_trigger_test_flags); 1102 1.2 christos } 1103 1.2 christos 1104 1.2 christos static void 1105 1.2 christos trigger_readcb(struct bufferevent *bev, void *ctx) 1106 1.2 christos { 1107 1.2 christos struct timeval timeout = { 30, 0 }; 1108 1.2 christos struct event_base *base = ctx; 1109 1.2 christos size_t low, high, len; 1110 1.2 christos int expected_reads; 1111 1.2 christos 1112 1.2 christos TT_BLATHER(("Read invoked on %d.", (int)bufferevent_getfd(bev))); 1113 1.2 christos expected_reads = ++n_reads_invoked; 1114 1.2 christos 1115 1.2 christos bufferevent_setcb(bev, trigger_readcb_triggered, NULL, trigger_eventcb, ctx); 1116 1.2 christos 1117 1.2 christos bufferevent_getwatermark(bev, EV_READ, &low, &high); 1118 1.2 christos len = evbuffer_get_length(bufferevent_get_input(bev)); 1119 1.2 christos 1120 1.2 christos bufferevent_setwatermark(bev, EV_READ, len + 1, 0); 1121 1.2 christos bufferevent_trigger(bev, EV_READ, bufferevent_trigger_test_flags); 1122 1.2 christos /* no callback expected */ 1123 1.2 christos tt_int_op(n_reads_invoked, ==, expected_reads); 1124 1.2 christos 1125 1.2 christos if ((bufferevent_trigger_test_flags & BEV_TRIG_DEFER_CALLBACKS) || 1126 1.2 christos (bufferevent_connect_test_flags & BEV_OPT_DEFER_CALLBACKS)) { 1127 1.2 christos /* will be deferred */ 1128 1.2 christos } else { 1129 1.2 christos expected_reads++; 1130 1.2 christos } 1131 1.2 christos 1132 1.2 christos event_base_once(base, -1, EV_TIMEOUT, trigger_failure_cb, NULL, &timeout); 1133 1.2 christos 1134 1.2 christos bufferevent_trigger(bev, EV_READ, 1135 1.2 christos bufferevent_trigger_test_flags | BEV_TRIG_IGNORE_WATERMARKS); 1136 1.2 christos tt_int_op(n_reads_invoked, ==, expected_reads); 1137 1.2 christos 1138 1.2 christos bufferevent_setwatermark(bev, EV_READ, low, high); 1139 1.2 christos end: 1140 1.2 christos ; 1141 1.2 christos } 1142 1.2 christos 1143 1.2 christos static void 1144 1.2 christos test_bufferevent_trigger(void *arg) 1145 1.2 christos { 1146 1.2 christos struct basic_test_data *data = arg; 1147 1.2 christos struct evconnlistener *lev=NULL; 1148 1.2 christos struct bufferevent *bev=NULL; 1149 1.2 christos struct sockaddr_in localhost; 1150 1.2 christos struct sockaddr_storage ss; 1151 1.2 christos struct sockaddr *sa; 1152 1.2 christos ev_socklen_t slen; 1153 1.2 christos 1154 1.2 christos int be_flags=BEV_OPT_CLOSE_ON_FREE; 1155 1.2 christos int trig_flags=0; 1156 1.2 christos 1157 1.2 christos if (strstr((char*)data->setup_data, "defer")) { 1158 1.2 christos be_flags |= BEV_OPT_DEFER_CALLBACKS; 1159 1.2 christos } 1160 1.2 christos bufferevent_connect_test_flags = be_flags; 1161 1.2 christos 1162 1.2 christos if (strstr((char*)data->setup_data, "postpone")) { 1163 1.2 christos trig_flags |= BEV_TRIG_DEFER_CALLBACKS; 1164 1.2 christos } 1165 1.2 christos bufferevent_trigger_test_flags = trig_flags; 1166 1.2 christos 1167 1.2 christos memset(&localhost, 0, sizeof(localhost)); 1168 1.2 christos 1169 1.2 christos localhost.sin_port = 0; /* pick-a-port */ 1170 1.2 christos localhost.sin_addr.s_addr = htonl(0x7f000001L); 1171 1.2 christos localhost.sin_family = AF_INET; 1172 1.2 christos sa = (struct sockaddr *)&localhost; 1173 1.2 christos lev = evconnlistener_new_bind(data->base, listen_cb, data->base, 1174 1.2 christos LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 1175 1.2 christos 16, sa, sizeof(localhost)); 1176 1.2 christos tt_assert(lev); 1177 1.2 christos 1178 1.2 christos sa = (struct sockaddr *)&ss; 1179 1.2 christos slen = sizeof(ss); 1180 1.2 christos if (regress_get_listener_addr(lev, sa, &slen) < 0) { 1181 1.2 christos tt_abort_perror("getsockname"); 1182 1.2 christos } 1183 1.2 christos 1184 1.2 christos tt_assert(!evconnlistener_enable(lev)); 1185 1.2 christos bev = bufferevent_socket_new(data->base, -1, be_flags); 1186 1.2 christos tt_assert(bev); 1187 1.2 christos bufferevent_setcb(bev, trigger_readcb, NULL, trigger_eventcb, data->base); 1188 1.2 christos 1189 1.2 christos bufferevent_enable(bev, EV_READ); 1190 1.2 christos 1191 1.2 christos tt_want(!bufferevent_socket_connect(bev, sa, sizeof(localhost))); 1192 1.2 christos 1193 1.2 christos event_base_dispatch(data->base); 1194 1.2 christos 1195 1.2 christos tt_int_op(n_reads_invoked, ==, 2); 1196 1.2 christos end: 1197 1.2 christos if (lev) 1198 1.2 christos evconnlistener_free(lev); 1199 1.2 christos 1200 1.2 christos if (bev) 1201 1.2 christos bufferevent_free(bev); 1202 1.2 christos } 1203 1.2 christos 1204 1.7 christos static void 1205 1.7 christos test_bufferevent_socket_filter_inactive(void *arg) 1206 1.7 christos { 1207 1.7 christos struct basic_test_data *data = arg; 1208 1.7 christos struct bufferevent *bev = NULL, *bevf = NULL; 1209 1.7 christos 1210 1.7 christos bev = bufferevent_socket_new(data->base, -1, 0); 1211 1.7 christos tt_assert(bev); 1212 1.7 christos bevf = bufferevent_filter_new(bev, NULL, NULL, 0, NULL, NULL); 1213 1.7 christos tt_assert(bevf); 1214 1.7 christos 1215 1.7 christos end: 1216 1.7 christos if (bevf) 1217 1.7 christos bufferevent_free(bevf); 1218 1.7 christos if (bev) 1219 1.7 christos bufferevent_free(bev); 1220 1.7 christos } 1221 1.7 christos 1222 1.7 christos static void 1223 1.7 christos pair_flush_eventcb(struct bufferevent *bev, short what, void *ctx) 1224 1.7 christos { 1225 1.7 christos int *callback_what = ctx; 1226 1.7 christos *callback_what = what; 1227 1.7 christos } 1228 1.7 christos 1229 1.7 christos static void 1230 1.7 christos test_bufferevent_pair_flush(void *arg) 1231 1.7 christos { 1232 1.7 christos struct basic_test_data *data = arg; 1233 1.7 christos struct bufferevent *pair[2]; 1234 1.7 christos struct bufferevent *bev1 = NULL; 1235 1.7 christos struct bufferevent *bev2 = NULL; 1236 1.7 christos int callback_what = 0; 1237 1.7 christos 1238 1.7 christos tt_assert(0 == bufferevent_pair_new(data->base, 0, pair)); 1239 1.7 christos bev1 = pair[0]; 1240 1.7 christos bev2 = pair[1]; 1241 1.7 christos tt_assert(0 == bufferevent_enable(bev1, EV_WRITE)); 1242 1.7 christos tt_assert(0 == bufferevent_enable(bev2, EV_READ)); 1243 1.7 christos 1244 1.7 christos bufferevent_setcb(bev2, NULL, NULL, pair_flush_eventcb, &callback_what); 1245 1.7 christos 1246 1.7 christos bufferevent_flush(bev1, EV_WRITE, BEV_FINISHED); 1247 1.7 christos 1248 1.7 christos event_base_loop(data->base, EVLOOP_ONCE); 1249 1.7 christos 1250 1.7 christos tt_assert(callback_what == (BEV_EVENT_READING | BEV_EVENT_EOF)); 1251 1.7 christos 1252 1.7 christos end: 1253 1.7 christos if (bev1) 1254 1.7 christos bufferevent_free(bev1); 1255 1.7 christos if (bev2) 1256 1.7 christos bufferevent_free(bev2); 1257 1.7 christos } 1258 1.7 christos 1259 1.7 christos struct bufferevent_filter_data_stuck { 1260 1.7 christos size_t header_size; 1261 1.7 christos size_t total_read; 1262 1.7 christos }; 1263 1.7 christos 1264 1.7 christos static void 1265 1.7 christos bufferevent_filter_data_stuck_readcb(struct bufferevent *bev, void *arg) 1266 1.7 christos { 1267 1.7 christos struct bufferevent_filter_data_stuck *filter_data = arg; 1268 1.7 christos struct evbuffer *input = bufferevent_get_input(bev); 1269 1.7 christos size_t read_size = evbuffer_get_length(input); 1270 1.7 christos evbuffer_drain(input, read_size); 1271 1.7 christos filter_data->total_read += read_size; 1272 1.7 christos } 1273 1.7 christos 1274 1.7 christos /** 1275 1.7 christos * This filter prepends header once before forwarding data. 1276 1.7 christos */ 1277 1.7 christos static enum bufferevent_filter_result 1278 1.7 christos bufferevent_filter_data_stuck_inputcb( 1279 1.7 christos struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit, 1280 1.7 christos enum bufferevent_flush_mode mode, void *ctx) 1281 1.7 christos { 1282 1.7 christos struct bufferevent_filter_data_stuck *filter_data = ctx; 1283 1.7 christos static int header_inserted = 0; 1284 1.7 christos size_t payload_size; 1285 1.7 christos size_t header_size = 0; 1286 1.7 christos 1287 1.7 christos if (!header_inserted) { 1288 1.7 christos char *header = calloc(filter_data->header_size, 1); 1289 1.7 christos evbuffer_add(dst, header, filter_data->header_size); 1290 1.7 christos free(header); 1291 1.7 christos header_size = filter_data->header_size; 1292 1.7 christos header_inserted = 1; 1293 1.7 christos } 1294 1.7 christos 1295 1.7 christos payload_size = evbuffer_get_length(src); 1296 1.7 christos if (payload_size > dst_limit - header_size) { 1297 1.7 christos payload_size = dst_limit - header_size; 1298 1.7 christos } 1299 1.7 christos 1300 1.7 christos tt_int_op(payload_size, ==, evbuffer_remove_buffer(src, dst, payload_size)); 1301 1.7 christos 1302 1.7 christos end: 1303 1.7 christos return BEV_OK; 1304 1.7 christos } 1305 1.7 christos 1306 1.7 christos static void 1307 1.7 christos test_bufferevent_filter_data_stuck(void *arg) 1308 1.7 christos { 1309 1.7 christos const size_t read_high_wm = 4096; 1310 1.7 christos struct bufferevent_filter_data_stuck filter_data; 1311 1.7 christos struct basic_test_data *data = arg; 1312 1.7 christos struct bufferevent *pair[2]; 1313 1.7 christos struct bufferevent *filter = NULL; 1314 1.7 christos 1315 1.7 christos int options = BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS; 1316 1.7 christos 1317 1.7 christos char payload[4096]; 1318 1.7 christos int payload_size = sizeof(payload); 1319 1.7 christos 1320 1.7 christos memset(&filter_data, 0, sizeof(filter_data)); 1321 1.7 christos filter_data.header_size = 20; 1322 1.7 christos 1323 1.7 christos tt_assert(bufferevent_pair_new(data->base, options, pair) == 0); 1324 1.7 christos 1325 1.7 christos bufferevent_setwatermark(pair[0], EV_READ, 0, read_high_wm); 1326 1.7 christos bufferevent_setwatermark(pair[1], EV_READ, 0, read_high_wm); 1327 1.7 christos 1328 1.7 christos tt_assert( 1329 1.7 christos filter = 1330 1.7 christos bufferevent_filter_new(pair[1], 1331 1.7 christos bufferevent_filter_data_stuck_inputcb, 1332 1.7 christos NULL, 1333 1.7 christos options, 1334 1.7 christos NULL, 1335 1.7 christos &filter_data)); 1336 1.7 christos 1337 1.7 christos bufferevent_setcb(filter, 1338 1.7 christos bufferevent_filter_data_stuck_readcb, 1339 1.7 christos NULL, 1340 1.7 christos NULL, 1341 1.7 christos &filter_data); 1342 1.7 christos 1343 1.7 christos tt_assert(bufferevent_enable(filter, EV_READ|EV_WRITE) == 0); 1344 1.7 christos 1345 1.7 christos bufferevent_setwatermark(filter, EV_READ, 0, read_high_wm); 1346 1.7 christos 1347 1.7 christos tt_assert(bufferevent_write(pair[0], payload, sizeof(payload)) == 0); 1348 1.7 christos 1349 1.7 christos event_base_dispatch(data->base); 1350 1.7 christos 1351 1.7 christos tt_int_op(filter_data.total_read, ==, payload_size + filter_data.header_size); 1352 1.7 christos end: 1353 1.7 christos if (pair[0]) 1354 1.7 christos bufferevent_free(pair[0]); 1355 1.7 christos if (filter) 1356 1.7 christos bufferevent_free(filter); 1357 1.7 christos } 1358 1.7 christos 1359 1.1 christos struct testcase_t bufferevent_testcases[] = { 1360 1.1 christos 1361 1.1 christos LEGACY(bufferevent, TT_ISOLATED), 1362 1.1 christos LEGACY(bufferevent_pair, TT_ISOLATED), 1363 1.7 christos LEGACY(bufferevent_flush_normal, TT_ISOLATED), 1364 1.7 christos LEGACY(bufferevent_flush_flush, TT_ISOLATED), 1365 1.7 christos LEGACY(bufferevent_flush_finished, TT_ISOLATED), 1366 1.7 christos LEGACY(bufferevent_pair_flush_normal, TT_ISOLATED), 1367 1.7 christos LEGACY(bufferevent_pair_flush_flush, TT_ISOLATED), 1368 1.7 christos LEGACY(bufferevent_pair_flush_finished, TT_ISOLATED), 1369 1.7 christos #if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) && !defined(__SANITIZE_ADDRESS__) 1370 1.3 christos { "bufferevent_pair_release_lock", test_bufferevent_pair_release_lock, 1371 1.7 christos TT_FORK|TT_ISOLATED|TT_NEED_THREADS|TT_NEED_BASE|TT_LEGACY|TT_NO_LOGS, 1372 1.3 christos &basic_setup, NULL }, 1373 1.3 christos #endif 1374 1.1 christos LEGACY(bufferevent_watermarks, TT_ISOLATED), 1375 1.1 christos LEGACY(bufferevent_pair_watermarks, TT_ISOLATED), 1376 1.1 christos LEGACY(bufferevent_filters, TT_ISOLATED), 1377 1.1 christos LEGACY(bufferevent_pair_filters, TT_ISOLATED), 1378 1.7 christos LEGACY(bufferevent_filters_disable, TT_ISOLATED), 1379 1.7 christos LEGACY(bufferevent_pair_filters_disable, TT_ISOLATED), 1380 1.1 christos { "bufferevent_connect", test_bufferevent_connect, TT_FORK|TT_NEED_BASE, 1381 1.1 christos &basic_setup, (void*)"" }, 1382 1.1 christos { "bufferevent_connect_defer", test_bufferevent_connect, 1383 1.1 christos TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"defer" }, 1384 1.1 christos { "bufferevent_connect_lock", test_bufferevent_connect, 1385 1.1 christos TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, (void*)"lock" }, 1386 1.1 christos { "bufferevent_connect_lock_defer", test_bufferevent_connect, 1387 1.1 christos TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1388 1.1 christos (void*)"defer lock" }, 1389 1.1 christos { "bufferevent_connect_unlocked_cbs", test_bufferevent_connect, 1390 1.1 christos TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1391 1.1 christos (void*)"lock defer unlocked" }, 1392 1.1 christos { "bufferevent_connect_fail", test_bufferevent_connect_fail, 1393 1.1 christos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1394 1.1 christos { "bufferevent_timeout", test_bufferevent_timeouts, 1395 1.7 christos TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"" }, 1396 1.1 christos { "bufferevent_timeout_pair", test_bufferevent_timeouts, 1397 1.1 christos TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"pair" }, 1398 1.1 christos { "bufferevent_timeout_filter", test_bufferevent_timeouts, 1399 1.1 christos TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter" }, 1400 1.1 christos { "bufferevent_timeout_filter_pair", test_bufferevent_timeouts, 1401 1.1 christos TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter pair" }, 1402 1.2 christos { "bufferevent_trigger", test_bufferevent_trigger, TT_FORK|TT_NEED_BASE, 1403 1.2 christos &basic_setup, (void*)"" }, 1404 1.2 christos { "bufferevent_trigger_defer", test_bufferevent_trigger, 1405 1.2 christos TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"defer" }, 1406 1.2 christos { "bufferevent_trigger_postpone", test_bufferevent_trigger, 1407 1.2 christos TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1408 1.2 christos (void*)"postpone" }, 1409 1.2 christos { "bufferevent_trigger_defer_postpone", test_bufferevent_trigger, 1410 1.2 christos TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, 1411 1.2 christos (void*)"defer postpone" }, 1412 1.1 christos #ifdef EVENT__HAVE_LIBZ 1413 1.1 christos LEGACY(bufferevent_zlib, TT_ISOLATED), 1414 1.1 christos #else 1415 1.1 christos { "bufferevent_zlib", NULL, TT_SKIP, NULL, NULL }, 1416 1.1 christos #endif 1417 1.1 christos 1418 1.7 christos { "bufferevent_connect_fail_eventcb_defer", 1419 1.7 christos test_bufferevent_connect_fail_eventcb, 1420 1.7 christos TT_FORK|TT_NEED_BASE, &basic_setup, (void*)BEV_OPT_DEFER_CALLBACKS }, 1421 1.7 christos { "bufferevent_connect_fail_eventcb", 1422 1.7 christos test_bufferevent_connect_fail_eventcb, 1423 1.7 christos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1424 1.7 christos 1425 1.7 christos { "bufferevent_socket_filter_inactive", 1426 1.7 christos test_bufferevent_socket_filter_inactive, 1427 1.7 christos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1428 1.7 christos { "bufferevent_pair_flush", 1429 1.7 christos test_bufferevent_pair_flush, 1430 1.7 christos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1431 1.7 christos { "bufferevent_filter_data_stuck", 1432 1.7 christos test_bufferevent_filter_data_stuck, 1433 1.7 christos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1434 1.7 christos 1435 1.1 christos END_OF_TESTCASES, 1436 1.1 christos }; 1437 1.1 christos 1438 1.7 christos #define TT_IOCP (TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP) 1439 1.7 christos #define TT_IOCP_LEGACY (TT_ISOLATED|TT_ENABLE_IOCP) 1440 1.1 christos struct testcase_t bufferevent_iocp_testcases[] = { 1441 1.7 christos LEGACY(bufferevent, TT_IOCP_LEGACY), 1442 1.7 christos LEGACY(bufferevent_flush_normal, TT_ISOLATED), 1443 1.7 christos LEGACY(bufferevent_flush_flush, TT_ISOLATED), 1444 1.7 christos LEGACY(bufferevent_flush_finished, TT_ISOLATED), 1445 1.7 christos LEGACY(bufferevent_watermarks, TT_IOCP_LEGACY), 1446 1.7 christos LEGACY(bufferevent_filters, TT_IOCP_LEGACY), 1447 1.7 christos LEGACY(bufferevent_filters_disable, TT_IOCP_LEGACY), 1448 1.1 christos 1449 1.1 christos { "bufferevent_connect", test_bufferevent_connect, 1450 1.7 christos TT_IOCP, &basic_setup, (void*)"" }, 1451 1.1 christos { "bufferevent_connect_defer", test_bufferevent_connect, 1452 1.7 christos TT_IOCP, &basic_setup, (void*)"defer" }, 1453 1.1 christos { "bufferevent_connect_lock", test_bufferevent_connect, 1454 1.7 christos TT_IOCP, &basic_setup, (void*)"lock" }, 1455 1.1 christos { "bufferevent_connect_lock_defer", test_bufferevent_connect, 1456 1.7 christos TT_IOCP, &basic_setup, (void*)"defer lock" }, 1457 1.1 christos { "bufferevent_connect_fail", test_bufferevent_connect_fail, 1458 1.7 christos TT_IOCP, &basic_setup, NULL }, 1459 1.1 christos { "bufferevent_connect_nonblocking", test_bufferevent_connect, 1460 1.7 christos TT_IOCP, &basic_setup, (void*)"unset_connectex" }, 1461 1.7 christos 1462 1.7 christos { "bufferevent_connect_fail_eventcb_defer", 1463 1.7 christos test_bufferevent_connect_fail_eventcb, 1464 1.7 christos TT_IOCP, &basic_setup, (void*)BEV_OPT_DEFER_CALLBACKS }, 1465 1.7 christos { "bufferevent_connect_fail_eventcb", 1466 1.7 christos test_bufferevent_connect_fail_eventcb, TT_IOCP, &basic_setup, NULL }, 1467 1.1 christos 1468 1.1 christos END_OF_TESTCASES, 1469 1.1 christos }; 1470