12b15cb3dSCy Schubert /* 22b15cb3dSCy Schubert * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 32b15cb3dSCy Schubert * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 42b15cb3dSCy Schubert * 52b15cb3dSCy Schubert * Redistribution and use in source and binary forms, with or without 62b15cb3dSCy Schubert * modification, are permitted provided that the following conditions 72b15cb3dSCy Schubert * are met: 82b15cb3dSCy Schubert * 1. Redistributions of source code must retain the above copyright 92b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer. 102b15cb3dSCy Schubert * 2. Redistributions in binary form must reproduce the above copyright 112b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer in the 122b15cb3dSCy Schubert * documentation and/or other materials provided with the distribution. 132b15cb3dSCy Schubert * 3. The name of the author may not be used to endorse or promote products 142b15cb3dSCy Schubert * derived from this software without specific prior written permission. 152b15cb3dSCy Schubert * 162b15cb3dSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 172b15cb3dSCy Schubert * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 182b15cb3dSCy Schubert * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 192b15cb3dSCy Schubert * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 202b15cb3dSCy Schubert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 212b15cb3dSCy Schubert * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 222b15cb3dSCy Schubert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 232b15cb3dSCy Schubert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 242b15cb3dSCy Schubert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 252b15cb3dSCy Schubert * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 262b15cb3dSCy Schubert */ 272b15cb3dSCy Schubert #include "util-internal.h" 282b15cb3dSCy Schubert 292b15cb3dSCy Schubert #ifdef _WIN32 302b15cb3dSCy Schubert #include <winsock2.h> 312b15cb3dSCy Schubert #include <windows.h> 322b15cb3dSCy Schubert #endif 332b15cb3dSCy Schubert 342b15cb3dSCy Schubert #include "event2/event-config.h" 352b15cb3dSCy Schubert 362b15cb3dSCy Schubert #include <sys/types.h> 372b15cb3dSCy Schubert #include <sys/stat.h> 382b15cb3dSCy Schubert #ifdef EVENT__HAVE_SYS_TIME_H 392b15cb3dSCy Schubert #include <sys/time.h> 402b15cb3dSCy Schubert #endif 412b15cb3dSCy Schubert #include <sys/queue.h> 422b15cb3dSCy Schubert #ifndef _WIN32 432b15cb3dSCy Schubert #include <sys/socket.h> 442b15cb3dSCy Schubert #include <sys/wait.h> 452b15cb3dSCy Schubert #include <signal.h> 462b15cb3dSCy Schubert #include <unistd.h> 472b15cb3dSCy Schubert #include <netdb.h> 482b15cb3dSCy Schubert #endif 492b15cb3dSCy Schubert #include <fcntl.h> 502b15cb3dSCy Schubert #include <signal.h> 512b15cb3dSCy Schubert #include <stdlib.h> 522b15cb3dSCy Schubert #include <stdio.h> 532b15cb3dSCy Schubert #include <string.h> 542b15cb3dSCy Schubert #include <errno.h> 552b15cb3dSCy Schubert #include <assert.h> 562b15cb3dSCy Schubert #include <ctype.h> 572b15cb3dSCy Schubert 582b15cb3dSCy Schubert #include "event2/event.h" 592b15cb3dSCy Schubert #include "event2/event_struct.h" 602b15cb3dSCy Schubert #include "event2/event_compat.h" 612b15cb3dSCy Schubert #include "event2/tag.h" 622b15cb3dSCy Schubert #include "event2/buffer.h" 632b15cb3dSCy Schubert #include "event2/buffer_compat.h" 642b15cb3dSCy Schubert #include "event2/util.h" 652b15cb3dSCy Schubert #include "event-internal.h" 662b15cb3dSCy Schubert #include "evthread-internal.h" 672b15cb3dSCy Schubert #include "log-internal.h" 682b15cb3dSCy Schubert #include "time-internal.h" 692b15cb3dSCy Schubert 702b15cb3dSCy Schubert #include "regress.h" 712b15cb3dSCy Schubert 722b15cb3dSCy Schubert #ifndef _WIN32 732b15cb3dSCy Schubert #include "regress.gen.h" 742b15cb3dSCy Schubert #endif 752b15cb3dSCy Schubert 762b15cb3dSCy Schubert evutil_socket_t pair[2]; 772b15cb3dSCy Schubert int test_ok; 782b15cb3dSCy Schubert int called; 792b15cb3dSCy Schubert struct event_base *global_base; 802b15cb3dSCy Schubert 812b15cb3dSCy Schubert static char wbuf[4096]; 822b15cb3dSCy Schubert static char rbuf[4096]; 832b15cb3dSCy Schubert static int woff; 842b15cb3dSCy Schubert static int roff; 852b15cb3dSCy Schubert static int usepersist; 862b15cb3dSCy Schubert static struct timeval tset; 872b15cb3dSCy Schubert static struct timeval tcalled; 882b15cb3dSCy Schubert 892b15cb3dSCy Schubert 902b15cb3dSCy Schubert #define TEST1 "this is a test" 912b15cb3dSCy Schubert 922b15cb3dSCy Schubert #ifndef SHUT_WR 932b15cb3dSCy Schubert #define SHUT_WR 1 942b15cb3dSCy Schubert #endif 952b15cb3dSCy Schubert 962b15cb3dSCy Schubert #ifdef _WIN32 972b15cb3dSCy Schubert #define write(fd,buf,len) send((fd),(buf),(int)(len),0) 982b15cb3dSCy Schubert #define read(fd,buf,len) recv((fd),(buf),(int)(len),0) 992b15cb3dSCy Schubert #endif 1002b15cb3dSCy Schubert 1012b15cb3dSCy Schubert struct basic_cb_args 1022b15cb3dSCy Schubert { 1032b15cb3dSCy Schubert struct event_base *eb; 1042b15cb3dSCy Schubert struct event *ev; 1052b15cb3dSCy Schubert unsigned int callcount; 1062b15cb3dSCy Schubert }; 1072b15cb3dSCy Schubert 1082b15cb3dSCy Schubert static void 1092b15cb3dSCy Schubert simple_read_cb(evutil_socket_t fd, short event, void *arg) 1102b15cb3dSCy Schubert { 1112b15cb3dSCy Schubert char buf[256]; 1122b15cb3dSCy Schubert int len; 1132b15cb3dSCy Schubert 1142b15cb3dSCy Schubert len = read(fd, buf, sizeof(buf)); 1152b15cb3dSCy Schubert 1162b15cb3dSCy Schubert if (len) { 1172b15cb3dSCy Schubert if (!called) { 1182b15cb3dSCy Schubert if (event_add(arg, NULL) == -1) 1192b15cb3dSCy Schubert exit(1); 1202b15cb3dSCy Schubert } 1212b15cb3dSCy Schubert } else if (called == 1) 1222b15cb3dSCy Schubert test_ok = 1; 1232b15cb3dSCy Schubert 1242b15cb3dSCy Schubert called++; 1252b15cb3dSCy Schubert } 1262b15cb3dSCy Schubert 1272b15cb3dSCy Schubert static void 1282b15cb3dSCy Schubert basic_read_cb(evutil_socket_t fd, short event, void *data) 1292b15cb3dSCy Schubert { 1302b15cb3dSCy Schubert char buf[256]; 1312b15cb3dSCy Schubert int len; 1322b15cb3dSCy Schubert struct basic_cb_args *arg = data; 1332b15cb3dSCy Schubert 1342b15cb3dSCy Schubert len = read(fd, buf, sizeof(buf)); 1352b15cb3dSCy Schubert 1362b15cb3dSCy Schubert if (len < 0) { 1372b15cb3dSCy Schubert tt_fail_perror("read (callback)"); 1382b15cb3dSCy Schubert } else { 1392b15cb3dSCy Schubert switch (arg->callcount++) { 1402b15cb3dSCy Schubert case 0: /* first call: expect to read data; cycle */ 1412b15cb3dSCy Schubert if (len > 0) 1422b15cb3dSCy Schubert return; 1432b15cb3dSCy Schubert 1442b15cb3dSCy Schubert tt_fail_msg("EOF before data read"); 1452b15cb3dSCy Schubert break; 1462b15cb3dSCy Schubert 1472b15cb3dSCy Schubert case 1: /* second call: expect EOF; stop */ 1482b15cb3dSCy Schubert if (len > 0) 1492b15cb3dSCy Schubert tt_fail_msg("not all data read on first cycle"); 1502b15cb3dSCy Schubert break; 1512b15cb3dSCy Schubert 1522b15cb3dSCy Schubert default: /* third call: should not happen */ 1532b15cb3dSCy Schubert tt_fail_msg("too many cycles"); 1542b15cb3dSCy Schubert } 1552b15cb3dSCy Schubert } 1562b15cb3dSCy Schubert 1572b15cb3dSCy Schubert event_del(arg->ev); 1582b15cb3dSCy Schubert event_base_loopexit(arg->eb, NULL); 1592b15cb3dSCy Schubert } 1602b15cb3dSCy Schubert 1612b15cb3dSCy Schubert static void 1622b15cb3dSCy Schubert dummy_read_cb(evutil_socket_t fd, short event, void *arg) 1632b15cb3dSCy Schubert { 1642b15cb3dSCy Schubert } 1652b15cb3dSCy Schubert 1662b15cb3dSCy Schubert static void 1672b15cb3dSCy Schubert simple_write_cb(evutil_socket_t fd, short event, void *arg) 1682b15cb3dSCy Schubert { 1692b15cb3dSCy Schubert int len; 1702b15cb3dSCy Schubert 1712b15cb3dSCy Schubert len = write(fd, TEST1, strlen(TEST1) + 1); 1722b15cb3dSCy Schubert if (len == -1) 1732b15cb3dSCy Schubert test_ok = 0; 1742b15cb3dSCy Schubert else 1752b15cb3dSCy Schubert test_ok = 1; 1762b15cb3dSCy Schubert } 1772b15cb3dSCy Schubert 1782b15cb3dSCy Schubert static void 1792b15cb3dSCy Schubert multiple_write_cb(evutil_socket_t fd, short event, void *arg) 1802b15cb3dSCy Schubert { 1812b15cb3dSCy Schubert struct event *ev = arg; 1822b15cb3dSCy Schubert int len; 1832b15cb3dSCy Schubert 1842b15cb3dSCy Schubert len = 128; 1852b15cb3dSCy Schubert if (woff + len >= (int)sizeof(wbuf)) 1862b15cb3dSCy Schubert len = sizeof(wbuf) - woff; 1872b15cb3dSCy Schubert 1882b15cb3dSCy Schubert len = write(fd, wbuf + woff, len); 1892b15cb3dSCy Schubert if (len == -1) { 1902b15cb3dSCy Schubert fprintf(stderr, "%s: write\n", __func__); 1912b15cb3dSCy Schubert if (usepersist) 1922b15cb3dSCy Schubert event_del(ev); 1932b15cb3dSCy Schubert return; 1942b15cb3dSCy Schubert } 1952b15cb3dSCy Schubert 1962b15cb3dSCy Schubert woff += len; 1972b15cb3dSCy Schubert 1982b15cb3dSCy Schubert if (woff >= (int)sizeof(wbuf)) { 1992b15cb3dSCy Schubert shutdown(fd, SHUT_WR); 2002b15cb3dSCy Schubert if (usepersist) 2012b15cb3dSCy Schubert event_del(ev); 2022b15cb3dSCy Schubert return; 2032b15cb3dSCy Schubert } 2042b15cb3dSCy Schubert 2052b15cb3dSCy Schubert if (!usepersist) { 2062b15cb3dSCy Schubert if (event_add(ev, NULL) == -1) 2072b15cb3dSCy Schubert exit(1); 2082b15cb3dSCy Schubert } 2092b15cb3dSCy Schubert } 2102b15cb3dSCy Schubert 2112b15cb3dSCy Schubert static void 2122b15cb3dSCy Schubert multiple_read_cb(evutil_socket_t fd, short event, void *arg) 2132b15cb3dSCy Schubert { 2142b15cb3dSCy Schubert struct event *ev = arg; 2152b15cb3dSCy Schubert int len; 2162b15cb3dSCy Schubert 2172b15cb3dSCy Schubert len = read(fd, rbuf + roff, sizeof(rbuf) - roff); 2182b15cb3dSCy Schubert if (len == -1) 2192b15cb3dSCy Schubert fprintf(stderr, "%s: read\n", __func__); 2202b15cb3dSCy Schubert if (len <= 0) { 2212b15cb3dSCy Schubert if (usepersist) 2222b15cb3dSCy Schubert event_del(ev); 2232b15cb3dSCy Schubert return; 2242b15cb3dSCy Schubert } 2252b15cb3dSCy Schubert 2262b15cb3dSCy Schubert roff += len; 2272b15cb3dSCy Schubert if (!usepersist) { 2282b15cb3dSCy Schubert if (event_add(ev, NULL) == -1) 2292b15cb3dSCy Schubert exit(1); 2302b15cb3dSCy Schubert } 2312b15cb3dSCy Schubert } 2322b15cb3dSCy Schubert 2332b15cb3dSCy Schubert static void 2342b15cb3dSCy Schubert timeout_cb(evutil_socket_t fd, short event, void *arg) 2352b15cb3dSCy Schubert { 2362b15cb3dSCy Schubert evutil_gettimeofday(&tcalled, NULL); 2372b15cb3dSCy Schubert } 2382b15cb3dSCy Schubert 2392b15cb3dSCy Schubert struct both { 2402b15cb3dSCy Schubert struct event ev; 2412b15cb3dSCy Schubert int nread; 2422b15cb3dSCy Schubert }; 2432b15cb3dSCy Schubert 2442b15cb3dSCy Schubert static void 2452b15cb3dSCy Schubert combined_read_cb(evutil_socket_t fd, short event, void *arg) 2462b15cb3dSCy Schubert { 2472b15cb3dSCy Schubert struct both *both = arg; 2482b15cb3dSCy Schubert char buf[128]; 2492b15cb3dSCy Schubert int len; 2502b15cb3dSCy Schubert 2512b15cb3dSCy Schubert len = read(fd, buf, sizeof(buf)); 2522b15cb3dSCy Schubert if (len == -1) 2532b15cb3dSCy Schubert fprintf(stderr, "%s: read\n", __func__); 2542b15cb3dSCy Schubert if (len <= 0) 2552b15cb3dSCy Schubert return; 2562b15cb3dSCy Schubert 2572b15cb3dSCy Schubert both->nread += len; 2582b15cb3dSCy Schubert if (event_add(&both->ev, NULL) == -1) 2592b15cb3dSCy Schubert exit(1); 2602b15cb3dSCy Schubert } 2612b15cb3dSCy Schubert 2622b15cb3dSCy Schubert static void 2632b15cb3dSCy Schubert combined_write_cb(evutil_socket_t fd, short event, void *arg) 2642b15cb3dSCy Schubert { 2652b15cb3dSCy Schubert struct both *both = arg; 2662b15cb3dSCy Schubert char buf[128]; 2672b15cb3dSCy Schubert int len; 2682b15cb3dSCy Schubert 2692b15cb3dSCy Schubert len = sizeof(buf); 2702b15cb3dSCy Schubert if (len > both->nread) 2712b15cb3dSCy Schubert len = both->nread; 2722b15cb3dSCy Schubert 2732b15cb3dSCy Schubert memset(buf, 'q', len); 2742b15cb3dSCy Schubert 2752b15cb3dSCy Schubert len = write(fd, buf, len); 2762b15cb3dSCy Schubert if (len == -1) 2772b15cb3dSCy Schubert fprintf(stderr, "%s: write\n", __func__); 2782b15cb3dSCy Schubert if (len <= 0) { 2792b15cb3dSCy Schubert shutdown(fd, SHUT_WR); 2802b15cb3dSCy Schubert return; 2812b15cb3dSCy Schubert } 2822b15cb3dSCy Schubert 2832b15cb3dSCy Schubert both->nread -= len; 2842b15cb3dSCy Schubert if (event_add(&both->ev, NULL) == -1) 2852b15cb3dSCy Schubert exit(1); 2862b15cb3dSCy Schubert } 2872b15cb3dSCy Schubert 2882b15cb3dSCy Schubert /* These macros used to replicate the work of the legacy test wrapper code */ 2892b15cb3dSCy Schubert #define setup_test(x) do { \ 2902b15cb3dSCy Schubert if (!in_legacy_test_wrapper) { \ 2912b15cb3dSCy Schubert TT_FAIL(("Legacy test %s not wrapped properly", x)); \ 2922b15cb3dSCy Schubert return; \ 2932b15cb3dSCy Schubert } \ 2942b15cb3dSCy Schubert } while (0) 2952b15cb3dSCy Schubert #define cleanup_test() setup_test("cleanup") 2962b15cb3dSCy Schubert 2972b15cb3dSCy Schubert static void 2982b15cb3dSCy Schubert test_simpleread(void) 2992b15cb3dSCy Schubert { 3002b15cb3dSCy Schubert struct event ev; 3012b15cb3dSCy Schubert 3022b15cb3dSCy Schubert /* Very simple read test */ 3032b15cb3dSCy Schubert setup_test("Simple read: "); 3042b15cb3dSCy Schubert 3052b15cb3dSCy Schubert if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 3062b15cb3dSCy Schubert tt_fail_perror("write"); 3072b15cb3dSCy Schubert } 3082b15cb3dSCy Schubert 3092b15cb3dSCy Schubert shutdown(pair[0], SHUT_WR); 3102b15cb3dSCy Schubert 3112b15cb3dSCy Schubert event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev); 3122b15cb3dSCy Schubert if (event_add(&ev, NULL) == -1) 3132b15cb3dSCy Schubert exit(1); 3142b15cb3dSCy Schubert event_dispatch(); 3152b15cb3dSCy Schubert 3162b15cb3dSCy Schubert cleanup_test(); 3172b15cb3dSCy Schubert } 3182b15cb3dSCy Schubert 3192b15cb3dSCy Schubert static void 3202b15cb3dSCy Schubert test_simplewrite(void) 3212b15cb3dSCy Schubert { 3222b15cb3dSCy Schubert struct event ev; 3232b15cb3dSCy Schubert 3242b15cb3dSCy Schubert /* Very simple write test */ 3252b15cb3dSCy Schubert setup_test("Simple write: "); 3262b15cb3dSCy Schubert 3272b15cb3dSCy Schubert event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev); 3282b15cb3dSCy Schubert if (event_add(&ev, NULL) == -1) 3292b15cb3dSCy Schubert exit(1); 3302b15cb3dSCy Schubert event_dispatch(); 3312b15cb3dSCy Schubert 3322b15cb3dSCy Schubert cleanup_test(); 3332b15cb3dSCy Schubert } 3342b15cb3dSCy Schubert 3352b15cb3dSCy Schubert static void 3362b15cb3dSCy Schubert simpleread_multiple_cb(evutil_socket_t fd, short event, void *arg) 3372b15cb3dSCy Schubert { 3382b15cb3dSCy Schubert if (++called == 2) 3392b15cb3dSCy Schubert test_ok = 1; 3402b15cb3dSCy Schubert } 3412b15cb3dSCy Schubert 3422b15cb3dSCy Schubert static void 3432b15cb3dSCy Schubert test_simpleread_multiple(void) 3442b15cb3dSCy Schubert { 3452b15cb3dSCy Schubert struct event one, two; 3462b15cb3dSCy Schubert 3472b15cb3dSCy Schubert /* Very simple read test */ 3482b15cb3dSCy Schubert setup_test("Simple read to multiple evens: "); 3492b15cb3dSCy Schubert 3502b15cb3dSCy Schubert if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 3512b15cb3dSCy Schubert tt_fail_perror("write"); 3522b15cb3dSCy Schubert } 3532b15cb3dSCy Schubert 3542b15cb3dSCy Schubert shutdown(pair[0], SHUT_WR); 3552b15cb3dSCy Schubert 3562b15cb3dSCy Schubert event_set(&one, pair[1], EV_READ, simpleread_multiple_cb, NULL); 3572b15cb3dSCy Schubert if (event_add(&one, NULL) == -1) 3582b15cb3dSCy Schubert exit(1); 3592b15cb3dSCy Schubert event_set(&two, pair[1], EV_READ, simpleread_multiple_cb, NULL); 3602b15cb3dSCy Schubert if (event_add(&two, NULL) == -1) 3612b15cb3dSCy Schubert exit(1); 3622b15cb3dSCy Schubert event_dispatch(); 3632b15cb3dSCy Schubert 3642b15cb3dSCy Schubert cleanup_test(); 3652b15cb3dSCy Schubert } 3662b15cb3dSCy Schubert 3672b15cb3dSCy Schubert static int have_closed = 0; 3682b15cb3dSCy Schubert static int premature_event = 0; 3692b15cb3dSCy Schubert static void 3702b15cb3dSCy Schubert simpleclose_close_fd_cb(evutil_socket_t s, short what, void *ptr) 3712b15cb3dSCy Schubert { 3722b15cb3dSCy Schubert evutil_socket_t **fds = ptr; 3732b15cb3dSCy Schubert TT_BLATHER(("Closing")); 3742b15cb3dSCy Schubert evutil_closesocket(*fds[0]); 3752b15cb3dSCy Schubert evutil_closesocket(*fds[1]); 3762b15cb3dSCy Schubert *fds[0] = -1; 3772b15cb3dSCy Schubert *fds[1] = -1; 3782b15cb3dSCy Schubert have_closed = 1; 3792b15cb3dSCy Schubert } 3802b15cb3dSCy Schubert 3812b15cb3dSCy Schubert static void 3822b15cb3dSCy Schubert record_event_cb(evutil_socket_t s, short what, void *ptr) 3832b15cb3dSCy Schubert { 3842b15cb3dSCy Schubert short *whatp = ptr; 3852b15cb3dSCy Schubert if (!have_closed) 3862b15cb3dSCy Schubert premature_event = 1; 3872b15cb3dSCy Schubert *whatp = what; 3882b15cb3dSCy Schubert TT_BLATHER(("Recorded %d on socket %d", (int)what, (int)s)); 3892b15cb3dSCy Schubert } 3902b15cb3dSCy Schubert 3912b15cb3dSCy Schubert static void 3922b15cb3dSCy Schubert test_simpleclose(void *ptr) 3932b15cb3dSCy Schubert { 3942b15cb3dSCy Schubert /* Test that a close of FD is detected as a read and as a write. */ 3952b15cb3dSCy Schubert struct event_base *base = event_base_new(); 3962b15cb3dSCy Schubert evutil_socket_t pair1[2]={-1,-1}, pair2[2] = {-1, -1}; 3972b15cb3dSCy Schubert evutil_socket_t *to_close[2]; 3982b15cb3dSCy Schubert struct event *rev=NULL, *wev=NULL, *closeev=NULL; 3992b15cb3dSCy Schubert struct timeval tv; 4002b15cb3dSCy Schubert short got_read_on_close = 0, got_write_on_close = 0; 4012b15cb3dSCy Schubert char buf[1024]; 4022b15cb3dSCy Schubert memset(buf, 99, sizeof(buf)); 4032b15cb3dSCy Schubert #ifdef _WIN32 4042b15cb3dSCy Schubert #define LOCAL_SOCKETPAIR_AF AF_INET 4052b15cb3dSCy Schubert #else 4062b15cb3dSCy Schubert #define LOCAL_SOCKETPAIR_AF AF_UNIX 4072b15cb3dSCy Schubert #endif 4082b15cb3dSCy Schubert if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair1)<0) 4092b15cb3dSCy Schubert TT_DIE(("socketpair: %s", strerror(errno))); 4102b15cb3dSCy Schubert if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair2)<0) 4112b15cb3dSCy Schubert TT_DIE(("socketpair: %s", strerror(errno))); 4122b15cb3dSCy Schubert if (evutil_make_socket_nonblocking(pair1[1]) < 0) 4132b15cb3dSCy Schubert TT_DIE(("make_socket_nonblocking")); 4142b15cb3dSCy Schubert if (evutil_make_socket_nonblocking(pair2[1]) < 0) 4152b15cb3dSCy Schubert TT_DIE(("make_socket_nonblocking")); 4162b15cb3dSCy Schubert 4172b15cb3dSCy Schubert /** Stuff pair2[1] full of data, until write fails */ 4182b15cb3dSCy Schubert while (1) { 4192b15cb3dSCy Schubert int r = write(pair2[1], buf, sizeof(buf)); 4202b15cb3dSCy Schubert if (r<0) { 4212b15cb3dSCy Schubert int err = evutil_socket_geterror(pair2[1]); 4222b15cb3dSCy Schubert if (! EVUTIL_ERR_RW_RETRIABLE(err)) 4232b15cb3dSCy Schubert TT_DIE(("write failed strangely: %s", 4242b15cb3dSCy Schubert evutil_socket_error_to_string(err))); 4252b15cb3dSCy Schubert break; 4262b15cb3dSCy Schubert } 4272b15cb3dSCy Schubert } 4282b15cb3dSCy Schubert to_close[0] = &pair1[0]; 4292b15cb3dSCy Schubert to_close[1] = &pair2[0]; 4302b15cb3dSCy Schubert 4312b15cb3dSCy Schubert closeev = event_new(base, -1, EV_TIMEOUT, simpleclose_close_fd_cb, 4322b15cb3dSCy Schubert to_close); 4332b15cb3dSCy Schubert rev = event_new(base, pair1[1], EV_READ, record_event_cb, 4342b15cb3dSCy Schubert &got_read_on_close); 4352b15cb3dSCy Schubert TT_BLATHER(("Waiting for read on %d", (int)pair1[1])); 4362b15cb3dSCy Schubert wev = event_new(base, pair2[1], EV_WRITE, record_event_cb, 4372b15cb3dSCy Schubert &got_write_on_close); 4382b15cb3dSCy Schubert TT_BLATHER(("Waiting for write on %d", (int)pair2[1])); 4392b15cb3dSCy Schubert tv.tv_sec = 0; 4402b15cb3dSCy Schubert tv.tv_usec = 100*1000; /* Close pair1[0] after a little while, and make 4412b15cb3dSCy Schubert * sure we get a read event. */ 4422b15cb3dSCy Schubert event_add(closeev, &tv); 4432b15cb3dSCy Schubert event_add(rev, NULL); 4442b15cb3dSCy Schubert event_add(wev, NULL); 4452b15cb3dSCy Schubert /* Don't let the test go on too long. */ 4462b15cb3dSCy Schubert tv.tv_sec = 0; 4472b15cb3dSCy Schubert tv.tv_usec = 200*1000; 4482b15cb3dSCy Schubert event_base_loopexit(base, &tv); 4492b15cb3dSCy Schubert event_base_loop(base, 0); 4502b15cb3dSCy Schubert 4512b15cb3dSCy Schubert tt_int_op(got_read_on_close, ==, EV_READ); 4522b15cb3dSCy Schubert tt_int_op(got_write_on_close, ==, EV_WRITE); 4532b15cb3dSCy Schubert tt_int_op(premature_event, ==, 0); 4542b15cb3dSCy Schubert 4552b15cb3dSCy Schubert end: 4562b15cb3dSCy Schubert if (pair1[0] >= 0) 4572b15cb3dSCy Schubert evutil_closesocket(pair1[0]); 4582b15cb3dSCy Schubert if (pair1[1] >= 0) 4592b15cb3dSCy Schubert evutil_closesocket(pair1[1]); 4602b15cb3dSCy Schubert if (pair2[0] >= 0) 4612b15cb3dSCy Schubert evutil_closesocket(pair2[0]); 4622b15cb3dSCy Schubert if (pair2[1] >= 0) 4632b15cb3dSCy Schubert evutil_closesocket(pair2[1]); 4642b15cb3dSCy Schubert if (rev) 4652b15cb3dSCy Schubert event_free(rev); 4662b15cb3dSCy Schubert if (wev) 4672b15cb3dSCy Schubert event_free(wev); 4682b15cb3dSCy Schubert if (closeev) 4692b15cb3dSCy Schubert event_free(closeev); 4702b15cb3dSCy Schubert if (base) 4712b15cb3dSCy Schubert event_base_free(base); 4722b15cb3dSCy Schubert } 4732b15cb3dSCy Schubert 4742b15cb3dSCy Schubert 4752b15cb3dSCy Schubert static void 4762b15cb3dSCy Schubert test_multiple(void) 4772b15cb3dSCy Schubert { 4782b15cb3dSCy Schubert struct event ev, ev2; 4792b15cb3dSCy Schubert int i; 4802b15cb3dSCy Schubert 4812b15cb3dSCy Schubert /* Multiple read and write test */ 4822b15cb3dSCy Schubert setup_test("Multiple read/write: "); 4832b15cb3dSCy Schubert memset(rbuf, 0, sizeof(rbuf)); 4842b15cb3dSCy Schubert for (i = 0; i < (int)sizeof(wbuf); i++) 4852b15cb3dSCy Schubert wbuf[i] = i; 4862b15cb3dSCy Schubert 4872b15cb3dSCy Schubert roff = woff = 0; 4882b15cb3dSCy Schubert usepersist = 0; 4892b15cb3dSCy Schubert 4902b15cb3dSCy Schubert event_set(&ev, pair[0], EV_WRITE, multiple_write_cb, &ev); 4912b15cb3dSCy Schubert if (event_add(&ev, NULL) == -1) 4922b15cb3dSCy Schubert exit(1); 4932b15cb3dSCy Schubert event_set(&ev2, pair[1], EV_READ, multiple_read_cb, &ev2); 4942b15cb3dSCy Schubert if (event_add(&ev2, NULL) == -1) 4952b15cb3dSCy Schubert exit(1); 4962b15cb3dSCy Schubert event_dispatch(); 4972b15cb3dSCy Schubert 4982b15cb3dSCy Schubert if (roff == woff) 4992b15cb3dSCy Schubert test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; 5002b15cb3dSCy Schubert 5012b15cb3dSCy Schubert cleanup_test(); 5022b15cb3dSCy Schubert } 5032b15cb3dSCy Schubert 5042b15cb3dSCy Schubert static void 5052b15cb3dSCy Schubert test_persistent(void) 5062b15cb3dSCy Schubert { 5072b15cb3dSCy Schubert struct event ev, ev2; 5082b15cb3dSCy Schubert int i; 5092b15cb3dSCy Schubert 5102b15cb3dSCy Schubert /* Multiple read and write test with persist */ 5112b15cb3dSCy Schubert setup_test("Persist read/write: "); 5122b15cb3dSCy Schubert memset(rbuf, 0, sizeof(rbuf)); 5132b15cb3dSCy Schubert for (i = 0; i < (int)sizeof(wbuf); i++) 5142b15cb3dSCy Schubert wbuf[i] = i; 5152b15cb3dSCy Schubert 5162b15cb3dSCy Schubert roff = woff = 0; 5172b15cb3dSCy Schubert usepersist = 1; 5182b15cb3dSCy Schubert 5192b15cb3dSCy Schubert event_set(&ev, pair[0], EV_WRITE|EV_PERSIST, multiple_write_cb, &ev); 5202b15cb3dSCy Schubert if (event_add(&ev, NULL) == -1) 5212b15cb3dSCy Schubert exit(1); 5222b15cb3dSCy Schubert event_set(&ev2, pair[1], EV_READ|EV_PERSIST, multiple_read_cb, &ev2); 5232b15cb3dSCy Schubert if (event_add(&ev2, NULL) == -1) 5242b15cb3dSCy Schubert exit(1); 5252b15cb3dSCy Schubert event_dispatch(); 5262b15cb3dSCy Schubert 5272b15cb3dSCy Schubert if (roff == woff) 5282b15cb3dSCy Schubert test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; 5292b15cb3dSCy Schubert 5302b15cb3dSCy Schubert cleanup_test(); 5312b15cb3dSCy Schubert } 5322b15cb3dSCy Schubert 5332b15cb3dSCy Schubert static void 5342b15cb3dSCy Schubert test_combined(void) 5352b15cb3dSCy Schubert { 5362b15cb3dSCy Schubert struct both r1, r2, w1, w2; 5372b15cb3dSCy Schubert 5382b15cb3dSCy Schubert setup_test("Combined read/write: "); 5392b15cb3dSCy Schubert memset(&r1, 0, sizeof(r1)); 5402b15cb3dSCy Schubert memset(&r2, 0, sizeof(r2)); 5412b15cb3dSCy Schubert memset(&w1, 0, sizeof(w1)); 5422b15cb3dSCy Schubert memset(&w2, 0, sizeof(w2)); 5432b15cb3dSCy Schubert 5442b15cb3dSCy Schubert w1.nread = 4096; 5452b15cb3dSCy Schubert w2.nread = 8192; 5462b15cb3dSCy Schubert 5472b15cb3dSCy Schubert event_set(&r1.ev, pair[0], EV_READ, combined_read_cb, &r1); 5482b15cb3dSCy Schubert event_set(&w1.ev, pair[0], EV_WRITE, combined_write_cb, &w1); 5492b15cb3dSCy Schubert event_set(&r2.ev, pair[1], EV_READ, combined_read_cb, &r2); 5502b15cb3dSCy Schubert event_set(&w2.ev, pair[1], EV_WRITE, combined_write_cb, &w2); 5512b15cb3dSCy Schubert tt_assert(event_add(&r1.ev, NULL) != -1); 5522b15cb3dSCy Schubert tt_assert(!event_add(&w1.ev, NULL)); 5532b15cb3dSCy Schubert tt_assert(!event_add(&r2.ev, NULL)); 5542b15cb3dSCy Schubert tt_assert(!event_add(&w2.ev, NULL)); 5552b15cb3dSCy Schubert event_dispatch(); 5562b15cb3dSCy Schubert 5572b15cb3dSCy Schubert if (r1.nread == 8192 && r2.nread == 4096) 5582b15cb3dSCy Schubert test_ok = 1; 5592b15cb3dSCy Schubert 5602b15cb3dSCy Schubert end: 5612b15cb3dSCy Schubert cleanup_test(); 5622b15cb3dSCy Schubert } 5632b15cb3dSCy Schubert 5642b15cb3dSCy Schubert static void 5652b15cb3dSCy Schubert test_simpletimeout(void) 5662b15cb3dSCy Schubert { 5672b15cb3dSCy Schubert struct timeval tv; 5682b15cb3dSCy Schubert struct event ev; 5692b15cb3dSCy Schubert 5702b15cb3dSCy Schubert setup_test("Simple timeout: "); 5712b15cb3dSCy Schubert 5722b15cb3dSCy Schubert tv.tv_usec = 200*1000; 5732b15cb3dSCy Schubert tv.tv_sec = 0; 5742b15cb3dSCy Schubert evutil_timerclear(&tcalled); 5752b15cb3dSCy Schubert evtimer_set(&ev, timeout_cb, NULL); 5762b15cb3dSCy Schubert evtimer_add(&ev, &tv); 5772b15cb3dSCy Schubert 5782b15cb3dSCy Schubert evutil_gettimeofday(&tset, NULL); 5792b15cb3dSCy Schubert event_dispatch(); 5802b15cb3dSCy Schubert test_timeval_diff_eq(&tset, &tcalled, 200); 5812b15cb3dSCy Schubert 5822b15cb3dSCy Schubert test_ok = 1; 5832b15cb3dSCy Schubert end: 5842b15cb3dSCy Schubert cleanup_test(); 5852b15cb3dSCy Schubert } 5862b15cb3dSCy Schubert 5872b15cb3dSCy Schubert static void 5882b15cb3dSCy Schubert periodic_timeout_cb(evutil_socket_t fd, short event, void *arg) 5892b15cb3dSCy Schubert { 5902b15cb3dSCy Schubert int *count = arg; 5912b15cb3dSCy Schubert 5922b15cb3dSCy Schubert (*count)++; 5932b15cb3dSCy Schubert if (*count == 6) { 5942b15cb3dSCy Schubert /* call loopexit only once - on slow machines(?), it is 5952b15cb3dSCy Schubert * apparently possible for this to get called twice. */ 5962b15cb3dSCy Schubert test_ok = 1; 5972b15cb3dSCy Schubert event_base_loopexit(global_base, NULL); 5982b15cb3dSCy Schubert } 5992b15cb3dSCy Schubert } 6002b15cb3dSCy Schubert 6012b15cb3dSCy Schubert static void 6022b15cb3dSCy Schubert test_persistent_timeout(void) 6032b15cb3dSCy Schubert { 6042b15cb3dSCy Schubert struct timeval tv; 6052b15cb3dSCy Schubert struct event ev; 6062b15cb3dSCy Schubert int count = 0; 6072b15cb3dSCy Schubert 6082b15cb3dSCy Schubert evutil_timerclear(&tv); 6092b15cb3dSCy Schubert tv.tv_usec = 10000; 6102b15cb3dSCy Schubert 6112b15cb3dSCy Schubert event_assign(&ev, global_base, -1, EV_TIMEOUT|EV_PERSIST, 6122b15cb3dSCy Schubert periodic_timeout_cb, &count); 6132b15cb3dSCy Schubert event_add(&ev, &tv); 6142b15cb3dSCy Schubert 6152b15cb3dSCy Schubert event_dispatch(); 6162b15cb3dSCy Schubert 6172b15cb3dSCy Schubert event_del(&ev); 6182b15cb3dSCy Schubert } 6192b15cb3dSCy Schubert 6202b15cb3dSCy Schubert static void 6212b15cb3dSCy Schubert test_persistent_timeout_jump(void *ptr) 6222b15cb3dSCy Schubert { 6232b15cb3dSCy Schubert struct basic_test_data *data = ptr; 6242b15cb3dSCy Schubert struct event ev; 6252b15cb3dSCy Schubert int count = 0; 6262b15cb3dSCy Schubert struct timeval msec100 = { 0, 100 * 1000 }; 6272b15cb3dSCy Schubert struct timeval msec50 = { 0, 50 * 1000 }; 6282b15cb3dSCy Schubert struct timeval msec300 = { 0, 300 * 1000 }; 6292b15cb3dSCy Schubert 6302b15cb3dSCy Schubert event_assign(&ev, data->base, -1, EV_PERSIST, periodic_timeout_cb, &count); 6312b15cb3dSCy Schubert event_add(&ev, &msec100); 6322b15cb3dSCy Schubert /* Wait for a bit */ 6332b15cb3dSCy Schubert evutil_usleep_(&msec300); 6342b15cb3dSCy Schubert event_base_loopexit(data->base, &msec50); 6352b15cb3dSCy Schubert event_base_dispatch(data->base); 6362b15cb3dSCy Schubert tt_int_op(count, ==, 1); 6372b15cb3dSCy Schubert 6382b15cb3dSCy Schubert end: 6392b15cb3dSCy Schubert event_del(&ev); 6402b15cb3dSCy Schubert } 6412b15cb3dSCy Schubert 6422b15cb3dSCy Schubert struct persist_active_timeout_called { 6432b15cb3dSCy Schubert int n; 6442b15cb3dSCy Schubert short events[16]; 6452b15cb3dSCy Schubert struct timeval tvs[16]; 6462b15cb3dSCy Schubert }; 6472b15cb3dSCy Schubert 6482b15cb3dSCy Schubert static void 6492b15cb3dSCy Schubert activate_cb(evutil_socket_t fd, short event, void *arg) 6502b15cb3dSCy Schubert { 6512b15cb3dSCy Schubert struct event *ev = arg; 6522b15cb3dSCy Schubert event_active(ev, EV_READ, 1); 6532b15cb3dSCy Schubert } 6542b15cb3dSCy Schubert 6552b15cb3dSCy Schubert static void 6562b15cb3dSCy Schubert persist_active_timeout_cb(evutil_socket_t fd, short event, void *arg) 6572b15cb3dSCy Schubert { 6582b15cb3dSCy Schubert struct persist_active_timeout_called *c = arg; 6592b15cb3dSCy Schubert if (c->n < 15) { 6602b15cb3dSCy Schubert c->events[c->n] = event; 6612b15cb3dSCy Schubert evutil_gettimeofday(&c->tvs[c->n], NULL); 6622b15cb3dSCy Schubert ++c->n; 6632b15cb3dSCy Schubert } 6642b15cb3dSCy Schubert } 6652b15cb3dSCy Schubert 6662b15cb3dSCy Schubert static void 6672b15cb3dSCy Schubert test_persistent_active_timeout(void *ptr) 6682b15cb3dSCy Schubert { 6692b15cb3dSCy Schubert struct timeval tv, tv2, tv_exit, start; 6702b15cb3dSCy Schubert struct event ev; 6712b15cb3dSCy Schubert struct persist_active_timeout_called res; 6722b15cb3dSCy Schubert 6732b15cb3dSCy Schubert struct basic_test_data *data = ptr; 6742b15cb3dSCy Schubert struct event_base *base = data->base; 6752b15cb3dSCy Schubert 6762b15cb3dSCy Schubert memset(&res, 0, sizeof(res)); 6772b15cb3dSCy Schubert 6782b15cb3dSCy Schubert tv.tv_sec = 0; 6792b15cb3dSCy Schubert tv.tv_usec = 200 * 1000; 6802b15cb3dSCy Schubert event_assign(&ev, base, -1, EV_TIMEOUT|EV_PERSIST, 6812b15cb3dSCy Schubert persist_active_timeout_cb, &res); 6822b15cb3dSCy Schubert event_add(&ev, &tv); 6832b15cb3dSCy Schubert 6842b15cb3dSCy Schubert tv2.tv_sec = 0; 6852b15cb3dSCy Schubert tv2.tv_usec = 100 * 1000; 6862b15cb3dSCy Schubert event_base_once(base, -1, EV_TIMEOUT, activate_cb, &ev, &tv2); 6872b15cb3dSCy Schubert 6882b15cb3dSCy Schubert tv_exit.tv_sec = 0; 6892b15cb3dSCy Schubert tv_exit.tv_usec = 600 * 1000; 6902b15cb3dSCy Schubert event_base_loopexit(base, &tv_exit); 6912b15cb3dSCy Schubert 6922b15cb3dSCy Schubert event_base_assert_ok_(base); 6932b15cb3dSCy Schubert evutil_gettimeofday(&start, NULL); 6942b15cb3dSCy Schubert 6952b15cb3dSCy Schubert event_base_dispatch(base); 6962b15cb3dSCy Schubert event_base_assert_ok_(base); 6972b15cb3dSCy Schubert 6982b15cb3dSCy Schubert tt_int_op(res.n, ==, 3); 6992b15cb3dSCy Schubert tt_int_op(res.events[0], ==, EV_READ); 7002b15cb3dSCy Schubert tt_int_op(res.events[1], ==, EV_TIMEOUT); 7012b15cb3dSCy Schubert tt_int_op(res.events[2], ==, EV_TIMEOUT); 7022b15cb3dSCy Schubert test_timeval_diff_eq(&start, &res.tvs[0], 100); 7032b15cb3dSCy Schubert test_timeval_diff_eq(&start, &res.tvs[1], 300); 7042b15cb3dSCy Schubert test_timeval_diff_eq(&start, &res.tvs[2], 500); 7052b15cb3dSCy Schubert end: 7062b15cb3dSCy Schubert event_del(&ev); 7072b15cb3dSCy Schubert } 7082b15cb3dSCy Schubert 7092b15cb3dSCy Schubert struct common_timeout_info { 7102b15cb3dSCy Schubert struct event ev; 7112b15cb3dSCy Schubert struct timeval called_at; 7122b15cb3dSCy Schubert int which; 7132b15cb3dSCy Schubert int count; 7142b15cb3dSCy Schubert }; 7152b15cb3dSCy Schubert 7162b15cb3dSCy Schubert static void 7172b15cb3dSCy Schubert common_timeout_cb(evutil_socket_t fd, short event, void *arg) 7182b15cb3dSCy Schubert { 7192b15cb3dSCy Schubert struct common_timeout_info *ti = arg; 7202b15cb3dSCy Schubert ++ti->count; 7212b15cb3dSCy Schubert evutil_gettimeofday(&ti->called_at, NULL); 7222b15cb3dSCy Schubert if (ti->count >= 4) 7232b15cb3dSCy Schubert event_del(&ti->ev); 7242b15cb3dSCy Schubert } 7252b15cb3dSCy Schubert 7262b15cb3dSCy Schubert static void 7272b15cb3dSCy Schubert test_common_timeout(void *ptr) 7282b15cb3dSCy Schubert { 7292b15cb3dSCy Schubert struct basic_test_data *data = ptr; 7302b15cb3dSCy Schubert 7312b15cb3dSCy Schubert struct event_base *base = data->base; 7322b15cb3dSCy Schubert int i; 7332b15cb3dSCy Schubert struct common_timeout_info info[100]; 7342b15cb3dSCy Schubert 7352b15cb3dSCy Schubert struct timeval start; 7362b15cb3dSCy Schubert struct timeval tmp_100_ms = { 0, 100*1000 }; 7372b15cb3dSCy Schubert struct timeval tmp_200_ms = { 0, 200*1000 }; 7382b15cb3dSCy Schubert struct timeval tmp_5_sec = { 5, 0 }; 7392b15cb3dSCy Schubert struct timeval tmp_5M_usec = { 0, 5*1000*1000 }; 7402b15cb3dSCy Schubert 7412b15cb3dSCy Schubert const struct timeval *ms_100, *ms_200, *sec_5; 7422b15cb3dSCy Schubert 7432b15cb3dSCy Schubert ms_100 = event_base_init_common_timeout(base, &tmp_100_ms); 7442b15cb3dSCy Schubert ms_200 = event_base_init_common_timeout(base, &tmp_200_ms); 7452b15cb3dSCy Schubert sec_5 = event_base_init_common_timeout(base, &tmp_5_sec); 7462b15cb3dSCy Schubert tt_assert(ms_100); 7472b15cb3dSCy Schubert tt_assert(ms_200); 7482b15cb3dSCy Schubert tt_assert(sec_5); 7492b15cb3dSCy Schubert tt_ptr_op(event_base_init_common_timeout(base, &tmp_200_ms), 7502b15cb3dSCy Schubert ==, ms_200); 7512b15cb3dSCy Schubert tt_ptr_op(event_base_init_common_timeout(base, ms_200), ==, ms_200); 7522b15cb3dSCy Schubert tt_ptr_op(event_base_init_common_timeout(base, &tmp_5M_usec), ==, sec_5); 7532b15cb3dSCy Schubert tt_int_op(ms_100->tv_sec, ==, 0); 7542b15cb3dSCy Schubert tt_int_op(ms_200->tv_sec, ==, 0); 7552b15cb3dSCy Schubert tt_int_op(sec_5->tv_sec, ==, 5); 7562b15cb3dSCy Schubert tt_int_op(ms_100->tv_usec, ==, 100000|0x50000000); 7572b15cb3dSCy Schubert tt_int_op(ms_200->tv_usec, ==, 200000|0x50100000); 7582b15cb3dSCy Schubert tt_int_op(sec_5->tv_usec, ==, 0|0x50200000); 7592b15cb3dSCy Schubert 7602b15cb3dSCy Schubert memset(info, 0, sizeof(info)); 7612b15cb3dSCy Schubert 7622b15cb3dSCy Schubert for (i=0; i<100; ++i) { 7632b15cb3dSCy Schubert info[i].which = i; 7642b15cb3dSCy Schubert event_assign(&info[i].ev, base, -1, EV_TIMEOUT|EV_PERSIST, 7652b15cb3dSCy Schubert common_timeout_cb, &info[i]); 7662b15cb3dSCy Schubert if (i % 2) { 7672b15cb3dSCy Schubert if ((i%20)==1) { 7682b15cb3dSCy Schubert /* Glass-box test: Make sure we survive the 7692b15cb3dSCy Schubert * transition to non-common timeouts. It's 7702b15cb3dSCy Schubert * a little tricky. */ 7712b15cb3dSCy Schubert event_add(&info[i].ev, ms_200); 7722b15cb3dSCy Schubert event_add(&info[i].ev, &tmp_100_ms); 7732b15cb3dSCy Schubert } else if ((i%20)==3) { 7742b15cb3dSCy Schubert /* Check heap-to-common too. */ 7752b15cb3dSCy Schubert event_add(&info[i].ev, &tmp_200_ms); 7762b15cb3dSCy Schubert event_add(&info[i].ev, ms_100); 7772b15cb3dSCy Schubert } else if ((i%20)==5) { 7782b15cb3dSCy Schubert /* Also check common-to-common. */ 7792b15cb3dSCy Schubert event_add(&info[i].ev, ms_200); 7802b15cb3dSCy Schubert event_add(&info[i].ev, ms_100); 7812b15cb3dSCy Schubert } else { 7822b15cb3dSCy Schubert event_add(&info[i].ev, ms_100); 7832b15cb3dSCy Schubert } 7842b15cb3dSCy Schubert } else { 7852b15cb3dSCy Schubert event_add(&info[i].ev, ms_200); 7862b15cb3dSCy Schubert } 7872b15cb3dSCy Schubert } 7882b15cb3dSCy Schubert 7892b15cb3dSCy Schubert event_base_assert_ok_(base); 7902b15cb3dSCy Schubert evutil_gettimeofday(&start, NULL); 7912b15cb3dSCy Schubert event_base_dispatch(base); 7922b15cb3dSCy Schubert 7932b15cb3dSCy Schubert event_base_assert_ok_(base); 7942b15cb3dSCy Schubert 7952b15cb3dSCy Schubert for (i=0; i<10; ++i) { 7962b15cb3dSCy Schubert tt_int_op(info[i].count, ==, 4); 7972b15cb3dSCy Schubert if (i % 2) { 7982b15cb3dSCy Schubert test_timeval_diff_eq(&start, &info[i].called_at, 400); 7992b15cb3dSCy Schubert } else { 8002b15cb3dSCy Schubert test_timeval_diff_eq(&start, &info[i].called_at, 800); 8012b15cb3dSCy Schubert } 8022b15cb3dSCy Schubert } 8032b15cb3dSCy Schubert 8042b15cb3dSCy Schubert /* Make sure we can free the base with some events in. */ 8052b15cb3dSCy Schubert for (i=0; i<100; ++i) { 8062b15cb3dSCy Schubert if (i % 2) { 8072b15cb3dSCy Schubert event_add(&info[i].ev, ms_100); 8082b15cb3dSCy Schubert } else { 8092b15cb3dSCy Schubert event_add(&info[i].ev, ms_200); 8102b15cb3dSCy Schubert } 8112b15cb3dSCy Schubert } 8122b15cb3dSCy Schubert 8132b15cb3dSCy Schubert end: 8142b15cb3dSCy Schubert event_base_free(data->base); /* need to do this here before info is 8152b15cb3dSCy Schubert * out-of-scope */ 8162b15cb3dSCy Schubert data->base = NULL; 8172b15cb3dSCy Schubert } 8182b15cb3dSCy Schubert 8192b15cb3dSCy Schubert #ifndef _WIN32 8202b15cb3dSCy Schubert static void signal_cb(evutil_socket_t fd, short event, void *arg); 8212b15cb3dSCy Schubert 8222b15cb3dSCy Schubert #define current_base event_global_current_base_ 8232b15cb3dSCy Schubert extern struct event_base *current_base; 8242b15cb3dSCy Schubert 8252b15cb3dSCy Schubert static void 8262b15cb3dSCy Schubert child_signal_cb(evutil_socket_t fd, short event, void *arg) 8272b15cb3dSCy Schubert { 8282b15cb3dSCy Schubert struct timeval tv; 8292b15cb3dSCy Schubert int *pint = arg; 8302b15cb3dSCy Schubert 8312b15cb3dSCy Schubert *pint = 1; 8322b15cb3dSCy Schubert 8332b15cb3dSCy Schubert tv.tv_usec = 500000; 8342b15cb3dSCy Schubert tv.tv_sec = 0; 8352b15cb3dSCy Schubert event_loopexit(&tv); 8362b15cb3dSCy Schubert } 8372b15cb3dSCy Schubert 8382b15cb3dSCy Schubert static void 8392b15cb3dSCy Schubert test_fork(void) 8402b15cb3dSCy Schubert { 8412b15cb3dSCy Schubert int status, got_sigchld = 0; 8422b15cb3dSCy Schubert struct event ev, sig_ev; 8432b15cb3dSCy Schubert pid_t pid; 8442b15cb3dSCy Schubert 8452b15cb3dSCy Schubert setup_test("After fork: "); 8462b15cb3dSCy Schubert 8472b15cb3dSCy Schubert tt_assert(current_base); 8482b15cb3dSCy Schubert evthread_make_base_notifiable(current_base); 8492b15cb3dSCy Schubert 8502b15cb3dSCy Schubert if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 8512b15cb3dSCy Schubert tt_fail_perror("write"); 8522b15cb3dSCy Schubert } 8532b15cb3dSCy Schubert 8542b15cb3dSCy Schubert event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev); 8552b15cb3dSCy Schubert if (event_add(&ev, NULL) == -1) 8562b15cb3dSCy Schubert exit(1); 8572b15cb3dSCy Schubert 8582b15cb3dSCy Schubert evsignal_set(&sig_ev, SIGCHLD, child_signal_cb, &got_sigchld); 8592b15cb3dSCy Schubert evsignal_add(&sig_ev, NULL); 8602b15cb3dSCy Schubert 8612b15cb3dSCy Schubert event_base_assert_ok_(current_base); 8622b15cb3dSCy Schubert TT_BLATHER(("Before fork")); 8632b15cb3dSCy Schubert if ((pid = regress_fork()) == 0) { 8642b15cb3dSCy Schubert /* in the child */ 8652b15cb3dSCy Schubert TT_BLATHER(("In child, before reinit")); 8662b15cb3dSCy Schubert event_base_assert_ok_(current_base); 8672b15cb3dSCy Schubert if (event_reinit(current_base) == -1) { 8682b15cb3dSCy Schubert fprintf(stdout, "FAILED (reinit)\n"); 8692b15cb3dSCy Schubert exit(1); 8702b15cb3dSCy Schubert } 8712b15cb3dSCy Schubert TT_BLATHER(("After reinit")); 8722b15cb3dSCy Schubert event_base_assert_ok_(current_base); 8732b15cb3dSCy Schubert TT_BLATHER(("After assert-ok")); 8742b15cb3dSCy Schubert 8752b15cb3dSCy Schubert evsignal_del(&sig_ev); 8762b15cb3dSCy Schubert 8772b15cb3dSCy Schubert called = 0; 8782b15cb3dSCy Schubert 8792b15cb3dSCy Schubert event_dispatch(); 8802b15cb3dSCy Schubert 8812b15cb3dSCy Schubert event_base_free(current_base); 8822b15cb3dSCy Schubert 8832b15cb3dSCy Schubert /* we do not send an EOF; simple_read_cb requires an EOF 8842b15cb3dSCy Schubert * to set test_ok. we just verify that the callback was 8852b15cb3dSCy Schubert * called. */ 8862b15cb3dSCy Schubert exit(test_ok != 0 || called != 2 ? -2 : 76); 8872b15cb3dSCy Schubert } 8882b15cb3dSCy Schubert 8892b15cb3dSCy Schubert /* wait for the child to read the data */ 8902b15cb3dSCy Schubert { 8912b15cb3dSCy Schubert const struct timeval tv = { 0, 100000 }; 8922b15cb3dSCy Schubert evutil_usleep_(&tv); 8932b15cb3dSCy Schubert } 8942b15cb3dSCy Schubert 8952b15cb3dSCy Schubert if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 8962b15cb3dSCy Schubert tt_fail_perror("write"); 8972b15cb3dSCy Schubert } 8982b15cb3dSCy Schubert 8992b15cb3dSCy Schubert TT_BLATHER(("Before waitpid")); 9002b15cb3dSCy Schubert if (waitpid(pid, &status, 0) == -1) { 9012b15cb3dSCy Schubert fprintf(stdout, "FAILED (fork)\n"); 9022b15cb3dSCy Schubert exit(1); 9032b15cb3dSCy Schubert } 9042b15cb3dSCy Schubert TT_BLATHER(("After waitpid")); 9052b15cb3dSCy Schubert 9062b15cb3dSCy Schubert if (WEXITSTATUS(status) != 76) { 9072b15cb3dSCy Schubert fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status)); 9082b15cb3dSCy Schubert exit(1); 9092b15cb3dSCy Schubert } 9102b15cb3dSCy Schubert 9112b15cb3dSCy Schubert /* test that the current event loop still works */ 9122b15cb3dSCy Schubert if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 9132b15cb3dSCy Schubert fprintf(stderr, "%s: write\n", __func__); 9142b15cb3dSCy Schubert } 9152b15cb3dSCy Schubert 9162b15cb3dSCy Schubert shutdown(pair[0], SHUT_WR); 9172b15cb3dSCy Schubert 9182b15cb3dSCy Schubert event_dispatch(); 9192b15cb3dSCy Schubert 9202b15cb3dSCy Schubert if (!got_sigchld) { 9212b15cb3dSCy Schubert fprintf(stdout, "FAILED (sigchld)\n"); 9222b15cb3dSCy Schubert exit(1); 9232b15cb3dSCy Schubert } 9242b15cb3dSCy Schubert 9252b15cb3dSCy Schubert evsignal_del(&sig_ev); 9262b15cb3dSCy Schubert 9272b15cb3dSCy Schubert end: 9282b15cb3dSCy Schubert cleanup_test(); 9292b15cb3dSCy Schubert } 9302b15cb3dSCy Schubert 9312b15cb3dSCy Schubert static void 9322b15cb3dSCy Schubert signal_cb_sa(int sig) 9332b15cb3dSCy Schubert { 9342b15cb3dSCy Schubert test_ok = 2; 9352b15cb3dSCy Schubert } 9362b15cb3dSCy Schubert 9372b15cb3dSCy Schubert static void 9382b15cb3dSCy Schubert signal_cb(evutil_socket_t fd, short event, void *arg) 9392b15cb3dSCy Schubert { 9402b15cb3dSCy Schubert struct event *ev = arg; 9412b15cb3dSCy Schubert 9422b15cb3dSCy Schubert evsignal_del(ev); 9432b15cb3dSCy Schubert test_ok = 1; 9442b15cb3dSCy Schubert } 9452b15cb3dSCy Schubert 9462b15cb3dSCy Schubert static void 947*a25439b6SCy Schubert test_simplesignal_impl(int find_reorder) 9482b15cb3dSCy Schubert { 9492b15cb3dSCy Schubert struct event ev; 9502b15cb3dSCy Schubert struct itimerval itv; 9512b15cb3dSCy Schubert 9522b15cb3dSCy Schubert evsignal_set(&ev, SIGALRM, signal_cb, &ev); 9532b15cb3dSCy Schubert evsignal_add(&ev, NULL); 9542b15cb3dSCy Schubert /* find bugs in which operations are re-ordered */ 955*a25439b6SCy Schubert if (find_reorder) { 9562b15cb3dSCy Schubert evsignal_del(&ev); 9572b15cb3dSCy Schubert evsignal_add(&ev, NULL); 958*a25439b6SCy Schubert } 9592b15cb3dSCy Schubert 9602b15cb3dSCy Schubert memset(&itv, 0, sizeof(itv)); 9612b15cb3dSCy Schubert itv.it_value.tv_sec = 0; 9622b15cb3dSCy Schubert itv.it_value.tv_usec = 100000; 9632b15cb3dSCy Schubert if (setitimer(ITIMER_REAL, &itv, NULL) == -1) 9642b15cb3dSCy Schubert goto skip_simplesignal; 9652b15cb3dSCy Schubert 9662b15cb3dSCy Schubert event_dispatch(); 9672b15cb3dSCy Schubert skip_simplesignal: 9682b15cb3dSCy Schubert if (evsignal_del(&ev) == -1) 9692b15cb3dSCy Schubert test_ok = 0; 9702b15cb3dSCy Schubert 9712b15cb3dSCy Schubert cleanup_test(); 9722b15cb3dSCy Schubert } 9732b15cb3dSCy Schubert 9742b15cb3dSCy Schubert static void 975*a25439b6SCy Schubert test_simplestsignal(void) 976*a25439b6SCy Schubert { 977*a25439b6SCy Schubert setup_test("Simplest one signal: "); 978*a25439b6SCy Schubert test_simplesignal_impl(0); 979*a25439b6SCy Schubert } 980*a25439b6SCy Schubert 981*a25439b6SCy Schubert static void 982*a25439b6SCy Schubert test_simplesignal(void) 983*a25439b6SCy Schubert { 984*a25439b6SCy Schubert setup_test("Simple signal: "); 985*a25439b6SCy Schubert test_simplesignal_impl(1); 986*a25439b6SCy Schubert } 987*a25439b6SCy Schubert 988*a25439b6SCy Schubert static void 9892b15cb3dSCy Schubert test_multiplesignal(void) 9902b15cb3dSCy Schubert { 9912b15cb3dSCy Schubert struct event ev_one, ev_two; 9922b15cb3dSCy Schubert struct itimerval itv; 9932b15cb3dSCy Schubert 9942b15cb3dSCy Schubert setup_test("Multiple signal: "); 9952b15cb3dSCy Schubert 9962b15cb3dSCy Schubert evsignal_set(&ev_one, SIGALRM, signal_cb, &ev_one); 9972b15cb3dSCy Schubert evsignal_add(&ev_one, NULL); 9982b15cb3dSCy Schubert 9992b15cb3dSCy Schubert evsignal_set(&ev_two, SIGALRM, signal_cb, &ev_two); 10002b15cb3dSCy Schubert evsignal_add(&ev_two, NULL); 10012b15cb3dSCy Schubert 10022b15cb3dSCy Schubert memset(&itv, 0, sizeof(itv)); 10032b15cb3dSCy Schubert itv.it_value.tv_sec = 0; 10042b15cb3dSCy Schubert itv.it_value.tv_usec = 100000; 10052b15cb3dSCy Schubert if (setitimer(ITIMER_REAL, &itv, NULL) == -1) 10062b15cb3dSCy Schubert goto skip_simplesignal; 10072b15cb3dSCy Schubert 10082b15cb3dSCy Schubert event_dispatch(); 10092b15cb3dSCy Schubert 10102b15cb3dSCy Schubert skip_simplesignal: 10112b15cb3dSCy Schubert if (evsignal_del(&ev_one) == -1) 10122b15cb3dSCy Schubert test_ok = 0; 10132b15cb3dSCy Schubert if (evsignal_del(&ev_two) == -1) 10142b15cb3dSCy Schubert test_ok = 0; 10152b15cb3dSCy Schubert 10162b15cb3dSCy Schubert cleanup_test(); 10172b15cb3dSCy Schubert } 10182b15cb3dSCy Schubert 10192b15cb3dSCy Schubert static void 10202b15cb3dSCy Schubert test_immediatesignal(void) 10212b15cb3dSCy Schubert { 10222b15cb3dSCy Schubert struct event ev; 10232b15cb3dSCy Schubert 10242b15cb3dSCy Schubert test_ok = 0; 10252b15cb3dSCy Schubert evsignal_set(&ev, SIGUSR1, signal_cb, &ev); 10262b15cb3dSCy Schubert evsignal_add(&ev, NULL); 10272b15cb3dSCy Schubert raise(SIGUSR1); 10282b15cb3dSCy Schubert event_loop(EVLOOP_NONBLOCK); 10292b15cb3dSCy Schubert evsignal_del(&ev); 10302b15cb3dSCy Schubert cleanup_test(); 10312b15cb3dSCy Schubert } 10322b15cb3dSCy Schubert 10332b15cb3dSCy Schubert static void 10342b15cb3dSCy Schubert test_signal_dealloc(void) 10352b15cb3dSCy Schubert { 10362b15cb3dSCy Schubert /* make sure that evsignal_event is event_del'ed and pipe closed */ 10372b15cb3dSCy Schubert struct event ev; 10382b15cb3dSCy Schubert struct event_base *base = event_init(); 10392b15cb3dSCy Schubert evsignal_set(&ev, SIGUSR1, signal_cb, &ev); 10402b15cb3dSCy Schubert evsignal_add(&ev, NULL); 10412b15cb3dSCy Schubert evsignal_del(&ev); 10422b15cb3dSCy Schubert event_base_free(base); 10432b15cb3dSCy Schubert /* If we got here without asserting, we're fine. */ 10442b15cb3dSCy Schubert test_ok = 1; 10452b15cb3dSCy Schubert cleanup_test(); 10462b15cb3dSCy Schubert } 10472b15cb3dSCy Schubert 10482b15cb3dSCy Schubert static void 10492b15cb3dSCy Schubert test_signal_pipeloss(void) 10502b15cb3dSCy Schubert { 10512b15cb3dSCy Schubert /* make sure that the base1 pipe is closed correctly. */ 10522b15cb3dSCy Schubert struct event_base *base1, *base2; 10532b15cb3dSCy Schubert int pipe1; 10542b15cb3dSCy Schubert test_ok = 0; 10552b15cb3dSCy Schubert base1 = event_init(); 10562b15cb3dSCy Schubert pipe1 = base1->sig.ev_signal_pair[0]; 10572b15cb3dSCy Schubert base2 = event_init(); 10582b15cb3dSCy Schubert event_base_free(base2); 10592b15cb3dSCy Schubert event_base_free(base1); 10602b15cb3dSCy Schubert if (close(pipe1) != -1 || errno!=EBADF) { 10612b15cb3dSCy Schubert /* fd must be closed, so second close gives -1, EBADF */ 10622b15cb3dSCy Schubert printf("signal pipe not closed. "); 10632b15cb3dSCy Schubert test_ok = 0; 10642b15cb3dSCy Schubert } else { 10652b15cb3dSCy Schubert test_ok = 1; 10662b15cb3dSCy Schubert } 10672b15cb3dSCy Schubert cleanup_test(); 10682b15cb3dSCy Schubert } 10692b15cb3dSCy Schubert 10702b15cb3dSCy Schubert /* 10712b15cb3dSCy Schubert * make two bases to catch signals, use both of them. this only works 10722b15cb3dSCy Schubert * for event mechanisms that use our signal pipe trick. kqueue handles 10732b15cb3dSCy Schubert * signals internally, and all interested kqueues get all the signals. 10742b15cb3dSCy Schubert */ 10752b15cb3dSCy Schubert static void 10762b15cb3dSCy Schubert test_signal_switchbase(void) 10772b15cb3dSCy Schubert { 10782b15cb3dSCy Schubert struct event ev1, ev2; 10792b15cb3dSCy Schubert struct event_base *base1, *base2; 10802b15cb3dSCy Schubert int is_kqueue; 10812b15cb3dSCy Schubert test_ok = 0; 10822b15cb3dSCy Schubert base1 = event_init(); 10832b15cb3dSCy Schubert base2 = event_init(); 10842b15cb3dSCy Schubert is_kqueue = !strcmp(event_get_method(),"kqueue"); 10852b15cb3dSCy Schubert evsignal_set(&ev1, SIGUSR1, signal_cb, &ev1); 10862b15cb3dSCy Schubert evsignal_set(&ev2, SIGUSR1, signal_cb, &ev2); 10872b15cb3dSCy Schubert if (event_base_set(base1, &ev1) || 10882b15cb3dSCy Schubert event_base_set(base2, &ev2) || 10892b15cb3dSCy Schubert event_add(&ev1, NULL) || 10902b15cb3dSCy Schubert event_add(&ev2, NULL)) { 10912b15cb3dSCy Schubert fprintf(stderr, "%s: cannot set base, add\n", __func__); 10922b15cb3dSCy Schubert exit(1); 10932b15cb3dSCy Schubert } 10942b15cb3dSCy Schubert 10952b15cb3dSCy Schubert tt_ptr_op(event_get_base(&ev1), ==, base1); 10962b15cb3dSCy Schubert tt_ptr_op(event_get_base(&ev2), ==, base2); 10972b15cb3dSCy Schubert 10982b15cb3dSCy Schubert test_ok = 0; 10992b15cb3dSCy Schubert /* can handle signal before loop is called */ 11002b15cb3dSCy Schubert raise(SIGUSR1); 11012b15cb3dSCy Schubert event_base_loop(base2, EVLOOP_NONBLOCK); 11022b15cb3dSCy Schubert if (is_kqueue) { 11032b15cb3dSCy Schubert if (!test_ok) 11042b15cb3dSCy Schubert goto end; 11052b15cb3dSCy Schubert test_ok = 0; 11062b15cb3dSCy Schubert } 11072b15cb3dSCy Schubert event_base_loop(base1, EVLOOP_NONBLOCK); 11082b15cb3dSCy Schubert if (test_ok && !is_kqueue) { 11092b15cb3dSCy Schubert test_ok = 0; 11102b15cb3dSCy Schubert 11112b15cb3dSCy Schubert /* set base1 to handle signals */ 11122b15cb3dSCy Schubert event_base_loop(base1, EVLOOP_NONBLOCK); 11132b15cb3dSCy Schubert raise(SIGUSR1); 11142b15cb3dSCy Schubert event_base_loop(base1, EVLOOP_NONBLOCK); 11152b15cb3dSCy Schubert event_base_loop(base2, EVLOOP_NONBLOCK); 11162b15cb3dSCy Schubert } 11172b15cb3dSCy Schubert end: 11182b15cb3dSCy Schubert event_base_free(base1); 11192b15cb3dSCy Schubert event_base_free(base2); 11202b15cb3dSCy Schubert cleanup_test(); 11212b15cb3dSCy Schubert } 11222b15cb3dSCy Schubert 11232b15cb3dSCy Schubert /* 11242b15cb3dSCy Schubert * assert that a signal event removed from the event queue really is 11252b15cb3dSCy Schubert * removed - with no possibility of it's parent handler being fired. 11262b15cb3dSCy Schubert */ 11272b15cb3dSCy Schubert static void 11282b15cb3dSCy Schubert test_signal_assert(void) 11292b15cb3dSCy Schubert { 11302b15cb3dSCy Schubert struct event ev; 11312b15cb3dSCy Schubert struct event_base *base = event_init(); 11322b15cb3dSCy Schubert test_ok = 0; 11332b15cb3dSCy Schubert /* use SIGCONT so we don't kill ourselves when we signal to nowhere */ 11342b15cb3dSCy Schubert evsignal_set(&ev, SIGCONT, signal_cb, &ev); 11352b15cb3dSCy Schubert evsignal_add(&ev, NULL); 11362b15cb3dSCy Schubert /* 11372b15cb3dSCy Schubert * if evsignal_del() fails to reset the handler, it's current handler 11382b15cb3dSCy Schubert * will still point to evsig_handler(). 11392b15cb3dSCy Schubert */ 11402b15cb3dSCy Schubert evsignal_del(&ev); 11412b15cb3dSCy Schubert 11422b15cb3dSCy Schubert raise(SIGCONT); 11432b15cb3dSCy Schubert #if 0 11442b15cb3dSCy Schubert /* only way to verify we were in evsig_handler() */ 11452b15cb3dSCy Schubert /* XXXX Now there's no longer a good way. */ 11462b15cb3dSCy Schubert if (base->sig.evsig_caught) 11472b15cb3dSCy Schubert test_ok = 0; 11482b15cb3dSCy Schubert else 11492b15cb3dSCy Schubert test_ok = 1; 11502b15cb3dSCy Schubert #else 11512b15cb3dSCy Schubert test_ok = 1; 11522b15cb3dSCy Schubert #endif 11532b15cb3dSCy Schubert 11542b15cb3dSCy Schubert event_base_free(base); 11552b15cb3dSCy Schubert cleanup_test(); 11562b15cb3dSCy Schubert return; 11572b15cb3dSCy Schubert } 11582b15cb3dSCy Schubert 11592b15cb3dSCy Schubert /* 11602b15cb3dSCy Schubert * assert that we restore our previous signal handler properly. 11612b15cb3dSCy Schubert */ 11622b15cb3dSCy Schubert static void 11632b15cb3dSCy Schubert test_signal_restore(void) 11642b15cb3dSCy Schubert { 11652b15cb3dSCy Schubert struct event ev; 11662b15cb3dSCy Schubert struct event_base *base = event_init(); 11672b15cb3dSCy Schubert #ifdef EVENT__HAVE_SIGACTION 11682b15cb3dSCy Schubert struct sigaction sa; 11692b15cb3dSCy Schubert #endif 11702b15cb3dSCy Schubert 11712b15cb3dSCy Schubert test_ok = 0; 11722b15cb3dSCy Schubert #ifdef EVENT__HAVE_SIGACTION 11732b15cb3dSCy Schubert sa.sa_handler = signal_cb_sa; 11742b15cb3dSCy Schubert sa.sa_flags = 0x0; 11752b15cb3dSCy Schubert sigemptyset(&sa.sa_mask); 11762b15cb3dSCy Schubert if (sigaction(SIGUSR1, &sa, NULL) == -1) 11772b15cb3dSCy Schubert goto out; 11782b15cb3dSCy Schubert #else 11792b15cb3dSCy Schubert if (signal(SIGUSR1, signal_cb_sa) == SIG_ERR) 11802b15cb3dSCy Schubert goto out; 11812b15cb3dSCy Schubert #endif 11822b15cb3dSCy Schubert evsignal_set(&ev, SIGUSR1, signal_cb, &ev); 11832b15cb3dSCy Schubert evsignal_add(&ev, NULL); 11842b15cb3dSCy Schubert evsignal_del(&ev); 11852b15cb3dSCy Schubert 11862b15cb3dSCy Schubert raise(SIGUSR1); 11872b15cb3dSCy Schubert /* 1 == signal_cb, 2 == signal_cb_sa, we want our previous handler */ 11882b15cb3dSCy Schubert if (test_ok != 2) 11892b15cb3dSCy Schubert test_ok = 0; 11902b15cb3dSCy Schubert out: 11912b15cb3dSCy Schubert event_base_free(base); 11922b15cb3dSCy Schubert cleanup_test(); 11932b15cb3dSCy Schubert return; 11942b15cb3dSCy Schubert } 11952b15cb3dSCy Schubert 11962b15cb3dSCy Schubert static void 11972b15cb3dSCy Schubert signal_cb_swp(int sig, short event, void *arg) 11982b15cb3dSCy Schubert { 11992b15cb3dSCy Schubert called++; 12002b15cb3dSCy Schubert if (called < 5) 12012b15cb3dSCy Schubert raise(sig); 12022b15cb3dSCy Schubert else 12032b15cb3dSCy Schubert event_loopexit(NULL); 12042b15cb3dSCy Schubert } 12052b15cb3dSCy Schubert static void 12062b15cb3dSCy Schubert timeout_cb_swp(evutil_socket_t fd, short event, void *arg) 12072b15cb3dSCy Schubert { 12082b15cb3dSCy Schubert if (called == -1) { 12092b15cb3dSCy Schubert struct timeval tv = {5, 0}; 12102b15cb3dSCy Schubert 12112b15cb3dSCy Schubert called = 0; 12122b15cb3dSCy Schubert evtimer_add((struct event *)arg, &tv); 12132b15cb3dSCy Schubert raise(SIGUSR1); 12142b15cb3dSCy Schubert return; 12152b15cb3dSCy Schubert } 12162b15cb3dSCy Schubert test_ok = 0; 12172b15cb3dSCy Schubert event_loopexit(NULL); 12182b15cb3dSCy Schubert } 12192b15cb3dSCy Schubert 12202b15cb3dSCy Schubert static void 12212b15cb3dSCy Schubert test_signal_while_processing(void) 12222b15cb3dSCy Schubert { 12232b15cb3dSCy Schubert struct event_base *base = event_init(); 12242b15cb3dSCy Schubert struct event ev, ev_timer; 12252b15cb3dSCy Schubert struct timeval tv = {0, 0}; 12262b15cb3dSCy Schubert 12272b15cb3dSCy Schubert setup_test("Receiving a signal while processing other signal: "); 12282b15cb3dSCy Schubert 12292b15cb3dSCy Schubert called = -1; 12302b15cb3dSCy Schubert test_ok = 1; 12312b15cb3dSCy Schubert signal_set(&ev, SIGUSR1, signal_cb_swp, NULL); 12322b15cb3dSCy Schubert signal_add(&ev, NULL); 12332b15cb3dSCy Schubert evtimer_set(&ev_timer, timeout_cb_swp, &ev_timer); 12342b15cb3dSCy Schubert evtimer_add(&ev_timer, &tv); 12352b15cb3dSCy Schubert event_dispatch(); 12362b15cb3dSCy Schubert 12372b15cb3dSCy Schubert event_base_free(base); 12382b15cb3dSCy Schubert cleanup_test(); 12392b15cb3dSCy Schubert return; 12402b15cb3dSCy Schubert } 12412b15cb3dSCy Schubert #endif 12422b15cb3dSCy Schubert 12432b15cb3dSCy Schubert static void 12442b15cb3dSCy Schubert test_free_active_base(void *ptr) 12452b15cb3dSCy Schubert { 12462b15cb3dSCy Schubert struct basic_test_data *data = ptr; 12472b15cb3dSCy Schubert struct event_base *base1; 12482b15cb3dSCy Schubert struct event ev1; 12492b15cb3dSCy Schubert 12502b15cb3dSCy Schubert base1 = event_init(); 12512b15cb3dSCy Schubert if (base1) { 12522b15cb3dSCy Schubert event_assign(&ev1, base1, data->pair[1], EV_READ, 12532b15cb3dSCy Schubert dummy_read_cb, NULL); 12542b15cb3dSCy Schubert event_add(&ev1, NULL); 12552b15cb3dSCy Schubert event_base_free(base1); /* should not crash */ 12562b15cb3dSCy Schubert } else { 12572b15cb3dSCy Schubert tt_fail_msg("failed to create event_base for test"); 12582b15cb3dSCy Schubert } 12592b15cb3dSCy Schubert 12602b15cb3dSCy Schubert base1 = event_init(); 12612b15cb3dSCy Schubert tt_assert(base1); 12622b15cb3dSCy Schubert event_assign(&ev1, base1, 0, 0, dummy_read_cb, NULL); 12632b15cb3dSCy Schubert event_active(&ev1, EV_READ, 1); 12642b15cb3dSCy Schubert event_base_free(base1); 12652b15cb3dSCy Schubert end: 12662b15cb3dSCy Schubert ; 12672b15cb3dSCy Schubert } 12682b15cb3dSCy Schubert 12692b15cb3dSCy Schubert static void 12702b15cb3dSCy Schubert test_manipulate_active_events(void *ptr) 12712b15cb3dSCy Schubert { 12722b15cb3dSCy Schubert struct basic_test_data *data = ptr; 12732b15cb3dSCy Schubert struct event_base *base = data->base; 12742b15cb3dSCy Schubert struct event ev1; 12752b15cb3dSCy Schubert 12762b15cb3dSCy Schubert event_assign(&ev1, base, -1, EV_TIMEOUT, dummy_read_cb, NULL); 12772b15cb3dSCy Schubert 12782b15cb3dSCy Schubert /* Make sure an active event is pending. */ 12792b15cb3dSCy Schubert event_active(&ev1, EV_READ, 1); 12802b15cb3dSCy Schubert tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL), 12812b15cb3dSCy Schubert ==, EV_READ); 12822b15cb3dSCy Schubert 12832b15cb3dSCy Schubert /* Make sure that activating an event twice works. */ 12842b15cb3dSCy Schubert event_active(&ev1, EV_WRITE, 1); 12852b15cb3dSCy Schubert tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL), 12862b15cb3dSCy Schubert ==, EV_READ|EV_WRITE); 12872b15cb3dSCy Schubert 12882b15cb3dSCy Schubert end: 12892b15cb3dSCy Schubert event_del(&ev1); 12902b15cb3dSCy Schubert } 12912b15cb3dSCy Schubert 12922b15cb3dSCy Schubert static void 12932b15cb3dSCy Schubert event_selfarg_cb(evutil_socket_t fd, short event, void *arg) 12942b15cb3dSCy Schubert { 12952b15cb3dSCy Schubert struct event *ev = arg; 12962b15cb3dSCy Schubert struct event_base *base = event_get_base(ev); 12972b15cb3dSCy Schubert event_base_assert_ok_(base); 12982b15cb3dSCy Schubert event_base_loopexit(base, NULL); 12992b15cb3dSCy Schubert tt_want(ev == event_base_get_running_event(base)); 13002b15cb3dSCy Schubert } 13012b15cb3dSCy Schubert 13022b15cb3dSCy Schubert static void 13032b15cb3dSCy Schubert test_event_new_selfarg(void *ptr) 13042b15cb3dSCy Schubert { 13052b15cb3dSCy Schubert struct basic_test_data *data = ptr; 13062b15cb3dSCy Schubert struct event_base *base = data->base; 13072b15cb3dSCy Schubert struct event *ev = event_new(base, -1, EV_READ, event_selfarg_cb, 13082b15cb3dSCy Schubert event_self_cbarg()); 13092b15cb3dSCy Schubert 13102b15cb3dSCy Schubert event_active(ev, EV_READ, 1); 13112b15cb3dSCy Schubert event_base_dispatch(base); 13122b15cb3dSCy Schubert 13132b15cb3dSCy Schubert event_free(ev); 13142b15cb3dSCy Schubert } 13152b15cb3dSCy Schubert 13162b15cb3dSCy Schubert static void 13172b15cb3dSCy Schubert test_event_assign_selfarg(void *ptr) 13182b15cb3dSCy Schubert { 13192b15cb3dSCy Schubert struct basic_test_data *data = ptr; 13202b15cb3dSCy Schubert struct event_base *base = data->base; 13212b15cb3dSCy Schubert struct event ev; 13222b15cb3dSCy Schubert 13232b15cb3dSCy Schubert event_assign(&ev, base, -1, EV_READ, event_selfarg_cb, 13242b15cb3dSCy Schubert event_self_cbarg()); 13252b15cb3dSCy Schubert event_active(&ev, EV_READ, 1); 13262b15cb3dSCy Schubert event_base_dispatch(base); 13272b15cb3dSCy Schubert } 13282b15cb3dSCy Schubert 13292b15cb3dSCy Schubert static void 13302b15cb3dSCy Schubert test_event_base_get_num_events(void *ptr) 13312b15cb3dSCy Schubert { 13322b15cb3dSCy Schubert struct basic_test_data *data = ptr; 13332b15cb3dSCy Schubert struct event_base *base = data->base; 13342b15cb3dSCy Schubert struct event ev; 13352b15cb3dSCy Schubert int event_count_active; 13362b15cb3dSCy Schubert int event_count_virtual; 13372b15cb3dSCy Schubert int event_count_added; 13382b15cb3dSCy Schubert int event_count_active_virtual; 13392b15cb3dSCy Schubert int event_count_active_added; 13402b15cb3dSCy Schubert int event_count_virtual_added; 13412b15cb3dSCy Schubert int event_count_active_added_virtual; 13422b15cb3dSCy Schubert 13432b15cb3dSCy Schubert struct timeval qsec = {0, 100000}; 13442b15cb3dSCy Schubert 13452b15cb3dSCy Schubert event_assign(&ev, base, -1, EV_READ, event_selfarg_cb, 13462b15cb3dSCy Schubert event_self_cbarg()); 13472b15cb3dSCy Schubert 13482b15cb3dSCy Schubert event_add(&ev, &qsec); 13492b15cb3dSCy Schubert event_count_active = event_base_get_num_events(base, 13502b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE); 13512b15cb3dSCy Schubert event_count_virtual = event_base_get_num_events(base, 13522b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL); 13532b15cb3dSCy Schubert event_count_added = event_base_get_num_events(base, 13542b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED); 13552b15cb3dSCy Schubert event_count_active_virtual = event_base_get_num_events(base, 13562b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 13572b15cb3dSCy Schubert event_count_active_added = event_base_get_num_events(base, 13582b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 13592b15cb3dSCy Schubert event_count_virtual_added = event_base_get_num_events(base, 13602b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 13612b15cb3dSCy Schubert event_count_active_added_virtual = event_base_get_num_events(base, 13622b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE| 13632b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED| 13642b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL); 13652b15cb3dSCy Schubert tt_int_op(event_count_active, ==, 0); 13662b15cb3dSCy Schubert tt_int_op(event_count_virtual, ==, 0); 13672b15cb3dSCy Schubert /* libevent itself adds a timeout event, so the event_count is 2 here */ 13682b15cb3dSCy Schubert tt_int_op(event_count_added, ==, 2); 13692b15cb3dSCy Schubert tt_int_op(event_count_active_virtual, ==, 0); 13702b15cb3dSCy Schubert tt_int_op(event_count_active_added, ==, 2); 13712b15cb3dSCy Schubert tt_int_op(event_count_virtual_added, ==, 2); 13722b15cb3dSCy Schubert tt_int_op(event_count_active_added_virtual, ==, 2); 13732b15cb3dSCy Schubert 13742b15cb3dSCy Schubert event_active(&ev, EV_READ, 1); 13752b15cb3dSCy Schubert event_count_active = event_base_get_num_events(base, 13762b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE); 13772b15cb3dSCy Schubert event_count_virtual = event_base_get_num_events(base, 13782b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL); 13792b15cb3dSCy Schubert event_count_added = event_base_get_num_events(base, 13802b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED); 13812b15cb3dSCy Schubert event_count_active_virtual = event_base_get_num_events(base, 13822b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 13832b15cb3dSCy Schubert event_count_active_added = event_base_get_num_events(base, 13842b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 13852b15cb3dSCy Schubert event_count_virtual_added = event_base_get_num_events(base, 13862b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 13872b15cb3dSCy Schubert event_count_active_added_virtual = event_base_get_num_events(base, 13882b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE| 13892b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED| 13902b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL); 13912b15cb3dSCy Schubert tt_int_op(event_count_active, ==, 1); 13922b15cb3dSCy Schubert tt_int_op(event_count_virtual, ==, 0); 13932b15cb3dSCy Schubert tt_int_op(event_count_added, ==, 3); 13942b15cb3dSCy Schubert tt_int_op(event_count_active_virtual, ==, 1); 13952b15cb3dSCy Schubert tt_int_op(event_count_active_added, ==, 4); 13962b15cb3dSCy Schubert tt_int_op(event_count_virtual_added, ==, 3); 13972b15cb3dSCy Schubert tt_int_op(event_count_active_added_virtual, ==, 4); 13982b15cb3dSCy Schubert 13992b15cb3dSCy Schubert event_base_loop(base, 0); 14002b15cb3dSCy Schubert event_count_active = event_base_get_num_events(base, 14012b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE); 14022b15cb3dSCy Schubert event_count_virtual = event_base_get_num_events(base, 14032b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL); 14042b15cb3dSCy Schubert event_count_added = event_base_get_num_events(base, 14052b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED); 14062b15cb3dSCy Schubert event_count_active_virtual = event_base_get_num_events(base, 14072b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 14082b15cb3dSCy Schubert event_count_active_added = event_base_get_num_events(base, 14092b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 14102b15cb3dSCy Schubert event_count_virtual_added = event_base_get_num_events(base, 14112b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 14122b15cb3dSCy Schubert event_count_active_added_virtual = event_base_get_num_events(base, 14132b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE| 14142b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED| 14152b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL); 14162b15cb3dSCy Schubert tt_int_op(event_count_active, ==, 0); 14172b15cb3dSCy Schubert tt_int_op(event_count_virtual, ==, 0); 14182b15cb3dSCy Schubert tt_int_op(event_count_added, ==, 0); 14192b15cb3dSCy Schubert tt_int_op(event_count_active_virtual, ==, 0); 14202b15cb3dSCy Schubert tt_int_op(event_count_active_added, ==, 0); 14212b15cb3dSCy Schubert tt_int_op(event_count_virtual_added, ==, 0); 14222b15cb3dSCy Schubert tt_int_op(event_count_active_added_virtual, ==, 0); 14232b15cb3dSCy Schubert 14242b15cb3dSCy Schubert event_base_add_virtual_(base); 14252b15cb3dSCy Schubert event_count_active = event_base_get_num_events(base, 14262b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE); 14272b15cb3dSCy Schubert event_count_virtual = event_base_get_num_events(base, 14282b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL); 14292b15cb3dSCy Schubert event_count_added = event_base_get_num_events(base, 14302b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED); 14312b15cb3dSCy Schubert event_count_active_virtual = event_base_get_num_events(base, 14322b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 14332b15cb3dSCy Schubert event_count_active_added = event_base_get_num_events(base, 14342b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 14352b15cb3dSCy Schubert event_count_virtual_added = event_base_get_num_events(base, 14362b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 14372b15cb3dSCy Schubert event_count_active_added_virtual = event_base_get_num_events(base, 14382b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE| 14392b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED| 14402b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL); 14412b15cb3dSCy Schubert tt_int_op(event_count_active, ==, 0); 14422b15cb3dSCy Schubert tt_int_op(event_count_virtual, ==, 1); 14432b15cb3dSCy Schubert tt_int_op(event_count_added, ==, 0); 14442b15cb3dSCy Schubert tt_int_op(event_count_active_virtual, ==, 1); 14452b15cb3dSCy Schubert tt_int_op(event_count_active_added, ==, 0); 14462b15cb3dSCy Schubert tt_int_op(event_count_virtual_added, ==, 1); 14472b15cb3dSCy Schubert tt_int_op(event_count_active_added_virtual, ==, 1); 14482b15cb3dSCy Schubert 14492b15cb3dSCy Schubert end: 14502b15cb3dSCy Schubert ; 14512b15cb3dSCy Schubert } 14522b15cb3dSCy Schubert 14532b15cb3dSCy Schubert static void 14542b15cb3dSCy Schubert test_event_base_get_max_events(void *ptr) 14552b15cb3dSCy Schubert { 14562b15cb3dSCy Schubert struct basic_test_data *data = ptr; 14572b15cb3dSCy Schubert struct event_base *base = data->base; 14582b15cb3dSCy Schubert struct event ev; 14592b15cb3dSCy Schubert struct event ev2; 14602b15cb3dSCy Schubert int event_count_active; 14612b15cb3dSCy Schubert int event_count_virtual; 14622b15cb3dSCy Schubert int event_count_added; 14632b15cb3dSCy Schubert int event_count_active_virtual; 14642b15cb3dSCy Schubert int event_count_active_added; 14652b15cb3dSCy Schubert int event_count_virtual_added; 14662b15cb3dSCy Schubert int event_count_active_added_virtual; 14672b15cb3dSCy Schubert 14682b15cb3dSCy Schubert struct timeval qsec = {0, 100000}; 14692b15cb3dSCy Schubert 14702b15cb3dSCy Schubert event_assign(&ev, base, -1, EV_READ, event_selfarg_cb, 14712b15cb3dSCy Schubert event_self_cbarg()); 14722b15cb3dSCy Schubert event_assign(&ev2, base, -1, EV_READ, event_selfarg_cb, 14732b15cb3dSCy Schubert event_self_cbarg()); 14742b15cb3dSCy Schubert 14752b15cb3dSCy Schubert event_add(&ev, &qsec); 14762b15cb3dSCy Schubert event_add(&ev2, &qsec); 14772b15cb3dSCy Schubert event_del(&ev2); 14782b15cb3dSCy Schubert 14792b15cb3dSCy Schubert event_count_active = event_base_get_max_events(base, 14802b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE, 0); 14812b15cb3dSCy Schubert event_count_virtual = event_base_get_max_events(base, 14822b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL, 0); 14832b15cb3dSCy Schubert event_count_added = event_base_get_max_events(base, 14842b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED, 0); 14852b15cb3dSCy Schubert event_count_active_virtual = event_base_get_max_events(base, 14862b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 14872b15cb3dSCy Schubert event_count_active_added = event_base_get_max_events(base, 14882b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 14892b15cb3dSCy Schubert event_count_virtual_added = event_base_get_max_events(base, 14902b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 14912b15cb3dSCy Schubert event_count_active_added_virtual = event_base_get_max_events(base, 14922b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | 14932b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED | 14942b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL, 0); 14952b15cb3dSCy Schubert 14962b15cb3dSCy Schubert tt_int_op(event_count_active, ==, 0); 14972b15cb3dSCy Schubert tt_int_op(event_count_virtual, ==, 0); 14982b15cb3dSCy Schubert /* libevent itself adds a timeout event, so the event_count is 4 here */ 14992b15cb3dSCy Schubert tt_int_op(event_count_added, ==, 4); 15002b15cb3dSCy Schubert tt_int_op(event_count_active_virtual, ==, 0); 15012b15cb3dSCy Schubert tt_int_op(event_count_active_added, ==, 4); 15022b15cb3dSCy Schubert tt_int_op(event_count_virtual_added, ==, 4); 15032b15cb3dSCy Schubert tt_int_op(event_count_active_added_virtual, ==, 4); 15042b15cb3dSCy Schubert 15052b15cb3dSCy Schubert event_active(&ev, EV_READ, 1); 15062b15cb3dSCy Schubert event_count_active = event_base_get_max_events(base, 15072b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE, 0); 15082b15cb3dSCy Schubert event_count_virtual = event_base_get_max_events(base, 15092b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL, 0); 15102b15cb3dSCy Schubert event_count_added = event_base_get_max_events(base, 15112b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED, 0); 15122b15cb3dSCy Schubert event_count_active_virtual = event_base_get_max_events(base, 15132b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 15142b15cb3dSCy Schubert event_count_active_added = event_base_get_max_events(base, 15152b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 15162b15cb3dSCy Schubert event_count_virtual_added = event_base_get_max_events(base, 15172b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 15182b15cb3dSCy Schubert event_count_active_added_virtual = event_base_get_max_events(base, 15192b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | 15202b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED | 15212b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL, 0); 15222b15cb3dSCy Schubert 15232b15cb3dSCy Schubert tt_int_op(event_count_active, ==, 1); 15242b15cb3dSCy Schubert tt_int_op(event_count_virtual, ==, 0); 15252b15cb3dSCy Schubert tt_int_op(event_count_added, ==, 4); 15262b15cb3dSCy Schubert tt_int_op(event_count_active_virtual, ==, 1); 15272b15cb3dSCy Schubert tt_int_op(event_count_active_added, ==, 5); 15282b15cb3dSCy Schubert tt_int_op(event_count_virtual_added, ==, 4); 15292b15cb3dSCy Schubert tt_int_op(event_count_active_added_virtual, ==, 5); 15302b15cb3dSCy Schubert 15312b15cb3dSCy Schubert event_base_loop(base, 0); 15322b15cb3dSCy Schubert event_count_active = event_base_get_max_events(base, 15332b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE, 1); 15342b15cb3dSCy Schubert event_count_virtual = event_base_get_max_events(base, 15352b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL, 1); 15362b15cb3dSCy Schubert event_count_added = event_base_get_max_events(base, 15372b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED, 1); 15382b15cb3dSCy Schubert event_count_active_virtual = event_base_get_max_events(base, 15392b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 15402b15cb3dSCy Schubert event_count_active_added = event_base_get_max_events(base, 15412b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 15422b15cb3dSCy Schubert event_count_virtual_added = event_base_get_max_events(base, 15432b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 15442b15cb3dSCy Schubert event_count_active_added_virtual = event_base_get_max_events(base, 15452b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | 15462b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED | 15472b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL, 1); 15482b15cb3dSCy Schubert 15492b15cb3dSCy Schubert tt_int_op(event_count_active, ==, 1); 15502b15cb3dSCy Schubert tt_int_op(event_count_virtual, ==, 0); 15512b15cb3dSCy Schubert tt_int_op(event_count_added, ==, 4); 15522b15cb3dSCy Schubert tt_int_op(event_count_active_virtual, ==, 0); 15532b15cb3dSCy Schubert tt_int_op(event_count_active_added, ==, 0); 15542b15cb3dSCy Schubert tt_int_op(event_count_virtual_added, ==, 0); 15552b15cb3dSCy Schubert tt_int_op(event_count_active_added_virtual, ==, 0); 15562b15cb3dSCy Schubert 15572b15cb3dSCy Schubert event_count_active = event_base_get_max_events(base, 15582b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE, 0); 15592b15cb3dSCy Schubert event_count_virtual = event_base_get_max_events(base, 15602b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL, 0); 15612b15cb3dSCy Schubert event_count_added = event_base_get_max_events(base, 15622b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED, 0); 15632b15cb3dSCy Schubert tt_int_op(event_count_active, ==, 0); 15642b15cb3dSCy Schubert tt_int_op(event_count_virtual, ==, 0); 15652b15cb3dSCy Schubert tt_int_op(event_count_added, ==, 0); 15662b15cb3dSCy Schubert 15672b15cb3dSCy Schubert event_base_add_virtual_(base); 15682b15cb3dSCy Schubert event_count_active = event_base_get_max_events(base, 15692b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE, 0); 15702b15cb3dSCy Schubert event_count_virtual = event_base_get_max_events(base, 15712b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL, 0); 15722b15cb3dSCy Schubert event_count_added = event_base_get_max_events(base, 15732b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED, 0); 15742b15cb3dSCy Schubert event_count_active_virtual = event_base_get_max_events(base, 15752b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 15762b15cb3dSCy Schubert event_count_active_added = event_base_get_max_events(base, 15772b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 15782b15cb3dSCy Schubert event_count_virtual_added = event_base_get_max_events(base, 15792b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 15802b15cb3dSCy Schubert event_count_active_added_virtual = event_base_get_max_events(base, 15812b15cb3dSCy Schubert EVENT_BASE_COUNT_ACTIVE | 15822b15cb3dSCy Schubert EVENT_BASE_COUNT_ADDED | 15832b15cb3dSCy Schubert EVENT_BASE_COUNT_VIRTUAL, 0); 15842b15cb3dSCy Schubert 15852b15cb3dSCy Schubert tt_int_op(event_count_active, ==, 0); 15862b15cb3dSCy Schubert tt_int_op(event_count_virtual, ==, 1); 15872b15cb3dSCy Schubert tt_int_op(event_count_added, ==, 0); 15882b15cb3dSCy Schubert tt_int_op(event_count_active_virtual, ==, 1); 15892b15cb3dSCy Schubert tt_int_op(event_count_active_added, ==, 0); 15902b15cb3dSCy Schubert tt_int_op(event_count_virtual_added, ==, 1); 15912b15cb3dSCy Schubert tt_int_op(event_count_active_added_virtual, ==, 1); 15922b15cb3dSCy Schubert 15932b15cb3dSCy Schubert end: 15942b15cb3dSCy Schubert ; 15952b15cb3dSCy Schubert } 15962b15cb3dSCy Schubert 15972b15cb3dSCy Schubert static void 15982b15cb3dSCy Schubert test_bad_assign(void *ptr) 15992b15cb3dSCy Schubert { 16002b15cb3dSCy Schubert struct event ev; 16012b15cb3dSCy Schubert int r; 16022b15cb3dSCy Schubert /* READ|SIGNAL is not allowed */ 16032b15cb3dSCy Schubert r = event_assign(&ev, NULL, -1, EV_SIGNAL|EV_READ, dummy_read_cb, NULL); 16042b15cb3dSCy Schubert tt_int_op(r,==,-1); 16052b15cb3dSCy Schubert 16062b15cb3dSCy Schubert end: 16072b15cb3dSCy Schubert ; 16082b15cb3dSCy Schubert } 16092b15cb3dSCy Schubert 16102b15cb3dSCy Schubert static int reentrant_cb_run = 0; 16112b15cb3dSCy Schubert 16122b15cb3dSCy Schubert static void 16132b15cb3dSCy Schubert bad_reentrant_run_loop_cb(evutil_socket_t fd, short what, void *ptr) 16142b15cb3dSCy Schubert { 16152b15cb3dSCy Schubert struct event_base *base = ptr; 16162b15cb3dSCy Schubert int r; 16172b15cb3dSCy Schubert reentrant_cb_run = 1; 16182b15cb3dSCy Schubert /* This reentrant call to event_base_loop should be detected and 16192b15cb3dSCy Schubert * should fail */ 16202b15cb3dSCy Schubert r = event_base_loop(base, 0); 16212b15cb3dSCy Schubert tt_int_op(r, ==, -1); 16222b15cb3dSCy Schubert end: 16232b15cb3dSCy Schubert ; 16242b15cb3dSCy Schubert } 16252b15cb3dSCy Schubert 16262b15cb3dSCy Schubert static void 16272b15cb3dSCy Schubert test_bad_reentrant(void *ptr) 16282b15cb3dSCy Schubert { 16292b15cb3dSCy Schubert struct basic_test_data *data = ptr; 16302b15cb3dSCy Schubert struct event_base *base = data->base; 16312b15cb3dSCy Schubert struct event ev; 16322b15cb3dSCy Schubert int r; 16332b15cb3dSCy Schubert event_assign(&ev, base, -1, 16342b15cb3dSCy Schubert 0, bad_reentrant_run_loop_cb, base); 16352b15cb3dSCy Schubert 16362b15cb3dSCy Schubert event_active(&ev, EV_WRITE, 1); 16372b15cb3dSCy Schubert r = event_base_loop(base, 0); 16382b15cb3dSCy Schubert tt_int_op(r, ==, 1); 16392b15cb3dSCy Schubert tt_int_op(reentrant_cb_run, ==, 1); 16402b15cb3dSCy Schubert end: 16412b15cb3dSCy Schubert ; 16422b15cb3dSCy Schubert } 16432b15cb3dSCy Schubert 16442b15cb3dSCy Schubert static int n_write_a_byte_cb=0; 16452b15cb3dSCy Schubert static int n_read_and_drain_cb=0; 16462b15cb3dSCy Schubert static int n_activate_other_event_cb=0; 16472b15cb3dSCy Schubert static void 16482b15cb3dSCy Schubert write_a_byte_cb(evutil_socket_t fd, short what, void *arg) 16492b15cb3dSCy Schubert { 16502b15cb3dSCy Schubert char buf[] = "x"; 16512b15cb3dSCy Schubert if (write(fd, buf, 1) == 1) 16522b15cb3dSCy Schubert ++n_write_a_byte_cb; 16532b15cb3dSCy Schubert } 16542b15cb3dSCy Schubert static void 16552b15cb3dSCy Schubert read_and_drain_cb(evutil_socket_t fd, short what, void *arg) 16562b15cb3dSCy Schubert { 16572b15cb3dSCy Schubert char buf[128]; 16582b15cb3dSCy Schubert int n; 16592b15cb3dSCy Schubert ++n_read_and_drain_cb; 16602b15cb3dSCy Schubert while ((n = read(fd, buf, sizeof(buf))) > 0) 16612b15cb3dSCy Schubert ; 16622b15cb3dSCy Schubert } 16632b15cb3dSCy Schubert 16642b15cb3dSCy Schubert static void 16652b15cb3dSCy Schubert activate_other_event_cb(evutil_socket_t fd, short what, void *other_) 16662b15cb3dSCy Schubert { 16672b15cb3dSCy Schubert struct event *ev_activate = other_; 16682b15cb3dSCy Schubert ++n_activate_other_event_cb; 16692b15cb3dSCy Schubert event_active_later_(ev_activate, EV_READ); 16702b15cb3dSCy Schubert } 16712b15cb3dSCy Schubert 16722b15cb3dSCy Schubert static void 16732b15cb3dSCy Schubert test_active_later(void *ptr) 16742b15cb3dSCy Schubert { 16752b15cb3dSCy Schubert struct basic_test_data *data = ptr; 1676*a25439b6SCy Schubert struct event *ev1 = NULL, *ev2 = NULL; 16772b15cb3dSCy Schubert struct event ev3, ev4; 16782b15cb3dSCy Schubert struct timeval qsec = {0, 100000}; 16792b15cb3dSCy Schubert ev1 = event_new(data->base, data->pair[0], EV_READ|EV_PERSIST, read_and_drain_cb, NULL); 16802b15cb3dSCy Schubert ev2 = event_new(data->base, data->pair[1], EV_WRITE|EV_PERSIST, write_a_byte_cb, NULL); 16812b15cb3dSCy Schubert event_assign(&ev3, data->base, -1, 0, activate_other_event_cb, &ev4); 16822b15cb3dSCy Schubert event_assign(&ev4, data->base, -1, 0, activate_other_event_cb, &ev3); 16832b15cb3dSCy Schubert event_add(ev1, NULL); 16842b15cb3dSCy Schubert event_add(ev2, NULL); 16852b15cb3dSCy Schubert event_active_later_(&ev3, EV_READ); 16862b15cb3dSCy Schubert 16872b15cb3dSCy Schubert event_base_loopexit(data->base, &qsec); 16882b15cb3dSCy Schubert 16892b15cb3dSCy Schubert event_base_loop(data->base, 0); 16902b15cb3dSCy Schubert 16912b15cb3dSCy Schubert TT_BLATHER(("%d write calls, %d read calls, %d activate-other calls.", 16922b15cb3dSCy Schubert n_write_a_byte_cb, n_read_and_drain_cb, n_activate_other_event_cb)); 16932b15cb3dSCy Schubert event_del(&ev3); 16942b15cb3dSCy Schubert event_del(&ev4); 16952b15cb3dSCy Schubert 16962b15cb3dSCy Schubert tt_int_op(n_write_a_byte_cb, ==, n_activate_other_event_cb); 16972b15cb3dSCy Schubert tt_int_op(n_write_a_byte_cb, >, 100); 16982b15cb3dSCy Schubert tt_int_op(n_read_and_drain_cb, >, 100); 16992b15cb3dSCy Schubert tt_int_op(n_activate_other_event_cb, >, 100); 17002b15cb3dSCy Schubert 17012b15cb3dSCy Schubert event_active_later_(&ev4, EV_READ); 17022b15cb3dSCy Schubert event_active(&ev4, EV_READ, 1); /* This should make the event 17032b15cb3dSCy Schubert active immediately. */ 17042b15cb3dSCy Schubert tt_assert((ev4.ev_flags & EVLIST_ACTIVE) != 0); 17052b15cb3dSCy Schubert tt_assert((ev4.ev_flags & EVLIST_ACTIVE_LATER) == 0); 17062b15cb3dSCy Schubert 17072b15cb3dSCy Schubert /* Now leave this one around, so that event_free sees it and removes 17082b15cb3dSCy Schubert * it. */ 17092b15cb3dSCy Schubert event_active_later_(&ev3, EV_READ); 17102b15cb3dSCy Schubert event_base_assert_ok_(data->base); 1711*a25439b6SCy Schubert 1712*a25439b6SCy Schubert end: 1713*a25439b6SCy Schubert if (ev1) 1714*a25439b6SCy Schubert event_free(ev1); 1715*a25439b6SCy Schubert if (ev2) 1716*a25439b6SCy Schubert event_free(ev2); 1717*a25439b6SCy Schubert 17182b15cb3dSCy Schubert event_base_free(data->base); 17192b15cb3dSCy Schubert data->base = NULL; 17202b15cb3dSCy Schubert } 17212b15cb3dSCy Schubert 17222b15cb3dSCy Schubert 17232b15cb3dSCy Schubert static void incr_arg_cb(evutil_socket_t fd, short what, void *arg) 17242b15cb3dSCy Schubert { 17252b15cb3dSCy Schubert int *intptr = arg; 17262b15cb3dSCy Schubert (void) fd; (void) what; 17272b15cb3dSCy Schubert ++*intptr; 17282b15cb3dSCy Schubert } 17292b15cb3dSCy Schubert static void remove_timers_cb(evutil_socket_t fd, short what, void *arg) 17302b15cb3dSCy Schubert { 17312b15cb3dSCy Schubert struct event **ep = arg; 17322b15cb3dSCy Schubert (void) fd; (void) what; 17332b15cb3dSCy Schubert event_remove_timer(ep[0]); 17342b15cb3dSCy Schubert event_remove_timer(ep[1]); 17352b15cb3dSCy Schubert } 17362b15cb3dSCy Schubert static void send_a_byte_cb(evutil_socket_t fd, short what, void *arg) 17372b15cb3dSCy Schubert { 17382b15cb3dSCy Schubert evutil_socket_t *sockp = arg; 17392b15cb3dSCy Schubert (void) fd; (void) what; 17402b15cb3dSCy Schubert (void) write(*sockp, "A", 1); 17412b15cb3dSCy Schubert } 17422b15cb3dSCy Schubert struct read_not_timeout_param 17432b15cb3dSCy Schubert { 17442b15cb3dSCy Schubert struct event **ev; 17452b15cb3dSCy Schubert int events; 17462b15cb3dSCy Schubert int count; 17472b15cb3dSCy Schubert }; 17482b15cb3dSCy Schubert static void read_not_timeout_cb(evutil_socket_t fd, short what, void *arg) 17492b15cb3dSCy Schubert { 17502b15cb3dSCy Schubert struct read_not_timeout_param *rntp = arg; 17512b15cb3dSCy Schubert char c; 17522b15cb3dSCy Schubert ev_ssize_t n; 17532b15cb3dSCy Schubert (void) fd; (void) what; 17542b15cb3dSCy Schubert n = read(fd, &c, 1); 17552b15cb3dSCy Schubert tt_int_op(n, ==, 1); 17562b15cb3dSCy Schubert rntp->events |= what; 17572b15cb3dSCy Schubert ++rntp->count; 17582b15cb3dSCy Schubert if(2 == rntp->count) event_del(rntp->ev[0]); 17592b15cb3dSCy Schubert end: 17602b15cb3dSCy Schubert ; 17612b15cb3dSCy Schubert } 17622b15cb3dSCy Schubert 17632b15cb3dSCy Schubert static void 17642b15cb3dSCy Schubert test_event_remove_timeout(void *ptr) 17652b15cb3dSCy Schubert { 17662b15cb3dSCy Schubert struct basic_test_data *data = ptr; 17672b15cb3dSCy Schubert struct event_base *base = data->base; 17682b15cb3dSCy Schubert struct event *ev[5]; 17692b15cb3dSCy Schubert int ev1_fired=0; 17702b15cb3dSCy Schubert struct timeval ms25 = { 0, 25*1000 }, 17712b15cb3dSCy Schubert ms40 = { 0, 40*1000 }, 17722b15cb3dSCy Schubert ms75 = { 0, 75*1000 }, 17732b15cb3dSCy Schubert ms125 = { 0, 125*1000 }; 17742b15cb3dSCy Schubert struct read_not_timeout_param rntp = { ev, 0, 0 }; 17752b15cb3dSCy Schubert 17762b15cb3dSCy Schubert event_base_assert_ok_(base); 17772b15cb3dSCy Schubert 17782b15cb3dSCy Schubert ev[0] = event_new(base, data->pair[0], EV_READ|EV_PERSIST, 17792b15cb3dSCy Schubert read_not_timeout_cb, &rntp); 17802b15cb3dSCy Schubert ev[1] = evtimer_new(base, incr_arg_cb, &ev1_fired); 17812b15cb3dSCy Schubert ev[2] = evtimer_new(base, remove_timers_cb, ev); 17822b15cb3dSCy Schubert ev[3] = evtimer_new(base, send_a_byte_cb, &data->pair[1]); 17832b15cb3dSCy Schubert ev[4] = evtimer_new(base, send_a_byte_cb, &data->pair[1]); 17842b15cb3dSCy Schubert tt_assert(base); 17852b15cb3dSCy Schubert event_add(ev[2], &ms25); /* remove timers */ 17862b15cb3dSCy Schubert event_add(ev[4], &ms40); /* write to test if timer re-activates */ 17872b15cb3dSCy Schubert event_add(ev[0], &ms75); /* read */ 17882b15cb3dSCy Schubert event_add(ev[1], &ms75); /* timer */ 17892b15cb3dSCy Schubert event_add(ev[3], &ms125); /* timeout. */ 17902b15cb3dSCy Schubert event_base_assert_ok_(base); 17912b15cb3dSCy Schubert 17922b15cb3dSCy Schubert event_base_dispatch(base); 17932b15cb3dSCy Schubert 17942b15cb3dSCy Schubert tt_int_op(ev1_fired, ==, 0); 17952b15cb3dSCy Schubert tt_int_op(rntp.events, ==, EV_READ); 17962b15cb3dSCy Schubert 17972b15cb3dSCy Schubert event_base_assert_ok_(base); 17982b15cb3dSCy Schubert end: 17992b15cb3dSCy Schubert event_free(ev[0]); 18002b15cb3dSCy Schubert event_free(ev[1]); 18012b15cb3dSCy Schubert event_free(ev[2]); 18022b15cb3dSCy Schubert event_free(ev[3]); 18032b15cb3dSCy Schubert event_free(ev[4]); 18042b15cb3dSCy Schubert } 18052b15cb3dSCy Schubert 18062b15cb3dSCy Schubert static void 18072b15cb3dSCy Schubert test_event_base_new(void *ptr) 18082b15cb3dSCy Schubert { 18092b15cb3dSCy Schubert struct basic_test_data *data = ptr; 18102b15cb3dSCy Schubert struct event_base *base = 0; 18112b15cb3dSCy Schubert struct event ev1; 18122b15cb3dSCy Schubert struct basic_cb_args args; 18132b15cb3dSCy Schubert 18142b15cb3dSCy Schubert int towrite = (int)strlen(TEST1)+1; 18152b15cb3dSCy Schubert int len = write(data->pair[0], TEST1, towrite); 18162b15cb3dSCy Schubert 18172b15cb3dSCy Schubert if (len < 0) 18182b15cb3dSCy Schubert tt_abort_perror("initial write"); 18192b15cb3dSCy Schubert else if (len != towrite) 18202b15cb3dSCy Schubert tt_abort_printf(("initial write fell short (%d of %d bytes)", 18212b15cb3dSCy Schubert len, towrite)); 18222b15cb3dSCy Schubert 18232b15cb3dSCy Schubert if (shutdown(data->pair[0], SHUT_WR)) 18242b15cb3dSCy Schubert tt_abort_perror("initial write shutdown"); 18252b15cb3dSCy Schubert 18262b15cb3dSCy Schubert base = event_base_new(); 18272b15cb3dSCy Schubert if (!base) 18282b15cb3dSCy Schubert tt_abort_msg("failed to create event base"); 18292b15cb3dSCy Schubert 18302b15cb3dSCy Schubert args.eb = base; 18312b15cb3dSCy Schubert args.ev = &ev1; 18322b15cb3dSCy Schubert args.callcount = 0; 18332b15cb3dSCy Schubert event_assign(&ev1, base, data->pair[1], 18342b15cb3dSCy Schubert EV_READ|EV_PERSIST, basic_read_cb, &args); 18352b15cb3dSCy Schubert 18362b15cb3dSCy Schubert if (event_add(&ev1, NULL)) 18372b15cb3dSCy Schubert tt_abort_perror("initial event_add"); 18382b15cb3dSCy Schubert 18392b15cb3dSCy Schubert if (event_base_loop(base, 0)) 18402b15cb3dSCy Schubert tt_abort_msg("unsuccessful exit from event loop"); 18412b15cb3dSCy Schubert 18422b15cb3dSCy Schubert end: 18432b15cb3dSCy Schubert if (base) 18442b15cb3dSCy Schubert event_base_free(base); 18452b15cb3dSCy Schubert } 18462b15cb3dSCy Schubert 18472b15cb3dSCy Schubert static void 18482b15cb3dSCy Schubert test_loopexit(void) 18492b15cb3dSCy Schubert { 18502b15cb3dSCy Schubert struct timeval tv, tv_start, tv_end; 18512b15cb3dSCy Schubert struct event ev; 18522b15cb3dSCy Schubert 18532b15cb3dSCy Schubert setup_test("Loop exit: "); 18542b15cb3dSCy Schubert 18552b15cb3dSCy Schubert tv.tv_usec = 0; 18562b15cb3dSCy Schubert tv.tv_sec = 60*60*24; 18572b15cb3dSCy Schubert evtimer_set(&ev, timeout_cb, NULL); 18582b15cb3dSCy Schubert evtimer_add(&ev, &tv); 18592b15cb3dSCy Schubert 18602b15cb3dSCy Schubert tv.tv_usec = 300*1000; 18612b15cb3dSCy Schubert tv.tv_sec = 0; 18622b15cb3dSCy Schubert event_loopexit(&tv); 18632b15cb3dSCy Schubert 18642b15cb3dSCy Schubert evutil_gettimeofday(&tv_start, NULL); 18652b15cb3dSCy Schubert event_dispatch(); 18662b15cb3dSCy Schubert evutil_gettimeofday(&tv_end, NULL); 18672b15cb3dSCy Schubert 18682b15cb3dSCy Schubert evtimer_del(&ev); 18692b15cb3dSCy Schubert 18702b15cb3dSCy Schubert tt_assert(event_base_got_exit(global_base)); 18712b15cb3dSCy Schubert tt_assert(!event_base_got_break(global_base)); 18722b15cb3dSCy Schubert 18732b15cb3dSCy Schubert test_timeval_diff_eq(&tv_start, &tv_end, 300); 18742b15cb3dSCy Schubert 18752b15cb3dSCy Schubert test_ok = 1; 18762b15cb3dSCy Schubert end: 18772b15cb3dSCy Schubert cleanup_test(); 18782b15cb3dSCy Schubert } 18792b15cb3dSCy Schubert 18802b15cb3dSCy Schubert static void 18812b15cb3dSCy Schubert test_loopexit_multiple(void) 18822b15cb3dSCy Schubert { 18832b15cb3dSCy Schubert struct timeval tv, tv_start, tv_end; 18842b15cb3dSCy Schubert struct event_base *base; 18852b15cb3dSCy Schubert 18862b15cb3dSCy Schubert setup_test("Loop Multiple exit: "); 18872b15cb3dSCy Schubert 18882b15cb3dSCy Schubert base = event_base_new(); 18892b15cb3dSCy Schubert 18902b15cb3dSCy Schubert tv.tv_usec = 200*1000; 18912b15cb3dSCy Schubert tv.tv_sec = 0; 18922b15cb3dSCy Schubert event_base_loopexit(base, &tv); 18932b15cb3dSCy Schubert 18942b15cb3dSCy Schubert tv.tv_usec = 0; 18952b15cb3dSCy Schubert tv.tv_sec = 3; 18962b15cb3dSCy Schubert event_base_loopexit(base, &tv); 18972b15cb3dSCy Schubert 18982b15cb3dSCy Schubert evutil_gettimeofday(&tv_start, NULL); 18992b15cb3dSCy Schubert event_base_dispatch(base); 19002b15cb3dSCy Schubert evutil_gettimeofday(&tv_end, NULL); 19012b15cb3dSCy Schubert 19022b15cb3dSCy Schubert tt_assert(event_base_got_exit(base)); 19032b15cb3dSCy Schubert tt_assert(!event_base_got_break(base)); 19042b15cb3dSCy Schubert 19052b15cb3dSCy Schubert event_base_free(base); 19062b15cb3dSCy Schubert 19072b15cb3dSCy Schubert test_timeval_diff_eq(&tv_start, &tv_end, 200); 19082b15cb3dSCy Schubert 19092b15cb3dSCy Schubert test_ok = 1; 19102b15cb3dSCy Schubert 19112b15cb3dSCy Schubert end: 19122b15cb3dSCy Schubert cleanup_test(); 19132b15cb3dSCy Schubert } 19142b15cb3dSCy Schubert 19152b15cb3dSCy Schubert static void 19162b15cb3dSCy Schubert break_cb(evutil_socket_t fd, short events, void *arg) 19172b15cb3dSCy Schubert { 19182b15cb3dSCy Schubert test_ok = 1; 19192b15cb3dSCy Schubert event_loopbreak(); 19202b15cb3dSCy Schubert } 19212b15cb3dSCy Schubert 19222b15cb3dSCy Schubert static void 19232b15cb3dSCy Schubert fail_cb(evutil_socket_t fd, short events, void *arg) 19242b15cb3dSCy Schubert { 19252b15cb3dSCy Schubert test_ok = 0; 19262b15cb3dSCy Schubert } 19272b15cb3dSCy Schubert 19282b15cb3dSCy Schubert static void 19292b15cb3dSCy Schubert test_loopbreak(void) 19302b15cb3dSCy Schubert { 19312b15cb3dSCy Schubert struct event ev1, ev2; 19322b15cb3dSCy Schubert struct timeval tv; 19332b15cb3dSCy Schubert 19342b15cb3dSCy Schubert setup_test("Loop break: "); 19352b15cb3dSCy Schubert 19362b15cb3dSCy Schubert tv.tv_sec = 0; 19372b15cb3dSCy Schubert tv.tv_usec = 0; 19382b15cb3dSCy Schubert evtimer_set(&ev1, break_cb, NULL); 19392b15cb3dSCy Schubert evtimer_add(&ev1, &tv); 19402b15cb3dSCy Schubert evtimer_set(&ev2, fail_cb, NULL); 19412b15cb3dSCy Schubert evtimer_add(&ev2, &tv); 19422b15cb3dSCy Schubert 19432b15cb3dSCy Schubert event_dispatch(); 19442b15cb3dSCy Schubert 19452b15cb3dSCy Schubert tt_assert(!event_base_got_exit(global_base)); 19462b15cb3dSCy Schubert tt_assert(event_base_got_break(global_base)); 19472b15cb3dSCy Schubert 19482b15cb3dSCy Schubert evtimer_del(&ev1); 19492b15cb3dSCy Schubert evtimer_del(&ev2); 19502b15cb3dSCy Schubert 19512b15cb3dSCy Schubert end: 19522b15cb3dSCy Schubert cleanup_test(); 19532b15cb3dSCy Schubert } 19542b15cb3dSCy Schubert 19552b15cb3dSCy Schubert static struct event *readd_test_event_last_added = NULL; 19562b15cb3dSCy Schubert static void 19572b15cb3dSCy Schubert re_add_read_cb(evutil_socket_t fd, short event, void *arg) 19582b15cb3dSCy Schubert { 19592b15cb3dSCy Schubert char buf[256]; 19602b15cb3dSCy Schubert struct event *ev_other = arg; 19612b15cb3dSCy Schubert ev_ssize_t n_read; 19622b15cb3dSCy Schubert 19632b15cb3dSCy Schubert readd_test_event_last_added = ev_other; 19642b15cb3dSCy Schubert 19652b15cb3dSCy Schubert n_read = read(fd, buf, sizeof(buf)); 19662b15cb3dSCy Schubert 19672b15cb3dSCy Schubert if (n_read < 0) { 19682b15cb3dSCy Schubert tt_fail_perror("read"); 19692b15cb3dSCy Schubert event_base_loopbreak(event_get_base(ev_other)); 19702b15cb3dSCy Schubert return; 19712b15cb3dSCy Schubert } else { 19722b15cb3dSCy Schubert event_add(ev_other, NULL); 19732b15cb3dSCy Schubert ++test_ok; 19742b15cb3dSCy Schubert } 19752b15cb3dSCy Schubert } 19762b15cb3dSCy Schubert 19772b15cb3dSCy Schubert static void 19782b15cb3dSCy Schubert test_nonpersist_readd(void) 19792b15cb3dSCy Schubert { 19802b15cb3dSCy Schubert struct event ev1, ev2; 19812b15cb3dSCy Schubert 19822b15cb3dSCy Schubert setup_test("Re-add nonpersistent events: "); 19832b15cb3dSCy Schubert event_set(&ev1, pair[0], EV_READ, re_add_read_cb, &ev2); 19842b15cb3dSCy Schubert event_set(&ev2, pair[1], EV_READ, re_add_read_cb, &ev1); 19852b15cb3dSCy Schubert 19862b15cb3dSCy Schubert if (write(pair[0], "Hello", 5) < 0) { 19872b15cb3dSCy Schubert tt_fail_perror("write(pair[0])"); 19882b15cb3dSCy Schubert } 19892b15cb3dSCy Schubert 19902b15cb3dSCy Schubert if (write(pair[1], "Hello", 5) < 0) { 19912b15cb3dSCy Schubert tt_fail_perror("write(pair[1])\n"); 19922b15cb3dSCy Schubert } 19932b15cb3dSCy Schubert 19942b15cb3dSCy Schubert if (event_add(&ev1, NULL) == -1 || 19952b15cb3dSCy Schubert event_add(&ev2, NULL) == -1) { 19962b15cb3dSCy Schubert test_ok = 0; 19972b15cb3dSCy Schubert } 19982b15cb3dSCy Schubert if (test_ok != 0) 19992b15cb3dSCy Schubert exit(1); 20002b15cb3dSCy Schubert event_loop(EVLOOP_ONCE); 20012b15cb3dSCy Schubert if (test_ok != 2) 20022b15cb3dSCy Schubert exit(1); 20032b15cb3dSCy Schubert /* At this point, we executed both callbacks. Whichever one got 20042b15cb3dSCy Schubert * called first added the second, but the second then immediately got 20052b15cb3dSCy Schubert * deleted before its callback was called. At this point, though, it 20062b15cb3dSCy Schubert * re-added the first. 20072b15cb3dSCy Schubert */ 20082b15cb3dSCy Schubert if (!readd_test_event_last_added) { 20092b15cb3dSCy Schubert test_ok = 0; 20102b15cb3dSCy Schubert } else if (readd_test_event_last_added == &ev1) { 20112b15cb3dSCy Schubert if (!event_pending(&ev1, EV_READ, NULL) || 20122b15cb3dSCy Schubert event_pending(&ev2, EV_READ, NULL)) 20132b15cb3dSCy Schubert test_ok = 0; 20142b15cb3dSCy Schubert } else { 20152b15cb3dSCy Schubert if (event_pending(&ev1, EV_READ, NULL) || 20162b15cb3dSCy Schubert !event_pending(&ev2, EV_READ, NULL)) 20172b15cb3dSCy Schubert test_ok = 0; 20182b15cb3dSCy Schubert } 20192b15cb3dSCy Schubert 20202b15cb3dSCy Schubert event_del(&ev1); 20212b15cb3dSCy Schubert event_del(&ev2); 20222b15cb3dSCy Schubert 20232b15cb3dSCy Schubert cleanup_test(); 20242b15cb3dSCy Schubert } 20252b15cb3dSCy Schubert 20262b15cb3dSCy Schubert struct test_pri_event { 20272b15cb3dSCy Schubert struct event ev; 20282b15cb3dSCy Schubert int count; 20292b15cb3dSCy Schubert }; 20302b15cb3dSCy Schubert 20312b15cb3dSCy Schubert static void 20322b15cb3dSCy Schubert test_priorities_cb(evutil_socket_t fd, short what, void *arg) 20332b15cb3dSCy Schubert { 20342b15cb3dSCy Schubert struct test_pri_event *pri = arg; 20352b15cb3dSCy Schubert struct timeval tv; 20362b15cb3dSCy Schubert 20372b15cb3dSCy Schubert if (pri->count == 3) { 20382b15cb3dSCy Schubert event_loopexit(NULL); 20392b15cb3dSCy Schubert return; 20402b15cb3dSCy Schubert } 20412b15cb3dSCy Schubert 20422b15cb3dSCy Schubert pri->count++; 20432b15cb3dSCy Schubert 20442b15cb3dSCy Schubert evutil_timerclear(&tv); 20452b15cb3dSCy Schubert event_add(&pri->ev, &tv); 20462b15cb3dSCy Schubert } 20472b15cb3dSCy Schubert 20482b15cb3dSCy Schubert static void 20492b15cb3dSCy Schubert test_priorities_impl(int npriorities) 20502b15cb3dSCy Schubert { 20512b15cb3dSCy Schubert struct test_pri_event one, two; 20522b15cb3dSCy Schubert struct timeval tv; 20532b15cb3dSCy Schubert 20542b15cb3dSCy Schubert TT_BLATHER(("Testing Priorities %d: ", npriorities)); 20552b15cb3dSCy Schubert 20562b15cb3dSCy Schubert event_base_priority_init(global_base, npriorities); 20572b15cb3dSCy Schubert 20582b15cb3dSCy Schubert memset(&one, 0, sizeof(one)); 20592b15cb3dSCy Schubert memset(&two, 0, sizeof(two)); 20602b15cb3dSCy Schubert 20612b15cb3dSCy Schubert timeout_set(&one.ev, test_priorities_cb, &one); 20622b15cb3dSCy Schubert if (event_priority_set(&one.ev, 0) == -1) { 20632b15cb3dSCy Schubert fprintf(stderr, "%s: failed to set priority", __func__); 20642b15cb3dSCy Schubert exit(1); 20652b15cb3dSCy Schubert } 20662b15cb3dSCy Schubert 20672b15cb3dSCy Schubert timeout_set(&two.ev, test_priorities_cb, &two); 20682b15cb3dSCy Schubert if (event_priority_set(&two.ev, npriorities - 1) == -1) { 20692b15cb3dSCy Schubert fprintf(stderr, "%s: failed to set priority", __func__); 20702b15cb3dSCy Schubert exit(1); 20712b15cb3dSCy Schubert } 20722b15cb3dSCy Schubert 20732b15cb3dSCy Schubert evutil_timerclear(&tv); 20742b15cb3dSCy Schubert 20752b15cb3dSCy Schubert if (event_add(&one.ev, &tv) == -1) 20762b15cb3dSCy Schubert exit(1); 20772b15cb3dSCy Schubert if (event_add(&two.ev, &tv) == -1) 20782b15cb3dSCy Schubert exit(1); 20792b15cb3dSCy Schubert 20802b15cb3dSCy Schubert event_dispatch(); 20812b15cb3dSCy Schubert 20822b15cb3dSCy Schubert event_del(&one.ev); 20832b15cb3dSCy Schubert event_del(&two.ev); 20842b15cb3dSCy Schubert 20852b15cb3dSCy Schubert if (npriorities == 1) { 20862b15cb3dSCy Schubert if (one.count == 3 && two.count == 3) 20872b15cb3dSCy Schubert test_ok = 1; 20882b15cb3dSCy Schubert } else if (npriorities == 2) { 20892b15cb3dSCy Schubert /* Two is called once because event_loopexit is priority 1 */ 20902b15cb3dSCy Schubert if (one.count == 3 && two.count == 1) 20912b15cb3dSCy Schubert test_ok = 1; 20922b15cb3dSCy Schubert } else { 20932b15cb3dSCy Schubert if (one.count == 3 && two.count == 0) 20942b15cb3dSCy Schubert test_ok = 1; 20952b15cb3dSCy Schubert } 20962b15cb3dSCy Schubert } 20972b15cb3dSCy Schubert 20982b15cb3dSCy Schubert static void 20992b15cb3dSCy Schubert test_priorities(void) 21002b15cb3dSCy Schubert { 21012b15cb3dSCy Schubert test_priorities_impl(1); 21022b15cb3dSCy Schubert if (test_ok) 21032b15cb3dSCy Schubert test_priorities_impl(2); 21042b15cb3dSCy Schubert if (test_ok) 21052b15cb3dSCy Schubert test_priorities_impl(3); 21062b15cb3dSCy Schubert } 21072b15cb3dSCy Schubert 21082b15cb3dSCy Schubert /* priority-active-inversion: activate a higher-priority event, and make sure 21092b15cb3dSCy Schubert * it keeps us from running a lower-priority event first. */ 21102b15cb3dSCy Schubert static int n_pai_calls = 0; 21112b15cb3dSCy Schubert static struct event pai_events[3]; 21122b15cb3dSCy Schubert 21132b15cb3dSCy Schubert static void 21142b15cb3dSCy Schubert prio_active_inversion_cb(evutil_socket_t fd, short what, void *arg) 21152b15cb3dSCy Schubert { 21162b15cb3dSCy Schubert int *call_order = arg; 21172b15cb3dSCy Schubert *call_order = n_pai_calls++; 21182b15cb3dSCy Schubert if (n_pai_calls == 1) { 21192b15cb3dSCy Schubert /* This should activate later, even though it shares a 21202b15cb3dSCy Schubert priority with us. */ 21212b15cb3dSCy Schubert event_active(&pai_events[1], EV_READ, 1); 21222b15cb3dSCy Schubert /* This should activate next, since its priority is higher, 21232b15cb3dSCy Schubert even though we activated it second. */ 21242b15cb3dSCy Schubert event_active(&pai_events[2], EV_TIMEOUT, 1); 21252b15cb3dSCy Schubert } 21262b15cb3dSCy Schubert } 21272b15cb3dSCy Schubert 21282b15cb3dSCy Schubert static void 21292b15cb3dSCy Schubert test_priority_active_inversion(void *data_) 21302b15cb3dSCy Schubert { 21312b15cb3dSCy Schubert struct basic_test_data *data = data_; 21322b15cb3dSCy Schubert struct event_base *base = data->base; 21332b15cb3dSCy Schubert int call_order[3]; 21342b15cb3dSCy Schubert int i; 21352b15cb3dSCy Schubert tt_int_op(event_base_priority_init(base, 8), ==, 0); 21362b15cb3dSCy Schubert 21372b15cb3dSCy Schubert n_pai_calls = 0; 21382b15cb3dSCy Schubert memset(call_order, 0, sizeof(call_order)); 21392b15cb3dSCy Schubert 21402b15cb3dSCy Schubert for (i=0;i<3;++i) { 21412b15cb3dSCy Schubert event_assign(&pai_events[i], data->base, -1, 0, 21422b15cb3dSCy Schubert prio_active_inversion_cb, &call_order[i]); 21432b15cb3dSCy Schubert } 21442b15cb3dSCy Schubert 21452b15cb3dSCy Schubert event_priority_set(&pai_events[0], 4); 21462b15cb3dSCy Schubert event_priority_set(&pai_events[1], 4); 21472b15cb3dSCy Schubert event_priority_set(&pai_events[2], 0); 21482b15cb3dSCy Schubert 21492b15cb3dSCy Schubert event_active(&pai_events[0], EV_WRITE, 1); 21502b15cb3dSCy Schubert 21512b15cb3dSCy Schubert event_base_dispatch(base); 21522b15cb3dSCy Schubert tt_int_op(n_pai_calls, ==, 3); 21532b15cb3dSCy Schubert tt_int_op(call_order[0], ==, 0); 21542b15cb3dSCy Schubert tt_int_op(call_order[1], ==, 2); 21552b15cb3dSCy Schubert tt_int_op(call_order[2], ==, 1); 21562b15cb3dSCy Schubert end: 21572b15cb3dSCy Schubert ; 21582b15cb3dSCy Schubert } 21592b15cb3dSCy Schubert 21602b15cb3dSCy Schubert 21612b15cb3dSCy Schubert static void 21622b15cb3dSCy Schubert test_multiple_cb(evutil_socket_t fd, short event, void *arg) 21632b15cb3dSCy Schubert { 21642b15cb3dSCy Schubert if (event & EV_READ) 21652b15cb3dSCy Schubert test_ok |= 1; 21662b15cb3dSCy Schubert else if (event & EV_WRITE) 21672b15cb3dSCy Schubert test_ok |= 2; 21682b15cb3dSCy Schubert } 21692b15cb3dSCy Schubert 21702b15cb3dSCy Schubert static void 21712b15cb3dSCy Schubert test_multiple_events_for_same_fd(void) 21722b15cb3dSCy Schubert { 21732b15cb3dSCy Schubert struct event e1, e2; 21742b15cb3dSCy Schubert 21752b15cb3dSCy Schubert setup_test("Multiple events for same fd: "); 21762b15cb3dSCy Schubert 21772b15cb3dSCy Schubert event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL); 21782b15cb3dSCy Schubert event_add(&e1, NULL); 21792b15cb3dSCy Schubert event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL); 21802b15cb3dSCy Schubert event_add(&e2, NULL); 21812b15cb3dSCy Schubert event_loop(EVLOOP_ONCE); 21822b15cb3dSCy Schubert event_del(&e2); 21832b15cb3dSCy Schubert 21842b15cb3dSCy Schubert if (write(pair[1], TEST1, strlen(TEST1)+1) < 0) { 21852b15cb3dSCy Schubert tt_fail_perror("write"); 21862b15cb3dSCy Schubert } 21872b15cb3dSCy Schubert 21882b15cb3dSCy Schubert event_loop(EVLOOP_ONCE); 21892b15cb3dSCy Schubert event_del(&e1); 21902b15cb3dSCy Schubert 21912b15cb3dSCy Schubert if (test_ok != 3) 21922b15cb3dSCy Schubert test_ok = 0; 21932b15cb3dSCy Schubert 21942b15cb3dSCy Schubert cleanup_test(); 21952b15cb3dSCy Schubert } 21962b15cb3dSCy Schubert 21972b15cb3dSCy Schubert int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf); 21982b15cb3dSCy Schubert int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf); 21992b15cb3dSCy Schubert int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t number); 22002b15cb3dSCy Schubert int evtag_decode_tag(ev_uint32_t *pnumber, struct evbuffer *evbuf); 22012b15cb3dSCy Schubert 22022b15cb3dSCy Schubert static void 22032b15cb3dSCy Schubert read_once_cb(evutil_socket_t fd, short event, void *arg) 22042b15cb3dSCy Schubert { 22052b15cb3dSCy Schubert char buf[256]; 22062b15cb3dSCy Schubert int len; 22072b15cb3dSCy Schubert 22082b15cb3dSCy Schubert len = read(fd, buf, sizeof(buf)); 22092b15cb3dSCy Schubert 22102b15cb3dSCy Schubert if (called) { 22112b15cb3dSCy Schubert test_ok = 0; 22122b15cb3dSCy Schubert } else if (len) { 22132b15cb3dSCy Schubert /* Assumes global pair[0] can be used for writing */ 22142b15cb3dSCy Schubert if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 22152b15cb3dSCy Schubert tt_fail_perror("write"); 22162b15cb3dSCy Schubert test_ok = 0; 22172b15cb3dSCy Schubert } else { 22182b15cb3dSCy Schubert test_ok = 1; 22192b15cb3dSCy Schubert } 22202b15cb3dSCy Schubert } 22212b15cb3dSCy Schubert 22222b15cb3dSCy Schubert called++; 22232b15cb3dSCy Schubert } 22242b15cb3dSCy Schubert 22252b15cb3dSCy Schubert static void 22262b15cb3dSCy Schubert test_want_only_once(void) 22272b15cb3dSCy Schubert { 22282b15cb3dSCy Schubert struct event ev; 22292b15cb3dSCy Schubert struct timeval tv; 22302b15cb3dSCy Schubert 22312b15cb3dSCy Schubert /* Very simple read test */ 22322b15cb3dSCy Schubert setup_test("Want read only once: "); 22332b15cb3dSCy Schubert 22342b15cb3dSCy Schubert if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 22352b15cb3dSCy Schubert tt_fail_perror("write"); 22362b15cb3dSCy Schubert } 22372b15cb3dSCy Schubert 22382b15cb3dSCy Schubert /* Setup the loop termination */ 22392b15cb3dSCy Schubert evutil_timerclear(&tv); 22402b15cb3dSCy Schubert tv.tv_usec = 300*1000; 22412b15cb3dSCy Schubert event_loopexit(&tv); 22422b15cb3dSCy Schubert 22432b15cb3dSCy Schubert event_set(&ev, pair[1], EV_READ, read_once_cb, &ev); 22442b15cb3dSCy Schubert if (event_add(&ev, NULL) == -1) 22452b15cb3dSCy Schubert exit(1); 22462b15cb3dSCy Schubert event_dispatch(); 22472b15cb3dSCy Schubert 22482b15cb3dSCy Schubert cleanup_test(); 22492b15cb3dSCy Schubert } 22502b15cb3dSCy Schubert 22512b15cb3dSCy Schubert #define TEST_MAX_INT 6 22522b15cb3dSCy Schubert 22532b15cb3dSCy Schubert static void 22542b15cb3dSCy Schubert evtag_int_test(void *ptr) 22552b15cb3dSCy Schubert { 22562b15cb3dSCy Schubert struct evbuffer *tmp = evbuffer_new(); 22572b15cb3dSCy Schubert ev_uint32_t integers[TEST_MAX_INT] = { 22582b15cb3dSCy Schubert 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 22592b15cb3dSCy Schubert }; 22602b15cb3dSCy Schubert ev_uint32_t integer; 22612b15cb3dSCy Schubert ev_uint64_t big_int; 22622b15cb3dSCy Schubert int i; 22632b15cb3dSCy Schubert 22642b15cb3dSCy Schubert evtag_init(); 22652b15cb3dSCy Schubert 22662b15cb3dSCy Schubert for (i = 0; i < TEST_MAX_INT; i++) { 22672b15cb3dSCy Schubert int oldlen, newlen; 22682b15cb3dSCy Schubert oldlen = (int)EVBUFFER_LENGTH(tmp); 22692b15cb3dSCy Schubert evtag_encode_int(tmp, integers[i]); 22702b15cb3dSCy Schubert newlen = (int)EVBUFFER_LENGTH(tmp); 22712b15cb3dSCy Schubert TT_BLATHER(("encoded 0x%08x with %d bytes", 22722b15cb3dSCy Schubert (unsigned)integers[i], newlen - oldlen)); 22732b15cb3dSCy Schubert big_int = integers[i]; 22742b15cb3dSCy Schubert big_int *= 1000000000; /* 1 billion */ 22752b15cb3dSCy Schubert evtag_encode_int64(tmp, big_int); 22762b15cb3dSCy Schubert } 22772b15cb3dSCy Schubert 22782b15cb3dSCy Schubert for (i = 0; i < TEST_MAX_INT; i++) { 22792b15cb3dSCy Schubert tt_int_op(evtag_decode_int(&integer, tmp), !=, -1); 22802b15cb3dSCy Schubert tt_uint_op(integer, ==, integers[i]); 22812b15cb3dSCy Schubert tt_int_op(evtag_decode_int64(&big_int, tmp), !=, -1); 22822b15cb3dSCy Schubert tt_assert((big_int / 1000000000) == integers[i]); 22832b15cb3dSCy Schubert } 22842b15cb3dSCy Schubert 22852b15cb3dSCy Schubert tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0); 22862b15cb3dSCy Schubert end: 22872b15cb3dSCy Schubert evbuffer_free(tmp); 22882b15cb3dSCy Schubert } 22892b15cb3dSCy Schubert 22902b15cb3dSCy Schubert static void 22912b15cb3dSCy Schubert evtag_fuzz(void *ptr) 22922b15cb3dSCy Schubert { 22932b15cb3dSCy Schubert u_char buffer[4096]; 22942b15cb3dSCy Schubert struct evbuffer *tmp = evbuffer_new(); 22952b15cb3dSCy Schubert struct timeval tv; 22962b15cb3dSCy Schubert int i, j; 22972b15cb3dSCy Schubert 22982b15cb3dSCy Schubert int not_failed = 0; 22992b15cb3dSCy Schubert 23002b15cb3dSCy Schubert evtag_init(); 23012b15cb3dSCy Schubert 23022b15cb3dSCy Schubert for (j = 0; j < 100; j++) { 23032b15cb3dSCy Schubert for (i = 0; i < (int)sizeof(buffer); i++) 2304*a25439b6SCy Schubert buffer[i] = test_weakrand(); 23052b15cb3dSCy Schubert evbuffer_drain(tmp, -1); 23062b15cb3dSCy Schubert evbuffer_add(tmp, buffer, sizeof(buffer)); 23072b15cb3dSCy Schubert 23082b15cb3dSCy Schubert if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) 23092b15cb3dSCy Schubert not_failed++; 23102b15cb3dSCy Schubert } 23112b15cb3dSCy Schubert 23122b15cb3dSCy Schubert /* The majority of decodes should fail */ 23132b15cb3dSCy Schubert tt_int_op(not_failed, <, 10); 23142b15cb3dSCy Schubert 23152b15cb3dSCy Schubert /* Now insert some corruption into the tag length field */ 23162b15cb3dSCy Schubert evbuffer_drain(tmp, -1); 23172b15cb3dSCy Schubert evutil_timerclear(&tv); 23182b15cb3dSCy Schubert tv.tv_sec = 1; 23192b15cb3dSCy Schubert evtag_marshal_timeval(tmp, 0, &tv); 23202b15cb3dSCy Schubert evbuffer_add(tmp, buffer, sizeof(buffer)); 23212b15cb3dSCy Schubert 23222b15cb3dSCy Schubert ((char *)EVBUFFER_DATA(tmp))[1] = '\xff'; 23232b15cb3dSCy Schubert if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) { 23242b15cb3dSCy Schubert tt_abort_msg("evtag_unmarshal_timeval should have failed"); 23252b15cb3dSCy Schubert } 23262b15cb3dSCy Schubert 23272b15cb3dSCy Schubert end: 23282b15cb3dSCy Schubert evbuffer_free(tmp); 23292b15cb3dSCy Schubert } 23302b15cb3dSCy Schubert 23312b15cb3dSCy Schubert static void 23322b15cb3dSCy Schubert evtag_tag_encoding(void *ptr) 23332b15cb3dSCy Schubert { 23342b15cb3dSCy Schubert struct evbuffer *tmp = evbuffer_new(); 23352b15cb3dSCy Schubert ev_uint32_t integers[TEST_MAX_INT] = { 23362b15cb3dSCy Schubert 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 23372b15cb3dSCy Schubert }; 23382b15cb3dSCy Schubert ev_uint32_t integer; 23392b15cb3dSCy Schubert int i; 23402b15cb3dSCy Schubert 23412b15cb3dSCy Schubert evtag_init(); 23422b15cb3dSCy Schubert 23432b15cb3dSCy Schubert for (i = 0; i < TEST_MAX_INT; i++) { 23442b15cb3dSCy Schubert int oldlen, newlen; 23452b15cb3dSCy Schubert oldlen = (int)EVBUFFER_LENGTH(tmp); 23462b15cb3dSCy Schubert evtag_encode_tag(tmp, integers[i]); 23472b15cb3dSCy Schubert newlen = (int)EVBUFFER_LENGTH(tmp); 23482b15cb3dSCy Schubert TT_BLATHER(("encoded 0x%08x with %d bytes", 23492b15cb3dSCy Schubert (unsigned)integers[i], newlen - oldlen)); 23502b15cb3dSCy Schubert } 23512b15cb3dSCy Schubert 23522b15cb3dSCy Schubert for (i = 0; i < TEST_MAX_INT; i++) { 23532b15cb3dSCy Schubert tt_int_op(evtag_decode_tag(&integer, tmp), !=, -1); 23542b15cb3dSCy Schubert tt_uint_op(integer, ==, integers[i]); 23552b15cb3dSCy Schubert } 23562b15cb3dSCy Schubert 23572b15cb3dSCy Schubert tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0); 23582b15cb3dSCy Schubert 23592b15cb3dSCy Schubert end: 23602b15cb3dSCy Schubert evbuffer_free(tmp); 23612b15cb3dSCy Schubert } 23622b15cb3dSCy Schubert 23632b15cb3dSCy Schubert static void 23642b15cb3dSCy Schubert evtag_test_peek(void *ptr) 23652b15cb3dSCy Schubert { 23662b15cb3dSCy Schubert struct evbuffer *tmp = evbuffer_new(); 23672b15cb3dSCy Schubert ev_uint32_t u32; 23682b15cb3dSCy Schubert 23692b15cb3dSCy Schubert evtag_marshal_int(tmp, 30, 0); 23702b15cb3dSCy Schubert evtag_marshal_string(tmp, 40, "Hello world"); 23712b15cb3dSCy Schubert 23722b15cb3dSCy Schubert tt_int_op(evtag_peek(tmp, &u32), ==, 1); 23732b15cb3dSCy Schubert tt_int_op(u32, ==, 30); 23742b15cb3dSCy Schubert tt_int_op(evtag_peek_length(tmp, &u32), ==, 0); 23752b15cb3dSCy Schubert tt_int_op(u32, ==, 1+1+1); 23762b15cb3dSCy Schubert tt_int_op(evtag_consume(tmp), ==, 0); 23772b15cb3dSCy Schubert 23782b15cb3dSCy Schubert tt_int_op(evtag_peek(tmp, &u32), ==, 1); 23792b15cb3dSCy Schubert tt_int_op(u32, ==, 40); 23802b15cb3dSCy Schubert tt_int_op(evtag_peek_length(tmp, &u32), ==, 0); 23812b15cb3dSCy Schubert tt_int_op(u32, ==, 1+1+11); 23822b15cb3dSCy Schubert tt_int_op(evtag_payload_length(tmp, &u32), ==, 0); 23832b15cb3dSCy Schubert tt_int_op(u32, ==, 11); 23842b15cb3dSCy Schubert 23852b15cb3dSCy Schubert end: 23862b15cb3dSCy Schubert evbuffer_free(tmp); 23872b15cb3dSCy Schubert } 23882b15cb3dSCy Schubert 23892b15cb3dSCy Schubert 23902b15cb3dSCy Schubert static void 23912b15cb3dSCy Schubert test_methods(void *ptr) 23922b15cb3dSCy Schubert { 23932b15cb3dSCy Schubert const char **methods = event_get_supported_methods(); 23942b15cb3dSCy Schubert struct event_config *cfg = NULL; 23952b15cb3dSCy Schubert struct event_base *base = NULL; 23962b15cb3dSCy Schubert const char *backend; 23972b15cb3dSCy Schubert int n_methods = 0; 23982b15cb3dSCy Schubert 23992b15cb3dSCy Schubert tt_assert(methods); 24002b15cb3dSCy Schubert 24012b15cb3dSCy Schubert backend = methods[0]; 24022b15cb3dSCy Schubert while (*methods != NULL) { 24032b15cb3dSCy Schubert TT_BLATHER(("Support method: %s", *methods)); 24042b15cb3dSCy Schubert ++methods; 24052b15cb3dSCy Schubert ++n_methods; 24062b15cb3dSCy Schubert } 24072b15cb3dSCy Schubert 24082b15cb3dSCy Schubert cfg = event_config_new(); 24092b15cb3dSCy Schubert assert(cfg != NULL); 24102b15cb3dSCy Schubert 24112b15cb3dSCy Schubert tt_int_op(event_config_avoid_method(cfg, backend), ==, 0); 24122b15cb3dSCy Schubert event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV); 24132b15cb3dSCy Schubert 24142b15cb3dSCy Schubert base = event_base_new_with_config(cfg); 24152b15cb3dSCy Schubert if (n_methods > 1) { 24162b15cb3dSCy Schubert tt_assert(base); 24172b15cb3dSCy Schubert tt_str_op(backend, !=, event_base_get_method(base)); 24182b15cb3dSCy Schubert } else { 24192b15cb3dSCy Schubert tt_assert(base == NULL); 24202b15cb3dSCy Schubert } 24212b15cb3dSCy Schubert 24222b15cb3dSCy Schubert end: 24232b15cb3dSCy Schubert if (base) 24242b15cb3dSCy Schubert event_base_free(base); 24252b15cb3dSCy Schubert if (cfg) 24262b15cb3dSCy Schubert event_config_free(cfg); 24272b15cb3dSCy Schubert } 24282b15cb3dSCy Schubert 24292b15cb3dSCy Schubert static void 24302b15cb3dSCy Schubert test_version(void *arg) 24312b15cb3dSCy Schubert { 24322b15cb3dSCy Schubert const char *vstr; 24332b15cb3dSCy Schubert ev_uint32_t vint; 24342b15cb3dSCy Schubert int major, minor, patch, n; 24352b15cb3dSCy Schubert 24362b15cb3dSCy Schubert vstr = event_get_version(); 24372b15cb3dSCy Schubert vint = event_get_version_number(); 24382b15cb3dSCy Schubert 24392b15cb3dSCy Schubert tt_assert(vstr); 24402b15cb3dSCy Schubert tt_assert(vint); 24412b15cb3dSCy Schubert 24422b15cb3dSCy Schubert tt_str_op(vstr, ==, LIBEVENT_VERSION); 24432b15cb3dSCy Schubert tt_int_op(vint, ==, LIBEVENT_VERSION_NUMBER); 24442b15cb3dSCy Schubert 24452b15cb3dSCy Schubert n = sscanf(vstr, "%d.%d.%d", &major, &minor, &patch); 24462b15cb3dSCy Schubert tt_assert(3 == n); 24472b15cb3dSCy Schubert tt_int_op((vint&0xffffff00), ==, ((major<<24)|(minor<<16)|(patch<<8))); 24482b15cb3dSCy Schubert end: 24492b15cb3dSCy Schubert ; 24502b15cb3dSCy Schubert } 24512b15cb3dSCy Schubert 24522b15cb3dSCy Schubert static void 24532b15cb3dSCy Schubert test_base_features(void *arg) 24542b15cb3dSCy Schubert { 24552b15cb3dSCy Schubert struct event_base *base = NULL; 24562b15cb3dSCy Schubert struct event_config *cfg = NULL; 24572b15cb3dSCy Schubert 24582b15cb3dSCy Schubert cfg = event_config_new(); 24592b15cb3dSCy Schubert 24602b15cb3dSCy Schubert tt_assert(0 == event_config_require_features(cfg, EV_FEATURE_ET)); 24612b15cb3dSCy Schubert 24622b15cb3dSCy Schubert base = event_base_new_with_config(cfg); 24632b15cb3dSCy Schubert if (base) { 24642b15cb3dSCy Schubert tt_int_op(EV_FEATURE_ET, ==, 24652b15cb3dSCy Schubert event_base_get_features(base) & EV_FEATURE_ET); 24662b15cb3dSCy Schubert } else { 24672b15cb3dSCy Schubert base = event_base_new(); 24682b15cb3dSCy Schubert tt_int_op(0, ==, event_base_get_features(base) & EV_FEATURE_ET); 24692b15cb3dSCy Schubert } 24702b15cb3dSCy Schubert 24712b15cb3dSCy Schubert end: 24722b15cb3dSCy Schubert if (base) 24732b15cb3dSCy Schubert event_base_free(base); 24742b15cb3dSCy Schubert if (cfg) 24752b15cb3dSCy Schubert event_config_free(cfg); 24762b15cb3dSCy Schubert } 24772b15cb3dSCy Schubert 24782b15cb3dSCy Schubert #ifdef EVENT__HAVE_SETENV 24792b15cb3dSCy Schubert #define SETENV_OK 24802b15cb3dSCy Schubert #elif !defined(EVENT__HAVE_SETENV) && defined(EVENT__HAVE_PUTENV) 24812b15cb3dSCy Schubert static void setenv(const char *k, const char *v, int o_) 24822b15cb3dSCy Schubert { 24832b15cb3dSCy Schubert char b[256]; 24842b15cb3dSCy Schubert evutil_snprintf(b, sizeof(b), "%s=%s",k,v); 24852b15cb3dSCy Schubert putenv(b); 24862b15cb3dSCy Schubert } 24872b15cb3dSCy Schubert #define SETENV_OK 24882b15cb3dSCy Schubert #endif 24892b15cb3dSCy Schubert 24902b15cb3dSCy Schubert #ifdef EVENT__HAVE_UNSETENV 24912b15cb3dSCy Schubert #define UNSETENV_OK 24922b15cb3dSCy Schubert #elif !defined(EVENT__HAVE_UNSETENV) && defined(EVENT__HAVE_PUTENV) 24932b15cb3dSCy Schubert static void unsetenv(const char *k) 24942b15cb3dSCy Schubert { 24952b15cb3dSCy Schubert char b[256]; 24962b15cb3dSCy Schubert evutil_snprintf(b, sizeof(b), "%s=",k); 24972b15cb3dSCy Schubert putenv(b); 24982b15cb3dSCy Schubert } 24992b15cb3dSCy Schubert #define UNSETENV_OK 25002b15cb3dSCy Schubert #endif 25012b15cb3dSCy Schubert 25022b15cb3dSCy Schubert #if defined(SETENV_OK) && defined(UNSETENV_OK) 25032b15cb3dSCy Schubert static void 25042b15cb3dSCy Schubert methodname_to_envvar(const char *mname, char *buf, size_t buflen) 25052b15cb3dSCy Schubert { 25062b15cb3dSCy Schubert char *cp; 25072b15cb3dSCy Schubert evutil_snprintf(buf, buflen, "EVENT_NO%s", mname); 25082b15cb3dSCy Schubert for (cp = buf; *cp; ++cp) { 25092b15cb3dSCy Schubert *cp = EVUTIL_TOUPPER_(*cp); 25102b15cb3dSCy Schubert } 25112b15cb3dSCy Schubert } 25122b15cb3dSCy Schubert #endif 25132b15cb3dSCy Schubert 25142b15cb3dSCy Schubert static void 25152b15cb3dSCy Schubert test_base_environ(void *arg) 25162b15cb3dSCy Schubert { 25172b15cb3dSCy Schubert struct event_base *base = NULL; 25182b15cb3dSCy Schubert struct event_config *cfg = NULL; 25192b15cb3dSCy Schubert 25202b15cb3dSCy Schubert #if defined(SETENV_OK) && defined(UNSETENV_OK) 25212b15cb3dSCy Schubert const char **basenames; 25222b15cb3dSCy Schubert int i, n_methods=0; 25232b15cb3dSCy Schubert char varbuf[128]; 25242b15cb3dSCy Schubert const char *defaultname, *ignoreenvname; 25252b15cb3dSCy Schubert 25262b15cb3dSCy Schubert /* See if unsetenv works before we rely on it. */ 25272b15cb3dSCy Schubert setenv("EVENT_NOWAFFLES", "1", 1); 25282b15cb3dSCy Schubert unsetenv("EVENT_NOWAFFLES"); 25292b15cb3dSCy Schubert if (getenv("EVENT_NOWAFFLES") != NULL) { 25302b15cb3dSCy Schubert #ifndef EVENT__HAVE_UNSETENV 25312b15cb3dSCy Schubert TT_DECLARE("NOTE", ("Can't fake unsetenv; skipping test")); 25322b15cb3dSCy Schubert #else 25332b15cb3dSCy Schubert TT_DECLARE("NOTE", ("unsetenv doesn't work; skipping test")); 25342b15cb3dSCy Schubert #endif 25352b15cb3dSCy Schubert tt_skip(); 25362b15cb3dSCy Schubert } 25372b15cb3dSCy Schubert 25382b15cb3dSCy Schubert basenames = event_get_supported_methods(); 25392b15cb3dSCy Schubert for (i = 0; basenames[i]; ++i) { 25402b15cb3dSCy Schubert methodname_to_envvar(basenames[i], varbuf, sizeof(varbuf)); 25412b15cb3dSCy Schubert unsetenv(varbuf); 25422b15cb3dSCy Schubert ++n_methods; 25432b15cb3dSCy Schubert } 25442b15cb3dSCy Schubert 25452b15cb3dSCy Schubert base = event_base_new(); 25462b15cb3dSCy Schubert tt_assert(base); 25472b15cb3dSCy Schubert 25482b15cb3dSCy Schubert defaultname = event_base_get_method(base); 25492b15cb3dSCy Schubert TT_BLATHER(("default is <%s>", defaultname)); 25502b15cb3dSCy Schubert event_base_free(base); 25512b15cb3dSCy Schubert base = NULL; 25522b15cb3dSCy Schubert 25532b15cb3dSCy Schubert /* Can we disable the method with EVENT_NOfoo ? */ 25542b15cb3dSCy Schubert if (!strcmp(defaultname, "epoll (with changelist)")) { 25552b15cb3dSCy Schubert setenv("EVENT_NOEPOLL", "1", 1); 25562b15cb3dSCy Schubert ignoreenvname = "epoll"; 25572b15cb3dSCy Schubert } else { 25582b15cb3dSCy Schubert methodname_to_envvar(defaultname, varbuf, sizeof(varbuf)); 25592b15cb3dSCy Schubert setenv(varbuf, "1", 1); 25602b15cb3dSCy Schubert ignoreenvname = defaultname; 25612b15cb3dSCy Schubert } 25622b15cb3dSCy Schubert 25632b15cb3dSCy Schubert /* Use an empty cfg rather than NULL so a failure doesn't exit() */ 25642b15cb3dSCy Schubert cfg = event_config_new(); 25652b15cb3dSCy Schubert base = event_base_new_with_config(cfg); 25662b15cb3dSCy Schubert event_config_free(cfg); 25672b15cb3dSCy Schubert cfg = NULL; 25682b15cb3dSCy Schubert if (n_methods == 1) { 25692b15cb3dSCy Schubert tt_assert(!base); 25702b15cb3dSCy Schubert } else { 25712b15cb3dSCy Schubert tt_assert(base); 25722b15cb3dSCy Schubert tt_str_op(defaultname, !=, event_base_get_method(base)); 25732b15cb3dSCy Schubert event_base_free(base); 25742b15cb3dSCy Schubert base = NULL; 25752b15cb3dSCy Schubert } 25762b15cb3dSCy Schubert 25772b15cb3dSCy Schubert /* Can we disable looking at the environment with IGNORE_ENV ? */ 25782b15cb3dSCy Schubert cfg = event_config_new(); 25792b15cb3dSCy Schubert event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV); 25802b15cb3dSCy Schubert base = event_base_new_with_config(cfg); 25812b15cb3dSCy Schubert tt_assert(base); 25822b15cb3dSCy Schubert tt_str_op(ignoreenvname, ==, event_base_get_method(base)); 25832b15cb3dSCy Schubert #else 25842b15cb3dSCy Schubert tt_skip(); 25852b15cb3dSCy Schubert #endif 25862b15cb3dSCy Schubert 25872b15cb3dSCy Schubert end: 25882b15cb3dSCy Schubert if (base) 25892b15cb3dSCy Schubert event_base_free(base); 25902b15cb3dSCy Schubert if (cfg) 25912b15cb3dSCy Schubert event_config_free(cfg); 25922b15cb3dSCy Schubert } 25932b15cb3dSCy Schubert 25942b15cb3dSCy Schubert static void 25952b15cb3dSCy Schubert read_called_once_cb(evutil_socket_t fd, short event, void *arg) 25962b15cb3dSCy Schubert { 25972b15cb3dSCy Schubert tt_int_op(event, ==, EV_READ); 25982b15cb3dSCy Schubert called += 1; 25992b15cb3dSCy Schubert end: 26002b15cb3dSCy Schubert ; 26012b15cb3dSCy Schubert } 26022b15cb3dSCy Schubert 26032b15cb3dSCy Schubert static void 26042b15cb3dSCy Schubert timeout_called_once_cb(evutil_socket_t fd, short event, void *arg) 26052b15cb3dSCy Schubert { 26062b15cb3dSCy Schubert tt_int_op(event, ==, EV_TIMEOUT); 26072b15cb3dSCy Schubert called += 100; 26082b15cb3dSCy Schubert end: 26092b15cb3dSCy Schubert ; 26102b15cb3dSCy Schubert } 26112b15cb3dSCy Schubert 26122b15cb3dSCy Schubert static void 26132b15cb3dSCy Schubert immediate_called_twice_cb(evutil_socket_t fd, short event, void *arg) 26142b15cb3dSCy Schubert { 26152b15cb3dSCy Schubert tt_int_op(event, ==, EV_TIMEOUT); 26162b15cb3dSCy Schubert called += 1000; 26172b15cb3dSCy Schubert end: 26182b15cb3dSCy Schubert ; 26192b15cb3dSCy Schubert } 26202b15cb3dSCy Schubert 26212b15cb3dSCy Schubert static void 26222b15cb3dSCy Schubert test_event_once(void *ptr) 26232b15cb3dSCy Schubert { 26242b15cb3dSCy Schubert struct basic_test_data *data = ptr; 26252b15cb3dSCy Schubert struct timeval tv; 26262b15cb3dSCy Schubert int r; 26272b15cb3dSCy Schubert 26282b15cb3dSCy Schubert tv.tv_sec = 0; 26292b15cb3dSCy Schubert tv.tv_usec = 50*1000; 26302b15cb3dSCy Schubert called = 0; 26312b15cb3dSCy Schubert r = event_base_once(data->base, data->pair[0], EV_READ, 26322b15cb3dSCy Schubert read_called_once_cb, NULL, NULL); 26332b15cb3dSCy Schubert tt_int_op(r, ==, 0); 26342b15cb3dSCy Schubert r = event_base_once(data->base, -1, EV_TIMEOUT, 26352b15cb3dSCy Schubert timeout_called_once_cb, NULL, &tv); 26362b15cb3dSCy Schubert tt_int_op(r, ==, 0); 26372b15cb3dSCy Schubert r = event_base_once(data->base, -1, 0, NULL, NULL, NULL); 26382b15cb3dSCy Schubert tt_int_op(r, <, 0); 26392b15cb3dSCy Schubert r = event_base_once(data->base, -1, EV_TIMEOUT, 26402b15cb3dSCy Schubert immediate_called_twice_cb, NULL, NULL); 26412b15cb3dSCy Schubert tt_int_op(r, ==, 0); 26422b15cb3dSCy Schubert tv.tv_sec = 0; 26432b15cb3dSCy Schubert tv.tv_usec = 0; 26442b15cb3dSCy Schubert r = event_base_once(data->base, -1, EV_TIMEOUT, 26452b15cb3dSCy Schubert immediate_called_twice_cb, NULL, &tv); 26462b15cb3dSCy Schubert tt_int_op(r, ==, 0); 26472b15cb3dSCy Schubert 26482b15cb3dSCy Schubert if (write(data->pair[1], TEST1, strlen(TEST1)+1) < 0) { 26492b15cb3dSCy Schubert tt_fail_perror("write"); 26502b15cb3dSCy Schubert } 26512b15cb3dSCy Schubert 26522b15cb3dSCy Schubert shutdown(data->pair[1], SHUT_WR); 26532b15cb3dSCy Schubert 26542b15cb3dSCy Schubert event_base_dispatch(data->base); 26552b15cb3dSCy Schubert 26562b15cb3dSCy Schubert tt_int_op(called, ==, 2101); 26572b15cb3dSCy Schubert end: 26582b15cb3dSCy Schubert ; 26592b15cb3dSCy Schubert } 26602b15cb3dSCy Schubert 26612b15cb3dSCy Schubert static void 26622b15cb3dSCy Schubert test_event_once_never(void *ptr) 26632b15cb3dSCy Schubert { 26642b15cb3dSCy Schubert struct basic_test_data *data = ptr; 26652b15cb3dSCy Schubert struct timeval tv; 26662b15cb3dSCy Schubert 26672b15cb3dSCy Schubert /* Have one trigger in 10 seconds (don't worry, because) */ 26682b15cb3dSCy Schubert tv.tv_sec = 10; 26692b15cb3dSCy Schubert tv.tv_usec = 0; 26702b15cb3dSCy Schubert called = 0; 26712b15cb3dSCy Schubert event_base_once(data->base, -1, EV_TIMEOUT, 26722b15cb3dSCy Schubert timeout_called_once_cb, NULL, &tv); 26732b15cb3dSCy Schubert 26742b15cb3dSCy Schubert /* But shut down the base in 75 msec. */ 26752b15cb3dSCy Schubert tv.tv_sec = 0; 26762b15cb3dSCy Schubert tv.tv_usec = 75*1000; 26772b15cb3dSCy Schubert event_base_loopexit(data->base, &tv); 26782b15cb3dSCy Schubert 26792b15cb3dSCy Schubert event_base_dispatch(data->base); 26802b15cb3dSCy Schubert 26812b15cb3dSCy Schubert tt_int_op(called, ==, 0); 26822b15cb3dSCy Schubert end: 26832b15cb3dSCy Schubert ; 26842b15cb3dSCy Schubert } 26852b15cb3dSCy Schubert 26862b15cb3dSCy Schubert static void 26872b15cb3dSCy Schubert test_event_pending(void *ptr) 26882b15cb3dSCy Schubert { 26892b15cb3dSCy Schubert struct basic_test_data *data = ptr; 26902b15cb3dSCy Schubert struct event *r=NULL, *w=NULL, *t=NULL; 26912b15cb3dSCy Schubert struct timeval tv, now, tv2; 26922b15cb3dSCy Schubert 26932b15cb3dSCy Schubert tv.tv_sec = 0; 26942b15cb3dSCy Schubert tv.tv_usec = 500 * 1000; 26952b15cb3dSCy Schubert r = event_new(data->base, data->pair[0], EV_READ, simple_read_cb, 26962b15cb3dSCy Schubert NULL); 26972b15cb3dSCy Schubert w = event_new(data->base, data->pair[1], EV_WRITE, simple_write_cb, 26982b15cb3dSCy Schubert NULL); 26992b15cb3dSCy Schubert t = evtimer_new(data->base, timeout_cb, NULL); 27002b15cb3dSCy Schubert 27012b15cb3dSCy Schubert tt_assert(r); 27022b15cb3dSCy Schubert tt_assert(w); 27032b15cb3dSCy Schubert tt_assert(t); 27042b15cb3dSCy Schubert 27052b15cb3dSCy Schubert evutil_gettimeofday(&now, NULL); 27062b15cb3dSCy Schubert event_add(r, NULL); 27072b15cb3dSCy Schubert event_add(t, &tv); 27082b15cb3dSCy Schubert 27092b15cb3dSCy Schubert tt_assert( event_pending(r, EV_READ, NULL)); 27102b15cb3dSCy Schubert tt_assert(!event_pending(w, EV_WRITE, NULL)); 27112b15cb3dSCy Schubert tt_assert(!event_pending(r, EV_WRITE, NULL)); 27122b15cb3dSCy Schubert tt_assert( event_pending(r, EV_READ|EV_WRITE, NULL)); 27132b15cb3dSCy Schubert tt_assert(!event_pending(r, EV_TIMEOUT, NULL)); 27142b15cb3dSCy Schubert tt_assert( event_pending(t, EV_TIMEOUT, NULL)); 27152b15cb3dSCy Schubert tt_assert( event_pending(t, EV_TIMEOUT, &tv2)); 27162b15cb3dSCy Schubert 27172b15cb3dSCy Schubert tt_assert(evutil_timercmp(&tv2, &now, >)); 27182b15cb3dSCy Schubert 27192b15cb3dSCy Schubert test_timeval_diff_eq(&now, &tv2, 500); 27202b15cb3dSCy Schubert 27212b15cb3dSCy Schubert end: 27222b15cb3dSCy Schubert if (r) { 27232b15cb3dSCy Schubert event_del(r); 27242b15cb3dSCy Schubert event_free(r); 27252b15cb3dSCy Schubert } 27262b15cb3dSCy Schubert if (w) { 27272b15cb3dSCy Schubert event_del(w); 27282b15cb3dSCy Schubert event_free(w); 27292b15cb3dSCy Schubert } 27302b15cb3dSCy Schubert if (t) { 27312b15cb3dSCy Schubert event_del(t); 27322b15cb3dSCy Schubert event_free(t); 27332b15cb3dSCy Schubert } 27342b15cb3dSCy Schubert } 27352b15cb3dSCy Schubert 27362b15cb3dSCy Schubert #ifndef _WIN32 27372b15cb3dSCy Schubert /* You can't do this test on windows, since dup2 doesn't work on sockets */ 27382b15cb3dSCy Schubert 27392b15cb3dSCy Schubert static void 27402b15cb3dSCy Schubert dfd_cb(evutil_socket_t fd, short e, void *data) 27412b15cb3dSCy Schubert { 27422b15cb3dSCy Schubert *(int*)data = (int)e; 27432b15cb3dSCy Schubert } 27442b15cb3dSCy Schubert 27452b15cb3dSCy Schubert /* Regression test for our workaround for a fun epoll/linux related bug 27462b15cb3dSCy Schubert * where fd2 = dup(fd1); add(fd2); close(fd2); dup2(fd1,fd2); add(fd2) 27472b15cb3dSCy Schubert * will get you an EEXIST */ 27482b15cb3dSCy Schubert static void 27492b15cb3dSCy Schubert test_dup_fd(void *arg) 27502b15cb3dSCy Schubert { 27512b15cb3dSCy Schubert struct basic_test_data *data = arg; 27522b15cb3dSCy Schubert struct event_base *base = data->base; 27532b15cb3dSCy Schubert struct event *ev1=NULL, *ev2=NULL; 27542b15cb3dSCy Schubert int fd, dfd=-1; 27552b15cb3dSCy Schubert int ev1_got, ev2_got; 27562b15cb3dSCy Schubert 27572b15cb3dSCy Schubert tt_int_op(write(data->pair[0], "Hello world", 27582b15cb3dSCy Schubert strlen("Hello world")), >, 0); 27592b15cb3dSCy Schubert fd = data->pair[1]; 27602b15cb3dSCy Schubert 27612b15cb3dSCy Schubert dfd = dup(fd); 27622b15cb3dSCy Schubert tt_int_op(dfd, >=, 0); 27632b15cb3dSCy Schubert 27642b15cb3dSCy Schubert ev1 = event_new(base, fd, EV_READ|EV_PERSIST, dfd_cb, &ev1_got); 27652b15cb3dSCy Schubert ev2 = event_new(base, dfd, EV_READ|EV_PERSIST, dfd_cb, &ev2_got); 27662b15cb3dSCy Schubert ev1_got = ev2_got = 0; 27672b15cb3dSCy Schubert event_add(ev1, NULL); 27682b15cb3dSCy Schubert event_add(ev2, NULL); 27692b15cb3dSCy Schubert event_base_loop(base, EVLOOP_ONCE); 27702b15cb3dSCy Schubert tt_int_op(ev1_got, ==, EV_READ); 27712b15cb3dSCy Schubert tt_int_op(ev2_got, ==, EV_READ); 27722b15cb3dSCy Schubert 27732b15cb3dSCy Schubert /* Now close and delete dfd then dispatch. We need to do the 27742b15cb3dSCy Schubert * dispatch here so that when we add it later, we think there 27752b15cb3dSCy Schubert * was an intermediate delete. */ 27762b15cb3dSCy Schubert close(dfd); 27772b15cb3dSCy Schubert event_del(ev2); 27782b15cb3dSCy Schubert ev1_got = ev2_got = 0; 27792b15cb3dSCy Schubert event_base_loop(base, EVLOOP_ONCE); 27802b15cb3dSCy Schubert tt_want_int_op(ev1_got, ==, EV_READ); 27812b15cb3dSCy Schubert tt_int_op(ev2_got, ==, 0); 27822b15cb3dSCy Schubert 27832b15cb3dSCy Schubert /* Re-duplicate the fd. We need to get the same duplicated 27842b15cb3dSCy Schubert * value that we closed to provoke the epoll quirk. Also, we 27852b15cb3dSCy Schubert * need to change the events to write, or else the old lingering 27862b15cb3dSCy Schubert * read event will make the test pass whether the change was 27872b15cb3dSCy Schubert * successful or not. */ 27882b15cb3dSCy Schubert tt_int_op(dup2(fd, dfd), ==, dfd); 27892b15cb3dSCy Schubert event_free(ev2); 27902b15cb3dSCy Schubert ev2 = event_new(base, dfd, EV_WRITE|EV_PERSIST, dfd_cb, &ev2_got); 27912b15cb3dSCy Schubert event_add(ev2, NULL); 27922b15cb3dSCy Schubert ev1_got = ev2_got = 0; 27932b15cb3dSCy Schubert event_base_loop(base, EVLOOP_ONCE); 27942b15cb3dSCy Schubert tt_want_int_op(ev1_got, ==, EV_READ); 27952b15cb3dSCy Schubert tt_int_op(ev2_got, ==, EV_WRITE); 27962b15cb3dSCy Schubert 27972b15cb3dSCy Schubert end: 27982b15cb3dSCy Schubert if (ev1) 27992b15cb3dSCy Schubert event_free(ev1); 28002b15cb3dSCy Schubert if (ev2) 28012b15cb3dSCy Schubert event_free(ev2); 28022b15cb3dSCy Schubert if (dfd >= 0) 28032b15cb3dSCy Schubert close(dfd); 28042b15cb3dSCy Schubert } 28052b15cb3dSCy Schubert #endif 28062b15cb3dSCy Schubert 28072b15cb3dSCy Schubert #ifdef EVENT__DISABLE_MM_REPLACEMENT 28082b15cb3dSCy Schubert static void 28092b15cb3dSCy Schubert test_mm_functions(void *arg) 28102b15cb3dSCy Schubert { 28112b15cb3dSCy Schubert tinytest_set_test_skipped_(); 28122b15cb3dSCy Schubert } 28132b15cb3dSCy Schubert #else 28142b15cb3dSCy Schubert static int 28152b15cb3dSCy Schubert check_dummy_mem_ok(void *mem_) 28162b15cb3dSCy Schubert { 28172b15cb3dSCy Schubert char *mem = mem_; 28182b15cb3dSCy Schubert mem -= 16; 28192b15cb3dSCy Schubert return !memcmp(mem, "{[<guardedram>]}", 16); 28202b15cb3dSCy Schubert } 28212b15cb3dSCy Schubert 28222b15cb3dSCy Schubert static void * 28232b15cb3dSCy Schubert dummy_malloc(size_t len) 28242b15cb3dSCy Schubert { 28252b15cb3dSCy Schubert char *mem = malloc(len+16); 28262b15cb3dSCy Schubert memcpy(mem, "{[<guardedram>]}", 16); 28272b15cb3dSCy Schubert return mem+16; 28282b15cb3dSCy Schubert } 28292b15cb3dSCy Schubert 28302b15cb3dSCy Schubert static void * 28312b15cb3dSCy Schubert dummy_realloc(void *mem_, size_t len) 28322b15cb3dSCy Schubert { 28332b15cb3dSCy Schubert char *mem = mem_; 28342b15cb3dSCy Schubert if (!mem) 28352b15cb3dSCy Schubert return dummy_malloc(len); 28362b15cb3dSCy Schubert tt_want(check_dummy_mem_ok(mem_)); 28372b15cb3dSCy Schubert mem -= 16; 28382b15cb3dSCy Schubert mem = realloc(mem, len+16); 28392b15cb3dSCy Schubert return mem+16; 28402b15cb3dSCy Schubert } 28412b15cb3dSCy Schubert 28422b15cb3dSCy Schubert static void 28432b15cb3dSCy Schubert dummy_free(void *mem_) 28442b15cb3dSCy Schubert { 28452b15cb3dSCy Schubert char *mem = mem_; 28462b15cb3dSCy Schubert tt_want(check_dummy_mem_ok(mem_)); 28472b15cb3dSCy Schubert mem -= 16; 28482b15cb3dSCy Schubert free(mem); 28492b15cb3dSCy Schubert } 28502b15cb3dSCy Schubert 28512b15cb3dSCy Schubert static void 28522b15cb3dSCy Schubert test_mm_functions(void *arg) 28532b15cb3dSCy Schubert { 28542b15cb3dSCy Schubert struct event_base *b = NULL; 28552b15cb3dSCy Schubert struct event_config *cfg = NULL; 28562b15cb3dSCy Schubert event_set_mem_functions(dummy_malloc, dummy_realloc, dummy_free); 28572b15cb3dSCy Schubert cfg = event_config_new(); 28582b15cb3dSCy Schubert event_config_avoid_method(cfg, "Nonesuch"); 28592b15cb3dSCy Schubert b = event_base_new_with_config(cfg); 28602b15cb3dSCy Schubert tt_assert(b); 28612b15cb3dSCy Schubert tt_assert(check_dummy_mem_ok(b)); 28622b15cb3dSCy Schubert end: 28632b15cb3dSCy Schubert if (cfg) 28642b15cb3dSCy Schubert event_config_free(cfg); 28652b15cb3dSCy Schubert if (b) 28662b15cb3dSCy Schubert event_base_free(b); 28672b15cb3dSCy Schubert } 28682b15cb3dSCy Schubert #endif 28692b15cb3dSCy Schubert 28702b15cb3dSCy Schubert static void 28712b15cb3dSCy Schubert many_event_cb(evutil_socket_t fd, short event, void *arg) 28722b15cb3dSCy Schubert { 28732b15cb3dSCy Schubert int *calledp = arg; 28742b15cb3dSCy Schubert *calledp += 1; 28752b15cb3dSCy Schubert } 28762b15cb3dSCy Schubert 28772b15cb3dSCy Schubert static void 28782b15cb3dSCy Schubert test_many_events(void *arg) 28792b15cb3dSCy Schubert { 28802b15cb3dSCy Schubert /* Try 70 events that should all be ready at once. This will 28812b15cb3dSCy Schubert * exercise the "resize" code on most of the backends, and will make 28822b15cb3dSCy Schubert * sure that we can get past the 64-handle limit of some windows 28832b15cb3dSCy Schubert * functions. */ 28842b15cb3dSCy Schubert #define MANY 70 28852b15cb3dSCy Schubert 28862b15cb3dSCy Schubert struct basic_test_data *data = arg; 28872b15cb3dSCy Schubert struct event_base *base = data->base; 28882b15cb3dSCy Schubert int one_at_a_time = data->setup_data != NULL; 28892b15cb3dSCy Schubert evutil_socket_t sock[MANY]; 28902b15cb3dSCy Schubert struct event *ev[MANY]; 28912b15cb3dSCy Schubert int called[MANY]; 28922b15cb3dSCy Schubert int i; 28932b15cb3dSCy Schubert int loopflags = EVLOOP_NONBLOCK, evflags=0; 28942b15cb3dSCy Schubert if (one_at_a_time) { 28952b15cb3dSCy Schubert loopflags |= EVLOOP_ONCE; 28962b15cb3dSCy Schubert evflags = EV_PERSIST; 28972b15cb3dSCy Schubert } 28982b15cb3dSCy Schubert 28992b15cb3dSCy Schubert memset(sock, 0xff, sizeof(sock)); 29002b15cb3dSCy Schubert memset(ev, 0, sizeof(ev)); 29012b15cb3dSCy Schubert memset(called, 0, sizeof(called)); 29022b15cb3dSCy Schubert 29032b15cb3dSCy Schubert for (i = 0; i < MANY; ++i) { 29042b15cb3dSCy Schubert /* We need an event that will hit the backend, and that will 29052b15cb3dSCy Schubert * be ready immediately. "Send a datagram" is an easy 29062b15cb3dSCy Schubert * instance of that. */ 29072b15cb3dSCy Schubert sock[i] = socket(AF_INET, SOCK_DGRAM, 0); 29082b15cb3dSCy Schubert tt_assert(sock[i] >= 0); 29092b15cb3dSCy Schubert called[i] = 0; 29102b15cb3dSCy Schubert ev[i] = event_new(base, sock[i], EV_WRITE|evflags, 29112b15cb3dSCy Schubert many_event_cb, &called[i]); 29122b15cb3dSCy Schubert event_add(ev[i], NULL); 29132b15cb3dSCy Schubert if (one_at_a_time) 29142b15cb3dSCy Schubert event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE); 29152b15cb3dSCy Schubert } 29162b15cb3dSCy Schubert 29172b15cb3dSCy Schubert event_base_loop(base, loopflags); 29182b15cb3dSCy Schubert 29192b15cb3dSCy Schubert for (i = 0; i < MANY; ++i) { 29202b15cb3dSCy Schubert if (one_at_a_time) 29212b15cb3dSCy Schubert tt_int_op(called[i], ==, MANY - i + 1); 29222b15cb3dSCy Schubert else 29232b15cb3dSCy Schubert tt_int_op(called[i], ==, 1); 29242b15cb3dSCy Schubert } 29252b15cb3dSCy Schubert 29262b15cb3dSCy Schubert end: 29272b15cb3dSCy Schubert for (i = 0; i < MANY; ++i) { 29282b15cb3dSCy Schubert if (ev[i]) 29292b15cb3dSCy Schubert event_free(ev[i]); 29302b15cb3dSCy Schubert if (sock[i] >= 0) 29312b15cb3dSCy Schubert evutil_closesocket(sock[i]); 29322b15cb3dSCy Schubert } 29332b15cb3dSCy Schubert #undef MANY 29342b15cb3dSCy Schubert } 29352b15cb3dSCy Schubert 29362b15cb3dSCy Schubert static void 29372b15cb3dSCy Schubert test_struct_event_size(void *arg) 29382b15cb3dSCy Schubert { 29392b15cb3dSCy Schubert tt_int_op(event_get_struct_event_size(), <=, sizeof(struct event)); 29402b15cb3dSCy Schubert end: 29412b15cb3dSCy Schubert ; 29422b15cb3dSCy Schubert } 29432b15cb3dSCy Schubert 29442b15cb3dSCy Schubert static void 29452b15cb3dSCy Schubert test_get_assignment(void *arg) 29462b15cb3dSCy Schubert { 29472b15cb3dSCy Schubert struct basic_test_data *data = arg; 29482b15cb3dSCy Schubert struct event_base *base = data->base; 29492b15cb3dSCy Schubert struct event *ev1 = NULL; 29502b15cb3dSCy Schubert const char *str = "foo"; 29512b15cb3dSCy Schubert 29522b15cb3dSCy Schubert struct event_base *b; 29532b15cb3dSCy Schubert evutil_socket_t s; 29542b15cb3dSCy Schubert short what; 29552b15cb3dSCy Schubert event_callback_fn cb; 29562b15cb3dSCy Schubert void *cb_arg; 29572b15cb3dSCy Schubert 29582b15cb3dSCy Schubert ev1 = event_new(base, data->pair[1], EV_READ, dummy_read_cb, (void*)str); 29592b15cb3dSCy Schubert event_get_assignment(ev1, &b, &s, &what, &cb, &cb_arg); 29602b15cb3dSCy Schubert 29612b15cb3dSCy Schubert tt_ptr_op(b, ==, base); 29622b15cb3dSCy Schubert tt_int_op(s, ==, data->pair[1]); 29632b15cb3dSCy Schubert tt_int_op(what, ==, EV_READ); 29642b15cb3dSCy Schubert tt_ptr_op(cb, ==, dummy_read_cb); 29652b15cb3dSCy Schubert tt_ptr_op(cb_arg, ==, str); 29662b15cb3dSCy Schubert 29672b15cb3dSCy Schubert /* Now make sure this doesn't crash. */ 29682b15cb3dSCy Schubert event_get_assignment(ev1, NULL, NULL, NULL, NULL, NULL); 29692b15cb3dSCy Schubert 29702b15cb3dSCy Schubert end: 29712b15cb3dSCy Schubert if (ev1) 29722b15cb3dSCy Schubert event_free(ev1); 29732b15cb3dSCy Schubert } 29742b15cb3dSCy Schubert 29752b15cb3dSCy Schubert struct foreach_helper { 29762b15cb3dSCy Schubert int count; 29772b15cb3dSCy Schubert const struct event *ev; 29782b15cb3dSCy Schubert }; 29792b15cb3dSCy Schubert 29802b15cb3dSCy Schubert static int 29812b15cb3dSCy Schubert foreach_count_cb(const struct event_base *base, const struct event *ev, void *arg) 29822b15cb3dSCy Schubert { 29832b15cb3dSCy Schubert struct foreach_helper *h = event_get_callback_arg(ev); 29842b15cb3dSCy Schubert struct timeval *tv = arg; 29852b15cb3dSCy Schubert if (event_get_callback(ev) != timeout_cb) 29862b15cb3dSCy Schubert return 0; 29872b15cb3dSCy Schubert tt_ptr_op(event_get_base(ev), ==, base); 29882b15cb3dSCy Schubert tt_int_op(tv->tv_sec, ==, 10); 29892b15cb3dSCy Schubert h->ev = ev; 29902b15cb3dSCy Schubert h->count++; 29912b15cb3dSCy Schubert return 0; 29922b15cb3dSCy Schubert end: 29932b15cb3dSCy Schubert return -1; 29942b15cb3dSCy Schubert } 29952b15cb3dSCy Schubert 29962b15cb3dSCy Schubert static int 29972b15cb3dSCy Schubert foreach_find_cb(const struct event_base *base, const struct event *ev, void *arg) 29982b15cb3dSCy Schubert { 29992b15cb3dSCy Schubert const struct event **ev_out = arg; 30002b15cb3dSCy Schubert struct foreach_helper *h = event_get_callback_arg(ev); 30012b15cb3dSCy Schubert if (event_get_callback(ev) != timeout_cb) 30022b15cb3dSCy Schubert return 0; 30032b15cb3dSCy Schubert if (h->count == 99) { 30042b15cb3dSCy Schubert *ev_out = ev; 30052b15cb3dSCy Schubert return 101; 30062b15cb3dSCy Schubert } 30072b15cb3dSCy Schubert return 0; 30082b15cb3dSCy Schubert } 30092b15cb3dSCy Schubert 30102b15cb3dSCy Schubert static void 30112b15cb3dSCy Schubert test_event_foreach(void *arg) 30122b15cb3dSCy Schubert { 30132b15cb3dSCy Schubert struct basic_test_data *data = arg; 30142b15cb3dSCy Schubert struct event_base *base = data->base; 30152b15cb3dSCy Schubert struct event *ev[5]; 30162b15cb3dSCy Schubert struct foreach_helper visited[5]; 30172b15cb3dSCy Schubert int i; 30182b15cb3dSCy Schubert struct timeval ten_sec = {10,0}; 30192b15cb3dSCy Schubert const struct event *ev_found = NULL; 30202b15cb3dSCy Schubert 30212b15cb3dSCy Schubert for (i = 0; i < 5; ++i) { 30222b15cb3dSCy Schubert visited[i].count = 0; 30232b15cb3dSCy Schubert visited[i].ev = NULL; 30242b15cb3dSCy Schubert ev[i] = event_new(base, -1, 0, timeout_cb, &visited[i]); 30252b15cb3dSCy Schubert } 30262b15cb3dSCy Schubert 30272b15cb3dSCy Schubert tt_int_op(-1, ==, event_base_foreach_event(NULL, foreach_count_cb, NULL)); 30282b15cb3dSCy Schubert tt_int_op(-1, ==, event_base_foreach_event(base, NULL, NULL)); 30292b15cb3dSCy Schubert 30302b15cb3dSCy Schubert event_add(ev[0], &ten_sec); 30312b15cb3dSCy Schubert event_add(ev[1], &ten_sec); 30322b15cb3dSCy Schubert event_active(ev[1], EV_TIMEOUT, 1); 30332b15cb3dSCy Schubert event_active(ev[2], EV_TIMEOUT, 1); 30342b15cb3dSCy Schubert event_add(ev[3], &ten_sec); 30352b15cb3dSCy Schubert /* Don't touch ev[4]. */ 30362b15cb3dSCy Schubert 30372b15cb3dSCy Schubert tt_int_op(0, ==, event_base_foreach_event(base, foreach_count_cb, 30382b15cb3dSCy Schubert &ten_sec)); 30392b15cb3dSCy Schubert tt_int_op(1, ==, visited[0].count); 30402b15cb3dSCy Schubert tt_int_op(1, ==, visited[1].count); 30412b15cb3dSCy Schubert tt_int_op(1, ==, visited[2].count); 30422b15cb3dSCy Schubert tt_int_op(1, ==, visited[3].count); 30432b15cb3dSCy Schubert tt_ptr_op(ev[0], ==, visited[0].ev); 30442b15cb3dSCy Schubert tt_ptr_op(ev[1], ==, visited[1].ev); 30452b15cb3dSCy Schubert tt_ptr_op(ev[2], ==, visited[2].ev); 30462b15cb3dSCy Schubert tt_ptr_op(ev[3], ==, visited[3].ev); 30472b15cb3dSCy Schubert 30482b15cb3dSCy Schubert visited[2].count = 99; 30492b15cb3dSCy Schubert tt_int_op(101, ==, event_base_foreach_event(base, foreach_find_cb, 30502b15cb3dSCy Schubert &ev_found)); 30512b15cb3dSCy Schubert tt_ptr_op(ev_found, ==, ev[2]); 30522b15cb3dSCy Schubert 30532b15cb3dSCy Schubert end: 30542b15cb3dSCy Schubert for (i=0; i<5; ++i) { 30552b15cb3dSCy Schubert event_free(ev[i]); 30562b15cb3dSCy Schubert } 30572b15cb3dSCy Schubert } 30582b15cb3dSCy Schubert 30592b15cb3dSCy Schubert static struct event_base *cached_time_base = NULL; 30602b15cb3dSCy Schubert static int cached_time_reset = 0; 30612b15cb3dSCy Schubert static int cached_time_sleep = 0; 30622b15cb3dSCy Schubert static void 30632b15cb3dSCy Schubert cache_time_cb(evutil_socket_t fd, short what, void *arg) 30642b15cb3dSCy Schubert { 30652b15cb3dSCy Schubert struct timeval *tv = arg; 30662b15cb3dSCy Schubert tt_int_op(0, ==, event_base_gettimeofday_cached(cached_time_base, tv)); 30672b15cb3dSCy Schubert if (cached_time_sleep) { 30682b15cb3dSCy Schubert struct timeval delay = { 0, 30*1000 }; 30692b15cb3dSCy Schubert evutil_usleep_(&delay); 30702b15cb3dSCy Schubert } 30712b15cb3dSCy Schubert if (cached_time_reset) { 30722b15cb3dSCy Schubert event_base_update_cache_time(cached_time_base); 30732b15cb3dSCy Schubert } 30742b15cb3dSCy Schubert end: 30752b15cb3dSCy Schubert ; 30762b15cb3dSCy Schubert } 30772b15cb3dSCy Schubert 30782b15cb3dSCy Schubert static void 30792b15cb3dSCy Schubert test_gettimeofday_cached(void *arg) 30802b15cb3dSCy Schubert { 30812b15cb3dSCy Schubert struct basic_test_data *data = arg; 30822b15cb3dSCy Schubert struct event_config *cfg = NULL; 30832b15cb3dSCy Schubert struct event_base *base = NULL; 30842b15cb3dSCy Schubert struct timeval tv1, tv2, tv3, now; 30852b15cb3dSCy Schubert struct event *ev1=NULL, *ev2=NULL, *ev3=NULL; 30862b15cb3dSCy Schubert int cached_time_disable = strstr(data->setup_data, "disable") != NULL; 30872b15cb3dSCy Schubert 30882b15cb3dSCy Schubert cfg = event_config_new(); 30892b15cb3dSCy Schubert if (cached_time_disable) { 30902b15cb3dSCy Schubert event_config_set_flag(cfg, EVENT_BASE_FLAG_NO_CACHE_TIME); 30912b15cb3dSCy Schubert } 30922b15cb3dSCy Schubert cached_time_base = base = event_base_new_with_config(cfg); 30932b15cb3dSCy Schubert tt_assert(base); 30942b15cb3dSCy Schubert 30952b15cb3dSCy Schubert /* Try gettimeofday_cached outside of an event loop. */ 30962b15cb3dSCy Schubert evutil_gettimeofday(&now, NULL); 30972b15cb3dSCy Schubert tt_int_op(0, ==, event_base_gettimeofday_cached(NULL, &tv1)); 30982b15cb3dSCy Schubert tt_int_op(0, ==, event_base_gettimeofday_cached(base, &tv2)); 30992b15cb3dSCy Schubert tt_int_op(timeval_msec_diff(&tv1, &tv2), <, 10); 31002b15cb3dSCy Schubert tt_int_op(timeval_msec_diff(&tv1, &now), <, 10); 31012b15cb3dSCy Schubert 31022b15cb3dSCy Schubert cached_time_reset = strstr(data->setup_data, "reset") != NULL; 31032b15cb3dSCy Schubert cached_time_sleep = strstr(data->setup_data, "sleep") != NULL; 31042b15cb3dSCy Schubert 31052b15cb3dSCy Schubert ev1 = event_new(base, -1, 0, cache_time_cb, &tv1); 31062b15cb3dSCy Schubert ev2 = event_new(base, -1, 0, cache_time_cb, &tv2); 31072b15cb3dSCy Schubert ev3 = event_new(base, -1, 0, cache_time_cb, &tv3); 31082b15cb3dSCy Schubert 31092b15cb3dSCy Schubert event_active(ev1, EV_TIMEOUT, 1); 31102b15cb3dSCy Schubert event_active(ev2, EV_TIMEOUT, 1); 31112b15cb3dSCy Schubert event_active(ev3, EV_TIMEOUT, 1); 31122b15cb3dSCy Schubert 31132b15cb3dSCy Schubert event_base_dispatch(base); 31142b15cb3dSCy Schubert 31152b15cb3dSCy Schubert if (cached_time_reset && cached_time_sleep) { 31162b15cb3dSCy Schubert tt_int_op(labs(timeval_msec_diff(&tv1,&tv2)), >, 10); 31172b15cb3dSCy Schubert tt_int_op(labs(timeval_msec_diff(&tv2,&tv3)), >, 10); 31182b15cb3dSCy Schubert } else if (cached_time_disable && cached_time_sleep) { 31192b15cb3dSCy Schubert tt_int_op(labs(timeval_msec_diff(&tv1,&tv2)), >, 10); 31202b15cb3dSCy Schubert tt_int_op(labs(timeval_msec_diff(&tv2,&tv3)), >, 10); 31212b15cb3dSCy Schubert } else if (! cached_time_disable) { 31222b15cb3dSCy Schubert tt_assert(evutil_timercmp(&tv1, &tv2, ==)); 31232b15cb3dSCy Schubert tt_assert(evutil_timercmp(&tv2, &tv3, ==)); 31242b15cb3dSCy Schubert } 31252b15cb3dSCy Schubert 31262b15cb3dSCy Schubert end: 31272b15cb3dSCy Schubert if (ev1) 31282b15cb3dSCy Schubert event_free(ev1); 31292b15cb3dSCy Schubert if (ev2) 31302b15cb3dSCy Schubert event_free(ev2); 31312b15cb3dSCy Schubert if (ev3) 31322b15cb3dSCy Schubert event_free(ev3); 31332b15cb3dSCy Schubert if (base) 31342b15cb3dSCy Schubert event_base_free(base); 31352b15cb3dSCy Schubert if (cfg) 31362b15cb3dSCy Schubert event_config_free(cfg); 31372b15cb3dSCy Schubert } 31382b15cb3dSCy Schubert 31392b15cb3dSCy Schubert static void 31402b15cb3dSCy Schubert tabf_cb(evutil_socket_t fd, short what, void *arg) 31412b15cb3dSCy Schubert { 31422b15cb3dSCy Schubert int *ptr = arg; 31432b15cb3dSCy Schubert *ptr = what; 31442b15cb3dSCy Schubert *ptr += 0x10000; 31452b15cb3dSCy Schubert } 31462b15cb3dSCy Schubert 31472b15cb3dSCy Schubert static void 31482b15cb3dSCy Schubert test_active_by_fd(void *arg) 31492b15cb3dSCy Schubert { 31502b15cb3dSCy Schubert struct basic_test_data *data = arg; 31512b15cb3dSCy Schubert struct event_base *base = data->base; 31522b15cb3dSCy Schubert struct event *ev1 = NULL, *ev2 = NULL, *ev3 = NULL, *ev4 = NULL; 31532b15cb3dSCy Schubert int e1,e2,e3,e4; 31542b15cb3dSCy Schubert #ifndef _WIN32 31552b15cb3dSCy Schubert struct event *evsig = NULL; 31562b15cb3dSCy Schubert int es; 31572b15cb3dSCy Schubert #endif 31582b15cb3dSCy Schubert struct timeval tenmin = { 600, 0 }; 31592b15cb3dSCy Schubert 31602b15cb3dSCy Schubert /* Ensure no crash on nonexistent FD. */ 31612b15cb3dSCy Schubert event_base_active_by_fd(base, 1000, EV_READ); 31622b15cb3dSCy Schubert 31632b15cb3dSCy Schubert /* Ensure no crash on bogus FD. */ 31642b15cb3dSCy Schubert event_base_active_by_fd(base, -1, EV_READ); 31652b15cb3dSCy Schubert 31662b15cb3dSCy Schubert /* Ensure no crash on nonexistent/bogus signal. */ 31672b15cb3dSCy Schubert event_base_active_by_signal(base, 1000); 31682b15cb3dSCy Schubert event_base_active_by_signal(base, -1); 31692b15cb3dSCy Schubert 31702b15cb3dSCy Schubert event_base_assert_ok_(base); 31712b15cb3dSCy Schubert 31722b15cb3dSCy Schubert e1 = e2 = e3 = e4 = 0; 31732b15cb3dSCy Schubert ev1 = event_new(base, data->pair[0], EV_READ, tabf_cb, &e1); 31742b15cb3dSCy Schubert ev2 = event_new(base, data->pair[0], EV_WRITE, tabf_cb, &e2); 31752b15cb3dSCy Schubert ev3 = event_new(base, data->pair[1], EV_READ, tabf_cb, &e3); 31762b15cb3dSCy Schubert ev4 = event_new(base, data->pair[1], EV_READ, tabf_cb, &e4); 31772b15cb3dSCy Schubert tt_assert(ev1); 31782b15cb3dSCy Schubert tt_assert(ev2); 31792b15cb3dSCy Schubert tt_assert(ev3); 31802b15cb3dSCy Schubert tt_assert(ev4); 31812b15cb3dSCy Schubert #ifndef _WIN32 31822b15cb3dSCy Schubert evsig = event_new(base, SIGHUP, EV_SIGNAL, tabf_cb, &es); 31832b15cb3dSCy Schubert tt_assert(evsig); 31842b15cb3dSCy Schubert event_add(evsig, &tenmin); 31852b15cb3dSCy Schubert #endif 31862b15cb3dSCy Schubert 31872b15cb3dSCy Schubert event_add(ev1, &tenmin); 31882b15cb3dSCy Schubert event_add(ev2, NULL); 31892b15cb3dSCy Schubert event_add(ev3, NULL); 31902b15cb3dSCy Schubert event_add(ev4, &tenmin); 31912b15cb3dSCy Schubert 31922b15cb3dSCy Schubert 31932b15cb3dSCy Schubert event_base_assert_ok_(base); 31942b15cb3dSCy Schubert 31952b15cb3dSCy Schubert /* Trigger 2, 3, 4 */ 31962b15cb3dSCy Schubert event_base_active_by_fd(base, data->pair[0], EV_WRITE); 31972b15cb3dSCy Schubert event_base_active_by_fd(base, data->pair[1], EV_READ); 31982b15cb3dSCy Schubert #ifndef _WIN32 31992b15cb3dSCy Schubert event_base_active_by_signal(base, SIGHUP); 32002b15cb3dSCy Schubert #endif 32012b15cb3dSCy Schubert 32022b15cb3dSCy Schubert event_base_assert_ok_(base); 32032b15cb3dSCy Schubert 32042b15cb3dSCy Schubert event_base_loop(base, EVLOOP_ONCE); 32052b15cb3dSCy Schubert 32062b15cb3dSCy Schubert tt_int_op(e1, ==, 0); 32072b15cb3dSCy Schubert tt_int_op(e2, ==, EV_WRITE | 0x10000); 32082b15cb3dSCy Schubert tt_int_op(e3, ==, EV_READ | 0x10000); 32092b15cb3dSCy Schubert /* Mask out EV_WRITE here, since it could be genuinely writeable. */ 32102b15cb3dSCy Schubert tt_int_op((e4 & ~EV_WRITE), ==, EV_READ | 0x10000); 32112b15cb3dSCy Schubert #ifndef _WIN32 32122b15cb3dSCy Schubert tt_int_op(es, ==, EV_SIGNAL | 0x10000); 32132b15cb3dSCy Schubert #endif 32142b15cb3dSCy Schubert 32152b15cb3dSCy Schubert end: 32162b15cb3dSCy Schubert if (ev1) 32172b15cb3dSCy Schubert event_free(ev1); 32182b15cb3dSCy Schubert if (ev2) 32192b15cb3dSCy Schubert event_free(ev2); 32202b15cb3dSCy Schubert if (ev3) 32212b15cb3dSCy Schubert event_free(ev3); 32222b15cb3dSCy Schubert if (ev4) 32232b15cb3dSCy Schubert event_free(ev4); 32242b15cb3dSCy Schubert #ifndef _WIN32 32252b15cb3dSCy Schubert if (evsig) 32262b15cb3dSCy Schubert event_free(evsig); 32272b15cb3dSCy Schubert #endif 32282b15cb3dSCy Schubert } 32292b15cb3dSCy Schubert 32302b15cb3dSCy Schubert struct testcase_t main_testcases[] = { 32312b15cb3dSCy Schubert /* Some converted-over tests */ 32322b15cb3dSCy Schubert { "methods", test_methods, TT_FORK, NULL, NULL }, 32332b15cb3dSCy Schubert { "version", test_version, 0, NULL, NULL }, 32342b15cb3dSCy Schubert BASIC(base_features, TT_FORK|TT_NO_LOGS), 32352b15cb3dSCy Schubert { "base_environ", test_base_environ, TT_FORK, NULL, NULL }, 32362b15cb3dSCy Schubert 32372b15cb3dSCy Schubert BASIC(event_base_new, TT_FORK|TT_NEED_SOCKETPAIR), 32382b15cb3dSCy Schubert BASIC(free_active_base, TT_FORK|TT_NEED_SOCKETPAIR), 32392b15cb3dSCy Schubert 32402b15cb3dSCy Schubert BASIC(manipulate_active_events, TT_FORK|TT_NEED_BASE), 32412b15cb3dSCy Schubert BASIC(event_new_selfarg, TT_FORK|TT_NEED_BASE), 32422b15cb3dSCy Schubert BASIC(event_assign_selfarg, TT_FORK|TT_NEED_BASE), 32432b15cb3dSCy Schubert BASIC(event_base_get_num_events, TT_FORK|TT_NEED_BASE), 32442b15cb3dSCy Schubert BASIC(event_base_get_max_events, TT_FORK|TT_NEED_BASE), 32452b15cb3dSCy Schubert 32462b15cb3dSCy Schubert BASIC(bad_assign, TT_FORK|TT_NEED_BASE|TT_NO_LOGS), 32472b15cb3dSCy Schubert BASIC(bad_reentrant, TT_FORK|TT_NEED_BASE|TT_NO_LOGS), 32482b15cb3dSCy Schubert BASIC(active_later, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 32492b15cb3dSCy Schubert BASIC(event_remove_timeout, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 32502b15cb3dSCy Schubert 32512b15cb3dSCy Schubert /* These are still using the old API */ 32522b15cb3dSCy Schubert LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE), 32532b15cb3dSCy Schubert { "persistent_timeout_jump", test_persistent_timeout_jump, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 32542b15cb3dSCy Schubert { "persistent_active_timeout", test_persistent_active_timeout, 32552b15cb3dSCy Schubert TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 32562b15cb3dSCy Schubert LEGACY(priorities, TT_FORK|TT_NEED_BASE), 32572b15cb3dSCy Schubert BASIC(priority_active_inversion, TT_FORK|TT_NEED_BASE), 32582b15cb3dSCy Schubert { "common_timeout", test_common_timeout, TT_FORK|TT_NEED_BASE, 32592b15cb3dSCy Schubert &basic_setup, NULL }, 32602b15cb3dSCy Schubert 32612b15cb3dSCy Schubert /* These legacy tests may not all need all of these flags. */ 32622b15cb3dSCy Schubert LEGACY(simpleread, TT_ISOLATED), 32632b15cb3dSCy Schubert LEGACY(simpleread_multiple, TT_ISOLATED), 32642b15cb3dSCy Schubert LEGACY(simplewrite, TT_ISOLATED), 32652b15cb3dSCy Schubert { "simpleclose", test_simpleclose, TT_FORK, &basic_setup, 32662b15cb3dSCy Schubert NULL }, 32672b15cb3dSCy Schubert LEGACY(multiple, TT_ISOLATED), 32682b15cb3dSCy Schubert LEGACY(persistent, TT_ISOLATED), 32692b15cb3dSCy Schubert LEGACY(combined, TT_ISOLATED), 32702b15cb3dSCy Schubert LEGACY(simpletimeout, TT_ISOLATED), 32712b15cb3dSCy Schubert LEGACY(loopbreak, TT_ISOLATED), 32722b15cb3dSCy Schubert LEGACY(loopexit, TT_ISOLATED), 32732b15cb3dSCy Schubert LEGACY(loopexit_multiple, TT_ISOLATED), 32742b15cb3dSCy Schubert LEGACY(nonpersist_readd, TT_ISOLATED), 32752b15cb3dSCy Schubert LEGACY(multiple_events_for_same_fd, TT_ISOLATED), 32762b15cb3dSCy Schubert LEGACY(want_only_once, TT_ISOLATED), 32772b15cb3dSCy Schubert { "event_once", test_event_once, TT_ISOLATED, &basic_setup, NULL }, 32782b15cb3dSCy Schubert { "event_once_never", test_event_once_never, TT_ISOLATED, &basic_setup, NULL }, 32792b15cb3dSCy Schubert { "event_pending", test_event_pending, TT_ISOLATED, &basic_setup, 32802b15cb3dSCy Schubert NULL }, 32812b15cb3dSCy Schubert #ifndef _WIN32 32822b15cb3dSCy Schubert { "dup_fd", test_dup_fd, TT_ISOLATED, &basic_setup, NULL }, 32832b15cb3dSCy Schubert #endif 32842b15cb3dSCy Schubert { "mm_functions", test_mm_functions, TT_FORK, NULL, NULL }, 32852b15cb3dSCy Schubert { "many_events", test_many_events, TT_ISOLATED, &basic_setup, NULL }, 32862b15cb3dSCy Schubert { "many_events_slow_add", test_many_events, TT_ISOLATED, &basic_setup, (void*)1 }, 32872b15cb3dSCy Schubert 32882b15cb3dSCy Schubert { "struct_event_size", test_struct_event_size, 0, NULL, NULL }, 32892b15cb3dSCy Schubert BASIC(get_assignment, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 32902b15cb3dSCy Schubert 32912b15cb3dSCy Schubert BASIC(event_foreach, TT_FORK|TT_NEED_BASE), 32922b15cb3dSCy Schubert { "gettimeofday_cached", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"" }, 32932b15cb3dSCy Schubert { "gettimeofday_cached_sleep", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep" }, 32942b15cb3dSCy Schubert { "gettimeofday_cached_reset", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep reset" }, 32952b15cb3dSCy Schubert { "gettimeofday_cached_disabled", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep disable" }, 32962b15cb3dSCy Schubert { "gettimeofday_cached_disabled_nosleep", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"disable" }, 32972b15cb3dSCy Schubert 32982b15cb3dSCy Schubert BASIC(active_by_fd, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 32992b15cb3dSCy Schubert 33002b15cb3dSCy Schubert #ifndef _WIN32 33012b15cb3dSCy Schubert LEGACY(fork, TT_ISOLATED), 33022b15cb3dSCy Schubert #endif 33032b15cb3dSCy Schubert END_OF_TESTCASES 33042b15cb3dSCy Schubert }; 33052b15cb3dSCy Schubert 33062b15cb3dSCy Schubert struct testcase_t evtag_testcases[] = { 33072b15cb3dSCy Schubert { "int", evtag_int_test, TT_FORK, NULL, NULL }, 33082b15cb3dSCy Schubert { "fuzz", evtag_fuzz, TT_FORK, NULL, NULL }, 33092b15cb3dSCy Schubert { "encoding", evtag_tag_encoding, TT_FORK, NULL, NULL }, 33102b15cb3dSCy Schubert { "peek", evtag_test_peek, 0, NULL, NULL }, 33112b15cb3dSCy Schubert 33122b15cb3dSCy Schubert END_OF_TESTCASES 33132b15cb3dSCy Schubert }; 33142b15cb3dSCy Schubert 33152b15cb3dSCy Schubert struct testcase_t signal_testcases[] = { 33162b15cb3dSCy Schubert #ifndef _WIN32 3317*a25439b6SCy Schubert LEGACY(simplestsignal, TT_ISOLATED), 33182b15cb3dSCy Schubert LEGACY(simplesignal, TT_ISOLATED), 33192b15cb3dSCy Schubert LEGACY(multiplesignal, TT_ISOLATED), 33202b15cb3dSCy Schubert LEGACY(immediatesignal, TT_ISOLATED), 33212b15cb3dSCy Schubert LEGACY(signal_dealloc, TT_ISOLATED), 33222b15cb3dSCy Schubert LEGACY(signal_pipeloss, TT_ISOLATED), 33232b15cb3dSCy Schubert LEGACY(signal_switchbase, TT_ISOLATED|TT_NO_LOGS), 33242b15cb3dSCy Schubert LEGACY(signal_restore, TT_ISOLATED), 33252b15cb3dSCy Schubert LEGACY(signal_assert, TT_ISOLATED), 33262b15cb3dSCy Schubert LEGACY(signal_while_processing, TT_ISOLATED), 33272b15cb3dSCy Schubert #endif 33282b15cb3dSCy Schubert END_OF_TESTCASES 33292b15cb3dSCy Schubert }; 33302b15cb3dSCy Schubert 3331