1 /* $NetBSD: regress_bufferevent.c,v 1.2 2013/04/11 16:56:42 christos Exp $ */
3 * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
4 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /* The old tests here need assertions to work. */
37 #include "event2/event-config.h"
38 #include <sys/cdefs.h>
39 __RCSID("$NetBSD: regress_bufferevent.c,v 1.2 2013/04/11 16:56:42 christos Exp $");
41 #include <sys/types.h>
43 #ifdef _EVENT_HAVE_SYS_TIME_H
46 #include <sys/queue.h>
48 #include <sys/socket.h>
53 #include <netinet/in.h>
63 #ifdef _EVENT_HAVE_ARPA_INET_H
64 #include <arpa/inet.h>
67 #include "event2/event-config.h"
68 #include <sys/cdefs.h>
69 __RCSID("$NetBSD: regress_bufferevent.c,v 1.2 2013/04/11 16:56:42 christos Exp $");
70 #include "event2/event.h"
71 #include "event2/event_struct.h"
72 #include "event2/event_compat.h"
73 #include "event2/tag.h"
74 #include "event2/buffer.h"
75 #include "event2/bufferevent.h"
76 #include "event2/bufferevent_compat.h"
77 #include "event2/bufferevent_struct.h"
78 #include "event2/listener.h"
79 #include "event2/util.h"
81 #include "bufferevent-internal.h"
82 #include "util-internal.h"
84 #include "iocp-internal.h"
88 #include "regress_testutils.h"
91 * simple bufferevent test
95 readcb(struct bufferevent
*bev
, void *arg
)
97 if (evbuffer_get_length(bev
->input
) == 8333) {
98 struct evbuffer
*evbuf
= evbuffer_new();
99 assert(evbuf
!= NULL
);
101 /* gratuitous test of bufferevent_read_buffer */
102 bufferevent_read_buffer(bev
, evbuf
);
104 bufferevent_disable(bev
, EV_READ
);
106 if (evbuffer_get_length(evbuf
) == 8333) {
110 evbuffer_free(evbuf
);
115 writecb(struct bufferevent
*bev
, void *arg
)
117 if (evbuffer_get_length(bev
->output
) == 0) {
123 errorcb(struct bufferevent
*bev
, short what
, void *arg
)
129 test_bufferevent_impl(int use_pair
)
131 struct bufferevent
*bev1
= NULL
, *bev2
= NULL
;
136 struct bufferevent
*xpair
[2];
137 tt_assert(0 == bufferevent_pair_new(NULL
, 0, xpair
));
140 bufferevent_setcb(bev1
, readcb
, writecb
, errorcb
, NULL
);
141 bufferevent_setcb(bev2
, readcb
, writecb
, errorcb
, NULL
);
142 tt_int_op(bufferevent_getfd(bev1
), ==, -1);
143 tt_ptr_op(bufferevent_get_underlying(bev1
), ==, NULL
);
144 tt_ptr_op(bufferevent_pair_get_partner(bev1
), ==, bev2
);
145 tt_ptr_op(bufferevent_pair_get_partner(bev2
), ==, bev1
);
147 bev1
= bufferevent_new(pair
[0], readcb
, writecb
, errorcb
, NULL
);
148 bev2
= bufferevent_new(pair
[1], readcb
, writecb
, errorcb
, NULL
);
149 tt_int_op(bufferevent_getfd(bev1
), ==, pair
[0]);
150 tt_ptr_op(bufferevent_get_underlying(bev1
), ==, NULL
);
151 tt_ptr_op(bufferevent_pair_get_partner(bev1
), ==, NULL
);
152 tt_ptr_op(bufferevent_pair_get_partner(bev2
), ==, NULL
);
155 bufferevent_disable(bev1
, EV_READ
);
156 bufferevent_enable(bev2
, EV_READ
);
158 tt_int_op(bufferevent_get_enabled(bev1
), ==, EV_WRITE
);
159 tt_int_op(bufferevent_get_enabled(bev2
), ==, EV_WRITE
|EV_READ
);
161 for (i
= 0; i
< (int)sizeof(buffer
); i
++)
164 bufferevent_write(bev1
, buffer
, sizeof(buffer
));
168 bufferevent_free(bev1
);
169 tt_ptr_op(bufferevent_pair_get_partner(bev2
), ==, NULL
);
170 bufferevent_free(bev2
);
179 test_bufferevent(void)
181 test_bufferevent_impl(0);
185 test_bufferevent_pair(void)
187 test_bufferevent_impl(1);
191 * test watermarks and bufferevent
195 wm_readcb(struct bufferevent
*bev
, void *arg
)
197 struct evbuffer
*evbuf
= evbuffer_new();
198 int len
= (int)evbuffer_get_length(bev
->input
);
201 assert(len
>= 10 && len
<= 20);
203 assert(evbuf
!= NULL
);
205 /* gratuitous test of bufferevent_read_buffer */
206 bufferevent_read_buffer(bev
, evbuf
);
209 if (nread
== 65000) {
210 bufferevent_disable(bev
, EV_READ
);
214 evbuffer_free(evbuf
);
218 wm_writecb(struct bufferevent
*bev
, void *arg
)
220 assert(evbuffer_get_length(bev
->output
) <= 100);
221 if (evbuffer_get_length(bev
->output
) == 0) {
222 evbuffer_drain(bev
->output
, evbuffer_get_length(bev
->output
));
228 wm_errorcb(struct bufferevent
*bev
, short what
, void *arg
)
234 test_bufferevent_watermarks_impl(int use_pair
)
236 struct bufferevent
*bev1
= NULL
, *bev2
= NULL
;
242 struct bufferevent
*xpair
[2];
243 tt_assert(0 == bufferevent_pair_new(NULL
, 0, xpair
));
246 bufferevent_setcb(bev1
, NULL
, wm_writecb
, errorcb
, NULL
);
247 bufferevent_setcb(bev2
, wm_readcb
, NULL
, errorcb
, NULL
);
249 bev1
= bufferevent_new(pair
[0], NULL
, wm_writecb
, wm_errorcb
, NULL
);
250 bev2
= bufferevent_new(pair
[1], wm_readcb
, NULL
, wm_errorcb
, NULL
);
254 bufferevent_disable(bev1
, EV_READ
);
255 bufferevent_enable(bev2
, EV_READ
);
257 for (i
= 0; i
< (int)sizeof(buffer
); i
++)
260 /* limit the reading on the receiving bufferevent */
261 bufferevent_setwatermark(bev2
, EV_READ
, 10, 20);
263 /* Tell the sending bufferevent not to notify us till it's down to
265 bufferevent_setwatermark(bev1
, EV_WRITE
, 100, 2000);
267 bufferevent_write(bev1
, buffer
, sizeof(buffer
));
271 tt_int_op(test_ok
, ==, 2);
273 /* The write callback drained all the data from outbuf, so we
274 * should have removed the write event... */
275 tt_assert(!event_pending(&bev2
->ev_write
, EV_WRITE
, NULL
));
279 bufferevent_free(bev1
);
281 bufferevent_free(bev2
);
285 test_bufferevent_watermarks(void)
287 test_bufferevent_watermarks_impl(0);
291 test_bufferevent_pair_watermarks(void)
293 test_bufferevent_watermarks_impl(1);
297 * Test bufferevent filters
300 /* strip an 'x' from each byte */
302 static enum bufferevent_filter_result
303 bufferevent_input_filter(struct evbuffer
*src
, struct evbuffer
*dst
,
304 ev_ssize_t lim
, enum bufferevent_flush_mode state
, void *ctx
)
306 const unsigned char *buffer
;
309 buffer
= evbuffer_pullup(src
, evbuffer_get_length(src
));
310 for (i
= 0; i
< evbuffer_get_length(src
); i
+= 2) {
311 assert(buffer
[i
] == 'x');
312 evbuffer_add(dst
, buffer
+ i
+ 1, 1);
314 if (i
+ 2 > evbuffer_get_length(src
))
318 evbuffer_drain(src
, i
);
322 /* add an 'x' before each byte */
324 static enum bufferevent_filter_result
325 bufferevent_output_filter(struct evbuffer
*src
, struct evbuffer
*dst
,
326 ev_ssize_t lim
, enum bufferevent_flush_mode state
, void *ctx
)
328 const unsigned char *buffer
;
331 buffer
= evbuffer_pullup(src
, evbuffer_get_length(src
));
332 for (i
= 0; i
< evbuffer_get_length(src
); ++i
) {
333 evbuffer_add(dst
, "x", 1);
334 evbuffer_add(dst
, buffer
+ i
, 1);
337 evbuffer_drain(src
, evbuffer_get_length(src
));
342 test_bufferevent_filters_impl(int use_pair
)
344 struct bufferevent
*bev1
= NULL
, *bev2
= NULL
;
345 struct bufferevent
*bev1_base
= NULL
, *bev2_base
= NULL
;
352 struct bufferevent
*xpair
[2];
353 tt_assert(0 == bufferevent_pair_new(NULL
, 0, xpair
));
357 bev1
= bufferevent_socket_new(NULL
, pair
[0], 0);
358 bev2
= bufferevent_socket_new(NULL
, pair
[1], 0);
363 for (i
= 0; i
< (int)sizeof(buffer
); i
++)
366 bev1
= bufferevent_filter_new(bev1
, NULL
, bufferevent_output_filter
,
367 BEV_OPT_CLOSE_ON_FREE
, NULL
, NULL
);
369 bev2
= bufferevent_filter_new(bev2
, bufferevent_input_filter
,
370 NULL
, BEV_OPT_CLOSE_ON_FREE
, NULL
, NULL
);
371 bufferevent_setcb(bev1
, NULL
, writecb
, errorcb
, NULL
);
372 bufferevent_setcb(bev2
, readcb
, NULL
, errorcb
, NULL
);
374 tt_ptr_op(bufferevent_get_underlying(bev1
), ==, bev1_base
);
375 tt_ptr_op(bufferevent_get_underlying(bev2
), ==, bev2_base
);
376 tt_int_op(bufferevent_getfd(bev1
), ==, -1);
377 tt_int_op(bufferevent_getfd(bev2
), ==, -1);
379 bufferevent_disable(bev1
, EV_READ
);
380 bufferevent_enable(bev2
, EV_READ
);
381 /* insert some filters */
382 bufferevent_write(bev1
, buffer
, sizeof(buffer
));
391 bufferevent_free(bev1
);
393 bufferevent_free(bev2
);
398 test_bufferevent_filters(void)
400 test_bufferevent_filters_impl(0);
404 test_bufferevent_pair_filters(void)
406 test_bufferevent_filters_impl(1);
411 sender_writecb(struct bufferevent
*bev
, void *ctx
)
413 if (evbuffer_get_length(bufferevent_get_output(bev
)) == 0) {
414 bufferevent_disable(bev
,EV_READ
|EV_WRITE
);
415 bufferevent_free(bev
);
420 sender_errorcb(struct bufferevent
*bev
, short what
, void *ctx
)
422 TT_FAIL(("Got sender error %d",(int)what
));
425 static int bufferevent_connect_test_flags
= 0;
426 static int n_strings_read
= 0;
427 static int n_reads_invoked
= 0;
429 #define TEST_STR "Now is the time for all good events to signal for " \
430 "the good of their protocol"
432 listen_cb(struct evconnlistener
*listener
, evutil_socket_t fd
,
433 struct sockaddr
*sa
, int socklen
, void *arg
)
435 struct event_base
*base
= arg
;
436 struct bufferevent
*bev
;
437 const char s
[] = TEST_STR
;
438 TT_BLATHER(("Got a request on socket %d", (int)fd
));
439 bev
= bufferevent_socket_new(base
, fd
, bufferevent_connect_test_flags
);
441 bufferevent_setcb(bev
, NULL
, sender_writecb
, sender_errorcb
, NULL
);
442 bufferevent_write(bev
, s
, sizeof(s
));
448 reader_eventcb(struct bufferevent
*bev
, short what
, void *ctx
)
450 struct event_base
*base
= ctx
;
451 if (what
& BEV_EVENT_ERROR
) {
453 TT_FAIL(("got connector error %d", (int)what
));
456 if (what
& BEV_EVENT_CONNECTED
) {
457 bufferevent_enable(bev
, EV_READ
);
459 if (what
& BEV_EVENT_EOF
) {
462 n
= bufferevent_read(bev
, buf
, sizeof(buf
)-1);
464 tt_str_op(buf
, ==, TEST_STR
);
465 if (++n_strings_read
== 2)
466 event_base_loopexit(base
, NULL
);
473 reader_readcb(struct bufferevent
*bev
, void *ctx
)
479 test_bufferevent_connect(void *arg
)
481 struct basic_test_data
*data
= arg
;
482 struct evconnlistener
*lev
=NULL
;
483 struct bufferevent
*bev1
=NULL
, *bev2
=NULL
;
484 struct sockaddr_in localhost
;
485 struct sockaddr_storage ss
;
489 int be_flags
=BEV_OPT_CLOSE_ON_FREE
;
491 if (strstr((char*)data
->setup_data
, "defer")) {
492 be_flags
|= BEV_OPT_DEFER_CALLBACKS
;
494 if (strstr((char*)data
->setup_data
, "unlocked")) {
495 be_flags
|= BEV_OPT_UNLOCK_CALLBACKS
;
497 if (strstr((char*)data
->setup_data
, "lock")) {
498 be_flags
|= BEV_OPT_THREADSAFE
;
500 bufferevent_connect_test_flags
= be_flags
;
502 if (!strcmp((char*)data
->setup_data
, "unset_connectex")) {
503 struct win32_extension_fns
*ext
=
504 (struct win32_extension_fns
*)
505 event_get_win32_extension_fns();
506 ext
->ConnectEx
= NULL
;
510 memset(&localhost
, 0, sizeof(localhost
));
512 localhost
.sin_port
= 0; /* pick-a-port */
513 localhost
.sin_addr
.s_addr
= htonl(0x7f000001L
);
514 localhost
.sin_family
= AF_INET
;
515 sa
= (struct sockaddr
*)&localhost
;
516 lev
= evconnlistener_new_bind(data
->base
, listen_cb
, data
->base
,
517 LEV_OPT_CLOSE_ON_FREE
|LEV_OPT_REUSEABLE
,
518 16, sa
, sizeof(localhost
));
521 sa
= (struct sockaddr
*)&ss
;
523 if (regress_get_listener_addr(lev
, sa
, &slen
) < 0) {
524 tt_abort_perror("getsockname");
527 tt_assert(!evconnlistener_enable(lev
));
528 bev1
= bufferevent_socket_new(data
->base
, -1, be_flags
);
529 bev2
= bufferevent_socket_new(data
->base
, -1, be_flags
);
532 bufferevent_setcb(bev1
, reader_readcb
,NULL
, reader_eventcb
, data
->base
);
533 bufferevent_setcb(bev2
, reader_readcb
,NULL
, reader_eventcb
, data
->base
);
535 bufferevent_enable(bev1
, EV_READ
);
536 bufferevent_enable(bev2
, EV_READ
);
538 tt_want(!bufferevent_socket_connect(bev1
, sa
, sizeof(localhost
)));
539 tt_want(!bufferevent_socket_connect(bev2
, sa
, sizeof(localhost
)));
541 event_base_dispatch(data
->base
);
543 tt_int_op(n_strings_read
, ==, 2);
544 tt_int_op(n_reads_invoked
, >=, 2);
547 evconnlistener_free(lev
);
550 bufferevent_free(bev1
);
553 bufferevent_free(bev2
);
557 want_fail_eventcb(struct bufferevent
*bev
, short what
, void *ctx
)
559 struct event_base
*base
= ctx
;
563 if (what
& BEV_EVENT_ERROR
) {
564 s
= bufferevent_getfd(bev
);
565 err
= evutil_socket_error_to_string(evutil_socket_geterror(s
));
566 TT_BLATHER(("connection failure on "EV_SOCK_FMT
": %s",
567 EV_SOCK_ARG(s
), err
));
570 TT_FAIL(("didn't fail? what %hd", what
));
573 event_base_loopexit(base
, NULL
);
577 close_socket_cb(evutil_socket_t fd
, short what
, void *arg
)
579 evutil_socket_t
*fdp
= arg
;
581 evutil_closesocket(*fdp
);
587 test_bufferevent_connect_fail(void *arg
)
589 struct basic_test_data
*data
= arg
;
590 struct bufferevent
*bev
=NULL
;
591 struct sockaddr_in localhost
;
592 struct sockaddr
*sa
= (struct sockaddr
*)&localhost
;
593 evutil_socket_t fake_listener
= -1;
594 ev_socklen_t slen
= sizeof(localhost
);
595 struct event close_listener_event
;
596 int close_listener_event_added
= 0;
597 struct timeval one_second
= { 1, 0 };
602 memset(&localhost
, 0, sizeof(localhost
));
603 localhost
.sin_port
= 0; /* have the kernel pick a port */
604 localhost
.sin_addr
.s_addr
= htonl(0x7f000001L
);
605 localhost
.sin_family
= AF_INET
;
607 /* bind, but don't listen or accept. should trigger
608 "Connection refused" reliably on most platforms. */
609 fake_listener
= socket(localhost
.sin_family
, SOCK_STREAM
, 0);
610 tt_assert(fake_listener
>= 0);
611 tt_assert(bind(fake_listener
, sa
, slen
) == 0);
612 tt_assert(getsockname(fake_listener
, sa
, &slen
) == 0);
613 bev
= bufferevent_socket_new(data
->base
, -1,
614 BEV_OPT_CLOSE_ON_FREE
| BEV_OPT_DEFER_CALLBACKS
);
616 bufferevent_setcb(bev
, NULL
, NULL
, want_fail_eventcb
, data
->base
);
618 r
= bufferevent_socket_connect(bev
, sa
, slen
);
619 /* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells
620 * detects the error immediately, which is not really wrong of it. */
621 tt_want(r
== 0 || r
== -1);
623 /* Close the listener socket after a second. This should trigger
624 "connection refused" on some other platforms, including OSX. */
625 evtimer_assign(&close_listener_event
, data
->base
, close_socket_cb
,
627 event_add(&close_listener_event
, &one_second
);
628 close_listener_event_added
= 1;
630 event_base_dispatch(data
->base
);
632 tt_int_op(test_ok
, ==, 1);
635 if (fake_listener
>= 0)
636 evutil_closesocket(fake_listener
);
639 bufferevent_free(bev
);
641 if (close_listener_event_added
)
642 event_del(&close_listener_event
);
645 struct timeout_cb_result
{
646 struct timeval read_timeout_at
;
647 struct timeval write_timeout_at
;
648 struct timeval last_wrote_at
;
650 int n_write_timeouts
;
655 bev_timeout_write_cb(struct bufferevent
*bev
, void *arg
)
657 struct timeout_cb_result
*res
= arg
;
658 evutil_gettimeofday(&res
->last_wrote_at
, NULL
);
662 bev_timeout_event_cb(struct bufferevent
*bev
, short what
, void *arg
)
664 struct timeout_cb_result
*res
= arg
;
667 if ((what
& (BEV_EVENT_READING
|BEV_EVENT_TIMEOUT
))
668 == (BEV_EVENT_READING
|BEV_EVENT_TIMEOUT
)) {
669 evutil_gettimeofday(&res
->read_timeout_at
, NULL
);
670 ++res
->n_read_timeouts
;
672 if ((what
& (BEV_EVENT_WRITING
|BEV_EVENT_TIMEOUT
))
673 == (BEV_EVENT_WRITING
|BEV_EVENT_TIMEOUT
)) {
674 evutil_gettimeofday(&res
->write_timeout_at
, NULL
);
675 ++res
->n_write_timeouts
;
680 test_bufferevent_timeouts(void *arg
)
682 /* "arg" is a string containing "pair" and/or "filter". */
683 struct bufferevent
*bev1
= NULL
, *bev2
= NULL
;
684 struct basic_test_data
*data
= arg
;
685 int use_pair
= 0, use_filter
= 0;
686 struct timeval tv_w
, tv_r
, started_at
;
687 struct timeout_cb_result res1
, res2
;
690 memset(&res1
, 0, sizeof(res1
));
691 memset(&res2
, 0, sizeof(res2
));
693 if (strstr((char*)data
->setup_data
, "pair"))
695 if (strstr((char*)data
->setup_data
, "filter"))
699 struct bufferevent
*p
[2];
700 tt_int_op(0, ==, bufferevent_pair_new(data
->base
, 0, p
));
704 bev1
= bufferevent_socket_new(data
->base
, data
->pair
[0], 0);
705 bev2
= bufferevent_socket_new(data
->base
, data
->pair
[1], 0);
712 struct bufferevent
*bevf1
, *bevf2
;
713 bevf1
= bufferevent_filter_new(bev1
, NULL
, NULL
,
714 BEV_OPT_CLOSE_ON_FREE
, NULL
, NULL
);
715 bevf2
= bufferevent_filter_new(bev2
, NULL
, NULL
,
716 BEV_OPT_CLOSE_ON_FREE
, NULL
, NULL
);
723 /* Do this nice and early. */
724 bufferevent_disable(bev2
, EV_READ
);
726 /* bev1 will try to write and read. Both will time out. */
727 evutil_gettimeofday(&started_at
, NULL
);
728 tv_w
.tv_sec
= tv_r
.tv_sec
= 0;
729 tv_w
.tv_usec
= 100*1000;
730 tv_r
.tv_usec
= 150*1000;
731 bufferevent_setcb(bev1
, NULL
, bev_timeout_write_cb
,
732 bev_timeout_event_cb
, &res1
);
733 bufferevent_setwatermark(bev1
, EV_WRITE
, 1024*1024+10, 0);
734 bufferevent_set_timeouts(bev1
, &tv_r
, &tv_w
);
736 /* For a pair, the fact that the other side isn't reading
737 * makes the writer stall */
738 bufferevent_write(bev1
, "ABCDEFG", 7);
740 /* For a real socket, the kernel's TCP buffers can eat a
741 * fair number of bytes; make sure that at some point we
742 * have some bytes that will stall. */
743 struct evbuffer
*output
= bufferevent_get_output(bev1
);
745 memset(buf
, 0xbb, sizeof(buf
));
746 for (i
=0;i
<1024;++i
) {
747 evbuffer_add_reference(output
, buf
, sizeof(buf
),
751 bufferevent_enable(bev1
, EV_READ
|EV_WRITE
);
753 /* bev2 has nothing to say, and isn't listening. */
754 bufferevent_setcb(bev2
, NULL
, bev_timeout_write_cb
,
755 bev_timeout_event_cb
, &res2
);
756 tv_w
.tv_sec
= tv_r
.tv_sec
= 0;
757 tv_w
.tv_usec
= 200*1000;
758 tv_r
.tv_usec
= 100*1000;
759 bufferevent_set_timeouts(bev2
, &tv_r
, &tv_w
);
760 bufferevent_enable(bev2
, EV_WRITE
);
765 event_base_loopexit(data
->base
, &tv_r
);
766 event_base_dispatch(data
->base
);
768 /* XXXX Test that actually reading or writing a little resets the
771 /* Each buf1 timeout happens, and happens only once. */
772 tt_want(res1
.n_read_timeouts
);
773 tt_want(res1
.n_write_timeouts
);
774 tt_want(res1
.n_read_timeouts
== 1);
775 tt_want(res1
.n_write_timeouts
== 1);
777 test_timeval_diff_eq(&started_at
, &res1
.read_timeout_at
, 150);
778 test_timeval_diff_eq(&started_at
, &res1
.write_timeout_at
, 100);
782 bufferevent_free(bev1
);
784 bufferevent_free(bev2
);
787 struct testcase_t bufferevent_testcases
[] = {
789 LEGACY(bufferevent
, TT_ISOLATED
),
790 LEGACY(bufferevent_pair
, TT_ISOLATED
),
791 LEGACY(bufferevent_watermarks
, TT_ISOLATED
),
792 LEGACY(bufferevent_pair_watermarks
, TT_ISOLATED
),
793 LEGACY(bufferevent_filters
, TT_ISOLATED
),
794 LEGACY(bufferevent_pair_filters
, TT_ISOLATED
),
795 { "bufferevent_connect", test_bufferevent_connect
, TT_FORK
|TT_NEED_BASE
,
796 &basic_setup
, __UNCONST("") },
797 { "bufferevent_connect_defer", test_bufferevent_connect
,
798 TT_FORK
|TT_NEED_BASE
, &basic_setup
, __UNCONST("defer") },
799 { "bufferevent_connect_lock", test_bufferevent_connect
,
800 TT_FORK
|TT_NEED_BASE
|TT_NEED_THREADS
, &basic_setup
, __UNCONST("lock") },
801 { "bufferevent_connect_lock_defer", test_bufferevent_connect
,
802 TT_FORK
|TT_NEED_BASE
|TT_NEED_THREADS
, &basic_setup
,
803 __UNCONST("defer lock") },
804 { "bufferevent_connect_unlocked_cbs", test_bufferevent_connect
,
805 TT_FORK
|TT_NEED_BASE
|TT_NEED_THREADS
, &basic_setup
,
806 __UNCONST("lock defer unlocked") },
807 { "bufferevent_connect_fail", test_bufferevent_connect_fail
,
808 TT_FORK
|TT_NEED_BASE
, &basic_setup
, NULL
},
809 { "bufferevent_timeout", test_bufferevent_timeouts
,
810 TT_FORK
|TT_NEED_BASE
|TT_NEED_SOCKETPAIR
, &basic_setup
, __UNCONST("") },
811 { "bufferevent_timeout_pair", test_bufferevent_timeouts
,
812 TT_FORK
|TT_NEED_BASE
, &basic_setup
, __UNCONST("pair") },
813 { "bufferevent_timeout_filter", test_bufferevent_timeouts
,
814 TT_FORK
|TT_NEED_BASE
, &basic_setup
, __UNCONST("filter") },
815 { "bufferevent_timeout_filter_pair", test_bufferevent_timeouts
,
816 TT_FORK
|TT_NEED_BASE
, &basic_setup
, __UNCONST("filter pair") },
817 #ifdef _EVENT_HAVE_LIBZ
818 LEGACY(bufferevent_zlib
, TT_ISOLATED
),
820 { "bufferevent_zlib", NULL
, TT_SKIP
, NULL
, NULL
},
826 struct testcase_t bufferevent_iocp_testcases
[] = {
828 LEGACY(bufferevent
, TT_ISOLATED
|TT_ENABLE_IOCP
),
829 LEGACY(bufferevent_watermarks
, TT_ISOLATED
|TT_ENABLE_IOCP
),
830 LEGACY(bufferevent_filters
, TT_ISOLATED
|TT_ENABLE_IOCP
),
831 { "bufferevent_connect", test_bufferevent_connect
,
832 TT_FORK
|TT_NEED_BASE
|TT_ENABLE_IOCP
, &basic_setup
, __UNCONST("") },
833 { "bufferevent_connect_defer", test_bufferevent_connect
,
834 TT_FORK
|TT_NEED_BASE
|TT_ENABLE_IOCP
, &basic_setup
, __UNCONST("defer") },
835 { "bufferevent_connect_lock", test_bufferevent_connect
,
836 TT_FORK
|TT_NEED_BASE
|TT_NEED_THREADS
|TT_ENABLE_IOCP
, &basic_setup
,
838 { "bufferevent_connect_lock_defer", test_bufferevent_connect
,
839 TT_FORK
|TT_NEED_BASE
|TT_NEED_THREADS
|TT_ENABLE_IOCP
, &basic_setup
,
840 __UNCONST("defer lock") },
841 { "bufferevent_connect_fail", test_bufferevent_connect_fail
,
842 TT_FORK
|TT_NEED_BASE
|TT_ENABLE_IOCP
, &basic_setup
, NULL
},
843 { "bufferevent_connect_nonblocking", test_bufferevent_connect
,
844 TT_FORK
|TT_NEED_BASE
|TT_ENABLE_IOCP
, &basic_setup
,
845 __UNCONST("unset_connectex") },