regress.c revision 275970
1275970Scy/* 2275970Scy * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 3275970Scy * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 4275970Scy * 5275970Scy * Redistribution and use in source and binary forms, with or without 6275970Scy * modification, are permitted provided that the following conditions 7275970Scy * are met: 8275970Scy * 1. Redistributions of source code must retain the above copyright 9275970Scy * notice, this list of conditions and the following disclaimer. 10275970Scy * 2. Redistributions in binary form must reproduce the above copyright 11275970Scy * notice, this list of conditions and the following disclaimer in the 12275970Scy * documentation and/or other materials provided with the distribution. 13275970Scy * 3. The name of the author may not be used to endorse or promote products 14275970Scy * derived from this software without specific prior written permission. 15275970Scy * 16275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26275970Scy */ 27275970Scy#include "util-internal.h" 28275970Scy 29275970Scy#ifdef _WIN32 30275970Scy#include <winsock2.h> 31275970Scy#include <windows.h> 32275970Scy#endif 33275970Scy 34275970Scy#include "event2/event-config.h" 35275970Scy 36275970Scy#include <sys/types.h> 37275970Scy#include <sys/stat.h> 38275970Scy#ifdef EVENT__HAVE_SYS_TIME_H 39275970Scy#include <sys/time.h> 40275970Scy#endif 41275970Scy#include <sys/queue.h> 42275970Scy#ifndef _WIN32 43275970Scy#include <sys/socket.h> 44275970Scy#include <sys/wait.h> 45275970Scy#include <signal.h> 46275970Scy#include <unistd.h> 47275970Scy#include <netdb.h> 48275970Scy#endif 49275970Scy#include <fcntl.h> 50275970Scy#include <signal.h> 51275970Scy#include <stdlib.h> 52275970Scy#include <stdio.h> 53275970Scy#include <string.h> 54275970Scy#include <errno.h> 55275970Scy#include <assert.h> 56275970Scy#include <ctype.h> 57275970Scy 58275970Scy#include "event2/event.h" 59275970Scy#include "event2/event_struct.h" 60275970Scy#include "event2/event_compat.h" 61275970Scy#include "event2/tag.h" 62275970Scy#include "event2/buffer.h" 63275970Scy#include "event2/buffer_compat.h" 64275970Scy#include "event2/util.h" 65275970Scy#include "event-internal.h" 66275970Scy#include "evthread-internal.h" 67275970Scy#include "log-internal.h" 68275970Scy#include "time-internal.h" 69275970Scy 70275970Scy#include "regress.h" 71275970Scy 72275970Scy#ifndef _WIN32 73275970Scy#include "regress.gen.h" 74275970Scy#endif 75275970Scy 76275970Scyevutil_socket_t pair[2]; 77275970Scyint test_ok; 78275970Scyint called; 79275970Scystruct event_base *global_base; 80275970Scy 81275970Scystatic char wbuf[4096]; 82275970Scystatic char rbuf[4096]; 83275970Scystatic int woff; 84275970Scystatic int roff; 85275970Scystatic int usepersist; 86275970Scystatic struct timeval tset; 87275970Scystatic struct timeval tcalled; 88275970Scy 89275970Scy 90275970Scy#define TEST1 "this is a test" 91275970Scy 92275970Scy#ifndef SHUT_WR 93275970Scy#define SHUT_WR 1 94275970Scy#endif 95275970Scy 96275970Scy#ifdef _WIN32 97275970Scy#define write(fd,buf,len) send((fd),(buf),(int)(len),0) 98275970Scy#define read(fd,buf,len) recv((fd),(buf),(int)(len),0) 99275970Scy#endif 100275970Scy 101275970Scystruct basic_cb_args 102275970Scy{ 103275970Scy struct event_base *eb; 104275970Scy struct event *ev; 105275970Scy unsigned int callcount; 106275970Scy}; 107275970Scy 108275970Scystatic void 109275970Scysimple_read_cb(evutil_socket_t fd, short event, void *arg) 110275970Scy{ 111275970Scy char buf[256]; 112275970Scy int len; 113275970Scy 114275970Scy len = read(fd, buf, sizeof(buf)); 115275970Scy 116275970Scy if (len) { 117275970Scy if (!called) { 118275970Scy if (event_add(arg, NULL) == -1) 119275970Scy exit(1); 120275970Scy } 121275970Scy } else if (called == 1) 122275970Scy test_ok = 1; 123275970Scy 124275970Scy called++; 125275970Scy} 126275970Scy 127275970Scystatic void 128275970Scybasic_read_cb(evutil_socket_t fd, short event, void *data) 129275970Scy{ 130275970Scy char buf[256]; 131275970Scy int len; 132275970Scy struct basic_cb_args *arg = data; 133275970Scy 134275970Scy len = read(fd, buf, sizeof(buf)); 135275970Scy 136275970Scy if (len < 0) { 137275970Scy tt_fail_perror("read (callback)"); 138275970Scy } else { 139275970Scy switch (arg->callcount++) { 140275970Scy case 0: /* first call: expect to read data; cycle */ 141275970Scy if (len > 0) 142275970Scy return; 143275970Scy 144275970Scy tt_fail_msg("EOF before data read"); 145275970Scy break; 146275970Scy 147275970Scy case 1: /* second call: expect EOF; stop */ 148275970Scy if (len > 0) 149275970Scy tt_fail_msg("not all data read on first cycle"); 150275970Scy break; 151275970Scy 152275970Scy default: /* third call: should not happen */ 153275970Scy tt_fail_msg("too many cycles"); 154275970Scy } 155275970Scy } 156275970Scy 157275970Scy event_del(arg->ev); 158275970Scy event_base_loopexit(arg->eb, NULL); 159275970Scy} 160275970Scy 161275970Scystatic void 162275970Scydummy_read_cb(evutil_socket_t fd, short event, void *arg) 163275970Scy{ 164275970Scy} 165275970Scy 166275970Scystatic void 167275970Scysimple_write_cb(evutil_socket_t fd, short event, void *arg) 168275970Scy{ 169275970Scy int len; 170275970Scy 171275970Scy len = write(fd, TEST1, strlen(TEST1) + 1); 172275970Scy if (len == -1) 173275970Scy test_ok = 0; 174275970Scy else 175275970Scy test_ok = 1; 176275970Scy} 177275970Scy 178275970Scystatic void 179275970Scymultiple_write_cb(evutil_socket_t fd, short event, void *arg) 180275970Scy{ 181275970Scy struct event *ev = arg; 182275970Scy int len; 183275970Scy 184275970Scy len = 128; 185275970Scy if (woff + len >= (int)sizeof(wbuf)) 186275970Scy len = sizeof(wbuf) - woff; 187275970Scy 188275970Scy len = write(fd, wbuf + woff, len); 189275970Scy if (len == -1) { 190275970Scy fprintf(stderr, "%s: write\n", __func__); 191275970Scy if (usepersist) 192275970Scy event_del(ev); 193275970Scy return; 194275970Scy } 195275970Scy 196275970Scy woff += len; 197275970Scy 198275970Scy if (woff >= (int)sizeof(wbuf)) { 199275970Scy shutdown(fd, SHUT_WR); 200275970Scy if (usepersist) 201275970Scy event_del(ev); 202275970Scy return; 203275970Scy } 204275970Scy 205275970Scy if (!usepersist) { 206275970Scy if (event_add(ev, NULL) == -1) 207275970Scy exit(1); 208275970Scy } 209275970Scy} 210275970Scy 211275970Scystatic void 212275970Scymultiple_read_cb(evutil_socket_t fd, short event, void *arg) 213275970Scy{ 214275970Scy struct event *ev = arg; 215275970Scy int len; 216275970Scy 217275970Scy len = read(fd, rbuf + roff, sizeof(rbuf) - roff); 218275970Scy if (len == -1) 219275970Scy fprintf(stderr, "%s: read\n", __func__); 220275970Scy if (len <= 0) { 221275970Scy if (usepersist) 222275970Scy event_del(ev); 223275970Scy return; 224275970Scy } 225275970Scy 226275970Scy roff += len; 227275970Scy if (!usepersist) { 228275970Scy if (event_add(ev, NULL) == -1) 229275970Scy exit(1); 230275970Scy } 231275970Scy} 232275970Scy 233275970Scystatic void 234275970Scytimeout_cb(evutil_socket_t fd, short event, void *arg) 235275970Scy{ 236275970Scy evutil_gettimeofday(&tcalled, NULL); 237275970Scy} 238275970Scy 239275970Scystruct both { 240275970Scy struct event ev; 241275970Scy int nread; 242275970Scy}; 243275970Scy 244275970Scystatic void 245275970Scycombined_read_cb(evutil_socket_t fd, short event, void *arg) 246275970Scy{ 247275970Scy struct both *both = arg; 248275970Scy char buf[128]; 249275970Scy int len; 250275970Scy 251275970Scy len = read(fd, buf, sizeof(buf)); 252275970Scy if (len == -1) 253275970Scy fprintf(stderr, "%s: read\n", __func__); 254275970Scy if (len <= 0) 255275970Scy return; 256275970Scy 257275970Scy both->nread += len; 258275970Scy if (event_add(&both->ev, NULL) == -1) 259275970Scy exit(1); 260275970Scy} 261275970Scy 262275970Scystatic void 263275970Scycombined_write_cb(evutil_socket_t fd, short event, void *arg) 264275970Scy{ 265275970Scy struct both *both = arg; 266275970Scy char buf[128]; 267275970Scy int len; 268275970Scy 269275970Scy len = sizeof(buf); 270275970Scy if (len > both->nread) 271275970Scy len = both->nread; 272275970Scy 273275970Scy memset(buf, 'q', len); 274275970Scy 275275970Scy len = write(fd, buf, len); 276275970Scy if (len == -1) 277275970Scy fprintf(stderr, "%s: write\n", __func__); 278275970Scy if (len <= 0) { 279275970Scy shutdown(fd, SHUT_WR); 280275970Scy return; 281275970Scy } 282275970Scy 283275970Scy both->nread -= len; 284275970Scy if (event_add(&both->ev, NULL) == -1) 285275970Scy exit(1); 286275970Scy} 287275970Scy 288275970Scy/* These macros used to replicate the work of the legacy test wrapper code */ 289275970Scy#define setup_test(x) do { \ 290275970Scy if (!in_legacy_test_wrapper) { \ 291275970Scy TT_FAIL(("Legacy test %s not wrapped properly", x)); \ 292275970Scy return; \ 293275970Scy } \ 294275970Scy } while (0) 295275970Scy#define cleanup_test() setup_test("cleanup") 296275970Scy 297275970Scystatic void 298275970Scytest_simpleread(void) 299275970Scy{ 300275970Scy struct event ev; 301275970Scy 302275970Scy /* Very simple read test */ 303275970Scy setup_test("Simple read: "); 304275970Scy 305275970Scy if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 306275970Scy tt_fail_perror("write"); 307275970Scy } 308275970Scy 309275970Scy shutdown(pair[0], SHUT_WR); 310275970Scy 311275970Scy event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev); 312275970Scy if (event_add(&ev, NULL) == -1) 313275970Scy exit(1); 314275970Scy event_dispatch(); 315275970Scy 316275970Scy cleanup_test(); 317275970Scy} 318275970Scy 319275970Scystatic void 320275970Scytest_simplewrite(void) 321275970Scy{ 322275970Scy struct event ev; 323275970Scy 324275970Scy /* Very simple write test */ 325275970Scy setup_test("Simple write: "); 326275970Scy 327275970Scy event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev); 328275970Scy if (event_add(&ev, NULL) == -1) 329275970Scy exit(1); 330275970Scy event_dispatch(); 331275970Scy 332275970Scy cleanup_test(); 333275970Scy} 334275970Scy 335275970Scystatic void 336275970Scysimpleread_multiple_cb(evutil_socket_t fd, short event, void *arg) 337275970Scy{ 338275970Scy if (++called == 2) 339275970Scy test_ok = 1; 340275970Scy} 341275970Scy 342275970Scystatic void 343275970Scytest_simpleread_multiple(void) 344275970Scy{ 345275970Scy struct event one, two; 346275970Scy 347275970Scy /* Very simple read test */ 348275970Scy setup_test("Simple read to multiple evens: "); 349275970Scy 350275970Scy if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 351275970Scy tt_fail_perror("write"); 352275970Scy } 353275970Scy 354275970Scy shutdown(pair[0], SHUT_WR); 355275970Scy 356275970Scy event_set(&one, pair[1], EV_READ, simpleread_multiple_cb, NULL); 357275970Scy if (event_add(&one, NULL) == -1) 358275970Scy exit(1); 359275970Scy event_set(&two, pair[1], EV_READ, simpleread_multiple_cb, NULL); 360275970Scy if (event_add(&two, NULL) == -1) 361275970Scy exit(1); 362275970Scy event_dispatch(); 363275970Scy 364275970Scy cleanup_test(); 365275970Scy} 366275970Scy 367275970Scystatic int have_closed = 0; 368275970Scystatic int premature_event = 0; 369275970Scystatic void 370275970Scysimpleclose_close_fd_cb(evutil_socket_t s, short what, void *ptr) 371275970Scy{ 372275970Scy evutil_socket_t **fds = ptr; 373275970Scy TT_BLATHER(("Closing")); 374275970Scy evutil_closesocket(*fds[0]); 375275970Scy evutil_closesocket(*fds[1]); 376275970Scy *fds[0] = -1; 377275970Scy *fds[1] = -1; 378275970Scy have_closed = 1; 379275970Scy} 380275970Scy 381275970Scystatic void 382275970Scyrecord_event_cb(evutil_socket_t s, short what, void *ptr) 383275970Scy{ 384275970Scy short *whatp = ptr; 385275970Scy if (!have_closed) 386275970Scy premature_event = 1; 387275970Scy *whatp = what; 388275970Scy TT_BLATHER(("Recorded %d on socket %d", (int)what, (int)s)); 389275970Scy} 390275970Scy 391275970Scystatic void 392275970Scytest_simpleclose(void *ptr) 393275970Scy{ 394275970Scy /* Test that a close of FD is detected as a read and as a write. */ 395275970Scy struct event_base *base = event_base_new(); 396275970Scy evutil_socket_t pair1[2]={-1,-1}, pair2[2] = {-1, -1}; 397275970Scy evutil_socket_t *to_close[2]; 398275970Scy struct event *rev=NULL, *wev=NULL, *closeev=NULL; 399275970Scy struct timeval tv; 400275970Scy short got_read_on_close = 0, got_write_on_close = 0; 401275970Scy char buf[1024]; 402275970Scy memset(buf, 99, sizeof(buf)); 403275970Scy#ifdef _WIN32 404275970Scy#define LOCAL_SOCKETPAIR_AF AF_INET 405275970Scy#else 406275970Scy#define LOCAL_SOCKETPAIR_AF AF_UNIX 407275970Scy#endif 408275970Scy if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair1)<0) 409275970Scy TT_DIE(("socketpair: %s", strerror(errno))); 410275970Scy if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair2)<0) 411275970Scy TT_DIE(("socketpair: %s", strerror(errno))); 412275970Scy if (evutil_make_socket_nonblocking(pair1[1]) < 0) 413275970Scy TT_DIE(("make_socket_nonblocking")); 414275970Scy if (evutil_make_socket_nonblocking(pair2[1]) < 0) 415275970Scy TT_DIE(("make_socket_nonblocking")); 416275970Scy 417275970Scy /** Stuff pair2[1] full of data, until write fails */ 418275970Scy while (1) { 419275970Scy int r = write(pair2[1], buf, sizeof(buf)); 420275970Scy if (r<0) { 421275970Scy int err = evutil_socket_geterror(pair2[1]); 422275970Scy if (! EVUTIL_ERR_RW_RETRIABLE(err)) 423275970Scy TT_DIE(("write failed strangely: %s", 424275970Scy evutil_socket_error_to_string(err))); 425275970Scy break; 426275970Scy } 427275970Scy } 428275970Scy to_close[0] = &pair1[0]; 429275970Scy to_close[1] = &pair2[0]; 430275970Scy 431275970Scy closeev = event_new(base, -1, EV_TIMEOUT, simpleclose_close_fd_cb, 432275970Scy to_close); 433275970Scy rev = event_new(base, pair1[1], EV_READ, record_event_cb, 434275970Scy &got_read_on_close); 435275970Scy TT_BLATHER(("Waiting for read on %d", (int)pair1[1])); 436275970Scy wev = event_new(base, pair2[1], EV_WRITE, record_event_cb, 437275970Scy &got_write_on_close); 438275970Scy TT_BLATHER(("Waiting for write on %d", (int)pair2[1])); 439275970Scy tv.tv_sec = 0; 440275970Scy tv.tv_usec = 100*1000; /* Close pair1[0] after a little while, and make 441275970Scy * sure we get a read event. */ 442275970Scy event_add(closeev, &tv); 443275970Scy event_add(rev, NULL); 444275970Scy event_add(wev, NULL); 445275970Scy /* Don't let the test go on too long. */ 446275970Scy tv.tv_sec = 0; 447275970Scy tv.tv_usec = 200*1000; 448275970Scy event_base_loopexit(base, &tv); 449275970Scy event_base_loop(base, 0); 450275970Scy 451275970Scy tt_int_op(got_read_on_close, ==, EV_READ); 452275970Scy tt_int_op(got_write_on_close, ==, EV_WRITE); 453275970Scy tt_int_op(premature_event, ==, 0); 454275970Scy 455275970Scyend: 456275970Scy if (pair1[0] >= 0) 457275970Scy evutil_closesocket(pair1[0]); 458275970Scy if (pair1[1] >= 0) 459275970Scy evutil_closesocket(pair1[1]); 460275970Scy if (pair2[0] >= 0) 461275970Scy evutil_closesocket(pair2[0]); 462275970Scy if (pair2[1] >= 0) 463275970Scy evutil_closesocket(pair2[1]); 464275970Scy if (rev) 465275970Scy event_free(rev); 466275970Scy if (wev) 467275970Scy event_free(wev); 468275970Scy if (closeev) 469275970Scy event_free(closeev); 470275970Scy if (base) 471275970Scy event_base_free(base); 472275970Scy} 473275970Scy 474275970Scy 475275970Scystatic void 476275970Scytest_multiple(void) 477275970Scy{ 478275970Scy struct event ev, ev2; 479275970Scy int i; 480275970Scy 481275970Scy /* Multiple read and write test */ 482275970Scy setup_test("Multiple read/write: "); 483275970Scy memset(rbuf, 0, sizeof(rbuf)); 484275970Scy for (i = 0; i < (int)sizeof(wbuf); i++) 485275970Scy wbuf[i] = i; 486275970Scy 487275970Scy roff = woff = 0; 488275970Scy usepersist = 0; 489275970Scy 490275970Scy event_set(&ev, pair[0], EV_WRITE, multiple_write_cb, &ev); 491275970Scy if (event_add(&ev, NULL) == -1) 492275970Scy exit(1); 493275970Scy event_set(&ev2, pair[1], EV_READ, multiple_read_cb, &ev2); 494275970Scy if (event_add(&ev2, NULL) == -1) 495275970Scy exit(1); 496275970Scy event_dispatch(); 497275970Scy 498275970Scy if (roff == woff) 499275970Scy test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; 500275970Scy 501275970Scy cleanup_test(); 502275970Scy} 503275970Scy 504275970Scystatic void 505275970Scytest_persistent(void) 506275970Scy{ 507275970Scy struct event ev, ev2; 508275970Scy int i; 509275970Scy 510275970Scy /* Multiple read and write test with persist */ 511275970Scy setup_test("Persist read/write: "); 512275970Scy memset(rbuf, 0, sizeof(rbuf)); 513275970Scy for (i = 0; i < (int)sizeof(wbuf); i++) 514275970Scy wbuf[i] = i; 515275970Scy 516275970Scy roff = woff = 0; 517275970Scy usepersist = 1; 518275970Scy 519275970Scy event_set(&ev, pair[0], EV_WRITE|EV_PERSIST, multiple_write_cb, &ev); 520275970Scy if (event_add(&ev, NULL) == -1) 521275970Scy exit(1); 522275970Scy event_set(&ev2, pair[1], EV_READ|EV_PERSIST, multiple_read_cb, &ev2); 523275970Scy if (event_add(&ev2, NULL) == -1) 524275970Scy exit(1); 525275970Scy event_dispatch(); 526275970Scy 527275970Scy if (roff == woff) 528275970Scy test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; 529275970Scy 530275970Scy cleanup_test(); 531275970Scy} 532275970Scy 533275970Scystatic void 534275970Scytest_combined(void) 535275970Scy{ 536275970Scy struct both r1, r2, w1, w2; 537275970Scy 538275970Scy setup_test("Combined read/write: "); 539275970Scy memset(&r1, 0, sizeof(r1)); 540275970Scy memset(&r2, 0, sizeof(r2)); 541275970Scy memset(&w1, 0, sizeof(w1)); 542275970Scy memset(&w2, 0, sizeof(w2)); 543275970Scy 544275970Scy w1.nread = 4096; 545275970Scy w2.nread = 8192; 546275970Scy 547275970Scy event_set(&r1.ev, pair[0], EV_READ, combined_read_cb, &r1); 548275970Scy event_set(&w1.ev, pair[0], EV_WRITE, combined_write_cb, &w1); 549275970Scy event_set(&r2.ev, pair[1], EV_READ, combined_read_cb, &r2); 550275970Scy event_set(&w2.ev, pair[1], EV_WRITE, combined_write_cb, &w2); 551275970Scy tt_assert(event_add(&r1.ev, NULL) != -1); 552275970Scy tt_assert(!event_add(&w1.ev, NULL)); 553275970Scy tt_assert(!event_add(&r2.ev, NULL)); 554275970Scy tt_assert(!event_add(&w2.ev, NULL)); 555275970Scy event_dispatch(); 556275970Scy 557275970Scy if (r1.nread == 8192 && r2.nread == 4096) 558275970Scy test_ok = 1; 559275970Scy 560275970Scyend: 561275970Scy cleanup_test(); 562275970Scy} 563275970Scy 564275970Scystatic void 565275970Scytest_simpletimeout(void) 566275970Scy{ 567275970Scy struct timeval tv; 568275970Scy struct event ev; 569275970Scy 570275970Scy setup_test("Simple timeout: "); 571275970Scy 572275970Scy tv.tv_usec = 200*1000; 573275970Scy tv.tv_sec = 0; 574275970Scy evutil_timerclear(&tcalled); 575275970Scy evtimer_set(&ev, timeout_cb, NULL); 576275970Scy evtimer_add(&ev, &tv); 577275970Scy 578275970Scy evutil_gettimeofday(&tset, NULL); 579275970Scy event_dispatch(); 580275970Scy test_timeval_diff_eq(&tset, &tcalled, 200); 581275970Scy 582275970Scy test_ok = 1; 583275970Scyend: 584275970Scy cleanup_test(); 585275970Scy} 586275970Scy 587275970Scystatic void 588275970Scyperiodic_timeout_cb(evutil_socket_t fd, short event, void *arg) 589275970Scy{ 590275970Scy int *count = arg; 591275970Scy 592275970Scy (*count)++; 593275970Scy if (*count == 6) { 594275970Scy /* call loopexit only once - on slow machines(?), it is 595275970Scy * apparently possible for this to get called twice. */ 596275970Scy test_ok = 1; 597275970Scy event_base_loopexit(global_base, NULL); 598275970Scy } 599275970Scy} 600275970Scy 601275970Scystatic void 602275970Scytest_persistent_timeout(void) 603275970Scy{ 604275970Scy struct timeval tv; 605275970Scy struct event ev; 606275970Scy int count = 0; 607275970Scy 608275970Scy evutil_timerclear(&tv); 609275970Scy tv.tv_usec = 10000; 610275970Scy 611275970Scy event_assign(&ev, global_base, -1, EV_TIMEOUT|EV_PERSIST, 612275970Scy periodic_timeout_cb, &count); 613275970Scy event_add(&ev, &tv); 614275970Scy 615275970Scy event_dispatch(); 616275970Scy 617275970Scy event_del(&ev); 618275970Scy} 619275970Scy 620275970Scystatic void 621275970Scytest_persistent_timeout_jump(void *ptr) 622275970Scy{ 623275970Scy struct basic_test_data *data = ptr; 624275970Scy struct event ev; 625275970Scy int count = 0; 626275970Scy struct timeval msec100 = { 0, 100 * 1000 }; 627275970Scy struct timeval msec50 = { 0, 50 * 1000 }; 628275970Scy struct timeval msec300 = { 0, 300 * 1000 }; 629275970Scy 630275970Scy event_assign(&ev, data->base, -1, EV_PERSIST, periodic_timeout_cb, &count); 631275970Scy event_add(&ev, &msec100); 632275970Scy /* Wait for a bit */ 633275970Scy evutil_usleep_(&msec300); 634275970Scy event_base_loopexit(data->base, &msec50); 635275970Scy event_base_dispatch(data->base); 636275970Scy tt_int_op(count, ==, 1); 637275970Scy 638275970Scyend: 639275970Scy event_del(&ev); 640275970Scy} 641275970Scy 642275970Scystruct persist_active_timeout_called { 643275970Scy int n; 644275970Scy short events[16]; 645275970Scy struct timeval tvs[16]; 646275970Scy}; 647275970Scy 648275970Scystatic void 649275970Scyactivate_cb(evutil_socket_t fd, short event, void *arg) 650275970Scy{ 651275970Scy struct event *ev = arg; 652275970Scy event_active(ev, EV_READ, 1); 653275970Scy} 654275970Scy 655275970Scystatic void 656275970Scypersist_active_timeout_cb(evutil_socket_t fd, short event, void *arg) 657275970Scy{ 658275970Scy struct persist_active_timeout_called *c = arg; 659275970Scy if (c->n < 15) { 660275970Scy c->events[c->n] = event; 661275970Scy evutil_gettimeofday(&c->tvs[c->n], NULL); 662275970Scy ++c->n; 663275970Scy } 664275970Scy} 665275970Scy 666275970Scystatic void 667275970Scytest_persistent_active_timeout(void *ptr) 668275970Scy{ 669275970Scy struct timeval tv, tv2, tv_exit, start; 670275970Scy struct event ev; 671275970Scy struct persist_active_timeout_called res; 672275970Scy 673275970Scy struct basic_test_data *data = ptr; 674275970Scy struct event_base *base = data->base; 675275970Scy 676275970Scy memset(&res, 0, sizeof(res)); 677275970Scy 678275970Scy tv.tv_sec = 0; 679275970Scy tv.tv_usec = 200 * 1000; 680275970Scy event_assign(&ev, base, -1, EV_TIMEOUT|EV_PERSIST, 681275970Scy persist_active_timeout_cb, &res); 682275970Scy event_add(&ev, &tv); 683275970Scy 684275970Scy tv2.tv_sec = 0; 685275970Scy tv2.tv_usec = 100 * 1000; 686275970Scy event_base_once(base, -1, EV_TIMEOUT, activate_cb, &ev, &tv2); 687275970Scy 688275970Scy tv_exit.tv_sec = 0; 689275970Scy tv_exit.tv_usec = 600 * 1000; 690275970Scy event_base_loopexit(base, &tv_exit); 691275970Scy 692275970Scy event_base_assert_ok_(base); 693275970Scy evutil_gettimeofday(&start, NULL); 694275970Scy 695275970Scy event_base_dispatch(base); 696275970Scy event_base_assert_ok_(base); 697275970Scy 698275970Scy tt_int_op(res.n, ==, 3); 699275970Scy tt_int_op(res.events[0], ==, EV_READ); 700275970Scy tt_int_op(res.events[1], ==, EV_TIMEOUT); 701275970Scy tt_int_op(res.events[2], ==, EV_TIMEOUT); 702275970Scy test_timeval_diff_eq(&start, &res.tvs[0], 100); 703275970Scy test_timeval_diff_eq(&start, &res.tvs[1], 300); 704275970Scy test_timeval_diff_eq(&start, &res.tvs[2], 500); 705275970Scyend: 706275970Scy event_del(&ev); 707275970Scy} 708275970Scy 709275970Scystruct common_timeout_info { 710275970Scy struct event ev; 711275970Scy struct timeval called_at; 712275970Scy int which; 713275970Scy int count; 714275970Scy}; 715275970Scy 716275970Scystatic void 717275970Scycommon_timeout_cb(evutil_socket_t fd, short event, void *arg) 718275970Scy{ 719275970Scy struct common_timeout_info *ti = arg; 720275970Scy ++ti->count; 721275970Scy evutil_gettimeofday(&ti->called_at, NULL); 722275970Scy if (ti->count >= 4) 723275970Scy event_del(&ti->ev); 724275970Scy} 725275970Scy 726275970Scystatic void 727275970Scytest_common_timeout(void *ptr) 728275970Scy{ 729275970Scy struct basic_test_data *data = ptr; 730275970Scy 731275970Scy struct event_base *base = data->base; 732275970Scy int i; 733275970Scy struct common_timeout_info info[100]; 734275970Scy 735275970Scy struct timeval start; 736275970Scy struct timeval tmp_100_ms = { 0, 100*1000 }; 737275970Scy struct timeval tmp_200_ms = { 0, 200*1000 }; 738275970Scy struct timeval tmp_5_sec = { 5, 0 }; 739275970Scy struct timeval tmp_5M_usec = { 0, 5*1000*1000 }; 740275970Scy 741275970Scy const struct timeval *ms_100, *ms_200, *sec_5; 742275970Scy 743275970Scy ms_100 = event_base_init_common_timeout(base, &tmp_100_ms); 744275970Scy ms_200 = event_base_init_common_timeout(base, &tmp_200_ms); 745275970Scy sec_5 = event_base_init_common_timeout(base, &tmp_5_sec); 746275970Scy tt_assert(ms_100); 747275970Scy tt_assert(ms_200); 748275970Scy tt_assert(sec_5); 749275970Scy tt_ptr_op(event_base_init_common_timeout(base, &tmp_200_ms), 750275970Scy ==, ms_200); 751275970Scy tt_ptr_op(event_base_init_common_timeout(base, ms_200), ==, ms_200); 752275970Scy tt_ptr_op(event_base_init_common_timeout(base, &tmp_5M_usec), ==, sec_5); 753275970Scy tt_int_op(ms_100->tv_sec, ==, 0); 754275970Scy tt_int_op(ms_200->tv_sec, ==, 0); 755275970Scy tt_int_op(sec_5->tv_sec, ==, 5); 756275970Scy tt_int_op(ms_100->tv_usec, ==, 100000|0x50000000); 757275970Scy tt_int_op(ms_200->tv_usec, ==, 200000|0x50100000); 758275970Scy tt_int_op(sec_5->tv_usec, ==, 0|0x50200000); 759275970Scy 760275970Scy memset(info, 0, sizeof(info)); 761275970Scy 762275970Scy for (i=0; i<100; ++i) { 763275970Scy info[i].which = i; 764275970Scy event_assign(&info[i].ev, base, -1, EV_TIMEOUT|EV_PERSIST, 765275970Scy common_timeout_cb, &info[i]); 766275970Scy if (i % 2) { 767275970Scy if ((i%20)==1) { 768275970Scy /* Glass-box test: Make sure we survive the 769275970Scy * transition to non-common timeouts. It's 770275970Scy * a little tricky. */ 771275970Scy event_add(&info[i].ev, ms_200); 772275970Scy event_add(&info[i].ev, &tmp_100_ms); 773275970Scy } else if ((i%20)==3) { 774275970Scy /* Check heap-to-common too. */ 775275970Scy event_add(&info[i].ev, &tmp_200_ms); 776275970Scy event_add(&info[i].ev, ms_100); 777275970Scy } else if ((i%20)==5) { 778275970Scy /* Also check common-to-common. */ 779275970Scy event_add(&info[i].ev, ms_200); 780275970Scy event_add(&info[i].ev, ms_100); 781275970Scy } else { 782275970Scy event_add(&info[i].ev, ms_100); 783275970Scy } 784275970Scy } else { 785275970Scy event_add(&info[i].ev, ms_200); 786275970Scy } 787275970Scy } 788275970Scy 789275970Scy event_base_assert_ok_(base); 790275970Scy evutil_gettimeofday(&start, NULL); 791275970Scy event_base_dispatch(base); 792275970Scy 793275970Scy event_base_assert_ok_(base); 794275970Scy 795275970Scy for (i=0; i<10; ++i) { 796275970Scy tt_int_op(info[i].count, ==, 4); 797275970Scy if (i % 2) { 798275970Scy test_timeval_diff_eq(&start, &info[i].called_at, 400); 799275970Scy } else { 800275970Scy test_timeval_diff_eq(&start, &info[i].called_at, 800); 801275970Scy } 802275970Scy } 803275970Scy 804275970Scy /* Make sure we can free the base with some events in. */ 805275970Scy for (i=0; i<100; ++i) { 806275970Scy if (i % 2) { 807275970Scy event_add(&info[i].ev, ms_100); 808275970Scy } else { 809275970Scy event_add(&info[i].ev, ms_200); 810275970Scy } 811275970Scy } 812275970Scy 813275970Scyend: 814275970Scy event_base_free(data->base); /* need to do this here before info is 815275970Scy * out-of-scope */ 816275970Scy data->base = NULL; 817275970Scy} 818275970Scy 819275970Scy#ifndef _WIN32 820275970Scystatic void signal_cb(evutil_socket_t fd, short event, void *arg); 821275970Scy 822275970Scy#define current_base event_global_current_base_ 823275970Scyextern struct event_base *current_base; 824275970Scy 825275970Scystatic void 826275970Scychild_signal_cb(evutil_socket_t fd, short event, void *arg) 827275970Scy{ 828275970Scy struct timeval tv; 829275970Scy int *pint = arg; 830275970Scy 831275970Scy *pint = 1; 832275970Scy 833275970Scy tv.tv_usec = 500000; 834275970Scy tv.tv_sec = 0; 835275970Scy event_loopexit(&tv); 836275970Scy} 837275970Scy 838275970Scystatic void 839275970Scytest_fork(void) 840275970Scy{ 841275970Scy int status, got_sigchld = 0; 842275970Scy struct event ev, sig_ev; 843275970Scy pid_t pid; 844275970Scy 845275970Scy setup_test("After fork: "); 846275970Scy 847275970Scy tt_assert(current_base); 848275970Scy evthread_make_base_notifiable(current_base); 849275970Scy 850275970Scy if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 851275970Scy tt_fail_perror("write"); 852275970Scy } 853275970Scy 854275970Scy event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev); 855275970Scy if (event_add(&ev, NULL) == -1) 856275970Scy exit(1); 857275970Scy 858275970Scy evsignal_set(&sig_ev, SIGCHLD, child_signal_cb, &got_sigchld); 859275970Scy evsignal_add(&sig_ev, NULL); 860275970Scy 861275970Scy event_base_assert_ok_(current_base); 862275970Scy TT_BLATHER(("Before fork")); 863275970Scy if ((pid = regress_fork()) == 0) { 864275970Scy /* in the child */ 865275970Scy TT_BLATHER(("In child, before reinit")); 866275970Scy event_base_assert_ok_(current_base); 867275970Scy if (event_reinit(current_base) == -1) { 868275970Scy fprintf(stdout, "FAILED (reinit)\n"); 869275970Scy exit(1); 870275970Scy } 871275970Scy TT_BLATHER(("After reinit")); 872275970Scy event_base_assert_ok_(current_base); 873275970Scy TT_BLATHER(("After assert-ok")); 874275970Scy 875275970Scy evsignal_del(&sig_ev); 876275970Scy 877275970Scy called = 0; 878275970Scy 879275970Scy event_dispatch(); 880275970Scy 881275970Scy event_base_free(current_base); 882275970Scy 883275970Scy /* we do not send an EOF; simple_read_cb requires an EOF 884275970Scy * to set test_ok. we just verify that the callback was 885275970Scy * called. */ 886275970Scy exit(test_ok != 0 || called != 2 ? -2 : 76); 887275970Scy } 888275970Scy 889275970Scy /* wait for the child to read the data */ 890275970Scy { 891275970Scy const struct timeval tv = { 0, 100000 }; 892275970Scy evutil_usleep_(&tv); 893275970Scy } 894275970Scy 895275970Scy if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 896275970Scy tt_fail_perror("write"); 897275970Scy } 898275970Scy 899275970Scy TT_BLATHER(("Before waitpid")); 900275970Scy if (waitpid(pid, &status, 0) == -1) { 901275970Scy fprintf(stdout, "FAILED (fork)\n"); 902275970Scy exit(1); 903275970Scy } 904275970Scy TT_BLATHER(("After waitpid")); 905275970Scy 906275970Scy if (WEXITSTATUS(status) != 76) { 907275970Scy fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status)); 908275970Scy exit(1); 909275970Scy } 910275970Scy 911275970Scy /* test that the current event loop still works */ 912275970Scy if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 913275970Scy fprintf(stderr, "%s: write\n", __func__); 914275970Scy } 915275970Scy 916275970Scy shutdown(pair[0], SHUT_WR); 917275970Scy 918275970Scy event_dispatch(); 919275970Scy 920275970Scy if (!got_sigchld) { 921275970Scy fprintf(stdout, "FAILED (sigchld)\n"); 922275970Scy exit(1); 923275970Scy } 924275970Scy 925275970Scy evsignal_del(&sig_ev); 926275970Scy 927275970Scy end: 928275970Scy cleanup_test(); 929275970Scy} 930275970Scy 931275970Scystatic void 932275970Scysignal_cb_sa(int sig) 933275970Scy{ 934275970Scy test_ok = 2; 935275970Scy} 936275970Scy 937275970Scystatic void 938275970Scysignal_cb(evutil_socket_t fd, short event, void *arg) 939275970Scy{ 940275970Scy struct event *ev = arg; 941275970Scy 942275970Scy evsignal_del(ev); 943275970Scy test_ok = 1; 944275970Scy} 945275970Scy 946275970Scystatic void 947275970Scytest_simplesignal(void) 948275970Scy{ 949275970Scy struct event ev; 950275970Scy struct itimerval itv; 951275970Scy 952275970Scy setup_test("Simple signal: "); 953275970Scy evsignal_set(&ev, SIGALRM, signal_cb, &ev); 954275970Scy evsignal_add(&ev, NULL); 955275970Scy /* find bugs in which operations are re-ordered */ 956275970Scy evsignal_del(&ev); 957275970Scy evsignal_add(&ev, NULL); 958275970Scy 959275970Scy memset(&itv, 0, sizeof(itv)); 960275970Scy itv.it_value.tv_sec = 0; 961275970Scy itv.it_value.tv_usec = 100000; 962275970Scy if (setitimer(ITIMER_REAL, &itv, NULL) == -1) 963275970Scy goto skip_simplesignal; 964275970Scy 965275970Scy event_dispatch(); 966275970Scy skip_simplesignal: 967275970Scy if (evsignal_del(&ev) == -1) 968275970Scy test_ok = 0; 969275970Scy 970275970Scy cleanup_test(); 971275970Scy} 972275970Scy 973275970Scystatic void 974275970Scytest_multiplesignal(void) 975275970Scy{ 976275970Scy struct event ev_one, ev_two; 977275970Scy struct itimerval itv; 978275970Scy 979275970Scy setup_test("Multiple signal: "); 980275970Scy 981275970Scy evsignal_set(&ev_one, SIGALRM, signal_cb, &ev_one); 982275970Scy evsignal_add(&ev_one, NULL); 983275970Scy 984275970Scy evsignal_set(&ev_two, SIGALRM, signal_cb, &ev_two); 985275970Scy evsignal_add(&ev_two, NULL); 986275970Scy 987275970Scy memset(&itv, 0, sizeof(itv)); 988275970Scy itv.it_value.tv_sec = 0; 989275970Scy itv.it_value.tv_usec = 100000; 990275970Scy if (setitimer(ITIMER_REAL, &itv, NULL) == -1) 991275970Scy goto skip_simplesignal; 992275970Scy 993275970Scy event_dispatch(); 994275970Scy 995275970Scy skip_simplesignal: 996275970Scy if (evsignal_del(&ev_one) == -1) 997275970Scy test_ok = 0; 998275970Scy if (evsignal_del(&ev_two) == -1) 999275970Scy test_ok = 0; 1000275970Scy 1001275970Scy cleanup_test(); 1002275970Scy} 1003275970Scy 1004275970Scystatic void 1005275970Scytest_immediatesignal(void) 1006275970Scy{ 1007275970Scy struct event ev; 1008275970Scy 1009275970Scy test_ok = 0; 1010275970Scy evsignal_set(&ev, SIGUSR1, signal_cb, &ev); 1011275970Scy evsignal_add(&ev, NULL); 1012275970Scy raise(SIGUSR1); 1013275970Scy event_loop(EVLOOP_NONBLOCK); 1014275970Scy evsignal_del(&ev); 1015275970Scy cleanup_test(); 1016275970Scy} 1017275970Scy 1018275970Scystatic void 1019275970Scytest_signal_dealloc(void) 1020275970Scy{ 1021275970Scy /* make sure that evsignal_event is event_del'ed and pipe closed */ 1022275970Scy struct event ev; 1023275970Scy struct event_base *base = event_init(); 1024275970Scy evsignal_set(&ev, SIGUSR1, signal_cb, &ev); 1025275970Scy evsignal_add(&ev, NULL); 1026275970Scy evsignal_del(&ev); 1027275970Scy event_base_free(base); 1028275970Scy /* If we got here without asserting, we're fine. */ 1029275970Scy test_ok = 1; 1030275970Scy cleanup_test(); 1031275970Scy} 1032275970Scy 1033275970Scystatic void 1034275970Scytest_signal_pipeloss(void) 1035275970Scy{ 1036275970Scy /* make sure that the base1 pipe is closed correctly. */ 1037275970Scy struct event_base *base1, *base2; 1038275970Scy int pipe1; 1039275970Scy test_ok = 0; 1040275970Scy base1 = event_init(); 1041275970Scy pipe1 = base1->sig.ev_signal_pair[0]; 1042275970Scy base2 = event_init(); 1043275970Scy event_base_free(base2); 1044275970Scy event_base_free(base1); 1045275970Scy if (close(pipe1) != -1 || errno!=EBADF) { 1046275970Scy /* fd must be closed, so second close gives -1, EBADF */ 1047275970Scy printf("signal pipe not closed. "); 1048275970Scy test_ok = 0; 1049275970Scy } else { 1050275970Scy test_ok = 1; 1051275970Scy } 1052275970Scy cleanup_test(); 1053275970Scy} 1054275970Scy 1055275970Scy/* 1056275970Scy * make two bases to catch signals, use both of them. this only works 1057275970Scy * for event mechanisms that use our signal pipe trick. kqueue handles 1058275970Scy * signals internally, and all interested kqueues get all the signals. 1059275970Scy */ 1060275970Scystatic void 1061275970Scytest_signal_switchbase(void) 1062275970Scy{ 1063275970Scy struct event ev1, ev2; 1064275970Scy struct event_base *base1, *base2; 1065275970Scy int is_kqueue; 1066275970Scy test_ok = 0; 1067275970Scy base1 = event_init(); 1068275970Scy base2 = event_init(); 1069275970Scy is_kqueue = !strcmp(event_get_method(),"kqueue"); 1070275970Scy evsignal_set(&ev1, SIGUSR1, signal_cb, &ev1); 1071275970Scy evsignal_set(&ev2, SIGUSR1, signal_cb, &ev2); 1072275970Scy if (event_base_set(base1, &ev1) || 1073275970Scy event_base_set(base2, &ev2) || 1074275970Scy event_add(&ev1, NULL) || 1075275970Scy event_add(&ev2, NULL)) { 1076275970Scy fprintf(stderr, "%s: cannot set base, add\n", __func__); 1077275970Scy exit(1); 1078275970Scy } 1079275970Scy 1080275970Scy tt_ptr_op(event_get_base(&ev1), ==, base1); 1081275970Scy tt_ptr_op(event_get_base(&ev2), ==, base2); 1082275970Scy 1083275970Scy test_ok = 0; 1084275970Scy /* can handle signal before loop is called */ 1085275970Scy raise(SIGUSR1); 1086275970Scy event_base_loop(base2, EVLOOP_NONBLOCK); 1087275970Scy if (is_kqueue) { 1088275970Scy if (!test_ok) 1089275970Scy goto end; 1090275970Scy test_ok = 0; 1091275970Scy } 1092275970Scy event_base_loop(base1, EVLOOP_NONBLOCK); 1093275970Scy if (test_ok && !is_kqueue) { 1094275970Scy test_ok = 0; 1095275970Scy 1096275970Scy /* set base1 to handle signals */ 1097275970Scy event_base_loop(base1, EVLOOP_NONBLOCK); 1098275970Scy raise(SIGUSR1); 1099275970Scy event_base_loop(base1, EVLOOP_NONBLOCK); 1100275970Scy event_base_loop(base2, EVLOOP_NONBLOCK); 1101275970Scy } 1102275970Scyend: 1103275970Scy event_base_free(base1); 1104275970Scy event_base_free(base2); 1105275970Scy cleanup_test(); 1106275970Scy} 1107275970Scy 1108275970Scy/* 1109275970Scy * assert that a signal event removed from the event queue really is 1110275970Scy * removed - with no possibility of it's parent handler being fired. 1111275970Scy */ 1112275970Scystatic void 1113275970Scytest_signal_assert(void) 1114275970Scy{ 1115275970Scy struct event ev; 1116275970Scy struct event_base *base = event_init(); 1117275970Scy test_ok = 0; 1118275970Scy /* use SIGCONT so we don't kill ourselves when we signal to nowhere */ 1119275970Scy evsignal_set(&ev, SIGCONT, signal_cb, &ev); 1120275970Scy evsignal_add(&ev, NULL); 1121275970Scy /* 1122275970Scy * if evsignal_del() fails to reset the handler, it's current handler 1123275970Scy * will still point to evsig_handler(). 1124275970Scy */ 1125275970Scy evsignal_del(&ev); 1126275970Scy 1127275970Scy raise(SIGCONT); 1128275970Scy#if 0 1129275970Scy /* only way to verify we were in evsig_handler() */ 1130275970Scy /* XXXX Now there's no longer a good way. */ 1131275970Scy if (base->sig.evsig_caught) 1132275970Scy test_ok = 0; 1133275970Scy else 1134275970Scy test_ok = 1; 1135275970Scy#else 1136275970Scy test_ok = 1; 1137275970Scy#endif 1138275970Scy 1139275970Scy event_base_free(base); 1140275970Scy cleanup_test(); 1141275970Scy return; 1142275970Scy} 1143275970Scy 1144275970Scy/* 1145275970Scy * assert that we restore our previous signal handler properly. 1146275970Scy */ 1147275970Scystatic void 1148275970Scytest_signal_restore(void) 1149275970Scy{ 1150275970Scy struct event ev; 1151275970Scy struct event_base *base = event_init(); 1152275970Scy#ifdef EVENT__HAVE_SIGACTION 1153275970Scy struct sigaction sa; 1154275970Scy#endif 1155275970Scy 1156275970Scy test_ok = 0; 1157275970Scy#ifdef EVENT__HAVE_SIGACTION 1158275970Scy sa.sa_handler = signal_cb_sa; 1159275970Scy sa.sa_flags = 0x0; 1160275970Scy sigemptyset(&sa.sa_mask); 1161275970Scy if (sigaction(SIGUSR1, &sa, NULL) == -1) 1162275970Scy goto out; 1163275970Scy#else 1164275970Scy if (signal(SIGUSR1, signal_cb_sa) == SIG_ERR) 1165275970Scy goto out; 1166275970Scy#endif 1167275970Scy evsignal_set(&ev, SIGUSR1, signal_cb, &ev); 1168275970Scy evsignal_add(&ev, NULL); 1169275970Scy evsignal_del(&ev); 1170275970Scy 1171275970Scy raise(SIGUSR1); 1172275970Scy /* 1 == signal_cb, 2 == signal_cb_sa, we want our previous handler */ 1173275970Scy if (test_ok != 2) 1174275970Scy test_ok = 0; 1175275970Scyout: 1176275970Scy event_base_free(base); 1177275970Scy cleanup_test(); 1178275970Scy return; 1179275970Scy} 1180275970Scy 1181275970Scystatic void 1182275970Scysignal_cb_swp(int sig, short event, void *arg) 1183275970Scy{ 1184275970Scy called++; 1185275970Scy if (called < 5) 1186275970Scy raise(sig); 1187275970Scy else 1188275970Scy event_loopexit(NULL); 1189275970Scy} 1190275970Scystatic void 1191275970Scytimeout_cb_swp(evutil_socket_t fd, short event, void *arg) 1192275970Scy{ 1193275970Scy if (called == -1) { 1194275970Scy struct timeval tv = {5, 0}; 1195275970Scy 1196275970Scy called = 0; 1197275970Scy evtimer_add((struct event *)arg, &tv); 1198275970Scy raise(SIGUSR1); 1199275970Scy return; 1200275970Scy } 1201275970Scy test_ok = 0; 1202275970Scy event_loopexit(NULL); 1203275970Scy} 1204275970Scy 1205275970Scystatic void 1206275970Scytest_signal_while_processing(void) 1207275970Scy{ 1208275970Scy struct event_base *base = event_init(); 1209275970Scy struct event ev, ev_timer; 1210275970Scy struct timeval tv = {0, 0}; 1211275970Scy 1212275970Scy setup_test("Receiving a signal while processing other signal: "); 1213275970Scy 1214275970Scy called = -1; 1215275970Scy test_ok = 1; 1216275970Scy signal_set(&ev, SIGUSR1, signal_cb_swp, NULL); 1217275970Scy signal_add(&ev, NULL); 1218275970Scy evtimer_set(&ev_timer, timeout_cb_swp, &ev_timer); 1219275970Scy evtimer_add(&ev_timer, &tv); 1220275970Scy event_dispatch(); 1221275970Scy 1222275970Scy event_base_free(base); 1223275970Scy cleanup_test(); 1224275970Scy return; 1225275970Scy} 1226275970Scy#endif 1227275970Scy 1228275970Scystatic void 1229275970Scytest_free_active_base(void *ptr) 1230275970Scy{ 1231275970Scy struct basic_test_data *data = ptr; 1232275970Scy struct event_base *base1; 1233275970Scy struct event ev1; 1234275970Scy 1235275970Scy base1 = event_init(); 1236275970Scy if (base1) { 1237275970Scy event_assign(&ev1, base1, data->pair[1], EV_READ, 1238275970Scy dummy_read_cb, NULL); 1239275970Scy event_add(&ev1, NULL); 1240275970Scy event_base_free(base1); /* should not crash */ 1241275970Scy } else { 1242275970Scy tt_fail_msg("failed to create event_base for test"); 1243275970Scy } 1244275970Scy 1245275970Scy base1 = event_init(); 1246275970Scy tt_assert(base1); 1247275970Scy event_assign(&ev1, base1, 0, 0, dummy_read_cb, NULL); 1248275970Scy event_active(&ev1, EV_READ, 1); 1249275970Scy event_base_free(base1); 1250275970Scyend: 1251275970Scy ; 1252275970Scy} 1253275970Scy 1254275970Scystatic void 1255275970Scytest_manipulate_active_events(void *ptr) 1256275970Scy{ 1257275970Scy struct basic_test_data *data = ptr; 1258275970Scy struct event_base *base = data->base; 1259275970Scy struct event ev1; 1260275970Scy 1261275970Scy event_assign(&ev1, base, -1, EV_TIMEOUT, dummy_read_cb, NULL); 1262275970Scy 1263275970Scy /* Make sure an active event is pending. */ 1264275970Scy event_active(&ev1, EV_READ, 1); 1265275970Scy tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL), 1266275970Scy ==, EV_READ); 1267275970Scy 1268275970Scy /* Make sure that activating an event twice works. */ 1269275970Scy event_active(&ev1, EV_WRITE, 1); 1270275970Scy tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL), 1271275970Scy ==, EV_READ|EV_WRITE); 1272275970Scy 1273275970Scyend: 1274275970Scy event_del(&ev1); 1275275970Scy} 1276275970Scy 1277275970Scystatic void 1278275970Scyevent_selfarg_cb(evutil_socket_t fd, short event, void *arg) 1279275970Scy{ 1280275970Scy struct event *ev = arg; 1281275970Scy struct event_base *base = event_get_base(ev); 1282275970Scy event_base_assert_ok_(base); 1283275970Scy event_base_loopexit(base, NULL); 1284275970Scy tt_want(ev == event_base_get_running_event(base)); 1285275970Scy} 1286275970Scy 1287275970Scystatic void 1288275970Scytest_event_new_selfarg(void *ptr) 1289275970Scy{ 1290275970Scy struct basic_test_data *data = ptr; 1291275970Scy struct event_base *base = data->base; 1292275970Scy struct event *ev = event_new(base, -1, EV_READ, event_selfarg_cb, 1293275970Scy event_self_cbarg()); 1294275970Scy 1295275970Scy event_active(ev, EV_READ, 1); 1296275970Scy event_base_dispatch(base); 1297275970Scy 1298275970Scy event_free(ev); 1299275970Scy} 1300275970Scy 1301275970Scystatic void 1302275970Scytest_event_assign_selfarg(void *ptr) 1303275970Scy{ 1304275970Scy struct basic_test_data *data = ptr; 1305275970Scy struct event_base *base = data->base; 1306275970Scy struct event ev; 1307275970Scy 1308275970Scy event_assign(&ev, base, -1, EV_READ, event_selfarg_cb, 1309275970Scy event_self_cbarg()); 1310275970Scy event_active(&ev, EV_READ, 1); 1311275970Scy event_base_dispatch(base); 1312275970Scy} 1313275970Scy 1314275970Scystatic void 1315275970Scytest_event_base_get_num_events(void *ptr) 1316275970Scy{ 1317275970Scy struct basic_test_data *data = ptr; 1318275970Scy struct event_base *base = data->base; 1319275970Scy struct event ev; 1320275970Scy int event_count_active; 1321275970Scy int event_count_virtual; 1322275970Scy int event_count_added; 1323275970Scy int event_count_active_virtual; 1324275970Scy int event_count_active_added; 1325275970Scy int event_count_virtual_added; 1326275970Scy int event_count_active_added_virtual; 1327275970Scy 1328275970Scy struct timeval qsec = {0, 100000}; 1329275970Scy 1330275970Scy event_assign(&ev, base, -1, EV_READ, event_selfarg_cb, 1331275970Scy event_self_cbarg()); 1332275970Scy 1333275970Scy event_add(&ev, &qsec); 1334275970Scy event_count_active = event_base_get_num_events(base, 1335275970Scy EVENT_BASE_COUNT_ACTIVE); 1336275970Scy event_count_virtual = event_base_get_num_events(base, 1337275970Scy EVENT_BASE_COUNT_VIRTUAL); 1338275970Scy event_count_added = event_base_get_num_events(base, 1339275970Scy EVENT_BASE_COUNT_ADDED); 1340275970Scy event_count_active_virtual = event_base_get_num_events(base, 1341275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 1342275970Scy event_count_active_added = event_base_get_num_events(base, 1343275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 1344275970Scy event_count_virtual_added = event_base_get_num_events(base, 1345275970Scy EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 1346275970Scy event_count_active_added_virtual = event_base_get_num_events(base, 1347275970Scy EVENT_BASE_COUNT_ACTIVE| 1348275970Scy EVENT_BASE_COUNT_ADDED| 1349275970Scy EVENT_BASE_COUNT_VIRTUAL); 1350275970Scy tt_int_op(event_count_active, ==, 0); 1351275970Scy tt_int_op(event_count_virtual, ==, 0); 1352275970Scy /* libevent itself adds a timeout event, so the event_count is 2 here */ 1353275970Scy tt_int_op(event_count_added, ==, 2); 1354275970Scy tt_int_op(event_count_active_virtual, ==, 0); 1355275970Scy tt_int_op(event_count_active_added, ==, 2); 1356275970Scy tt_int_op(event_count_virtual_added, ==, 2); 1357275970Scy tt_int_op(event_count_active_added_virtual, ==, 2); 1358275970Scy 1359275970Scy event_active(&ev, EV_READ, 1); 1360275970Scy event_count_active = event_base_get_num_events(base, 1361275970Scy EVENT_BASE_COUNT_ACTIVE); 1362275970Scy event_count_virtual = event_base_get_num_events(base, 1363275970Scy EVENT_BASE_COUNT_VIRTUAL); 1364275970Scy event_count_added = event_base_get_num_events(base, 1365275970Scy EVENT_BASE_COUNT_ADDED); 1366275970Scy event_count_active_virtual = event_base_get_num_events(base, 1367275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 1368275970Scy event_count_active_added = event_base_get_num_events(base, 1369275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 1370275970Scy event_count_virtual_added = event_base_get_num_events(base, 1371275970Scy EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 1372275970Scy event_count_active_added_virtual = event_base_get_num_events(base, 1373275970Scy EVENT_BASE_COUNT_ACTIVE| 1374275970Scy EVENT_BASE_COUNT_ADDED| 1375275970Scy EVENT_BASE_COUNT_VIRTUAL); 1376275970Scy tt_int_op(event_count_active, ==, 1); 1377275970Scy tt_int_op(event_count_virtual, ==, 0); 1378275970Scy tt_int_op(event_count_added, ==, 3); 1379275970Scy tt_int_op(event_count_active_virtual, ==, 1); 1380275970Scy tt_int_op(event_count_active_added, ==, 4); 1381275970Scy tt_int_op(event_count_virtual_added, ==, 3); 1382275970Scy tt_int_op(event_count_active_added_virtual, ==, 4); 1383275970Scy 1384275970Scy event_base_loop(base, 0); 1385275970Scy event_count_active = event_base_get_num_events(base, 1386275970Scy EVENT_BASE_COUNT_ACTIVE); 1387275970Scy event_count_virtual = event_base_get_num_events(base, 1388275970Scy EVENT_BASE_COUNT_VIRTUAL); 1389275970Scy event_count_added = event_base_get_num_events(base, 1390275970Scy EVENT_BASE_COUNT_ADDED); 1391275970Scy event_count_active_virtual = event_base_get_num_events(base, 1392275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 1393275970Scy event_count_active_added = event_base_get_num_events(base, 1394275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 1395275970Scy event_count_virtual_added = event_base_get_num_events(base, 1396275970Scy EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 1397275970Scy event_count_active_added_virtual = event_base_get_num_events(base, 1398275970Scy EVENT_BASE_COUNT_ACTIVE| 1399275970Scy EVENT_BASE_COUNT_ADDED| 1400275970Scy EVENT_BASE_COUNT_VIRTUAL); 1401275970Scy tt_int_op(event_count_active, ==, 0); 1402275970Scy tt_int_op(event_count_virtual, ==, 0); 1403275970Scy tt_int_op(event_count_added, ==, 0); 1404275970Scy tt_int_op(event_count_active_virtual, ==, 0); 1405275970Scy tt_int_op(event_count_active_added, ==, 0); 1406275970Scy tt_int_op(event_count_virtual_added, ==, 0); 1407275970Scy tt_int_op(event_count_active_added_virtual, ==, 0); 1408275970Scy 1409275970Scy event_base_add_virtual_(base); 1410275970Scy event_count_active = event_base_get_num_events(base, 1411275970Scy EVENT_BASE_COUNT_ACTIVE); 1412275970Scy event_count_virtual = event_base_get_num_events(base, 1413275970Scy EVENT_BASE_COUNT_VIRTUAL); 1414275970Scy event_count_added = event_base_get_num_events(base, 1415275970Scy EVENT_BASE_COUNT_ADDED); 1416275970Scy event_count_active_virtual = event_base_get_num_events(base, 1417275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 1418275970Scy event_count_active_added = event_base_get_num_events(base, 1419275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 1420275970Scy event_count_virtual_added = event_base_get_num_events(base, 1421275970Scy EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 1422275970Scy event_count_active_added_virtual = event_base_get_num_events(base, 1423275970Scy EVENT_BASE_COUNT_ACTIVE| 1424275970Scy EVENT_BASE_COUNT_ADDED| 1425275970Scy EVENT_BASE_COUNT_VIRTUAL); 1426275970Scy tt_int_op(event_count_active, ==, 0); 1427275970Scy tt_int_op(event_count_virtual, ==, 1); 1428275970Scy tt_int_op(event_count_added, ==, 0); 1429275970Scy tt_int_op(event_count_active_virtual, ==, 1); 1430275970Scy tt_int_op(event_count_active_added, ==, 0); 1431275970Scy tt_int_op(event_count_virtual_added, ==, 1); 1432275970Scy tt_int_op(event_count_active_added_virtual, ==, 1); 1433275970Scy 1434275970Scyend: 1435275970Scy ; 1436275970Scy} 1437275970Scy 1438275970Scystatic void 1439275970Scytest_event_base_get_max_events(void *ptr) 1440275970Scy{ 1441275970Scy struct basic_test_data *data = ptr; 1442275970Scy struct event_base *base = data->base; 1443275970Scy struct event ev; 1444275970Scy struct event ev2; 1445275970Scy int event_count_active; 1446275970Scy int event_count_virtual; 1447275970Scy int event_count_added; 1448275970Scy int event_count_active_virtual; 1449275970Scy int event_count_active_added; 1450275970Scy int event_count_virtual_added; 1451275970Scy int event_count_active_added_virtual; 1452275970Scy 1453275970Scy struct timeval qsec = {0, 100000}; 1454275970Scy 1455275970Scy event_assign(&ev, base, -1, EV_READ, event_selfarg_cb, 1456275970Scy event_self_cbarg()); 1457275970Scy event_assign(&ev2, base, -1, EV_READ, event_selfarg_cb, 1458275970Scy event_self_cbarg()); 1459275970Scy 1460275970Scy event_add(&ev, &qsec); 1461275970Scy event_add(&ev2, &qsec); 1462275970Scy event_del(&ev2); 1463275970Scy 1464275970Scy event_count_active = event_base_get_max_events(base, 1465275970Scy EVENT_BASE_COUNT_ACTIVE, 0); 1466275970Scy event_count_virtual = event_base_get_max_events(base, 1467275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1468275970Scy event_count_added = event_base_get_max_events(base, 1469275970Scy EVENT_BASE_COUNT_ADDED, 0); 1470275970Scy event_count_active_virtual = event_base_get_max_events(base, 1471275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 1472275970Scy event_count_active_added = event_base_get_max_events(base, 1473275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 1474275970Scy event_count_virtual_added = event_base_get_max_events(base, 1475275970Scy EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 1476275970Scy event_count_active_added_virtual = event_base_get_max_events(base, 1477275970Scy EVENT_BASE_COUNT_ACTIVE | 1478275970Scy EVENT_BASE_COUNT_ADDED | 1479275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1480275970Scy 1481275970Scy tt_int_op(event_count_active, ==, 0); 1482275970Scy tt_int_op(event_count_virtual, ==, 0); 1483275970Scy /* libevent itself adds a timeout event, so the event_count is 4 here */ 1484275970Scy tt_int_op(event_count_added, ==, 4); 1485275970Scy tt_int_op(event_count_active_virtual, ==, 0); 1486275970Scy tt_int_op(event_count_active_added, ==, 4); 1487275970Scy tt_int_op(event_count_virtual_added, ==, 4); 1488275970Scy tt_int_op(event_count_active_added_virtual, ==, 4); 1489275970Scy 1490275970Scy event_active(&ev, EV_READ, 1); 1491275970Scy event_count_active = event_base_get_max_events(base, 1492275970Scy EVENT_BASE_COUNT_ACTIVE, 0); 1493275970Scy event_count_virtual = event_base_get_max_events(base, 1494275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1495275970Scy event_count_added = event_base_get_max_events(base, 1496275970Scy EVENT_BASE_COUNT_ADDED, 0); 1497275970Scy event_count_active_virtual = event_base_get_max_events(base, 1498275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 1499275970Scy event_count_active_added = event_base_get_max_events(base, 1500275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 1501275970Scy event_count_virtual_added = event_base_get_max_events(base, 1502275970Scy EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 1503275970Scy event_count_active_added_virtual = event_base_get_max_events(base, 1504275970Scy EVENT_BASE_COUNT_ACTIVE | 1505275970Scy EVENT_BASE_COUNT_ADDED | 1506275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1507275970Scy 1508275970Scy tt_int_op(event_count_active, ==, 1); 1509275970Scy tt_int_op(event_count_virtual, ==, 0); 1510275970Scy tt_int_op(event_count_added, ==, 4); 1511275970Scy tt_int_op(event_count_active_virtual, ==, 1); 1512275970Scy tt_int_op(event_count_active_added, ==, 5); 1513275970Scy tt_int_op(event_count_virtual_added, ==, 4); 1514275970Scy tt_int_op(event_count_active_added_virtual, ==, 5); 1515275970Scy 1516275970Scy event_base_loop(base, 0); 1517275970Scy event_count_active = event_base_get_max_events(base, 1518275970Scy EVENT_BASE_COUNT_ACTIVE, 1); 1519275970Scy event_count_virtual = event_base_get_max_events(base, 1520275970Scy EVENT_BASE_COUNT_VIRTUAL, 1); 1521275970Scy event_count_added = event_base_get_max_events(base, 1522275970Scy EVENT_BASE_COUNT_ADDED, 1); 1523275970Scy event_count_active_virtual = event_base_get_max_events(base, 1524275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 1525275970Scy event_count_active_added = event_base_get_max_events(base, 1526275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 1527275970Scy event_count_virtual_added = event_base_get_max_events(base, 1528275970Scy EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 1529275970Scy event_count_active_added_virtual = event_base_get_max_events(base, 1530275970Scy EVENT_BASE_COUNT_ACTIVE | 1531275970Scy EVENT_BASE_COUNT_ADDED | 1532275970Scy EVENT_BASE_COUNT_VIRTUAL, 1); 1533275970Scy 1534275970Scy tt_int_op(event_count_active, ==, 1); 1535275970Scy tt_int_op(event_count_virtual, ==, 0); 1536275970Scy tt_int_op(event_count_added, ==, 4); 1537275970Scy tt_int_op(event_count_active_virtual, ==, 0); 1538275970Scy tt_int_op(event_count_active_added, ==, 0); 1539275970Scy tt_int_op(event_count_virtual_added, ==, 0); 1540275970Scy tt_int_op(event_count_active_added_virtual, ==, 0); 1541275970Scy 1542275970Scy event_count_active = event_base_get_max_events(base, 1543275970Scy EVENT_BASE_COUNT_ACTIVE, 0); 1544275970Scy event_count_virtual = event_base_get_max_events(base, 1545275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1546275970Scy event_count_added = event_base_get_max_events(base, 1547275970Scy EVENT_BASE_COUNT_ADDED, 0); 1548275970Scy tt_int_op(event_count_active, ==, 0); 1549275970Scy tt_int_op(event_count_virtual, ==, 0); 1550275970Scy tt_int_op(event_count_added, ==, 0); 1551275970Scy 1552275970Scy event_base_add_virtual_(base); 1553275970Scy event_count_active = event_base_get_max_events(base, 1554275970Scy EVENT_BASE_COUNT_ACTIVE, 0); 1555275970Scy event_count_virtual = event_base_get_max_events(base, 1556275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1557275970Scy event_count_added = event_base_get_max_events(base, 1558275970Scy EVENT_BASE_COUNT_ADDED, 0); 1559275970Scy event_count_active_virtual = event_base_get_max_events(base, 1560275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 1561275970Scy event_count_active_added = event_base_get_max_events(base, 1562275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 1563275970Scy event_count_virtual_added = event_base_get_max_events(base, 1564275970Scy EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 1565275970Scy event_count_active_added_virtual = event_base_get_max_events(base, 1566275970Scy EVENT_BASE_COUNT_ACTIVE | 1567275970Scy EVENT_BASE_COUNT_ADDED | 1568275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1569275970Scy 1570275970Scy tt_int_op(event_count_active, ==, 0); 1571275970Scy tt_int_op(event_count_virtual, ==, 1); 1572275970Scy tt_int_op(event_count_added, ==, 0); 1573275970Scy tt_int_op(event_count_active_virtual, ==, 1); 1574275970Scy tt_int_op(event_count_active_added, ==, 0); 1575275970Scy tt_int_op(event_count_virtual_added, ==, 1); 1576275970Scy tt_int_op(event_count_active_added_virtual, ==, 1); 1577275970Scy 1578275970Scyend: 1579275970Scy ; 1580275970Scy} 1581275970Scy 1582275970Scystatic void 1583275970Scytest_bad_assign(void *ptr) 1584275970Scy{ 1585275970Scy struct event ev; 1586275970Scy int r; 1587275970Scy /* READ|SIGNAL is not allowed */ 1588275970Scy r = event_assign(&ev, NULL, -1, EV_SIGNAL|EV_READ, dummy_read_cb, NULL); 1589275970Scy tt_int_op(r,==,-1); 1590275970Scy 1591275970Scyend: 1592275970Scy ; 1593275970Scy} 1594275970Scy 1595275970Scystatic int reentrant_cb_run = 0; 1596275970Scy 1597275970Scystatic void 1598275970Scybad_reentrant_run_loop_cb(evutil_socket_t fd, short what, void *ptr) 1599275970Scy{ 1600275970Scy struct event_base *base = ptr; 1601275970Scy int r; 1602275970Scy reentrant_cb_run = 1; 1603275970Scy /* This reentrant call to event_base_loop should be detected and 1604275970Scy * should fail */ 1605275970Scy r = event_base_loop(base, 0); 1606275970Scy tt_int_op(r, ==, -1); 1607275970Scyend: 1608275970Scy ; 1609275970Scy} 1610275970Scy 1611275970Scystatic void 1612275970Scytest_bad_reentrant(void *ptr) 1613275970Scy{ 1614275970Scy struct basic_test_data *data = ptr; 1615275970Scy struct event_base *base = data->base; 1616275970Scy struct event ev; 1617275970Scy int r; 1618275970Scy event_assign(&ev, base, -1, 1619275970Scy 0, bad_reentrant_run_loop_cb, base); 1620275970Scy 1621275970Scy event_active(&ev, EV_WRITE, 1); 1622275970Scy r = event_base_loop(base, 0); 1623275970Scy tt_int_op(r, ==, 1); 1624275970Scy tt_int_op(reentrant_cb_run, ==, 1); 1625275970Scyend: 1626275970Scy ; 1627275970Scy} 1628275970Scy 1629275970Scystatic int n_write_a_byte_cb=0; 1630275970Scystatic int n_read_and_drain_cb=0; 1631275970Scystatic int n_activate_other_event_cb=0; 1632275970Scystatic void 1633275970Scywrite_a_byte_cb(evutil_socket_t fd, short what, void *arg) 1634275970Scy{ 1635275970Scy char buf[] = "x"; 1636275970Scy if (write(fd, buf, 1) == 1) 1637275970Scy ++n_write_a_byte_cb; 1638275970Scy} 1639275970Scystatic void 1640275970Scyread_and_drain_cb(evutil_socket_t fd, short what, void *arg) 1641275970Scy{ 1642275970Scy char buf[128]; 1643275970Scy int n; 1644275970Scy ++n_read_and_drain_cb; 1645275970Scy while ((n = read(fd, buf, sizeof(buf))) > 0) 1646275970Scy ; 1647275970Scy} 1648275970Scy 1649275970Scystatic void 1650275970Scyactivate_other_event_cb(evutil_socket_t fd, short what, void *other_) 1651275970Scy{ 1652275970Scy struct event *ev_activate = other_; 1653275970Scy ++n_activate_other_event_cb; 1654275970Scy event_active_later_(ev_activate, EV_READ); 1655275970Scy} 1656275970Scy 1657275970Scystatic void 1658275970Scytest_active_later(void *ptr) 1659275970Scy{ 1660275970Scy struct basic_test_data *data = ptr; 1661275970Scy struct event *ev1, *ev2; 1662275970Scy struct event ev3, ev4; 1663275970Scy struct timeval qsec = {0, 100000}; 1664275970Scy ev1 = event_new(data->base, data->pair[0], EV_READ|EV_PERSIST, read_and_drain_cb, NULL); 1665275970Scy ev2 = event_new(data->base, data->pair[1], EV_WRITE|EV_PERSIST, write_a_byte_cb, NULL); 1666275970Scy event_assign(&ev3, data->base, -1, 0, activate_other_event_cb, &ev4); 1667275970Scy event_assign(&ev4, data->base, -1, 0, activate_other_event_cb, &ev3); 1668275970Scy event_add(ev1, NULL); 1669275970Scy event_add(ev2, NULL); 1670275970Scy event_active_later_(&ev3, EV_READ); 1671275970Scy 1672275970Scy event_base_loopexit(data->base, &qsec); 1673275970Scy 1674275970Scy event_base_loop(data->base, 0); 1675275970Scy 1676275970Scy TT_BLATHER(("%d write calls, %d read calls, %d activate-other calls.", 1677275970Scy n_write_a_byte_cb, n_read_and_drain_cb, n_activate_other_event_cb)); 1678275970Scy event_del(&ev3); 1679275970Scy event_del(&ev4); 1680275970Scy 1681275970Scy tt_int_op(n_write_a_byte_cb, ==, n_activate_other_event_cb); 1682275970Scy tt_int_op(n_write_a_byte_cb, >, 100); 1683275970Scy tt_int_op(n_read_and_drain_cb, >, 100); 1684275970Scy tt_int_op(n_activate_other_event_cb, >, 100); 1685275970Scy 1686275970Scy event_active_later_(&ev4, EV_READ); 1687275970Scy event_active(&ev4, EV_READ, 1); /* This should make the event 1688275970Scy active immediately. */ 1689275970Scy tt_assert((ev4.ev_flags & EVLIST_ACTIVE) != 0); 1690275970Scy tt_assert((ev4.ev_flags & EVLIST_ACTIVE_LATER) == 0); 1691275970Scy 1692275970Scy /* Now leave this one around, so that event_free sees it and removes 1693275970Scy * it. */ 1694275970Scy event_active_later_(&ev3, EV_READ); 1695275970Scy event_base_assert_ok_(data->base); 1696275970Scy event_base_free(data->base); 1697275970Scy data->base = NULL; 1698275970Scyend: 1699275970Scy ; 1700275970Scy} 1701275970Scy 1702275970Scy 1703275970Scystatic void incr_arg_cb(evutil_socket_t fd, short what, void *arg) 1704275970Scy{ 1705275970Scy int *intptr = arg; 1706275970Scy (void) fd; (void) what; 1707275970Scy ++*intptr; 1708275970Scy} 1709275970Scystatic void remove_timers_cb(evutil_socket_t fd, short what, void *arg) 1710275970Scy{ 1711275970Scy struct event **ep = arg; 1712275970Scy (void) fd; (void) what; 1713275970Scy event_remove_timer(ep[0]); 1714275970Scy event_remove_timer(ep[1]); 1715275970Scy} 1716275970Scystatic void send_a_byte_cb(evutil_socket_t fd, short what, void *arg) 1717275970Scy{ 1718275970Scy evutil_socket_t *sockp = arg; 1719275970Scy (void) fd; (void) what; 1720275970Scy (void) write(*sockp, "A", 1); 1721275970Scy} 1722275970Scystruct read_not_timeout_param 1723275970Scy{ 1724275970Scy struct event **ev; 1725275970Scy int events; 1726275970Scy int count; 1727275970Scy}; 1728275970Scystatic void read_not_timeout_cb(evutil_socket_t fd, short what, void *arg) 1729275970Scy{ 1730275970Scy struct read_not_timeout_param *rntp = arg; 1731275970Scy char c; 1732275970Scy ev_ssize_t n; 1733275970Scy (void) fd; (void) what; 1734275970Scy n = read(fd, &c, 1); 1735275970Scy tt_int_op(n, ==, 1); 1736275970Scy rntp->events |= what; 1737275970Scy ++rntp->count; 1738275970Scy if(2 == rntp->count) event_del(rntp->ev[0]); 1739275970Scyend: 1740275970Scy ; 1741275970Scy} 1742275970Scy 1743275970Scystatic void 1744275970Scytest_event_remove_timeout(void *ptr) 1745275970Scy{ 1746275970Scy struct basic_test_data *data = ptr; 1747275970Scy struct event_base *base = data->base; 1748275970Scy struct event *ev[5]; 1749275970Scy int ev1_fired=0; 1750275970Scy struct timeval ms25 = { 0, 25*1000 }, 1751275970Scy ms40 = { 0, 40*1000 }, 1752275970Scy ms75 = { 0, 75*1000 }, 1753275970Scy ms125 = { 0, 125*1000 }; 1754275970Scy struct read_not_timeout_param rntp = { ev, 0, 0 }; 1755275970Scy 1756275970Scy event_base_assert_ok_(base); 1757275970Scy 1758275970Scy ev[0] = event_new(base, data->pair[0], EV_READ|EV_PERSIST, 1759275970Scy read_not_timeout_cb, &rntp); 1760275970Scy ev[1] = evtimer_new(base, incr_arg_cb, &ev1_fired); 1761275970Scy ev[2] = evtimer_new(base, remove_timers_cb, ev); 1762275970Scy ev[3] = evtimer_new(base, send_a_byte_cb, &data->pair[1]); 1763275970Scy ev[4] = evtimer_new(base, send_a_byte_cb, &data->pair[1]); 1764275970Scy tt_assert(base); 1765275970Scy event_add(ev[2], &ms25); /* remove timers */ 1766275970Scy event_add(ev[4], &ms40); /* write to test if timer re-activates */ 1767275970Scy event_add(ev[0], &ms75); /* read */ 1768275970Scy event_add(ev[1], &ms75); /* timer */ 1769275970Scy event_add(ev[3], &ms125); /* timeout. */ 1770275970Scy event_base_assert_ok_(base); 1771275970Scy 1772275970Scy event_base_dispatch(base); 1773275970Scy 1774275970Scy tt_int_op(ev1_fired, ==, 0); 1775275970Scy tt_int_op(rntp.events, ==, EV_READ); 1776275970Scy 1777275970Scy event_base_assert_ok_(base); 1778275970Scyend: 1779275970Scy event_free(ev[0]); 1780275970Scy event_free(ev[1]); 1781275970Scy event_free(ev[2]); 1782275970Scy event_free(ev[3]); 1783275970Scy event_free(ev[4]); 1784275970Scy} 1785275970Scy 1786275970Scystatic void 1787275970Scytest_event_base_new(void *ptr) 1788275970Scy{ 1789275970Scy struct basic_test_data *data = ptr; 1790275970Scy struct event_base *base = 0; 1791275970Scy struct event ev1; 1792275970Scy struct basic_cb_args args; 1793275970Scy 1794275970Scy int towrite = (int)strlen(TEST1)+1; 1795275970Scy int len = write(data->pair[0], TEST1, towrite); 1796275970Scy 1797275970Scy if (len < 0) 1798275970Scy tt_abort_perror("initial write"); 1799275970Scy else if (len != towrite) 1800275970Scy tt_abort_printf(("initial write fell short (%d of %d bytes)", 1801275970Scy len, towrite)); 1802275970Scy 1803275970Scy if (shutdown(data->pair[0], SHUT_WR)) 1804275970Scy tt_abort_perror("initial write shutdown"); 1805275970Scy 1806275970Scy base = event_base_new(); 1807275970Scy if (!base) 1808275970Scy tt_abort_msg("failed to create event base"); 1809275970Scy 1810275970Scy args.eb = base; 1811275970Scy args.ev = &ev1; 1812275970Scy args.callcount = 0; 1813275970Scy event_assign(&ev1, base, data->pair[1], 1814275970Scy EV_READ|EV_PERSIST, basic_read_cb, &args); 1815275970Scy 1816275970Scy if (event_add(&ev1, NULL)) 1817275970Scy tt_abort_perror("initial event_add"); 1818275970Scy 1819275970Scy if (event_base_loop(base, 0)) 1820275970Scy tt_abort_msg("unsuccessful exit from event loop"); 1821275970Scy 1822275970Scyend: 1823275970Scy if (base) 1824275970Scy event_base_free(base); 1825275970Scy} 1826275970Scy 1827275970Scystatic void 1828275970Scytest_loopexit(void) 1829275970Scy{ 1830275970Scy struct timeval tv, tv_start, tv_end; 1831275970Scy struct event ev; 1832275970Scy 1833275970Scy setup_test("Loop exit: "); 1834275970Scy 1835275970Scy tv.tv_usec = 0; 1836275970Scy tv.tv_sec = 60*60*24; 1837275970Scy evtimer_set(&ev, timeout_cb, NULL); 1838275970Scy evtimer_add(&ev, &tv); 1839275970Scy 1840275970Scy tv.tv_usec = 300*1000; 1841275970Scy tv.tv_sec = 0; 1842275970Scy event_loopexit(&tv); 1843275970Scy 1844275970Scy evutil_gettimeofday(&tv_start, NULL); 1845275970Scy event_dispatch(); 1846275970Scy evutil_gettimeofday(&tv_end, NULL); 1847275970Scy 1848275970Scy evtimer_del(&ev); 1849275970Scy 1850275970Scy tt_assert(event_base_got_exit(global_base)); 1851275970Scy tt_assert(!event_base_got_break(global_base)); 1852275970Scy 1853275970Scy test_timeval_diff_eq(&tv_start, &tv_end, 300); 1854275970Scy 1855275970Scy test_ok = 1; 1856275970Scyend: 1857275970Scy cleanup_test(); 1858275970Scy} 1859275970Scy 1860275970Scystatic void 1861275970Scytest_loopexit_multiple(void) 1862275970Scy{ 1863275970Scy struct timeval tv, tv_start, tv_end; 1864275970Scy struct event_base *base; 1865275970Scy 1866275970Scy setup_test("Loop Multiple exit: "); 1867275970Scy 1868275970Scy base = event_base_new(); 1869275970Scy 1870275970Scy tv.tv_usec = 200*1000; 1871275970Scy tv.tv_sec = 0; 1872275970Scy event_base_loopexit(base, &tv); 1873275970Scy 1874275970Scy tv.tv_usec = 0; 1875275970Scy tv.tv_sec = 3; 1876275970Scy event_base_loopexit(base, &tv); 1877275970Scy 1878275970Scy evutil_gettimeofday(&tv_start, NULL); 1879275970Scy event_base_dispatch(base); 1880275970Scy evutil_gettimeofday(&tv_end, NULL); 1881275970Scy 1882275970Scy tt_assert(event_base_got_exit(base)); 1883275970Scy tt_assert(!event_base_got_break(base)); 1884275970Scy 1885275970Scy event_base_free(base); 1886275970Scy 1887275970Scy test_timeval_diff_eq(&tv_start, &tv_end, 200); 1888275970Scy 1889275970Scy test_ok = 1; 1890275970Scy 1891275970Scyend: 1892275970Scy cleanup_test(); 1893275970Scy} 1894275970Scy 1895275970Scystatic void 1896275970Scybreak_cb(evutil_socket_t fd, short events, void *arg) 1897275970Scy{ 1898275970Scy test_ok = 1; 1899275970Scy event_loopbreak(); 1900275970Scy} 1901275970Scy 1902275970Scystatic void 1903275970Scyfail_cb(evutil_socket_t fd, short events, void *arg) 1904275970Scy{ 1905275970Scy test_ok = 0; 1906275970Scy} 1907275970Scy 1908275970Scystatic void 1909275970Scytest_loopbreak(void) 1910275970Scy{ 1911275970Scy struct event ev1, ev2; 1912275970Scy struct timeval tv; 1913275970Scy 1914275970Scy setup_test("Loop break: "); 1915275970Scy 1916275970Scy tv.tv_sec = 0; 1917275970Scy tv.tv_usec = 0; 1918275970Scy evtimer_set(&ev1, break_cb, NULL); 1919275970Scy evtimer_add(&ev1, &tv); 1920275970Scy evtimer_set(&ev2, fail_cb, NULL); 1921275970Scy evtimer_add(&ev2, &tv); 1922275970Scy 1923275970Scy event_dispatch(); 1924275970Scy 1925275970Scy tt_assert(!event_base_got_exit(global_base)); 1926275970Scy tt_assert(event_base_got_break(global_base)); 1927275970Scy 1928275970Scy evtimer_del(&ev1); 1929275970Scy evtimer_del(&ev2); 1930275970Scy 1931275970Scyend: 1932275970Scy cleanup_test(); 1933275970Scy} 1934275970Scy 1935275970Scystatic struct event *readd_test_event_last_added = NULL; 1936275970Scystatic void 1937275970Scyre_add_read_cb(evutil_socket_t fd, short event, void *arg) 1938275970Scy{ 1939275970Scy char buf[256]; 1940275970Scy struct event *ev_other = arg; 1941275970Scy ev_ssize_t n_read; 1942275970Scy 1943275970Scy readd_test_event_last_added = ev_other; 1944275970Scy 1945275970Scy n_read = read(fd, buf, sizeof(buf)); 1946275970Scy 1947275970Scy if (n_read < 0) { 1948275970Scy tt_fail_perror("read"); 1949275970Scy event_base_loopbreak(event_get_base(ev_other)); 1950275970Scy return; 1951275970Scy } else { 1952275970Scy event_add(ev_other, NULL); 1953275970Scy ++test_ok; 1954275970Scy } 1955275970Scy} 1956275970Scy 1957275970Scystatic void 1958275970Scytest_nonpersist_readd(void) 1959275970Scy{ 1960275970Scy struct event ev1, ev2; 1961275970Scy 1962275970Scy setup_test("Re-add nonpersistent events: "); 1963275970Scy event_set(&ev1, pair[0], EV_READ, re_add_read_cb, &ev2); 1964275970Scy event_set(&ev2, pair[1], EV_READ, re_add_read_cb, &ev1); 1965275970Scy 1966275970Scy if (write(pair[0], "Hello", 5) < 0) { 1967275970Scy tt_fail_perror("write(pair[0])"); 1968275970Scy } 1969275970Scy 1970275970Scy if (write(pair[1], "Hello", 5) < 0) { 1971275970Scy tt_fail_perror("write(pair[1])\n"); 1972275970Scy } 1973275970Scy 1974275970Scy if (event_add(&ev1, NULL) == -1 || 1975275970Scy event_add(&ev2, NULL) == -1) { 1976275970Scy test_ok = 0; 1977275970Scy } 1978275970Scy if (test_ok != 0) 1979275970Scy exit(1); 1980275970Scy event_loop(EVLOOP_ONCE); 1981275970Scy if (test_ok != 2) 1982275970Scy exit(1); 1983275970Scy /* At this point, we executed both callbacks. Whichever one got 1984275970Scy * called first added the second, but the second then immediately got 1985275970Scy * deleted before its callback was called. At this point, though, it 1986275970Scy * re-added the first. 1987275970Scy */ 1988275970Scy if (!readd_test_event_last_added) { 1989275970Scy test_ok = 0; 1990275970Scy } else if (readd_test_event_last_added == &ev1) { 1991275970Scy if (!event_pending(&ev1, EV_READ, NULL) || 1992275970Scy event_pending(&ev2, EV_READ, NULL)) 1993275970Scy test_ok = 0; 1994275970Scy } else { 1995275970Scy if (event_pending(&ev1, EV_READ, NULL) || 1996275970Scy !event_pending(&ev2, EV_READ, NULL)) 1997275970Scy test_ok = 0; 1998275970Scy } 1999275970Scy 2000275970Scy event_del(&ev1); 2001275970Scy event_del(&ev2); 2002275970Scy 2003275970Scy cleanup_test(); 2004275970Scy} 2005275970Scy 2006275970Scystruct test_pri_event { 2007275970Scy struct event ev; 2008275970Scy int count; 2009275970Scy}; 2010275970Scy 2011275970Scystatic void 2012275970Scytest_priorities_cb(evutil_socket_t fd, short what, void *arg) 2013275970Scy{ 2014275970Scy struct test_pri_event *pri = arg; 2015275970Scy struct timeval tv; 2016275970Scy 2017275970Scy if (pri->count == 3) { 2018275970Scy event_loopexit(NULL); 2019275970Scy return; 2020275970Scy } 2021275970Scy 2022275970Scy pri->count++; 2023275970Scy 2024275970Scy evutil_timerclear(&tv); 2025275970Scy event_add(&pri->ev, &tv); 2026275970Scy} 2027275970Scy 2028275970Scystatic void 2029275970Scytest_priorities_impl(int npriorities) 2030275970Scy{ 2031275970Scy struct test_pri_event one, two; 2032275970Scy struct timeval tv; 2033275970Scy 2034275970Scy TT_BLATHER(("Testing Priorities %d: ", npriorities)); 2035275970Scy 2036275970Scy event_base_priority_init(global_base, npriorities); 2037275970Scy 2038275970Scy memset(&one, 0, sizeof(one)); 2039275970Scy memset(&two, 0, sizeof(two)); 2040275970Scy 2041275970Scy timeout_set(&one.ev, test_priorities_cb, &one); 2042275970Scy if (event_priority_set(&one.ev, 0) == -1) { 2043275970Scy fprintf(stderr, "%s: failed to set priority", __func__); 2044275970Scy exit(1); 2045275970Scy } 2046275970Scy 2047275970Scy timeout_set(&two.ev, test_priorities_cb, &two); 2048275970Scy if (event_priority_set(&two.ev, npriorities - 1) == -1) { 2049275970Scy fprintf(stderr, "%s: failed to set priority", __func__); 2050275970Scy exit(1); 2051275970Scy } 2052275970Scy 2053275970Scy evutil_timerclear(&tv); 2054275970Scy 2055275970Scy if (event_add(&one.ev, &tv) == -1) 2056275970Scy exit(1); 2057275970Scy if (event_add(&two.ev, &tv) == -1) 2058275970Scy exit(1); 2059275970Scy 2060275970Scy event_dispatch(); 2061275970Scy 2062275970Scy event_del(&one.ev); 2063275970Scy event_del(&two.ev); 2064275970Scy 2065275970Scy if (npriorities == 1) { 2066275970Scy if (one.count == 3 && two.count == 3) 2067275970Scy test_ok = 1; 2068275970Scy } else if (npriorities == 2) { 2069275970Scy /* Two is called once because event_loopexit is priority 1 */ 2070275970Scy if (one.count == 3 && two.count == 1) 2071275970Scy test_ok = 1; 2072275970Scy } else { 2073275970Scy if (one.count == 3 && two.count == 0) 2074275970Scy test_ok = 1; 2075275970Scy } 2076275970Scy} 2077275970Scy 2078275970Scystatic void 2079275970Scytest_priorities(void) 2080275970Scy{ 2081275970Scy test_priorities_impl(1); 2082275970Scy if (test_ok) 2083275970Scy test_priorities_impl(2); 2084275970Scy if (test_ok) 2085275970Scy test_priorities_impl(3); 2086275970Scy} 2087275970Scy 2088275970Scy/* priority-active-inversion: activate a higher-priority event, and make sure 2089275970Scy * it keeps us from running a lower-priority event first. */ 2090275970Scystatic int n_pai_calls = 0; 2091275970Scystatic struct event pai_events[3]; 2092275970Scy 2093275970Scystatic void 2094275970Scyprio_active_inversion_cb(evutil_socket_t fd, short what, void *arg) 2095275970Scy{ 2096275970Scy int *call_order = arg; 2097275970Scy *call_order = n_pai_calls++; 2098275970Scy if (n_pai_calls == 1) { 2099275970Scy /* This should activate later, even though it shares a 2100275970Scy priority with us. */ 2101275970Scy event_active(&pai_events[1], EV_READ, 1); 2102275970Scy /* This should activate next, since its priority is higher, 2103275970Scy even though we activated it second. */ 2104275970Scy event_active(&pai_events[2], EV_TIMEOUT, 1); 2105275970Scy } 2106275970Scy} 2107275970Scy 2108275970Scystatic void 2109275970Scytest_priority_active_inversion(void *data_) 2110275970Scy{ 2111275970Scy struct basic_test_data *data = data_; 2112275970Scy struct event_base *base = data->base; 2113275970Scy int call_order[3]; 2114275970Scy int i; 2115275970Scy tt_int_op(event_base_priority_init(base, 8), ==, 0); 2116275970Scy 2117275970Scy n_pai_calls = 0; 2118275970Scy memset(call_order, 0, sizeof(call_order)); 2119275970Scy 2120275970Scy for (i=0;i<3;++i) { 2121275970Scy event_assign(&pai_events[i], data->base, -1, 0, 2122275970Scy prio_active_inversion_cb, &call_order[i]); 2123275970Scy } 2124275970Scy 2125275970Scy event_priority_set(&pai_events[0], 4); 2126275970Scy event_priority_set(&pai_events[1], 4); 2127275970Scy event_priority_set(&pai_events[2], 0); 2128275970Scy 2129275970Scy event_active(&pai_events[0], EV_WRITE, 1); 2130275970Scy 2131275970Scy event_base_dispatch(base); 2132275970Scy tt_int_op(n_pai_calls, ==, 3); 2133275970Scy tt_int_op(call_order[0], ==, 0); 2134275970Scy tt_int_op(call_order[1], ==, 2); 2135275970Scy tt_int_op(call_order[2], ==, 1); 2136275970Scyend: 2137275970Scy ; 2138275970Scy} 2139275970Scy 2140275970Scy 2141275970Scystatic void 2142275970Scytest_multiple_cb(evutil_socket_t fd, short event, void *arg) 2143275970Scy{ 2144275970Scy if (event & EV_READ) 2145275970Scy test_ok |= 1; 2146275970Scy else if (event & EV_WRITE) 2147275970Scy test_ok |= 2; 2148275970Scy} 2149275970Scy 2150275970Scystatic void 2151275970Scytest_multiple_events_for_same_fd(void) 2152275970Scy{ 2153275970Scy struct event e1, e2; 2154275970Scy 2155275970Scy setup_test("Multiple events for same fd: "); 2156275970Scy 2157275970Scy event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL); 2158275970Scy event_add(&e1, NULL); 2159275970Scy event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL); 2160275970Scy event_add(&e2, NULL); 2161275970Scy event_loop(EVLOOP_ONCE); 2162275970Scy event_del(&e2); 2163275970Scy 2164275970Scy if (write(pair[1], TEST1, strlen(TEST1)+1) < 0) { 2165275970Scy tt_fail_perror("write"); 2166275970Scy } 2167275970Scy 2168275970Scy event_loop(EVLOOP_ONCE); 2169275970Scy event_del(&e1); 2170275970Scy 2171275970Scy if (test_ok != 3) 2172275970Scy test_ok = 0; 2173275970Scy 2174275970Scy cleanup_test(); 2175275970Scy} 2176275970Scy 2177275970Scyint evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf); 2178275970Scyint evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf); 2179275970Scyint evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t number); 2180275970Scyint evtag_decode_tag(ev_uint32_t *pnumber, struct evbuffer *evbuf); 2181275970Scy 2182275970Scystatic void 2183275970Scyread_once_cb(evutil_socket_t fd, short event, void *arg) 2184275970Scy{ 2185275970Scy char buf[256]; 2186275970Scy int len; 2187275970Scy 2188275970Scy len = read(fd, buf, sizeof(buf)); 2189275970Scy 2190275970Scy if (called) { 2191275970Scy test_ok = 0; 2192275970Scy } else if (len) { 2193275970Scy /* Assumes global pair[0] can be used for writing */ 2194275970Scy if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 2195275970Scy tt_fail_perror("write"); 2196275970Scy test_ok = 0; 2197275970Scy } else { 2198275970Scy test_ok = 1; 2199275970Scy } 2200275970Scy } 2201275970Scy 2202275970Scy called++; 2203275970Scy} 2204275970Scy 2205275970Scystatic void 2206275970Scytest_want_only_once(void) 2207275970Scy{ 2208275970Scy struct event ev; 2209275970Scy struct timeval tv; 2210275970Scy 2211275970Scy /* Very simple read test */ 2212275970Scy setup_test("Want read only once: "); 2213275970Scy 2214275970Scy if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 2215275970Scy tt_fail_perror("write"); 2216275970Scy } 2217275970Scy 2218275970Scy /* Setup the loop termination */ 2219275970Scy evutil_timerclear(&tv); 2220275970Scy tv.tv_usec = 300*1000; 2221275970Scy event_loopexit(&tv); 2222275970Scy 2223275970Scy event_set(&ev, pair[1], EV_READ, read_once_cb, &ev); 2224275970Scy if (event_add(&ev, NULL) == -1) 2225275970Scy exit(1); 2226275970Scy event_dispatch(); 2227275970Scy 2228275970Scy cleanup_test(); 2229275970Scy} 2230275970Scy 2231275970Scy#define TEST_MAX_INT 6 2232275970Scy 2233275970Scystatic void 2234275970Scyevtag_int_test(void *ptr) 2235275970Scy{ 2236275970Scy struct evbuffer *tmp = evbuffer_new(); 2237275970Scy ev_uint32_t integers[TEST_MAX_INT] = { 2238275970Scy 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 2239275970Scy }; 2240275970Scy ev_uint32_t integer; 2241275970Scy ev_uint64_t big_int; 2242275970Scy int i; 2243275970Scy 2244275970Scy evtag_init(); 2245275970Scy 2246275970Scy for (i = 0; i < TEST_MAX_INT; i++) { 2247275970Scy int oldlen, newlen; 2248275970Scy oldlen = (int)EVBUFFER_LENGTH(tmp); 2249275970Scy evtag_encode_int(tmp, integers[i]); 2250275970Scy newlen = (int)EVBUFFER_LENGTH(tmp); 2251275970Scy TT_BLATHER(("encoded 0x%08x with %d bytes", 2252275970Scy (unsigned)integers[i], newlen - oldlen)); 2253275970Scy big_int = integers[i]; 2254275970Scy big_int *= 1000000000; /* 1 billion */ 2255275970Scy evtag_encode_int64(tmp, big_int); 2256275970Scy } 2257275970Scy 2258275970Scy for (i = 0; i < TEST_MAX_INT; i++) { 2259275970Scy tt_int_op(evtag_decode_int(&integer, tmp), !=, -1); 2260275970Scy tt_uint_op(integer, ==, integers[i]); 2261275970Scy tt_int_op(evtag_decode_int64(&big_int, tmp), !=, -1); 2262275970Scy tt_assert((big_int / 1000000000) == integers[i]); 2263275970Scy } 2264275970Scy 2265275970Scy tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0); 2266275970Scyend: 2267275970Scy evbuffer_free(tmp); 2268275970Scy} 2269275970Scy 2270275970Scystatic void 2271275970Scyevtag_fuzz(void *ptr) 2272275970Scy{ 2273275970Scy u_char buffer[4096]; 2274275970Scy struct evbuffer *tmp = evbuffer_new(); 2275275970Scy struct timeval tv; 2276275970Scy int i, j; 2277275970Scy 2278275970Scy int not_failed = 0; 2279275970Scy 2280275970Scy evtag_init(); 2281275970Scy 2282275970Scy for (j = 0; j < 100; j++) { 2283275970Scy for (i = 0; i < (int)sizeof(buffer); i++) 2284275970Scy buffer[i] = rand(); 2285275970Scy evbuffer_drain(tmp, -1); 2286275970Scy evbuffer_add(tmp, buffer, sizeof(buffer)); 2287275970Scy 2288275970Scy if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) 2289275970Scy not_failed++; 2290275970Scy } 2291275970Scy 2292275970Scy /* The majority of decodes should fail */ 2293275970Scy tt_int_op(not_failed, <, 10); 2294275970Scy 2295275970Scy /* Now insert some corruption into the tag length field */ 2296275970Scy evbuffer_drain(tmp, -1); 2297275970Scy evutil_timerclear(&tv); 2298275970Scy tv.tv_sec = 1; 2299275970Scy evtag_marshal_timeval(tmp, 0, &tv); 2300275970Scy evbuffer_add(tmp, buffer, sizeof(buffer)); 2301275970Scy 2302275970Scy ((char *)EVBUFFER_DATA(tmp))[1] = '\xff'; 2303275970Scy if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) { 2304275970Scy tt_abort_msg("evtag_unmarshal_timeval should have failed"); 2305275970Scy } 2306275970Scy 2307275970Scyend: 2308275970Scy evbuffer_free(tmp); 2309275970Scy} 2310275970Scy 2311275970Scystatic void 2312275970Scyevtag_tag_encoding(void *ptr) 2313275970Scy{ 2314275970Scy struct evbuffer *tmp = evbuffer_new(); 2315275970Scy ev_uint32_t integers[TEST_MAX_INT] = { 2316275970Scy 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 2317275970Scy }; 2318275970Scy ev_uint32_t integer; 2319275970Scy int i; 2320275970Scy 2321275970Scy evtag_init(); 2322275970Scy 2323275970Scy for (i = 0; i < TEST_MAX_INT; i++) { 2324275970Scy int oldlen, newlen; 2325275970Scy oldlen = (int)EVBUFFER_LENGTH(tmp); 2326275970Scy evtag_encode_tag(tmp, integers[i]); 2327275970Scy newlen = (int)EVBUFFER_LENGTH(tmp); 2328275970Scy TT_BLATHER(("encoded 0x%08x with %d bytes", 2329275970Scy (unsigned)integers[i], newlen - oldlen)); 2330275970Scy } 2331275970Scy 2332275970Scy for (i = 0; i < TEST_MAX_INT; i++) { 2333275970Scy tt_int_op(evtag_decode_tag(&integer, tmp), !=, -1); 2334275970Scy tt_uint_op(integer, ==, integers[i]); 2335275970Scy } 2336275970Scy 2337275970Scy tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0); 2338275970Scy 2339275970Scyend: 2340275970Scy evbuffer_free(tmp); 2341275970Scy} 2342275970Scy 2343275970Scystatic void 2344275970Scyevtag_test_peek(void *ptr) 2345275970Scy{ 2346275970Scy struct evbuffer *tmp = evbuffer_new(); 2347275970Scy ev_uint32_t u32; 2348275970Scy 2349275970Scy evtag_marshal_int(tmp, 30, 0); 2350275970Scy evtag_marshal_string(tmp, 40, "Hello world"); 2351275970Scy 2352275970Scy tt_int_op(evtag_peek(tmp, &u32), ==, 1); 2353275970Scy tt_int_op(u32, ==, 30); 2354275970Scy tt_int_op(evtag_peek_length(tmp, &u32), ==, 0); 2355275970Scy tt_int_op(u32, ==, 1+1+1); 2356275970Scy tt_int_op(evtag_consume(tmp), ==, 0); 2357275970Scy 2358275970Scy tt_int_op(evtag_peek(tmp, &u32), ==, 1); 2359275970Scy tt_int_op(u32, ==, 40); 2360275970Scy tt_int_op(evtag_peek_length(tmp, &u32), ==, 0); 2361275970Scy tt_int_op(u32, ==, 1+1+11); 2362275970Scy tt_int_op(evtag_payload_length(tmp, &u32), ==, 0); 2363275970Scy tt_int_op(u32, ==, 11); 2364275970Scy 2365275970Scyend: 2366275970Scy evbuffer_free(tmp); 2367275970Scy} 2368275970Scy 2369275970Scy 2370275970Scystatic void 2371275970Scytest_methods(void *ptr) 2372275970Scy{ 2373275970Scy const char **methods = event_get_supported_methods(); 2374275970Scy struct event_config *cfg = NULL; 2375275970Scy struct event_base *base = NULL; 2376275970Scy const char *backend; 2377275970Scy int n_methods = 0; 2378275970Scy 2379275970Scy tt_assert(methods); 2380275970Scy 2381275970Scy backend = methods[0]; 2382275970Scy while (*methods != NULL) { 2383275970Scy TT_BLATHER(("Support method: %s", *methods)); 2384275970Scy ++methods; 2385275970Scy ++n_methods; 2386275970Scy } 2387275970Scy 2388275970Scy cfg = event_config_new(); 2389275970Scy assert(cfg != NULL); 2390275970Scy 2391275970Scy tt_int_op(event_config_avoid_method(cfg, backend), ==, 0); 2392275970Scy event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV); 2393275970Scy 2394275970Scy base = event_base_new_with_config(cfg); 2395275970Scy if (n_methods > 1) { 2396275970Scy tt_assert(base); 2397275970Scy tt_str_op(backend, !=, event_base_get_method(base)); 2398275970Scy } else { 2399275970Scy tt_assert(base == NULL); 2400275970Scy } 2401275970Scy 2402275970Scyend: 2403275970Scy if (base) 2404275970Scy event_base_free(base); 2405275970Scy if (cfg) 2406275970Scy event_config_free(cfg); 2407275970Scy} 2408275970Scy 2409275970Scystatic void 2410275970Scytest_version(void *arg) 2411275970Scy{ 2412275970Scy const char *vstr; 2413275970Scy ev_uint32_t vint; 2414275970Scy int major, minor, patch, n; 2415275970Scy 2416275970Scy vstr = event_get_version(); 2417275970Scy vint = event_get_version_number(); 2418275970Scy 2419275970Scy tt_assert(vstr); 2420275970Scy tt_assert(vint); 2421275970Scy 2422275970Scy tt_str_op(vstr, ==, LIBEVENT_VERSION); 2423275970Scy tt_int_op(vint, ==, LIBEVENT_VERSION_NUMBER); 2424275970Scy 2425275970Scy n = sscanf(vstr, "%d.%d.%d", &major, &minor, &patch); 2426275970Scy tt_assert(3 == n); 2427275970Scy tt_int_op((vint&0xffffff00), ==, ((major<<24)|(minor<<16)|(patch<<8))); 2428275970Scyend: 2429275970Scy ; 2430275970Scy} 2431275970Scy 2432275970Scystatic void 2433275970Scytest_base_features(void *arg) 2434275970Scy{ 2435275970Scy struct event_base *base = NULL; 2436275970Scy struct event_config *cfg = NULL; 2437275970Scy 2438275970Scy cfg = event_config_new(); 2439275970Scy 2440275970Scy tt_assert(0 == event_config_require_features(cfg, EV_FEATURE_ET)); 2441275970Scy 2442275970Scy base = event_base_new_with_config(cfg); 2443275970Scy if (base) { 2444275970Scy tt_int_op(EV_FEATURE_ET, ==, 2445275970Scy event_base_get_features(base) & EV_FEATURE_ET); 2446275970Scy } else { 2447275970Scy base = event_base_new(); 2448275970Scy tt_int_op(0, ==, event_base_get_features(base) & EV_FEATURE_ET); 2449275970Scy } 2450275970Scy 2451275970Scyend: 2452275970Scy if (base) 2453275970Scy event_base_free(base); 2454275970Scy if (cfg) 2455275970Scy event_config_free(cfg); 2456275970Scy} 2457275970Scy 2458275970Scy#ifdef EVENT__HAVE_SETENV 2459275970Scy#define SETENV_OK 2460275970Scy#elif !defined(EVENT__HAVE_SETENV) && defined(EVENT__HAVE_PUTENV) 2461275970Scystatic void setenv(const char *k, const char *v, int o_) 2462275970Scy{ 2463275970Scy char b[256]; 2464275970Scy evutil_snprintf(b, sizeof(b), "%s=%s",k,v); 2465275970Scy putenv(b); 2466275970Scy} 2467275970Scy#define SETENV_OK 2468275970Scy#endif 2469275970Scy 2470275970Scy#ifdef EVENT__HAVE_UNSETENV 2471275970Scy#define UNSETENV_OK 2472275970Scy#elif !defined(EVENT__HAVE_UNSETENV) && defined(EVENT__HAVE_PUTENV) 2473275970Scystatic void unsetenv(const char *k) 2474275970Scy{ 2475275970Scy char b[256]; 2476275970Scy evutil_snprintf(b, sizeof(b), "%s=",k); 2477275970Scy putenv(b); 2478275970Scy} 2479275970Scy#define UNSETENV_OK 2480275970Scy#endif 2481275970Scy 2482275970Scy#if defined(SETENV_OK) && defined(UNSETENV_OK) 2483275970Scystatic void 2484275970Scymethodname_to_envvar(const char *mname, char *buf, size_t buflen) 2485275970Scy{ 2486275970Scy char *cp; 2487275970Scy evutil_snprintf(buf, buflen, "EVENT_NO%s", mname); 2488275970Scy for (cp = buf; *cp; ++cp) { 2489275970Scy *cp = EVUTIL_TOUPPER_(*cp); 2490275970Scy } 2491275970Scy} 2492275970Scy#endif 2493275970Scy 2494275970Scystatic void 2495275970Scytest_base_environ(void *arg) 2496275970Scy{ 2497275970Scy struct event_base *base = NULL; 2498275970Scy struct event_config *cfg = NULL; 2499275970Scy 2500275970Scy#if defined(SETENV_OK) && defined(UNSETENV_OK) 2501275970Scy const char **basenames; 2502275970Scy int i, n_methods=0; 2503275970Scy char varbuf[128]; 2504275970Scy const char *defaultname, *ignoreenvname; 2505275970Scy 2506275970Scy /* See if unsetenv works before we rely on it. */ 2507275970Scy setenv("EVENT_NOWAFFLES", "1", 1); 2508275970Scy unsetenv("EVENT_NOWAFFLES"); 2509275970Scy if (getenv("EVENT_NOWAFFLES") != NULL) { 2510275970Scy#ifndef EVENT__HAVE_UNSETENV 2511275970Scy TT_DECLARE("NOTE", ("Can't fake unsetenv; skipping test")); 2512275970Scy#else 2513275970Scy TT_DECLARE("NOTE", ("unsetenv doesn't work; skipping test")); 2514275970Scy#endif 2515275970Scy tt_skip(); 2516275970Scy } 2517275970Scy 2518275970Scy basenames = event_get_supported_methods(); 2519275970Scy for (i = 0; basenames[i]; ++i) { 2520275970Scy methodname_to_envvar(basenames[i], varbuf, sizeof(varbuf)); 2521275970Scy unsetenv(varbuf); 2522275970Scy ++n_methods; 2523275970Scy } 2524275970Scy 2525275970Scy base = event_base_new(); 2526275970Scy tt_assert(base); 2527275970Scy 2528275970Scy defaultname = event_base_get_method(base); 2529275970Scy TT_BLATHER(("default is <%s>", defaultname)); 2530275970Scy event_base_free(base); 2531275970Scy base = NULL; 2532275970Scy 2533275970Scy /* Can we disable the method with EVENT_NOfoo ? */ 2534275970Scy if (!strcmp(defaultname, "epoll (with changelist)")) { 2535275970Scy setenv("EVENT_NOEPOLL", "1", 1); 2536275970Scy ignoreenvname = "epoll"; 2537275970Scy } else { 2538275970Scy methodname_to_envvar(defaultname, varbuf, sizeof(varbuf)); 2539275970Scy setenv(varbuf, "1", 1); 2540275970Scy ignoreenvname = defaultname; 2541275970Scy } 2542275970Scy 2543275970Scy /* Use an empty cfg rather than NULL so a failure doesn't exit() */ 2544275970Scy cfg = event_config_new(); 2545275970Scy base = event_base_new_with_config(cfg); 2546275970Scy event_config_free(cfg); 2547275970Scy cfg = NULL; 2548275970Scy if (n_methods == 1) { 2549275970Scy tt_assert(!base); 2550275970Scy } else { 2551275970Scy tt_assert(base); 2552275970Scy tt_str_op(defaultname, !=, event_base_get_method(base)); 2553275970Scy event_base_free(base); 2554275970Scy base = NULL; 2555275970Scy } 2556275970Scy 2557275970Scy /* Can we disable looking at the environment with IGNORE_ENV ? */ 2558275970Scy cfg = event_config_new(); 2559275970Scy event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV); 2560275970Scy base = event_base_new_with_config(cfg); 2561275970Scy tt_assert(base); 2562275970Scy tt_str_op(ignoreenvname, ==, event_base_get_method(base)); 2563275970Scy#else 2564275970Scy tt_skip(); 2565275970Scy#endif 2566275970Scy 2567275970Scyend: 2568275970Scy if (base) 2569275970Scy event_base_free(base); 2570275970Scy if (cfg) 2571275970Scy event_config_free(cfg); 2572275970Scy} 2573275970Scy 2574275970Scystatic void 2575275970Scyread_called_once_cb(evutil_socket_t fd, short event, void *arg) 2576275970Scy{ 2577275970Scy tt_int_op(event, ==, EV_READ); 2578275970Scy called += 1; 2579275970Scyend: 2580275970Scy ; 2581275970Scy} 2582275970Scy 2583275970Scystatic void 2584275970Scytimeout_called_once_cb(evutil_socket_t fd, short event, void *arg) 2585275970Scy{ 2586275970Scy tt_int_op(event, ==, EV_TIMEOUT); 2587275970Scy called += 100; 2588275970Scyend: 2589275970Scy ; 2590275970Scy} 2591275970Scy 2592275970Scystatic void 2593275970Scyimmediate_called_twice_cb(evutil_socket_t fd, short event, void *arg) 2594275970Scy{ 2595275970Scy tt_int_op(event, ==, EV_TIMEOUT); 2596275970Scy called += 1000; 2597275970Scyend: 2598275970Scy ; 2599275970Scy} 2600275970Scy 2601275970Scystatic void 2602275970Scytest_event_once(void *ptr) 2603275970Scy{ 2604275970Scy struct basic_test_data *data = ptr; 2605275970Scy struct timeval tv; 2606275970Scy int r; 2607275970Scy 2608275970Scy tv.tv_sec = 0; 2609275970Scy tv.tv_usec = 50*1000; 2610275970Scy called = 0; 2611275970Scy r = event_base_once(data->base, data->pair[0], EV_READ, 2612275970Scy read_called_once_cb, NULL, NULL); 2613275970Scy tt_int_op(r, ==, 0); 2614275970Scy r = event_base_once(data->base, -1, EV_TIMEOUT, 2615275970Scy timeout_called_once_cb, NULL, &tv); 2616275970Scy tt_int_op(r, ==, 0); 2617275970Scy r = event_base_once(data->base, -1, 0, NULL, NULL, NULL); 2618275970Scy tt_int_op(r, <, 0); 2619275970Scy r = event_base_once(data->base, -1, EV_TIMEOUT, 2620275970Scy immediate_called_twice_cb, NULL, NULL); 2621275970Scy tt_int_op(r, ==, 0); 2622275970Scy tv.tv_sec = 0; 2623275970Scy tv.tv_usec = 0; 2624275970Scy r = event_base_once(data->base, -1, EV_TIMEOUT, 2625275970Scy immediate_called_twice_cb, NULL, &tv); 2626275970Scy tt_int_op(r, ==, 0); 2627275970Scy 2628275970Scy if (write(data->pair[1], TEST1, strlen(TEST1)+1) < 0) { 2629275970Scy tt_fail_perror("write"); 2630275970Scy } 2631275970Scy 2632275970Scy shutdown(data->pair[1], SHUT_WR); 2633275970Scy 2634275970Scy event_base_dispatch(data->base); 2635275970Scy 2636275970Scy tt_int_op(called, ==, 2101); 2637275970Scyend: 2638275970Scy ; 2639275970Scy} 2640275970Scy 2641275970Scystatic void 2642275970Scytest_event_once_never(void *ptr) 2643275970Scy{ 2644275970Scy struct basic_test_data *data = ptr; 2645275970Scy struct timeval tv; 2646275970Scy 2647275970Scy /* Have one trigger in 10 seconds (don't worry, because) */ 2648275970Scy tv.tv_sec = 10; 2649275970Scy tv.tv_usec = 0; 2650275970Scy called = 0; 2651275970Scy event_base_once(data->base, -1, EV_TIMEOUT, 2652275970Scy timeout_called_once_cb, NULL, &tv); 2653275970Scy 2654275970Scy /* But shut down the base in 75 msec. */ 2655275970Scy tv.tv_sec = 0; 2656275970Scy tv.tv_usec = 75*1000; 2657275970Scy event_base_loopexit(data->base, &tv); 2658275970Scy 2659275970Scy event_base_dispatch(data->base); 2660275970Scy 2661275970Scy tt_int_op(called, ==, 0); 2662275970Scyend: 2663275970Scy ; 2664275970Scy} 2665275970Scy 2666275970Scystatic void 2667275970Scytest_event_pending(void *ptr) 2668275970Scy{ 2669275970Scy struct basic_test_data *data = ptr; 2670275970Scy struct event *r=NULL, *w=NULL, *t=NULL; 2671275970Scy struct timeval tv, now, tv2; 2672275970Scy 2673275970Scy tv.tv_sec = 0; 2674275970Scy tv.tv_usec = 500 * 1000; 2675275970Scy r = event_new(data->base, data->pair[0], EV_READ, simple_read_cb, 2676275970Scy NULL); 2677275970Scy w = event_new(data->base, data->pair[1], EV_WRITE, simple_write_cb, 2678275970Scy NULL); 2679275970Scy t = evtimer_new(data->base, timeout_cb, NULL); 2680275970Scy 2681275970Scy tt_assert(r); 2682275970Scy tt_assert(w); 2683275970Scy tt_assert(t); 2684275970Scy 2685275970Scy evutil_gettimeofday(&now, NULL); 2686275970Scy event_add(r, NULL); 2687275970Scy event_add(t, &tv); 2688275970Scy 2689275970Scy tt_assert( event_pending(r, EV_READ, NULL)); 2690275970Scy tt_assert(!event_pending(w, EV_WRITE, NULL)); 2691275970Scy tt_assert(!event_pending(r, EV_WRITE, NULL)); 2692275970Scy tt_assert( event_pending(r, EV_READ|EV_WRITE, NULL)); 2693275970Scy tt_assert(!event_pending(r, EV_TIMEOUT, NULL)); 2694275970Scy tt_assert( event_pending(t, EV_TIMEOUT, NULL)); 2695275970Scy tt_assert( event_pending(t, EV_TIMEOUT, &tv2)); 2696275970Scy 2697275970Scy tt_assert(evutil_timercmp(&tv2, &now, >)); 2698275970Scy 2699275970Scy test_timeval_diff_eq(&now, &tv2, 500); 2700275970Scy 2701275970Scyend: 2702275970Scy if (r) { 2703275970Scy event_del(r); 2704275970Scy event_free(r); 2705275970Scy } 2706275970Scy if (w) { 2707275970Scy event_del(w); 2708275970Scy event_free(w); 2709275970Scy } 2710275970Scy if (t) { 2711275970Scy event_del(t); 2712275970Scy event_free(t); 2713275970Scy } 2714275970Scy} 2715275970Scy 2716275970Scy#ifndef _WIN32 2717275970Scy/* You can't do this test on windows, since dup2 doesn't work on sockets */ 2718275970Scy 2719275970Scystatic void 2720275970Scydfd_cb(evutil_socket_t fd, short e, void *data) 2721275970Scy{ 2722275970Scy *(int*)data = (int)e; 2723275970Scy} 2724275970Scy 2725275970Scy/* Regression test for our workaround for a fun epoll/linux related bug 2726275970Scy * where fd2 = dup(fd1); add(fd2); close(fd2); dup2(fd1,fd2); add(fd2) 2727275970Scy * will get you an EEXIST */ 2728275970Scystatic void 2729275970Scytest_dup_fd(void *arg) 2730275970Scy{ 2731275970Scy struct basic_test_data *data = arg; 2732275970Scy struct event_base *base = data->base; 2733275970Scy struct event *ev1=NULL, *ev2=NULL; 2734275970Scy int fd, dfd=-1; 2735275970Scy int ev1_got, ev2_got; 2736275970Scy 2737275970Scy tt_int_op(write(data->pair[0], "Hello world", 2738275970Scy strlen("Hello world")), >, 0); 2739275970Scy fd = data->pair[1]; 2740275970Scy 2741275970Scy dfd = dup(fd); 2742275970Scy tt_int_op(dfd, >=, 0); 2743275970Scy 2744275970Scy ev1 = event_new(base, fd, EV_READ|EV_PERSIST, dfd_cb, &ev1_got); 2745275970Scy ev2 = event_new(base, dfd, EV_READ|EV_PERSIST, dfd_cb, &ev2_got); 2746275970Scy ev1_got = ev2_got = 0; 2747275970Scy event_add(ev1, NULL); 2748275970Scy event_add(ev2, NULL); 2749275970Scy event_base_loop(base, EVLOOP_ONCE); 2750275970Scy tt_int_op(ev1_got, ==, EV_READ); 2751275970Scy tt_int_op(ev2_got, ==, EV_READ); 2752275970Scy 2753275970Scy /* Now close and delete dfd then dispatch. We need to do the 2754275970Scy * dispatch here so that when we add it later, we think there 2755275970Scy * was an intermediate delete. */ 2756275970Scy close(dfd); 2757275970Scy event_del(ev2); 2758275970Scy ev1_got = ev2_got = 0; 2759275970Scy event_base_loop(base, EVLOOP_ONCE); 2760275970Scy tt_want_int_op(ev1_got, ==, EV_READ); 2761275970Scy tt_int_op(ev2_got, ==, 0); 2762275970Scy 2763275970Scy /* Re-duplicate the fd. We need to get the same duplicated 2764275970Scy * value that we closed to provoke the epoll quirk. Also, we 2765275970Scy * need to change the events to write, or else the old lingering 2766275970Scy * read event will make the test pass whether the change was 2767275970Scy * successful or not. */ 2768275970Scy tt_int_op(dup2(fd, dfd), ==, dfd); 2769275970Scy event_free(ev2); 2770275970Scy ev2 = event_new(base, dfd, EV_WRITE|EV_PERSIST, dfd_cb, &ev2_got); 2771275970Scy event_add(ev2, NULL); 2772275970Scy ev1_got = ev2_got = 0; 2773275970Scy event_base_loop(base, EVLOOP_ONCE); 2774275970Scy tt_want_int_op(ev1_got, ==, EV_READ); 2775275970Scy tt_int_op(ev2_got, ==, EV_WRITE); 2776275970Scy 2777275970Scyend: 2778275970Scy if (ev1) 2779275970Scy event_free(ev1); 2780275970Scy if (ev2) 2781275970Scy event_free(ev2); 2782275970Scy if (dfd >= 0) 2783275970Scy close(dfd); 2784275970Scy} 2785275970Scy#endif 2786275970Scy 2787275970Scy#ifdef EVENT__DISABLE_MM_REPLACEMENT 2788275970Scystatic void 2789275970Scytest_mm_functions(void *arg) 2790275970Scy{ 2791275970Scy tinytest_set_test_skipped_(); 2792275970Scy} 2793275970Scy#else 2794275970Scystatic int 2795275970Scycheck_dummy_mem_ok(void *mem_) 2796275970Scy{ 2797275970Scy char *mem = mem_; 2798275970Scy mem -= 16; 2799275970Scy return !memcmp(mem, "{[<guardedram>]}", 16); 2800275970Scy} 2801275970Scy 2802275970Scystatic void * 2803275970Scydummy_malloc(size_t len) 2804275970Scy{ 2805275970Scy char *mem = malloc(len+16); 2806275970Scy memcpy(mem, "{[<guardedram>]}", 16); 2807275970Scy return mem+16; 2808275970Scy} 2809275970Scy 2810275970Scystatic void * 2811275970Scydummy_realloc(void *mem_, size_t len) 2812275970Scy{ 2813275970Scy char *mem = mem_; 2814275970Scy if (!mem) 2815275970Scy return dummy_malloc(len); 2816275970Scy tt_want(check_dummy_mem_ok(mem_)); 2817275970Scy mem -= 16; 2818275970Scy mem = realloc(mem, len+16); 2819275970Scy return mem+16; 2820275970Scy} 2821275970Scy 2822275970Scystatic void 2823275970Scydummy_free(void *mem_) 2824275970Scy{ 2825275970Scy char *mem = mem_; 2826275970Scy tt_want(check_dummy_mem_ok(mem_)); 2827275970Scy mem -= 16; 2828275970Scy free(mem); 2829275970Scy} 2830275970Scy 2831275970Scystatic void 2832275970Scytest_mm_functions(void *arg) 2833275970Scy{ 2834275970Scy struct event_base *b = NULL; 2835275970Scy struct event_config *cfg = NULL; 2836275970Scy event_set_mem_functions(dummy_malloc, dummy_realloc, dummy_free); 2837275970Scy cfg = event_config_new(); 2838275970Scy event_config_avoid_method(cfg, "Nonesuch"); 2839275970Scy b = event_base_new_with_config(cfg); 2840275970Scy tt_assert(b); 2841275970Scy tt_assert(check_dummy_mem_ok(b)); 2842275970Scyend: 2843275970Scy if (cfg) 2844275970Scy event_config_free(cfg); 2845275970Scy if (b) 2846275970Scy event_base_free(b); 2847275970Scy} 2848275970Scy#endif 2849275970Scy 2850275970Scystatic void 2851275970Scymany_event_cb(evutil_socket_t fd, short event, void *arg) 2852275970Scy{ 2853275970Scy int *calledp = arg; 2854275970Scy *calledp += 1; 2855275970Scy} 2856275970Scy 2857275970Scystatic void 2858275970Scytest_many_events(void *arg) 2859275970Scy{ 2860275970Scy /* Try 70 events that should all be ready at once. This will 2861275970Scy * exercise the "resize" code on most of the backends, and will make 2862275970Scy * sure that we can get past the 64-handle limit of some windows 2863275970Scy * functions. */ 2864275970Scy#define MANY 70 2865275970Scy 2866275970Scy struct basic_test_data *data = arg; 2867275970Scy struct event_base *base = data->base; 2868275970Scy int one_at_a_time = data->setup_data != NULL; 2869275970Scy evutil_socket_t sock[MANY]; 2870275970Scy struct event *ev[MANY]; 2871275970Scy int called[MANY]; 2872275970Scy int i; 2873275970Scy int loopflags = EVLOOP_NONBLOCK, evflags=0; 2874275970Scy if (one_at_a_time) { 2875275970Scy loopflags |= EVLOOP_ONCE; 2876275970Scy evflags = EV_PERSIST; 2877275970Scy } 2878275970Scy 2879275970Scy memset(sock, 0xff, sizeof(sock)); 2880275970Scy memset(ev, 0, sizeof(ev)); 2881275970Scy memset(called, 0, sizeof(called)); 2882275970Scy 2883275970Scy for (i = 0; i < MANY; ++i) { 2884275970Scy /* We need an event that will hit the backend, and that will 2885275970Scy * be ready immediately. "Send a datagram" is an easy 2886275970Scy * instance of that. */ 2887275970Scy sock[i] = socket(AF_INET, SOCK_DGRAM, 0); 2888275970Scy tt_assert(sock[i] >= 0); 2889275970Scy called[i] = 0; 2890275970Scy ev[i] = event_new(base, sock[i], EV_WRITE|evflags, 2891275970Scy many_event_cb, &called[i]); 2892275970Scy event_add(ev[i], NULL); 2893275970Scy if (one_at_a_time) 2894275970Scy event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE); 2895275970Scy } 2896275970Scy 2897275970Scy event_base_loop(base, loopflags); 2898275970Scy 2899275970Scy for (i = 0; i < MANY; ++i) { 2900275970Scy if (one_at_a_time) 2901275970Scy tt_int_op(called[i], ==, MANY - i + 1); 2902275970Scy else 2903275970Scy tt_int_op(called[i], ==, 1); 2904275970Scy } 2905275970Scy 2906275970Scyend: 2907275970Scy for (i = 0; i < MANY; ++i) { 2908275970Scy if (ev[i]) 2909275970Scy event_free(ev[i]); 2910275970Scy if (sock[i] >= 0) 2911275970Scy evutil_closesocket(sock[i]); 2912275970Scy } 2913275970Scy#undef MANY 2914275970Scy} 2915275970Scy 2916275970Scystatic void 2917275970Scytest_struct_event_size(void *arg) 2918275970Scy{ 2919275970Scy tt_int_op(event_get_struct_event_size(), <=, sizeof(struct event)); 2920275970Scyend: 2921275970Scy ; 2922275970Scy} 2923275970Scy 2924275970Scystatic void 2925275970Scytest_get_assignment(void *arg) 2926275970Scy{ 2927275970Scy struct basic_test_data *data = arg; 2928275970Scy struct event_base *base = data->base; 2929275970Scy struct event *ev1 = NULL; 2930275970Scy const char *str = "foo"; 2931275970Scy 2932275970Scy struct event_base *b; 2933275970Scy evutil_socket_t s; 2934275970Scy short what; 2935275970Scy event_callback_fn cb; 2936275970Scy void *cb_arg; 2937275970Scy 2938275970Scy ev1 = event_new(base, data->pair[1], EV_READ, dummy_read_cb, (void*)str); 2939275970Scy event_get_assignment(ev1, &b, &s, &what, &cb, &cb_arg); 2940275970Scy 2941275970Scy tt_ptr_op(b, ==, base); 2942275970Scy tt_int_op(s, ==, data->pair[1]); 2943275970Scy tt_int_op(what, ==, EV_READ); 2944275970Scy tt_ptr_op(cb, ==, dummy_read_cb); 2945275970Scy tt_ptr_op(cb_arg, ==, str); 2946275970Scy 2947275970Scy /* Now make sure this doesn't crash. */ 2948275970Scy event_get_assignment(ev1, NULL, NULL, NULL, NULL, NULL); 2949275970Scy 2950275970Scyend: 2951275970Scy if (ev1) 2952275970Scy event_free(ev1); 2953275970Scy} 2954275970Scy 2955275970Scystruct foreach_helper { 2956275970Scy int count; 2957275970Scy const struct event *ev; 2958275970Scy}; 2959275970Scy 2960275970Scystatic int 2961275970Scyforeach_count_cb(const struct event_base *base, const struct event *ev, void *arg) 2962275970Scy{ 2963275970Scy struct foreach_helper *h = event_get_callback_arg(ev); 2964275970Scy struct timeval *tv = arg; 2965275970Scy if (event_get_callback(ev) != timeout_cb) 2966275970Scy return 0; 2967275970Scy tt_ptr_op(event_get_base(ev), ==, base); 2968275970Scy tt_int_op(tv->tv_sec, ==, 10); 2969275970Scy h->ev = ev; 2970275970Scy h->count++; 2971275970Scy return 0; 2972275970Scyend: 2973275970Scy return -1; 2974275970Scy} 2975275970Scy 2976275970Scystatic int 2977275970Scyforeach_find_cb(const struct event_base *base, const struct event *ev, void *arg) 2978275970Scy{ 2979275970Scy const struct event **ev_out = arg; 2980275970Scy struct foreach_helper *h = event_get_callback_arg(ev); 2981275970Scy if (event_get_callback(ev) != timeout_cb) 2982275970Scy return 0; 2983275970Scy if (h->count == 99) { 2984275970Scy *ev_out = ev; 2985275970Scy return 101; 2986275970Scy } 2987275970Scy return 0; 2988275970Scy} 2989275970Scy 2990275970Scystatic void 2991275970Scytest_event_foreach(void *arg) 2992275970Scy{ 2993275970Scy struct basic_test_data *data = arg; 2994275970Scy struct event_base *base = data->base; 2995275970Scy struct event *ev[5]; 2996275970Scy struct foreach_helper visited[5]; 2997275970Scy int i; 2998275970Scy struct timeval ten_sec = {10,0}; 2999275970Scy const struct event *ev_found = NULL; 3000275970Scy 3001275970Scy for (i = 0; i < 5; ++i) { 3002275970Scy visited[i].count = 0; 3003275970Scy visited[i].ev = NULL; 3004275970Scy ev[i] = event_new(base, -1, 0, timeout_cb, &visited[i]); 3005275970Scy } 3006275970Scy 3007275970Scy tt_int_op(-1, ==, event_base_foreach_event(NULL, foreach_count_cb, NULL)); 3008275970Scy tt_int_op(-1, ==, event_base_foreach_event(base, NULL, NULL)); 3009275970Scy 3010275970Scy event_add(ev[0], &ten_sec); 3011275970Scy event_add(ev[1], &ten_sec); 3012275970Scy event_active(ev[1], EV_TIMEOUT, 1); 3013275970Scy event_active(ev[2], EV_TIMEOUT, 1); 3014275970Scy event_add(ev[3], &ten_sec); 3015275970Scy /* Don't touch ev[4]. */ 3016275970Scy 3017275970Scy tt_int_op(0, ==, event_base_foreach_event(base, foreach_count_cb, 3018275970Scy &ten_sec)); 3019275970Scy tt_int_op(1, ==, visited[0].count); 3020275970Scy tt_int_op(1, ==, visited[1].count); 3021275970Scy tt_int_op(1, ==, visited[2].count); 3022275970Scy tt_int_op(1, ==, visited[3].count); 3023275970Scy tt_ptr_op(ev[0], ==, visited[0].ev); 3024275970Scy tt_ptr_op(ev[1], ==, visited[1].ev); 3025275970Scy tt_ptr_op(ev[2], ==, visited[2].ev); 3026275970Scy tt_ptr_op(ev[3], ==, visited[3].ev); 3027275970Scy 3028275970Scy visited[2].count = 99; 3029275970Scy tt_int_op(101, ==, event_base_foreach_event(base, foreach_find_cb, 3030275970Scy &ev_found)); 3031275970Scy tt_ptr_op(ev_found, ==, ev[2]); 3032275970Scy 3033275970Scyend: 3034275970Scy for (i=0; i<5; ++i) { 3035275970Scy event_free(ev[i]); 3036275970Scy } 3037275970Scy} 3038275970Scy 3039275970Scystatic struct event_base *cached_time_base = NULL; 3040275970Scystatic int cached_time_reset = 0; 3041275970Scystatic int cached_time_sleep = 0; 3042275970Scystatic void 3043275970Scycache_time_cb(evutil_socket_t fd, short what, void *arg) 3044275970Scy{ 3045275970Scy struct timeval *tv = arg; 3046275970Scy tt_int_op(0, ==, event_base_gettimeofday_cached(cached_time_base, tv)); 3047275970Scy if (cached_time_sleep) { 3048275970Scy struct timeval delay = { 0, 30*1000 }; 3049275970Scy evutil_usleep_(&delay); 3050275970Scy } 3051275970Scy if (cached_time_reset) { 3052275970Scy event_base_update_cache_time(cached_time_base); 3053275970Scy } 3054275970Scyend: 3055275970Scy ; 3056275970Scy} 3057275970Scy 3058275970Scystatic void 3059275970Scytest_gettimeofday_cached(void *arg) 3060275970Scy{ 3061275970Scy struct basic_test_data *data = arg; 3062275970Scy struct event_config *cfg = NULL; 3063275970Scy struct event_base *base = NULL; 3064275970Scy struct timeval tv1, tv2, tv3, now; 3065275970Scy struct event *ev1=NULL, *ev2=NULL, *ev3=NULL; 3066275970Scy int cached_time_disable = strstr(data->setup_data, "disable") != NULL; 3067275970Scy 3068275970Scy cfg = event_config_new(); 3069275970Scy if (cached_time_disable) { 3070275970Scy event_config_set_flag(cfg, EVENT_BASE_FLAG_NO_CACHE_TIME); 3071275970Scy } 3072275970Scy cached_time_base = base = event_base_new_with_config(cfg); 3073275970Scy tt_assert(base); 3074275970Scy 3075275970Scy /* Try gettimeofday_cached outside of an event loop. */ 3076275970Scy evutil_gettimeofday(&now, NULL); 3077275970Scy tt_int_op(0, ==, event_base_gettimeofday_cached(NULL, &tv1)); 3078275970Scy tt_int_op(0, ==, event_base_gettimeofday_cached(base, &tv2)); 3079275970Scy tt_int_op(timeval_msec_diff(&tv1, &tv2), <, 10); 3080275970Scy tt_int_op(timeval_msec_diff(&tv1, &now), <, 10); 3081275970Scy 3082275970Scy cached_time_reset = strstr(data->setup_data, "reset") != NULL; 3083275970Scy cached_time_sleep = strstr(data->setup_data, "sleep") != NULL; 3084275970Scy 3085275970Scy ev1 = event_new(base, -1, 0, cache_time_cb, &tv1); 3086275970Scy ev2 = event_new(base, -1, 0, cache_time_cb, &tv2); 3087275970Scy ev3 = event_new(base, -1, 0, cache_time_cb, &tv3); 3088275970Scy 3089275970Scy event_active(ev1, EV_TIMEOUT, 1); 3090275970Scy event_active(ev2, EV_TIMEOUT, 1); 3091275970Scy event_active(ev3, EV_TIMEOUT, 1); 3092275970Scy 3093275970Scy event_base_dispatch(base); 3094275970Scy 3095275970Scy if (cached_time_reset && cached_time_sleep) { 3096275970Scy tt_int_op(labs(timeval_msec_diff(&tv1,&tv2)), >, 10); 3097275970Scy tt_int_op(labs(timeval_msec_diff(&tv2,&tv3)), >, 10); 3098275970Scy } else if (cached_time_disable && cached_time_sleep) { 3099275970Scy tt_int_op(labs(timeval_msec_diff(&tv1,&tv2)), >, 10); 3100275970Scy tt_int_op(labs(timeval_msec_diff(&tv2,&tv3)), >, 10); 3101275970Scy } else if (! cached_time_disable) { 3102275970Scy tt_assert(evutil_timercmp(&tv1, &tv2, ==)); 3103275970Scy tt_assert(evutil_timercmp(&tv2, &tv3, ==)); 3104275970Scy } 3105275970Scy 3106275970Scyend: 3107275970Scy if (ev1) 3108275970Scy event_free(ev1); 3109275970Scy if (ev2) 3110275970Scy event_free(ev2); 3111275970Scy if (ev3) 3112275970Scy event_free(ev3); 3113275970Scy if (base) 3114275970Scy event_base_free(base); 3115275970Scy if (cfg) 3116275970Scy event_config_free(cfg); 3117275970Scy} 3118275970Scy 3119275970Scystatic void 3120275970Scytabf_cb(evutil_socket_t fd, short what, void *arg) 3121275970Scy{ 3122275970Scy int *ptr = arg; 3123275970Scy *ptr = what; 3124275970Scy *ptr += 0x10000; 3125275970Scy} 3126275970Scy 3127275970Scystatic void 3128275970Scytest_active_by_fd(void *arg) 3129275970Scy{ 3130275970Scy struct basic_test_data *data = arg; 3131275970Scy struct event_base *base = data->base; 3132275970Scy struct event *ev1 = NULL, *ev2 = NULL, *ev3 = NULL, *ev4 = NULL; 3133275970Scy int e1,e2,e3,e4; 3134275970Scy#ifndef _WIN32 3135275970Scy struct event *evsig = NULL; 3136275970Scy int es; 3137275970Scy#endif 3138275970Scy struct timeval tenmin = { 600, 0 }; 3139275970Scy 3140275970Scy /* Ensure no crash on nonexistent FD. */ 3141275970Scy event_base_active_by_fd(base, 1000, EV_READ); 3142275970Scy 3143275970Scy /* Ensure no crash on bogus FD. */ 3144275970Scy event_base_active_by_fd(base, -1, EV_READ); 3145275970Scy 3146275970Scy /* Ensure no crash on nonexistent/bogus signal. */ 3147275970Scy event_base_active_by_signal(base, 1000); 3148275970Scy event_base_active_by_signal(base, -1); 3149275970Scy 3150275970Scy event_base_assert_ok_(base); 3151275970Scy 3152275970Scy e1 = e2 = e3 = e4 = 0; 3153275970Scy ev1 = event_new(base, data->pair[0], EV_READ, tabf_cb, &e1); 3154275970Scy ev2 = event_new(base, data->pair[0], EV_WRITE, tabf_cb, &e2); 3155275970Scy ev3 = event_new(base, data->pair[1], EV_READ, tabf_cb, &e3); 3156275970Scy ev4 = event_new(base, data->pair[1], EV_READ, tabf_cb, &e4); 3157275970Scy tt_assert(ev1); 3158275970Scy tt_assert(ev2); 3159275970Scy tt_assert(ev3); 3160275970Scy tt_assert(ev4); 3161275970Scy#ifndef _WIN32 3162275970Scy evsig = event_new(base, SIGHUP, EV_SIGNAL, tabf_cb, &es); 3163275970Scy tt_assert(evsig); 3164275970Scy event_add(evsig, &tenmin); 3165275970Scy#endif 3166275970Scy 3167275970Scy event_add(ev1, &tenmin); 3168275970Scy event_add(ev2, NULL); 3169275970Scy event_add(ev3, NULL); 3170275970Scy event_add(ev4, &tenmin); 3171275970Scy 3172275970Scy 3173275970Scy event_base_assert_ok_(base); 3174275970Scy 3175275970Scy /* Trigger 2, 3, 4 */ 3176275970Scy event_base_active_by_fd(base, data->pair[0], EV_WRITE); 3177275970Scy event_base_active_by_fd(base, data->pair[1], EV_READ); 3178275970Scy#ifndef _WIN32 3179275970Scy event_base_active_by_signal(base, SIGHUP); 3180275970Scy#endif 3181275970Scy 3182275970Scy event_base_assert_ok_(base); 3183275970Scy 3184275970Scy event_base_loop(base, EVLOOP_ONCE); 3185275970Scy 3186275970Scy tt_int_op(e1, ==, 0); 3187275970Scy tt_int_op(e2, ==, EV_WRITE | 0x10000); 3188275970Scy tt_int_op(e3, ==, EV_READ | 0x10000); 3189275970Scy /* Mask out EV_WRITE here, since it could be genuinely writeable. */ 3190275970Scy tt_int_op((e4 & ~EV_WRITE), ==, EV_READ | 0x10000); 3191275970Scy#ifndef _WIN32 3192275970Scy tt_int_op(es, ==, EV_SIGNAL | 0x10000); 3193275970Scy#endif 3194275970Scy 3195275970Scyend: 3196275970Scy if (ev1) 3197275970Scy event_free(ev1); 3198275970Scy if (ev2) 3199275970Scy event_free(ev2); 3200275970Scy if (ev3) 3201275970Scy event_free(ev3); 3202275970Scy if (ev4) 3203275970Scy event_free(ev4); 3204275970Scy#ifndef _WIN32 3205275970Scy if (evsig) 3206275970Scy event_free(evsig); 3207275970Scy#endif 3208275970Scy} 3209275970Scy 3210275970Scystruct testcase_t main_testcases[] = { 3211275970Scy /* Some converted-over tests */ 3212275970Scy { "methods", test_methods, TT_FORK, NULL, NULL }, 3213275970Scy { "version", test_version, 0, NULL, NULL }, 3214275970Scy BASIC(base_features, TT_FORK|TT_NO_LOGS), 3215275970Scy { "base_environ", test_base_environ, TT_FORK, NULL, NULL }, 3216275970Scy 3217275970Scy BASIC(event_base_new, TT_FORK|TT_NEED_SOCKETPAIR), 3218275970Scy BASIC(free_active_base, TT_FORK|TT_NEED_SOCKETPAIR), 3219275970Scy 3220275970Scy BASIC(manipulate_active_events, TT_FORK|TT_NEED_BASE), 3221275970Scy BASIC(event_new_selfarg, TT_FORK|TT_NEED_BASE), 3222275970Scy BASIC(event_assign_selfarg, TT_FORK|TT_NEED_BASE), 3223275970Scy BASIC(event_base_get_num_events, TT_FORK|TT_NEED_BASE), 3224275970Scy BASIC(event_base_get_max_events, TT_FORK|TT_NEED_BASE), 3225275970Scy 3226275970Scy BASIC(bad_assign, TT_FORK|TT_NEED_BASE|TT_NO_LOGS), 3227275970Scy BASIC(bad_reentrant, TT_FORK|TT_NEED_BASE|TT_NO_LOGS), 3228275970Scy BASIC(active_later, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 3229275970Scy BASIC(event_remove_timeout, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 3230275970Scy 3231275970Scy /* These are still using the old API */ 3232275970Scy LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE), 3233275970Scy { "persistent_timeout_jump", test_persistent_timeout_jump, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 3234275970Scy { "persistent_active_timeout", test_persistent_active_timeout, 3235275970Scy TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 3236275970Scy LEGACY(priorities, TT_FORK|TT_NEED_BASE), 3237275970Scy BASIC(priority_active_inversion, TT_FORK|TT_NEED_BASE), 3238275970Scy { "common_timeout", test_common_timeout, TT_FORK|TT_NEED_BASE, 3239275970Scy &basic_setup, NULL }, 3240275970Scy 3241275970Scy /* These legacy tests may not all need all of these flags. */ 3242275970Scy LEGACY(simpleread, TT_ISOLATED), 3243275970Scy LEGACY(simpleread_multiple, TT_ISOLATED), 3244275970Scy LEGACY(simplewrite, TT_ISOLATED), 3245275970Scy { "simpleclose", test_simpleclose, TT_FORK, &basic_setup, 3246275970Scy NULL }, 3247275970Scy LEGACY(multiple, TT_ISOLATED), 3248275970Scy LEGACY(persistent, TT_ISOLATED), 3249275970Scy LEGACY(combined, TT_ISOLATED), 3250275970Scy LEGACY(simpletimeout, TT_ISOLATED), 3251275970Scy LEGACY(loopbreak, TT_ISOLATED), 3252275970Scy LEGACY(loopexit, TT_ISOLATED), 3253275970Scy LEGACY(loopexit_multiple, TT_ISOLATED), 3254275970Scy LEGACY(nonpersist_readd, TT_ISOLATED), 3255275970Scy LEGACY(multiple_events_for_same_fd, TT_ISOLATED), 3256275970Scy LEGACY(want_only_once, TT_ISOLATED), 3257275970Scy { "event_once", test_event_once, TT_ISOLATED, &basic_setup, NULL }, 3258275970Scy { "event_once_never", test_event_once_never, TT_ISOLATED, &basic_setup, NULL }, 3259275970Scy { "event_pending", test_event_pending, TT_ISOLATED, &basic_setup, 3260275970Scy NULL }, 3261275970Scy#ifndef _WIN32 3262275970Scy { "dup_fd", test_dup_fd, TT_ISOLATED, &basic_setup, NULL }, 3263275970Scy#endif 3264275970Scy { "mm_functions", test_mm_functions, TT_FORK, NULL, NULL }, 3265275970Scy { "many_events", test_many_events, TT_ISOLATED, &basic_setup, NULL }, 3266275970Scy { "many_events_slow_add", test_many_events, TT_ISOLATED, &basic_setup, (void*)1 }, 3267275970Scy 3268275970Scy { "struct_event_size", test_struct_event_size, 0, NULL, NULL }, 3269275970Scy BASIC(get_assignment, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 3270275970Scy 3271275970Scy BASIC(event_foreach, TT_FORK|TT_NEED_BASE), 3272275970Scy { "gettimeofday_cached", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"" }, 3273275970Scy { "gettimeofday_cached_sleep", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep" }, 3274275970Scy { "gettimeofday_cached_reset", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep reset" }, 3275275970Scy { "gettimeofday_cached_disabled", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep disable" }, 3276275970Scy { "gettimeofday_cached_disabled_nosleep", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"disable" }, 3277275970Scy 3278275970Scy BASIC(active_by_fd, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 3279275970Scy 3280275970Scy#ifndef _WIN32 3281275970Scy LEGACY(fork, TT_ISOLATED), 3282275970Scy#endif 3283275970Scy END_OF_TESTCASES 3284275970Scy}; 3285275970Scy 3286275970Scystruct testcase_t evtag_testcases[] = { 3287275970Scy { "int", evtag_int_test, TT_FORK, NULL, NULL }, 3288275970Scy { "fuzz", evtag_fuzz, TT_FORK, NULL, NULL }, 3289275970Scy { "encoding", evtag_tag_encoding, TT_FORK, NULL, NULL }, 3290275970Scy { "peek", evtag_test_peek, 0, NULL, NULL }, 3291275970Scy 3292275970Scy END_OF_TESTCASES 3293275970Scy}; 3294275970Scy 3295275970Scystruct testcase_t signal_testcases[] = { 3296275970Scy#ifndef _WIN32 3297275970Scy LEGACY(simplesignal, TT_ISOLATED), 3298275970Scy LEGACY(multiplesignal, TT_ISOLATED), 3299275970Scy LEGACY(immediatesignal, TT_ISOLATED), 3300275970Scy LEGACY(signal_dealloc, TT_ISOLATED), 3301275970Scy LEGACY(signal_pipeloss, TT_ISOLATED), 3302275970Scy LEGACY(signal_switchbase, TT_ISOLATED|TT_NO_LOGS), 3303275970Scy LEGACY(signal_restore, TT_ISOLATED), 3304275970Scy LEGACY(signal_assert, TT_ISOLATED), 3305275970Scy LEGACY(signal_while_processing, TT_ISOLATED), 3306275970Scy#endif 3307275970Scy END_OF_TESTCASES 3308275970Scy}; 3309275970Scy 3310