regress.c revision 285612
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 947285612Sdelphijtest_simplesignal_impl(int find_reorder) 948275970Scy{ 949275970Scy struct event ev; 950275970Scy struct itimerval itv; 951275970Scy 952275970Scy evsignal_set(&ev, SIGALRM, signal_cb, &ev); 953275970Scy evsignal_add(&ev, NULL); 954275970Scy /* find bugs in which operations are re-ordered */ 955285612Sdelphij if (find_reorder) { 956285612Sdelphij evsignal_del(&ev); 957285612Sdelphij evsignal_add(&ev, NULL); 958285612Sdelphij } 959275970Scy 960275970Scy memset(&itv, 0, sizeof(itv)); 961275970Scy itv.it_value.tv_sec = 0; 962275970Scy itv.it_value.tv_usec = 100000; 963275970Scy if (setitimer(ITIMER_REAL, &itv, NULL) == -1) 964275970Scy goto skip_simplesignal; 965275970Scy 966275970Scy event_dispatch(); 967275970Scy skip_simplesignal: 968275970Scy if (evsignal_del(&ev) == -1) 969275970Scy test_ok = 0; 970275970Scy 971275970Scy cleanup_test(); 972275970Scy} 973275970Scy 974275970Scystatic void 975285612Sdelphijtest_simplestsignal(void) 976285612Sdelphij{ 977285612Sdelphij setup_test("Simplest one signal: "); 978285612Sdelphij test_simplesignal_impl(0); 979285612Sdelphij} 980285612Sdelphij 981285612Sdelphijstatic void 982285612Sdelphijtest_simplesignal(void) 983285612Sdelphij{ 984285612Sdelphij setup_test("Simple signal: "); 985285612Sdelphij test_simplesignal_impl(1); 986285612Sdelphij} 987285612Sdelphij 988285612Sdelphijstatic void 989275970Scytest_multiplesignal(void) 990275970Scy{ 991275970Scy struct event ev_one, ev_two; 992275970Scy struct itimerval itv; 993275970Scy 994275970Scy setup_test("Multiple signal: "); 995275970Scy 996275970Scy evsignal_set(&ev_one, SIGALRM, signal_cb, &ev_one); 997275970Scy evsignal_add(&ev_one, NULL); 998275970Scy 999275970Scy evsignal_set(&ev_two, SIGALRM, signal_cb, &ev_two); 1000275970Scy evsignal_add(&ev_two, NULL); 1001275970Scy 1002275970Scy memset(&itv, 0, sizeof(itv)); 1003275970Scy itv.it_value.tv_sec = 0; 1004275970Scy itv.it_value.tv_usec = 100000; 1005275970Scy if (setitimer(ITIMER_REAL, &itv, NULL) == -1) 1006275970Scy goto skip_simplesignal; 1007275970Scy 1008275970Scy event_dispatch(); 1009275970Scy 1010275970Scy skip_simplesignal: 1011275970Scy if (evsignal_del(&ev_one) == -1) 1012275970Scy test_ok = 0; 1013275970Scy if (evsignal_del(&ev_two) == -1) 1014275970Scy test_ok = 0; 1015275970Scy 1016275970Scy cleanup_test(); 1017275970Scy} 1018275970Scy 1019275970Scystatic void 1020275970Scytest_immediatesignal(void) 1021275970Scy{ 1022275970Scy struct event ev; 1023275970Scy 1024275970Scy test_ok = 0; 1025275970Scy evsignal_set(&ev, SIGUSR1, signal_cb, &ev); 1026275970Scy evsignal_add(&ev, NULL); 1027275970Scy raise(SIGUSR1); 1028275970Scy event_loop(EVLOOP_NONBLOCK); 1029275970Scy evsignal_del(&ev); 1030275970Scy cleanup_test(); 1031275970Scy} 1032275970Scy 1033275970Scystatic void 1034275970Scytest_signal_dealloc(void) 1035275970Scy{ 1036275970Scy /* make sure that evsignal_event is event_del'ed and pipe closed */ 1037275970Scy struct event ev; 1038275970Scy struct event_base *base = event_init(); 1039275970Scy evsignal_set(&ev, SIGUSR1, signal_cb, &ev); 1040275970Scy evsignal_add(&ev, NULL); 1041275970Scy evsignal_del(&ev); 1042275970Scy event_base_free(base); 1043275970Scy /* If we got here without asserting, we're fine. */ 1044275970Scy test_ok = 1; 1045275970Scy cleanup_test(); 1046275970Scy} 1047275970Scy 1048275970Scystatic void 1049275970Scytest_signal_pipeloss(void) 1050275970Scy{ 1051275970Scy /* make sure that the base1 pipe is closed correctly. */ 1052275970Scy struct event_base *base1, *base2; 1053275970Scy int pipe1; 1054275970Scy test_ok = 0; 1055275970Scy base1 = event_init(); 1056275970Scy pipe1 = base1->sig.ev_signal_pair[0]; 1057275970Scy base2 = event_init(); 1058275970Scy event_base_free(base2); 1059275970Scy event_base_free(base1); 1060275970Scy if (close(pipe1) != -1 || errno!=EBADF) { 1061275970Scy /* fd must be closed, so second close gives -1, EBADF */ 1062275970Scy printf("signal pipe not closed. "); 1063275970Scy test_ok = 0; 1064275970Scy } else { 1065275970Scy test_ok = 1; 1066275970Scy } 1067275970Scy cleanup_test(); 1068275970Scy} 1069275970Scy 1070275970Scy/* 1071275970Scy * make two bases to catch signals, use both of them. this only works 1072275970Scy * for event mechanisms that use our signal pipe trick. kqueue handles 1073275970Scy * signals internally, and all interested kqueues get all the signals. 1074275970Scy */ 1075275970Scystatic void 1076275970Scytest_signal_switchbase(void) 1077275970Scy{ 1078275970Scy struct event ev1, ev2; 1079275970Scy struct event_base *base1, *base2; 1080275970Scy int is_kqueue; 1081275970Scy test_ok = 0; 1082275970Scy base1 = event_init(); 1083275970Scy base2 = event_init(); 1084275970Scy is_kqueue = !strcmp(event_get_method(),"kqueue"); 1085275970Scy evsignal_set(&ev1, SIGUSR1, signal_cb, &ev1); 1086275970Scy evsignal_set(&ev2, SIGUSR1, signal_cb, &ev2); 1087275970Scy if (event_base_set(base1, &ev1) || 1088275970Scy event_base_set(base2, &ev2) || 1089275970Scy event_add(&ev1, NULL) || 1090275970Scy event_add(&ev2, NULL)) { 1091275970Scy fprintf(stderr, "%s: cannot set base, add\n", __func__); 1092275970Scy exit(1); 1093275970Scy } 1094275970Scy 1095275970Scy tt_ptr_op(event_get_base(&ev1), ==, base1); 1096275970Scy tt_ptr_op(event_get_base(&ev2), ==, base2); 1097275970Scy 1098275970Scy test_ok = 0; 1099275970Scy /* can handle signal before loop is called */ 1100275970Scy raise(SIGUSR1); 1101275970Scy event_base_loop(base2, EVLOOP_NONBLOCK); 1102275970Scy if (is_kqueue) { 1103275970Scy if (!test_ok) 1104275970Scy goto end; 1105275970Scy test_ok = 0; 1106275970Scy } 1107275970Scy event_base_loop(base1, EVLOOP_NONBLOCK); 1108275970Scy if (test_ok && !is_kqueue) { 1109275970Scy test_ok = 0; 1110275970Scy 1111275970Scy /* set base1 to handle signals */ 1112275970Scy event_base_loop(base1, EVLOOP_NONBLOCK); 1113275970Scy raise(SIGUSR1); 1114275970Scy event_base_loop(base1, EVLOOP_NONBLOCK); 1115275970Scy event_base_loop(base2, EVLOOP_NONBLOCK); 1116275970Scy } 1117275970Scyend: 1118275970Scy event_base_free(base1); 1119275970Scy event_base_free(base2); 1120275970Scy cleanup_test(); 1121275970Scy} 1122275970Scy 1123275970Scy/* 1124275970Scy * assert that a signal event removed from the event queue really is 1125275970Scy * removed - with no possibility of it's parent handler being fired. 1126275970Scy */ 1127275970Scystatic void 1128275970Scytest_signal_assert(void) 1129275970Scy{ 1130275970Scy struct event ev; 1131275970Scy struct event_base *base = event_init(); 1132275970Scy test_ok = 0; 1133275970Scy /* use SIGCONT so we don't kill ourselves when we signal to nowhere */ 1134275970Scy evsignal_set(&ev, SIGCONT, signal_cb, &ev); 1135275970Scy evsignal_add(&ev, NULL); 1136275970Scy /* 1137275970Scy * if evsignal_del() fails to reset the handler, it's current handler 1138275970Scy * will still point to evsig_handler(). 1139275970Scy */ 1140275970Scy evsignal_del(&ev); 1141275970Scy 1142275970Scy raise(SIGCONT); 1143275970Scy#if 0 1144275970Scy /* only way to verify we were in evsig_handler() */ 1145275970Scy /* XXXX Now there's no longer a good way. */ 1146275970Scy if (base->sig.evsig_caught) 1147275970Scy test_ok = 0; 1148275970Scy else 1149275970Scy test_ok = 1; 1150275970Scy#else 1151275970Scy test_ok = 1; 1152275970Scy#endif 1153275970Scy 1154275970Scy event_base_free(base); 1155275970Scy cleanup_test(); 1156275970Scy return; 1157275970Scy} 1158275970Scy 1159275970Scy/* 1160275970Scy * assert that we restore our previous signal handler properly. 1161275970Scy */ 1162275970Scystatic void 1163275970Scytest_signal_restore(void) 1164275970Scy{ 1165275970Scy struct event ev; 1166275970Scy struct event_base *base = event_init(); 1167275970Scy#ifdef EVENT__HAVE_SIGACTION 1168275970Scy struct sigaction sa; 1169275970Scy#endif 1170275970Scy 1171275970Scy test_ok = 0; 1172275970Scy#ifdef EVENT__HAVE_SIGACTION 1173275970Scy sa.sa_handler = signal_cb_sa; 1174275970Scy sa.sa_flags = 0x0; 1175275970Scy sigemptyset(&sa.sa_mask); 1176275970Scy if (sigaction(SIGUSR1, &sa, NULL) == -1) 1177275970Scy goto out; 1178275970Scy#else 1179275970Scy if (signal(SIGUSR1, signal_cb_sa) == SIG_ERR) 1180275970Scy goto out; 1181275970Scy#endif 1182275970Scy evsignal_set(&ev, SIGUSR1, signal_cb, &ev); 1183275970Scy evsignal_add(&ev, NULL); 1184275970Scy evsignal_del(&ev); 1185275970Scy 1186275970Scy raise(SIGUSR1); 1187275970Scy /* 1 == signal_cb, 2 == signal_cb_sa, we want our previous handler */ 1188275970Scy if (test_ok != 2) 1189275970Scy test_ok = 0; 1190275970Scyout: 1191275970Scy event_base_free(base); 1192275970Scy cleanup_test(); 1193275970Scy return; 1194275970Scy} 1195275970Scy 1196275970Scystatic void 1197275970Scysignal_cb_swp(int sig, short event, void *arg) 1198275970Scy{ 1199275970Scy called++; 1200275970Scy if (called < 5) 1201275970Scy raise(sig); 1202275970Scy else 1203275970Scy event_loopexit(NULL); 1204275970Scy} 1205275970Scystatic void 1206275970Scytimeout_cb_swp(evutil_socket_t fd, short event, void *arg) 1207275970Scy{ 1208275970Scy if (called == -1) { 1209275970Scy struct timeval tv = {5, 0}; 1210275970Scy 1211275970Scy called = 0; 1212275970Scy evtimer_add((struct event *)arg, &tv); 1213275970Scy raise(SIGUSR1); 1214275970Scy return; 1215275970Scy } 1216275970Scy test_ok = 0; 1217275970Scy event_loopexit(NULL); 1218275970Scy} 1219275970Scy 1220275970Scystatic void 1221275970Scytest_signal_while_processing(void) 1222275970Scy{ 1223275970Scy struct event_base *base = event_init(); 1224275970Scy struct event ev, ev_timer; 1225275970Scy struct timeval tv = {0, 0}; 1226275970Scy 1227275970Scy setup_test("Receiving a signal while processing other signal: "); 1228275970Scy 1229275970Scy called = -1; 1230275970Scy test_ok = 1; 1231275970Scy signal_set(&ev, SIGUSR1, signal_cb_swp, NULL); 1232275970Scy signal_add(&ev, NULL); 1233275970Scy evtimer_set(&ev_timer, timeout_cb_swp, &ev_timer); 1234275970Scy evtimer_add(&ev_timer, &tv); 1235275970Scy event_dispatch(); 1236275970Scy 1237275970Scy event_base_free(base); 1238275970Scy cleanup_test(); 1239275970Scy return; 1240275970Scy} 1241275970Scy#endif 1242275970Scy 1243275970Scystatic void 1244275970Scytest_free_active_base(void *ptr) 1245275970Scy{ 1246275970Scy struct basic_test_data *data = ptr; 1247275970Scy struct event_base *base1; 1248275970Scy struct event ev1; 1249275970Scy 1250275970Scy base1 = event_init(); 1251275970Scy if (base1) { 1252275970Scy event_assign(&ev1, base1, data->pair[1], EV_READ, 1253275970Scy dummy_read_cb, NULL); 1254275970Scy event_add(&ev1, NULL); 1255275970Scy event_base_free(base1); /* should not crash */ 1256275970Scy } else { 1257275970Scy tt_fail_msg("failed to create event_base for test"); 1258275970Scy } 1259275970Scy 1260275970Scy base1 = event_init(); 1261275970Scy tt_assert(base1); 1262275970Scy event_assign(&ev1, base1, 0, 0, dummy_read_cb, NULL); 1263275970Scy event_active(&ev1, EV_READ, 1); 1264275970Scy event_base_free(base1); 1265275970Scyend: 1266275970Scy ; 1267275970Scy} 1268275970Scy 1269275970Scystatic void 1270275970Scytest_manipulate_active_events(void *ptr) 1271275970Scy{ 1272275970Scy struct basic_test_data *data = ptr; 1273275970Scy struct event_base *base = data->base; 1274275970Scy struct event ev1; 1275275970Scy 1276275970Scy event_assign(&ev1, base, -1, EV_TIMEOUT, dummy_read_cb, NULL); 1277275970Scy 1278275970Scy /* Make sure an active event is pending. */ 1279275970Scy event_active(&ev1, EV_READ, 1); 1280275970Scy tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL), 1281275970Scy ==, EV_READ); 1282275970Scy 1283275970Scy /* Make sure that activating an event twice works. */ 1284275970Scy event_active(&ev1, EV_WRITE, 1); 1285275970Scy tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL), 1286275970Scy ==, EV_READ|EV_WRITE); 1287275970Scy 1288275970Scyend: 1289275970Scy event_del(&ev1); 1290275970Scy} 1291275970Scy 1292275970Scystatic void 1293275970Scyevent_selfarg_cb(evutil_socket_t fd, short event, void *arg) 1294275970Scy{ 1295275970Scy struct event *ev = arg; 1296275970Scy struct event_base *base = event_get_base(ev); 1297275970Scy event_base_assert_ok_(base); 1298275970Scy event_base_loopexit(base, NULL); 1299275970Scy tt_want(ev == event_base_get_running_event(base)); 1300275970Scy} 1301275970Scy 1302275970Scystatic void 1303275970Scytest_event_new_selfarg(void *ptr) 1304275970Scy{ 1305275970Scy struct basic_test_data *data = ptr; 1306275970Scy struct event_base *base = data->base; 1307275970Scy struct event *ev = event_new(base, -1, EV_READ, event_selfarg_cb, 1308275970Scy event_self_cbarg()); 1309275970Scy 1310275970Scy event_active(ev, EV_READ, 1); 1311275970Scy event_base_dispatch(base); 1312275970Scy 1313275970Scy event_free(ev); 1314275970Scy} 1315275970Scy 1316275970Scystatic void 1317275970Scytest_event_assign_selfarg(void *ptr) 1318275970Scy{ 1319275970Scy struct basic_test_data *data = ptr; 1320275970Scy struct event_base *base = data->base; 1321275970Scy struct event ev; 1322275970Scy 1323275970Scy event_assign(&ev, base, -1, EV_READ, event_selfarg_cb, 1324275970Scy event_self_cbarg()); 1325275970Scy event_active(&ev, EV_READ, 1); 1326275970Scy event_base_dispatch(base); 1327275970Scy} 1328275970Scy 1329275970Scystatic void 1330275970Scytest_event_base_get_num_events(void *ptr) 1331275970Scy{ 1332275970Scy struct basic_test_data *data = ptr; 1333275970Scy struct event_base *base = data->base; 1334275970Scy struct event ev; 1335275970Scy int event_count_active; 1336275970Scy int event_count_virtual; 1337275970Scy int event_count_added; 1338275970Scy int event_count_active_virtual; 1339275970Scy int event_count_active_added; 1340275970Scy int event_count_virtual_added; 1341275970Scy int event_count_active_added_virtual; 1342275970Scy 1343275970Scy struct timeval qsec = {0, 100000}; 1344275970Scy 1345275970Scy event_assign(&ev, base, -1, EV_READ, event_selfarg_cb, 1346275970Scy event_self_cbarg()); 1347275970Scy 1348275970Scy event_add(&ev, &qsec); 1349275970Scy event_count_active = event_base_get_num_events(base, 1350275970Scy EVENT_BASE_COUNT_ACTIVE); 1351275970Scy event_count_virtual = event_base_get_num_events(base, 1352275970Scy EVENT_BASE_COUNT_VIRTUAL); 1353275970Scy event_count_added = event_base_get_num_events(base, 1354275970Scy EVENT_BASE_COUNT_ADDED); 1355275970Scy event_count_active_virtual = event_base_get_num_events(base, 1356275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 1357275970Scy event_count_active_added = event_base_get_num_events(base, 1358275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 1359275970Scy event_count_virtual_added = event_base_get_num_events(base, 1360275970Scy EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 1361275970Scy event_count_active_added_virtual = event_base_get_num_events(base, 1362275970Scy EVENT_BASE_COUNT_ACTIVE| 1363275970Scy EVENT_BASE_COUNT_ADDED| 1364275970Scy EVENT_BASE_COUNT_VIRTUAL); 1365275970Scy tt_int_op(event_count_active, ==, 0); 1366275970Scy tt_int_op(event_count_virtual, ==, 0); 1367275970Scy /* libevent itself adds a timeout event, so the event_count is 2 here */ 1368275970Scy tt_int_op(event_count_added, ==, 2); 1369275970Scy tt_int_op(event_count_active_virtual, ==, 0); 1370275970Scy tt_int_op(event_count_active_added, ==, 2); 1371275970Scy tt_int_op(event_count_virtual_added, ==, 2); 1372275970Scy tt_int_op(event_count_active_added_virtual, ==, 2); 1373275970Scy 1374275970Scy event_active(&ev, EV_READ, 1); 1375275970Scy event_count_active = event_base_get_num_events(base, 1376275970Scy EVENT_BASE_COUNT_ACTIVE); 1377275970Scy event_count_virtual = event_base_get_num_events(base, 1378275970Scy EVENT_BASE_COUNT_VIRTUAL); 1379275970Scy event_count_added = event_base_get_num_events(base, 1380275970Scy EVENT_BASE_COUNT_ADDED); 1381275970Scy event_count_active_virtual = event_base_get_num_events(base, 1382275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 1383275970Scy event_count_active_added = event_base_get_num_events(base, 1384275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 1385275970Scy event_count_virtual_added = event_base_get_num_events(base, 1386275970Scy EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 1387275970Scy event_count_active_added_virtual = event_base_get_num_events(base, 1388275970Scy EVENT_BASE_COUNT_ACTIVE| 1389275970Scy EVENT_BASE_COUNT_ADDED| 1390275970Scy EVENT_BASE_COUNT_VIRTUAL); 1391275970Scy tt_int_op(event_count_active, ==, 1); 1392275970Scy tt_int_op(event_count_virtual, ==, 0); 1393275970Scy tt_int_op(event_count_added, ==, 3); 1394275970Scy tt_int_op(event_count_active_virtual, ==, 1); 1395275970Scy tt_int_op(event_count_active_added, ==, 4); 1396275970Scy tt_int_op(event_count_virtual_added, ==, 3); 1397275970Scy tt_int_op(event_count_active_added_virtual, ==, 4); 1398275970Scy 1399275970Scy event_base_loop(base, 0); 1400275970Scy event_count_active = event_base_get_num_events(base, 1401275970Scy EVENT_BASE_COUNT_ACTIVE); 1402275970Scy event_count_virtual = event_base_get_num_events(base, 1403275970Scy EVENT_BASE_COUNT_VIRTUAL); 1404275970Scy event_count_added = event_base_get_num_events(base, 1405275970Scy EVENT_BASE_COUNT_ADDED); 1406275970Scy event_count_active_virtual = event_base_get_num_events(base, 1407275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 1408275970Scy event_count_active_added = event_base_get_num_events(base, 1409275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 1410275970Scy event_count_virtual_added = event_base_get_num_events(base, 1411275970Scy EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 1412275970Scy event_count_active_added_virtual = event_base_get_num_events(base, 1413275970Scy EVENT_BASE_COUNT_ACTIVE| 1414275970Scy EVENT_BASE_COUNT_ADDED| 1415275970Scy EVENT_BASE_COUNT_VIRTUAL); 1416275970Scy tt_int_op(event_count_active, ==, 0); 1417275970Scy tt_int_op(event_count_virtual, ==, 0); 1418275970Scy tt_int_op(event_count_added, ==, 0); 1419275970Scy tt_int_op(event_count_active_virtual, ==, 0); 1420275970Scy tt_int_op(event_count_active_added, ==, 0); 1421275970Scy tt_int_op(event_count_virtual_added, ==, 0); 1422275970Scy tt_int_op(event_count_active_added_virtual, ==, 0); 1423275970Scy 1424275970Scy event_base_add_virtual_(base); 1425275970Scy event_count_active = event_base_get_num_events(base, 1426275970Scy EVENT_BASE_COUNT_ACTIVE); 1427275970Scy event_count_virtual = event_base_get_num_events(base, 1428275970Scy EVENT_BASE_COUNT_VIRTUAL); 1429275970Scy event_count_added = event_base_get_num_events(base, 1430275970Scy EVENT_BASE_COUNT_ADDED); 1431275970Scy event_count_active_virtual = event_base_get_num_events(base, 1432275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL); 1433275970Scy event_count_active_added = event_base_get_num_events(base, 1434275970Scy EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED); 1435275970Scy event_count_virtual_added = event_base_get_num_events(base, 1436275970Scy EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED); 1437275970Scy event_count_active_added_virtual = event_base_get_num_events(base, 1438275970Scy EVENT_BASE_COUNT_ACTIVE| 1439275970Scy EVENT_BASE_COUNT_ADDED| 1440275970Scy EVENT_BASE_COUNT_VIRTUAL); 1441275970Scy tt_int_op(event_count_active, ==, 0); 1442275970Scy tt_int_op(event_count_virtual, ==, 1); 1443275970Scy tt_int_op(event_count_added, ==, 0); 1444275970Scy tt_int_op(event_count_active_virtual, ==, 1); 1445275970Scy tt_int_op(event_count_active_added, ==, 0); 1446275970Scy tt_int_op(event_count_virtual_added, ==, 1); 1447275970Scy tt_int_op(event_count_active_added_virtual, ==, 1); 1448275970Scy 1449275970Scyend: 1450275970Scy ; 1451275970Scy} 1452275970Scy 1453275970Scystatic void 1454275970Scytest_event_base_get_max_events(void *ptr) 1455275970Scy{ 1456275970Scy struct basic_test_data *data = ptr; 1457275970Scy struct event_base *base = data->base; 1458275970Scy struct event ev; 1459275970Scy struct event ev2; 1460275970Scy int event_count_active; 1461275970Scy int event_count_virtual; 1462275970Scy int event_count_added; 1463275970Scy int event_count_active_virtual; 1464275970Scy int event_count_active_added; 1465275970Scy int event_count_virtual_added; 1466275970Scy int event_count_active_added_virtual; 1467275970Scy 1468275970Scy struct timeval qsec = {0, 100000}; 1469275970Scy 1470275970Scy event_assign(&ev, base, -1, EV_READ, event_selfarg_cb, 1471275970Scy event_self_cbarg()); 1472275970Scy event_assign(&ev2, base, -1, EV_READ, event_selfarg_cb, 1473275970Scy event_self_cbarg()); 1474275970Scy 1475275970Scy event_add(&ev, &qsec); 1476275970Scy event_add(&ev2, &qsec); 1477275970Scy event_del(&ev2); 1478275970Scy 1479275970Scy event_count_active = event_base_get_max_events(base, 1480275970Scy EVENT_BASE_COUNT_ACTIVE, 0); 1481275970Scy event_count_virtual = event_base_get_max_events(base, 1482275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1483275970Scy event_count_added = event_base_get_max_events(base, 1484275970Scy EVENT_BASE_COUNT_ADDED, 0); 1485275970Scy event_count_active_virtual = event_base_get_max_events(base, 1486275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 1487275970Scy event_count_active_added = event_base_get_max_events(base, 1488275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 1489275970Scy event_count_virtual_added = event_base_get_max_events(base, 1490275970Scy EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 1491275970Scy event_count_active_added_virtual = event_base_get_max_events(base, 1492275970Scy EVENT_BASE_COUNT_ACTIVE | 1493275970Scy EVENT_BASE_COUNT_ADDED | 1494275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1495275970Scy 1496275970Scy tt_int_op(event_count_active, ==, 0); 1497275970Scy tt_int_op(event_count_virtual, ==, 0); 1498275970Scy /* libevent itself adds a timeout event, so the event_count is 4 here */ 1499275970Scy tt_int_op(event_count_added, ==, 4); 1500275970Scy tt_int_op(event_count_active_virtual, ==, 0); 1501275970Scy tt_int_op(event_count_active_added, ==, 4); 1502275970Scy tt_int_op(event_count_virtual_added, ==, 4); 1503275970Scy tt_int_op(event_count_active_added_virtual, ==, 4); 1504275970Scy 1505275970Scy event_active(&ev, EV_READ, 1); 1506275970Scy event_count_active = event_base_get_max_events(base, 1507275970Scy EVENT_BASE_COUNT_ACTIVE, 0); 1508275970Scy event_count_virtual = event_base_get_max_events(base, 1509275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1510275970Scy event_count_added = event_base_get_max_events(base, 1511275970Scy EVENT_BASE_COUNT_ADDED, 0); 1512275970Scy event_count_active_virtual = event_base_get_max_events(base, 1513275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 1514275970Scy event_count_active_added = event_base_get_max_events(base, 1515275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 1516275970Scy event_count_virtual_added = event_base_get_max_events(base, 1517275970Scy EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 1518275970Scy event_count_active_added_virtual = event_base_get_max_events(base, 1519275970Scy EVENT_BASE_COUNT_ACTIVE | 1520275970Scy EVENT_BASE_COUNT_ADDED | 1521275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1522275970Scy 1523275970Scy tt_int_op(event_count_active, ==, 1); 1524275970Scy tt_int_op(event_count_virtual, ==, 0); 1525275970Scy tt_int_op(event_count_added, ==, 4); 1526275970Scy tt_int_op(event_count_active_virtual, ==, 1); 1527275970Scy tt_int_op(event_count_active_added, ==, 5); 1528275970Scy tt_int_op(event_count_virtual_added, ==, 4); 1529275970Scy tt_int_op(event_count_active_added_virtual, ==, 5); 1530275970Scy 1531275970Scy event_base_loop(base, 0); 1532275970Scy event_count_active = event_base_get_max_events(base, 1533275970Scy EVENT_BASE_COUNT_ACTIVE, 1); 1534275970Scy event_count_virtual = event_base_get_max_events(base, 1535275970Scy EVENT_BASE_COUNT_VIRTUAL, 1); 1536275970Scy event_count_added = event_base_get_max_events(base, 1537275970Scy EVENT_BASE_COUNT_ADDED, 1); 1538275970Scy event_count_active_virtual = event_base_get_max_events(base, 1539275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 1540275970Scy event_count_active_added = event_base_get_max_events(base, 1541275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 1542275970Scy event_count_virtual_added = event_base_get_max_events(base, 1543275970Scy EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 1544275970Scy event_count_active_added_virtual = event_base_get_max_events(base, 1545275970Scy EVENT_BASE_COUNT_ACTIVE | 1546275970Scy EVENT_BASE_COUNT_ADDED | 1547275970Scy EVENT_BASE_COUNT_VIRTUAL, 1); 1548275970Scy 1549275970Scy tt_int_op(event_count_active, ==, 1); 1550275970Scy tt_int_op(event_count_virtual, ==, 0); 1551275970Scy tt_int_op(event_count_added, ==, 4); 1552275970Scy tt_int_op(event_count_active_virtual, ==, 0); 1553275970Scy tt_int_op(event_count_active_added, ==, 0); 1554275970Scy tt_int_op(event_count_virtual_added, ==, 0); 1555275970Scy tt_int_op(event_count_active_added_virtual, ==, 0); 1556275970Scy 1557275970Scy event_count_active = event_base_get_max_events(base, 1558275970Scy EVENT_BASE_COUNT_ACTIVE, 0); 1559275970Scy event_count_virtual = event_base_get_max_events(base, 1560275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1561275970Scy event_count_added = event_base_get_max_events(base, 1562275970Scy EVENT_BASE_COUNT_ADDED, 0); 1563275970Scy tt_int_op(event_count_active, ==, 0); 1564275970Scy tt_int_op(event_count_virtual, ==, 0); 1565275970Scy tt_int_op(event_count_added, ==, 0); 1566275970Scy 1567275970Scy event_base_add_virtual_(base); 1568275970Scy event_count_active = event_base_get_max_events(base, 1569275970Scy EVENT_BASE_COUNT_ACTIVE, 0); 1570275970Scy event_count_virtual = event_base_get_max_events(base, 1571275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1572275970Scy event_count_added = event_base_get_max_events(base, 1573275970Scy EVENT_BASE_COUNT_ADDED, 0); 1574275970Scy event_count_active_virtual = event_base_get_max_events(base, 1575275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0); 1576275970Scy event_count_active_added = event_base_get_max_events(base, 1577275970Scy EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0); 1578275970Scy event_count_virtual_added = event_base_get_max_events(base, 1579275970Scy EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0); 1580275970Scy event_count_active_added_virtual = event_base_get_max_events(base, 1581275970Scy EVENT_BASE_COUNT_ACTIVE | 1582275970Scy EVENT_BASE_COUNT_ADDED | 1583275970Scy EVENT_BASE_COUNT_VIRTUAL, 0); 1584275970Scy 1585275970Scy tt_int_op(event_count_active, ==, 0); 1586275970Scy tt_int_op(event_count_virtual, ==, 1); 1587275970Scy tt_int_op(event_count_added, ==, 0); 1588275970Scy tt_int_op(event_count_active_virtual, ==, 1); 1589275970Scy tt_int_op(event_count_active_added, ==, 0); 1590275970Scy tt_int_op(event_count_virtual_added, ==, 1); 1591275970Scy tt_int_op(event_count_active_added_virtual, ==, 1); 1592275970Scy 1593275970Scyend: 1594275970Scy ; 1595275970Scy} 1596275970Scy 1597275970Scystatic void 1598275970Scytest_bad_assign(void *ptr) 1599275970Scy{ 1600275970Scy struct event ev; 1601275970Scy int r; 1602275970Scy /* READ|SIGNAL is not allowed */ 1603275970Scy r = event_assign(&ev, NULL, -1, EV_SIGNAL|EV_READ, dummy_read_cb, NULL); 1604275970Scy tt_int_op(r,==,-1); 1605275970Scy 1606275970Scyend: 1607275970Scy ; 1608275970Scy} 1609275970Scy 1610275970Scystatic int reentrant_cb_run = 0; 1611275970Scy 1612275970Scystatic void 1613275970Scybad_reentrant_run_loop_cb(evutil_socket_t fd, short what, void *ptr) 1614275970Scy{ 1615275970Scy struct event_base *base = ptr; 1616275970Scy int r; 1617275970Scy reentrant_cb_run = 1; 1618275970Scy /* This reentrant call to event_base_loop should be detected and 1619275970Scy * should fail */ 1620275970Scy r = event_base_loop(base, 0); 1621275970Scy tt_int_op(r, ==, -1); 1622275970Scyend: 1623275970Scy ; 1624275970Scy} 1625275970Scy 1626275970Scystatic void 1627275970Scytest_bad_reentrant(void *ptr) 1628275970Scy{ 1629275970Scy struct basic_test_data *data = ptr; 1630275970Scy struct event_base *base = data->base; 1631275970Scy struct event ev; 1632275970Scy int r; 1633275970Scy event_assign(&ev, base, -1, 1634275970Scy 0, bad_reentrant_run_loop_cb, base); 1635275970Scy 1636275970Scy event_active(&ev, EV_WRITE, 1); 1637275970Scy r = event_base_loop(base, 0); 1638275970Scy tt_int_op(r, ==, 1); 1639275970Scy tt_int_op(reentrant_cb_run, ==, 1); 1640275970Scyend: 1641275970Scy ; 1642275970Scy} 1643275970Scy 1644275970Scystatic int n_write_a_byte_cb=0; 1645275970Scystatic int n_read_and_drain_cb=0; 1646275970Scystatic int n_activate_other_event_cb=0; 1647275970Scystatic void 1648275970Scywrite_a_byte_cb(evutil_socket_t fd, short what, void *arg) 1649275970Scy{ 1650275970Scy char buf[] = "x"; 1651275970Scy if (write(fd, buf, 1) == 1) 1652275970Scy ++n_write_a_byte_cb; 1653275970Scy} 1654275970Scystatic void 1655275970Scyread_and_drain_cb(evutil_socket_t fd, short what, void *arg) 1656275970Scy{ 1657275970Scy char buf[128]; 1658275970Scy int n; 1659275970Scy ++n_read_and_drain_cb; 1660275970Scy while ((n = read(fd, buf, sizeof(buf))) > 0) 1661275970Scy ; 1662275970Scy} 1663275970Scy 1664275970Scystatic void 1665275970Scyactivate_other_event_cb(evutil_socket_t fd, short what, void *other_) 1666275970Scy{ 1667275970Scy struct event *ev_activate = other_; 1668275970Scy ++n_activate_other_event_cb; 1669275970Scy event_active_later_(ev_activate, EV_READ); 1670275970Scy} 1671275970Scy 1672275970Scystatic void 1673275970Scytest_active_later(void *ptr) 1674275970Scy{ 1675275970Scy struct basic_test_data *data = ptr; 1676285612Sdelphij struct event *ev1 = NULL, *ev2 = NULL; 1677275970Scy struct event ev3, ev4; 1678275970Scy struct timeval qsec = {0, 100000}; 1679275970Scy ev1 = event_new(data->base, data->pair[0], EV_READ|EV_PERSIST, read_and_drain_cb, NULL); 1680275970Scy ev2 = event_new(data->base, data->pair[1], EV_WRITE|EV_PERSIST, write_a_byte_cb, NULL); 1681275970Scy event_assign(&ev3, data->base, -1, 0, activate_other_event_cb, &ev4); 1682275970Scy event_assign(&ev4, data->base, -1, 0, activate_other_event_cb, &ev3); 1683275970Scy event_add(ev1, NULL); 1684275970Scy event_add(ev2, NULL); 1685275970Scy event_active_later_(&ev3, EV_READ); 1686275970Scy 1687275970Scy event_base_loopexit(data->base, &qsec); 1688275970Scy 1689275970Scy event_base_loop(data->base, 0); 1690275970Scy 1691275970Scy TT_BLATHER(("%d write calls, %d read calls, %d activate-other calls.", 1692275970Scy n_write_a_byte_cb, n_read_and_drain_cb, n_activate_other_event_cb)); 1693275970Scy event_del(&ev3); 1694275970Scy event_del(&ev4); 1695275970Scy 1696275970Scy tt_int_op(n_write_a_byte_cb, ==, n_activate_other_event_cb); 1697275970Scy tt_int_op(n_write_a_byte_cb, >, 100); 1698275970Scy tt_int_op(n_read_and_drain_cb, >, 100); 1699275970Scy tt_int_op(n_activate_other_event_cb, >, 100); 1700275970Scy 1701275970Scy event_active_later_(&ev4, EV_READ); 1702275970Scy event_active(&ev4, EV_READ, 1); /* This should make the event 1703275970Scy active immediately. */ 1704275970Scy tt_assert((ev4.ev_flags & EVLIST_ACTIVE) != 0); 1705275970Scy tt_assert((ev4.ev_flags & EVLIST_ACTIVE_LATER) == 0); 1706275970Scy 1707275970Scy /* Now leave this one around, so that event_free sees it and removes 1708275970Scy * it. */ 1709275970Scy event_active_later_(&ev3, EV_READ); 1710275970Scy event_base_assert_ok_(data->base); 1711285612Sdelphij 1712285612Sdelphijend: 1713285612Sdelphij if (ev1) 1714285612Sdelphij event_free(ev1); 1715285612Sdelphij if (ev2) 1716285612Sdelphij event_free(ev2); 1717285612Sdelphij 1718275970Scy event_base_free(data->base); 1719275970Scy data->base = NULL; 1720275970Scy} 1721275970Scy 1722275970Scy 1723275970Scystatic void incr_arg_cb(evutil_socket_t fd, short what, void *arg) 1724275970Scy{ 1725275970Scy int *intptr = arg; 1726275970Scy (void) fd; (void) what; 1727275970Scy ++*intptr; 1728275970Scy} 1729275970Scystatic void remove_timers_cb(evutil_socket_t fd, short what, void *arg) 1730275970Scy{ 1731275970Scy struct event **ep = arg; 1732275970Scy (void) fd; (void) what; 1733275970Scy event_remove_timer(ep[0]); 1734275970Scy event_remove_timer(ep[1]); 1735275970Scy} 1736275970Scystatic void send_a_byte_cb(evutil_socket_t fd, short what, void *arg) 1737275970Scy{ 1738275970Scy evutil_socket_t *sockp = arg; 1739275970Scy (void) fd; (void) what; 1740275970Scy (void) write(*sockp, "A", 1); 1741275970Scy} 1742275970Scystruct read_not_timeout_param 1743275970Scy{ 1744275970Scy struct event **ev; 1745275970Scy int events; 1746275970Scy int count; 1747275970Scy}; 1748275970Scystatic void read_not_timeout_cb(evutil_socket_t fd, short what, void *arg) 1749275970Scy{ 1750275970Scy struct read_not_timeout_param *rntp = arg; 1751275970Scy char c; 1752275970Scy ev_ssize_t n; 1753275970Scy (void) fd; (void) what; 1754275970Scy n = read(fd, &c, 1); 1755275970Scy tt_int_op(n, ==, 1); 1756275970Scy rntp->events |= what; 1757275970Scy ++rntp->count; 1758275970Scy if(2 == rntp->count) event_del(rntp->ev[0]); 1759275970Scyend: 1760275970Scy ; 1761275970Scy} 1762275970Scy 1763275970Scystatic void 1764275970Scytest_event_remove_timeout(void *ptr) 1765275970Scy{ 1766275970Scy struct basic_test_data *data = ptr; 1767275970Scy struct event_base *base = data->base; 1768275970Scy struct event *ev[5]; 1769275970Scy int ev1_fired=0; 1770275970Scy struct timeval ms25 = { 0, 25*1000 }, 1771275970Scy ms40 = { 0, 40*1000 }, 1772275970Scy ms75 = { 0, 75*1000 }, 1773275970Scy ms125 = { 0, 125*1000 }; 1774275970Scy struct read_not_timeout_param rntp = { ev, 0, 0 }; 1775275970Scy 1776275970Scy event_base_assert_ok_(base); 1777275970Scy 1778275970Scy ev[0] = event_new(base, data->pair[0], EV_READ|EV_PERSIST, 1779275970Scy read_not_timeout_cb, &rntp); 1780275970Scy ev[1] = evtimer_new(base, incr_arg_cb, &ev1_fired); 1781275970Scy ev[2] = evtimer_new(base, remove_timers_cb, ev); 1782275970Scy ev[3] = evtimer_new(base, send_a_byte_cb, &data->pair[1]); 1783275970Scy ev[4] = evtimer_new(base, send_a_byte_cb, &data->pair[1]); 1784275970Scy tt_assert(base); 1785275970Scy event_add(ev[2], &ms25); /* remove timers */ 1786275970Scy event_add(ev[4], &ms40); /* write to test if timer re-activates */ 1787275970Scy event_add(ev[0], &ms75); /* read */ 1788275970Scy event_add(ev[1], &ms75); /* timer */ 1789275970Scy event_add(ev[3], &ms125); /* timeout. */ 1790275970Scy event_base_assert_ok_(base); 1791275970Scy 1792275970Scy event_base_dispatch(base); 1793275970Scy 1794275970Scy tt_int_op(ev1_fired, ==, 0); 1795275970Scy tt_int_op(rntp.events, ==, EV_READ); 1796275970Scy 1797275970Scy event_base_assert_ok_(base); 1798275970Scyend: 1799275970Scy event_free(ev[0]); 1800275970Scy event_free(ev[1]); 1801275970Scy event_free(ev[2]); 1802275970Scy event_free(ev[3]); 1803275970Scy event_free(ev[4]); 1804275970Scy} 1805275970Scy 1806275970Scystatic void 1807275970Scytest_event_base_new(void *ptr) 1808275970Scy{ 1809275970Scy struct basic_test_data *data = ptr; 1810275970Scy struct event_base *base = 0; 1811275970Scy struct event ev1; 1812275970Scy struct basic_cb_args args; 1813275970Scy 1814275970Scy int towrite = (int)strlen(TEST1)+1; 1815275970Scy int len = write(data->pair[0], TEST1, towrite); 1816275970Scy 1817275970Scy if (len < 0) 1818275970Scy tt_abort_perror("initial write"); 1819275970Scy else if (len != towrite) 1820275970Scy tt_abort_printf(("initial write fell short (%d of %d bytes)", 1821275970Scy len, towrite)); 1822275970Scy 1823275970Scy if (shutdown(data->pair[0], SHUT_WR)) 1824275970Scy tt_abort_perror("initial write shutdown"); 1825275970Scy 1826275970Scy base = event_base_new(); 1827275970Scy if (!base) 1828275970Scy tt_abort_msg("failed to create event base"); 1829275970Scy 1830275970Scy args.eb = base; 1831275970Scy args.ev = &ev1; 1832275970Scy args.callcount = 0; 1833275970Scy event_assign(&ev1, base, data->pair[1], 1834275970Scy EV_READ|EV_PERSIST, basic_read_cb, &args); 1835275970Scy 1836275970Scy if (event_add(&ev1, NULL)) 1837275970Scy tt_abort_perror("initial event_add"); 1838275970Scy 1839275970Scy if (event_base_loop(base, 0)) 1840275970Scy tt_abort_msg("unsuccessful exit from event loop"); 1841275970Scy 1842275970Scyend: 1843275970Scy if (base) 1844275970Scy event_base_free(base); 1845275970Scy} 1846275970Scy 1847275970Scystatic void 1848275970Scytest_loopexit(void) 1849275970Scy{ 1850275970Scy struct timeval tv, tv_start, tv_end; 1851275970Scy struct event ev; 1852275970Scy 1853275970Scy setup_test("Loop exit: "); 1854275970Scy 1855275970Scy tv.tv_usec = 0; 1856275970Scy tv.tv_sec = 60*60*24; 1857275970Scy evtimer_set(&ev, timeout_cb, NULL); 1858275970Scy evtimer_add(&ev, &tv); 1859275970Scy 1860275970Scy tv.tv_usec = 300*1000; 1861275970Scy tv.tv_sec = 0; 1862275970Scy event_loopexit(&tv); 1863275970Scy 1864275970Scy evutil_gettimeofday(&tv_start, NULL); 1865275970Scy event_dispatch(); 1866275970Scy evutil_gettimeofday(&tv_end, NULL); 1867275970Scy 1868275970Scy evtimer_del(&ev); 1869275970Scy 1870275970Scy tt_assert(event_base_got_exit(global_base)); 1871275970Scy tt_assert(!event_base_got_break(global_base)); 1872275970Scy 1873275970Scy test_timeval_diff_eq(&tv_start, &tv_end, 300); 1874275970Scy 1875275970Scy test_ok = 1; 1876275970Scyend: 1877275970Scy cleanup_test(); 1878275970Scy} 1879275970Scy 1880275970Scystatic void 1881275970Scytest_loopexit_multiple(void) 1882275970Scy{ 1883275970Scy struct timeval tv, tv_start, tv_end; 1884275970Scy struct event_base *base; 1885275970Scy 1886275970Scy setup_test("Loop Multiple exit: "); 1887275970Scy 1888275970Scy base = event_base_new(); 1889275970Scy 1890275970Scy tv.tv_usec = 200*1000; 1891275970Scy tv.tv_sec = 0; 1892275970Scy event_base_loopexit(base, &tv); 1893275970Scy 1894275970Scy tv.tv_usec = 0; 1895275970Scy tv.tv_sec = 3; 1896275970Scy event_base_loopexit(base, &tv); 1897275970Scy 1898275970Scy evutil_gettimeofday(&tv_start, NULL); 1899275970Scy event_base_dispatch(base); 1900275970Scy evutil_gettimeofday(&tv_end, NULL); 1901275970Scy 1902275970Scy tt_assert(event_base_got_exit(base)); 1903275970Scy tt_assert(!event_base_got_break(base)); 1904275970Scy 1905275970Scy event_base_free(base); 1906275970Scy 1907275970Scy test_timeval_diff_eq(&tv_start, &tv_end, 200); 1908275970Scy 1909275970Scy test_ok = 1; 1910275970Scy 1911275970Scyend: 1912275970Scy cleanup_test(); 1913275970Scy} 1914275970Scy 1915275970Scystatic void 1916275970Scybreak_cb(evutil_socket_t fd, short events, void *arg) 1917275970Scy{ 1918275970Scy test_ok = 1; 1919275970Scy event_loopbreak(); 1920275970Scy} 1921275970Scy 1922275970Scystatic void 1923275970Scyfail_cb(evutil_socket_t fd, short events, void *arg) 1924275970Scy{ 1925275970Scy test_ok = 0; 1926275970Scy} 1927275970Scy 1928275970Scystatic void 1929275970Scytest_loopbreak(void) 1930275970Scy{ 1931275970Scy struct event ev1, ev2; 1932275970Scy struct timeval tv; 1933275970Scy 1934275970Scy setup_test("Loop break: "); 1935275970Scy 1936275970Scy tv.tv_sec = 0; 1937275970Scy tv.tv_usec = 0; 1938275970Scy evtimer_set(&ev1, break_cb, NULL); 1939275970Scy evtimer_add(&ev1, &tv); 1940275970Scy evtimer_set(&ev2, fail_cb, NULL); 1941275970Scy evtimer_add(&ev2, &tv); 1942275970Scy 1943275970Scy event_dispatch(); 1944275970Scy 1945275970Scy tt_assert(!event_base_got_exit(global_base)); 1946275970Scy tt_assert(event_base_got_break(global_base)); 1947275970Scy 1948275970Scy evtimer_del(&ev1); 1949275970Scy evtimer_del(&ev2); 1950275970Scy 1951275970Scyend: 1952275970Scy cleanup_test(); 1953275970Scy} 1954275970Scy 1955275970Scystatic struct event *readd_test_event_last_added = NULL; 1956275970Scystatic void 1957275970Scyre_add_read_cb(evutil_socket_t fd, short event, void *arg) 1958275970Scy{ 1959275970Scy char buf[256]; 1960275970Scy struct event *ev_other = arg; 1961275970Scy ev_ssize_t n_read; 1962275970Scy 1963275970Scy readd_test_event_last_added = ev_other; 1964275970Scy 1965275970Scy n_read = read(fd, buf, sizeof(buf)); 1966275970Scy 1967275970Scy if (n_read < 0) { 1968275970Scy tt_fail_perror("read"); 1969275970Scy event_base_loopbreak(event_get_base(ev_other)); 1970275970Scy return; 1971275970Scy } else { 1972275970Scy event_add(ev_other, NULL); 1973275970Scy ++test_ok; 1974275970Scy } 1975275970Scy} 1976275970Scy 1977275970Scystatic void 1978275970Scytest_nonpersist_readd(void) 1979275970Scy{ 1980275970Scy struct event ev1, ev2; 1981275970Scy 1982275970Scy setup_test("Re-add nonpersistent events: "); 1983275970Scy event_set(&ev1, pair[0], EV_READ, re_add_read_cb, &ev2); 1984275970Scy event_set(&ev2, pair[1], EV_READ, re_add_read_cb, &ev1); 1985275970Scy 1986275970Scy if (write(pair[0], "Hello", 5) < 0) { 1987275970Scy tt_fail_perror("write(pair[0])"); 1988275970Scy } 1989275970Scy 1990275970Scy if (write(pair[1], "Hello", 5) < 0) { 1991275970Scy tt_fail_perror("write(pair[1])\n"); 1992275970Scy } 1993275970Scy 1994275970Scy if (event_add(&ev1, NULL) == -1 || 1995275970Scy event_add(&ev2, NULL) == -1) { 1996275970Scy test_ok = 0; 1997275970Scy } 1998275970Scy if (test_ok != 0) 1999275970Scy exit(1); 2000275970Scy event_loop(EVLOOP_ONCE); 2001275970Scy if (test_ok != 2) 2002275970Scy exit(1); 2003275970Scy /* At this point, we executed both callbacks. Whichever one got 2004275970Scy * called first added the second, but the second then immediately got 2005275970Scy * deleted before its callback was called. At this point, though, it 2006275970Scy * re-added the first. 2007275970Scy */ 2008275970Scy if (!readd_test_event_last_added) { 2009275970Scy test_ok = 0; 2010275970Scy } else if (readd_test_event_last_added == &ev1) { 2011275970Scy if (!event_pending(&ev1, EV_READ, NULL) || 2012275970Scy event_pending(&ev2, EV_READ, NULL)) 2013275970Scy test_ok = 0; 2014275970Scy } else { 2015275970Scy if (event_pending(&ev1, EV_READ, NULL) || 2016275970Scy !event_pending(&ev2, EV_READ, NULL)) 2017275970Scy test_ok = 0; 2018275970Scy } 2019275970Scy 2020275970Scy event_del(&ev1); 2021275970Scy event_del(&ev2); 2022275970Scy 2023275970Scy cleanup_test(); 2024275970Scy} 2025275970Scy 2026275970Scystruct test_pri_event { 2027275970Scy struct event ev; 2028275970Scy int count; 2029275970Scy}; 2030275970Scy 2031275970Scystatic void 2032275970Scytest_priorities_cb(evutil_socket_t fd, short what, void *arg) 2033275970Scy{ 2034275970Scy struct test_pri_event *pri = arg; 2035275970Scy struct timeval tv; 2036275970Scy 2037275970Scy if (pri->count == 3) { 2038275970Scy event_loopexit(NULL); 2039275970Scy return; 2040275970Scy } 2041275970Scy 2042275970Scy pri->count++; 2043275970Scy 2044275970Scy evutil_timerclear(&tv); 2045275970Scy event_add(&pri->ev, &tv); 2046275970Scy} 2047275970Scy 2048275970Scystatic void 2049275970Scytest_priorities_impl(int npriorities) 2050275970Scy{ 2051275970Scy struct test_pri_event one, two; 2052275970Scy struct timeval tv; 2053275970Scy 2054275970Scy TT_BLATHER(("Testing Priorities %d: ", npriorities)); 2055275970Scy 2056275970Scy event_base_priority_init(global_base, npriorities); 2057275970Scy 2058275970Scy memset(&one, 0, sizeof(one)); 2059275970Scy memset(&two, 0, sizeof(two)); 2060275970Scy 2061275970Scy timeout_set(&one.ev, test_priorities_cb, &one); 2062275970Scy if (event_priority_set(&one.ev, 0) == -1) { 2063275970Scy fprintf(stderr, "%s: failed to set priority", __func__); 2064275970Scy exit(1); 2065275970Scy } 2066275970Scy 2067275970Scy timeout_set(&two.ev, test_priorities_cb, &two); 2068275970Scy if (event_priority_set(&two.ev, npriorities - 1) == -1) { 2069275970Scy fprintf(stderr, "%s: failed to set priority", __func__); 2070275970Scy exit(1); 2071275970Scy } 2072275970Scy 2073275970Scy evutil_timerclear(&tv); 2074275970Scy 2075275970Scy if (event_add(&one.ev, &tv) == -1) 2076275970Scy exit(1); 2077275970Scy if (event_add(&two.ev, &tv) == -1) 2078275970Scy exit(1); 2079275970Scy 2080275970Scy event_dispatch(); 2081275970Scy 2082275970Scy event_del(&one.ev); 2083275970Scy event_del(&two.ev); 2084275970Scy 2085275970Scy if (npriorities == 1) { 2086275970Scy if (one.count == 3 && two.count == 3) 2087275970Scy test_ok = 1; 2088275970Scy } else if (npriorities == 2) { 2089275970Scy /* Two is called once because event_loopexit is priority 1 */ 2090275970Scy if (one.count == 3 && two.count == 1) 2091275970Scy test_ok = 1; 2092275970Scy } else { 2093275970Scy if (one.count == 3 && two.count == 0) 2094275970Scy test_ok = 1; 2095275970Scy } 2096275970Scy} 2097275970Scy 2098275970Scystatic void 2099275970Scytest_priorities(void) 2100275970Scy{ 2101275970Scy test_priorities_impl(1); 2102275970Scy if (test_ok) 2103275970Scy test_priorities_impl(2); 2104275970Scy if (test_ok) 2105275970Scy test_priorities_impl(3); 2106275970Scy} 2107275970Scy 2108275970Scy/* priority-active-inversion: activate a higher-priority event, and make sure 2109275970Scy * it keeps us from running a lower-priority event first. */ 2110275970Scystatic int n_pai_calls = 0; 2111275970Scystatic struct event pai_events[3]; 2112275970Scy 2113275970Scystatic void 2114275970Scyprio_active_inversion_cb(evutil_socket_t fd, short what, void *arg) 2115275970Scy{ 2116275970Scy int *call_order = arg; 2117275970Scy *call_order = n_pai_calls++; 2118275970Scy if (n_pai_calls == 1) { 2119275970Scy /* This should activate later, even though it shares a 2120275970Scy priority with us. */ 2121275970Scy event_active(&pai_events[1], EV_READ, 1); 2122275970Scy /* This should activate next, since its priority is higher, 2123275970Scy even though we activated it second. */ 2124275970Scy event_active(&pai_events[2], EV_TIMEOUT, 1); 2125275970Scy } 2126275970Scy} 2127275970Scy 2128275970Scystatic void 2129275970Scytest_priority_active_inversion(void *data_) 2130275970Scy{ 2131275970Scy struct basic_test_data *data = data_; 2132275970Scy struct event_base *base = data->base; 2133275970Scy int call_order[3]; 2134275970Scy int i; 2135275970Scy tt_int_op(event_base_priority_init(base, 8), ==, 0); 2136275970Scy 2137275970Scy n_pai_calls = 0; 2138275970Scy memset(call_order, 0, sizeof(call_order)); 2139275970Scy 2140275970Scy for (i=0;i<3;++i) { 2141275970Scy event_assign(&pai_events[i], data->base, -1, 0, 2142275970Scy prio_active_inversion_cb, &call_order[i]); 2143275970Scy } 2144275970Scy 2145275970Scy event_priority_set(&pai_events[0], 4); 2146275970Scy event_priority_set(&pai_events[1], 4); 2147275970Scy event_priority_set(&pai_events[2], 0); 2148275970Scy 2149275970Scy event_active(&pai_events[0], EV_WRITE, 1); 2150275970Scy 2151275970Scy event_base_dispatch(base); 2152275970Scy tt_int_op(n_pai_calls, ==, 3); 2153275970Scy tt_int_op(call_order[0], ==, 0); 2154275970Scy tt_int_op(call_order[1], ==, 2); 2155275970Scy tt_int_op(call_order[2], ==, 1); 2156275970Scyend: 2157275970Scy ; 2158275970Scy} 2159275970Scy 2160275970Scy 2161275970Scystatic void 2162275970Scytest_multiple_cb(evutil_socket_t fd, short event, void *arg) 2163275970Scy{ 2164275970Scy if (event & EV_READ) 2165275970Scy test_ok |= 1; 2166275970Scy else if (event & EV_WRITE) 2167275970Scy test_ok |= 2; 2168275970Scy} 2169275970Scy 2170275970Scystatic void 2171275970Scytest_multiple_events_for_same_fd(void) 2172275970Scy{ 2173275970Scy struct event e1, e2; 2174275970Scy 2175275970Scy setup_test("Multiple events for same fd: "); 2176275970Scy 2177275970Scy event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL); 2178275970Scy event_add(&e1, NULL); 2179275970Scy event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL); 2180275970Scy event_add(&e2, NULL); 2181275970Scy event_loop(EVLOOP_ONCE); 2182275970Scy event_del(&e2); 2183275970Scy 2184275970Scy if (write(pair[1], TEST1, strlen(TEST1)+1) < 0) { 2185275970Scy tt_fail_perror("write"); 2186275970Scy } 2187275970Scy 2188275970Scy event_loop(EVLOOP_ONCE); 2189275970Scy event_del(&e1); 2190275970Scy 2191275970Scy if (test_ok != 3) 2192275970Scy test_ok = 0; 2193275970Scy 2194275970Scy cleanup_test(); 2195275970Scy} 2196275970Scy 2197275970Scyint evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf); 2198275970Scyint evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf); 2199275970Scyint evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t number); 2200275970Scyint evtag_decode_tag(ev_uint32_t *pnumber, struct evbuffer *evbuf); 2201275970Scy 2202275970Scystatic void 2203275970Scyread_once_cb(evutil_socket_t fd, short event, void *arg) 2204275970Scy{ 2205275970Scy char buf[256]; 2206275970Scy int len; 2207275970Scy 2208275970Scy len = read(fd, buf, sizeof(buf)); 2209275970Scy 2210275970Scy if (called) { 2211275970Scy test_ok = 0; 2212275970Scy } else if (len) { 2213275970Scy /* Assumes global pair[0] can be used for writing */ 2214275970Scy if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 2215275970Scy tt_fail_perror("write"); 2216275970Scy test_ok = 0; 2217275970Scy } else { 2218275970Scy test_ok = 1; 2219275970Scy } 2220275970Scy } 2221275970Scy 2222275970Scy called++; 2223275970Scy} 2224275970Scy 2225275970Scystatic void 2226275970Scytest_want_only_once(void) 2227275970Scy{ 2228275970Scy struct event ev; 2229275970Scy struct timeval tv; 2230275970Scy 2231275970Scy /* Very simple read test */ 2232275970Scy setup_test("Want read only once: "); 2233275970Scy 2234275970Scy if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { 2235275970Scy tt_fail_perror("write"); 2236275970Scy } 2237275970Scy 2238275970Scy /* Setup the loop termination */ 2239275970Scy evutil_timerclear(&tv); 2240275970Scy tv.tv_usec = 300*1000; 2241275970Scy event_loopexit(&tv); 2242275970Scy 2243275970Scy event_set(&ev, pair[1], EV_READ, read_once_cb, &ev); 2244275970Scy if (event_add(&ev, NULL) == -1) 2245275970Scy exit(1); 2246275970Scy event_dispatch(); 2247275970Scy 2248275970Scy cleanup_test(); 2249275970Scy} 2250275970Scy 2251275970Scy#define TEST_MAX_INT 6 2252275970Scy 2253275970Scystatic void 2254275970Scyevtag_int_test(void *ptr) 2255275970Scy{ 2256275970Scy struct evbuffer *tmp = evbuffer_new(); 2257275970Scy ev_uint32_t integers[TEST_MAX_INT] = { 2258275970Scy 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 2259275970Scy }; 2260275970Scy ev_uint32_t integer; 2261275970Scy ev_uint64_t big_int; 2262275970Scy int i; 2263275970Scy 2264275970Scy evtag_init(); 2265275970Scy 2266275970Scy for (i = 0; i < TEST_MAX_INT; i++) { 2267275970Scy int oldlen, newlen; 2268275970Scy oldlen = (int)EVBUFFER_LENGTH(tmp); 2269275970Scy evtag_encode_int(tmp, integers[i]); 2270275970Scy newlen = (int)EVBUFFER_LENGTH(tmp); 2271275970Scy TT_BLATHER(("encoded 0x%08x with %d bytes", 2272275970Scy (unsigned)integers[i], newlen - oldlen)); 2273275970Scy big_int = integers[i]; 2274275970Scy big_int *= 1000000000; /* 1 billion */ 2275275970Scy evtag_encode_int64(tmp, big_int); 2276275970Scy } 2277275970Scy 2278275970Scy for (i = 0; i < TEST_MAX_INT; i++) { 2279275970Scy tt_int_op(evtag_decode_int(&integer, tmp), !=, -1); 2280275970Scy tt_uint_op(integer, ==, integers[i]); 2281275970Scy tt_int_op(evtag_decode_int64(&big_int, tmp), !=, -1); 2282275970Scy tt_assert((big_int / 1000000000) == integers[i]); 2283275970Scy } 2284275970Scy 2285275970Scy tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0); 2286275970Scyend: 2287275970Scy evbuffer_free(tmp); 2288275970Scy} 2289275970Scy 2290275970Scystatic void 2291275970Scyevtag_fuzz(void *ptr) 2292275970Scy{ 2293275970Scy u_char buffer[4096]; 2294275970Scy struct evbuffer *tmp = evbuffer_new(); 2295275970Scy struct timeval tv; 2296275970Scy int i, j; 2297275970Scy 2298275970Scy int not_failed = 0; 2299275970Scy 2300275970Scy evtag_init(); 2301275970Scy 2302275970Scy for (j = 0; j < 100; j++) { 2303275970Scy for (i = 0; i < (int)sizeof(buffer); i++) 2304285612Sdelphij buffer[i] = test_weakrand(); 2305275970Scy evbuffer_drain(tmp, -1); 2306275970Scy evbuffer_add(tmp, buffer, sizeof(buffer)); 2307275970Scy 2308275970Scy if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) 2309275970Scy not_failed++; 2310275970Scy } 2311275970Scy 2312275970Scy /* The majority of decodes should fail */ 2313275970Scy tt_int_op(not_failed, <, 10); 2314275970Scy 2315275970Scy /* Now insert some corruption into the tag length field */ 2316275970Scy evbuffer_drain(tmp, -1); 2317275970Scy evutil_timerclear(&tv); 2318275970Scy tv.tv_sec = 1; 2319275970Scy evtag_marshal_timeval(tmp, 0, &tv); 2320275970Scy evbuffer_add(tmp, buffer, sizeof(buffer)); 2321275970Scy 2322275970Scy ((char *)EVBUFFER_DATA(tmp))[1] = '\xff'; 2323275970Scy if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) { 2324275970Scy tt_abort_msg("evtag_unmarshal_timeval should have failed"); 2325275970Scy } 2326275970Scy 2327275970Scyend: 2328275970Scy evbuffer_free(tmp); 2329275970Scy} 2330275970Scy 2331275970Scystatic void 2332275970Scyevtag_tag_encoding(void *ptr) 2333275970Scy{ 2334275970Scy struct evbuffer *tmp = evbuffer_new(); 2335275970Scy ev_uint32_t integers[TEST_MAX_INT] = { 2336275970Scy 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 2337275970Scy }; 2338275970Scy ev_uint32_t integer; 2339275970Scy int i; 2340275970Scy 2341275970Scy evtag_init(); 2342275970Scy 2343275970Scy for (i = 0; i < TEST_MAX_INT; i++) { 2344275970Scy int oldlen, newlen; 2345275970Scy oldlen = (int)EVBUFFER_LENGTH(tmp); 2346275970Scy evtag_encode_tag(tmp, integers[i]); 2347275970Scy newlen = (int)EVBUFFER_LENGTH(tmp); 2348275970Scy TT_BLATHER(("encoded 0x%08x with %d bytes", 2349275970Scy (unsigned)integers[i], newlen - oldlen)); 2350275970Scy } 2351275970Scy 2352275970Scy for (i = 0; i < TEST_MAX_INT; i++) { 2353275970Scy tt_int_op(evtag_decode_tag(&integer, tmp), !=, -1); 2354275970Scy tt_uint_op(integer, ==, integers[i]); 2355275970Scy } 2356275970Scy 2357275970Scy tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0); 2358275970Scy 2359275970Scyend: 2360275970Scy evbuffer_free(tmp); 2361275970Scy} 2362275970Scy 2363275970Scystatic void 2364275970Scyevtag_test_peek(void *ptr) 2365275970Scy{ 2366275970Scy struct evbuffer *tmp = evbuffer_new(); 2367275970Scy ev_uint32_t u32; 2368275970Scy 2369275970Scy evtag_marshal_int(tmp, 30, 0); 2370275970Scy evtag_marshal_string(tmp, 40, "Hello world"); 2371275970Scy 2372275970Scy tt_int_op(evtag_peek(tmp, &u32), ==, 1); 2373275970Scy tt_int_op(u32, ==, 30); 2374275970Scy tt_int_op(evtag_peek_length(tmp, &u32), ==, 0); 2375275970Scy tt_int_op(u32, ==, 1+1+1); 2376275970Scy tt_int_op(evtag_consume(tmp), ==, 0); 2377275970Scy 2378275970Scy tt_int_op(evtag_peek(tmp, &u32), ==, 1); 2379275970Scy tt_int_op(u32, ==, 40); 2380275970Scy tt_int_op(evtag_peek_length(tmp, &u32), ==, 0); 2381275970Scy tt_int_op(u32, ==, 1+1+11); 2382275970Scy tt_int_op(evtag_payload_length(tmp, &u32), ==, 0); 2383275970Scy tt_int_op(u32, ==, 11); 2384275970Scy 2385275970Scyend: 2386275970Scy evbuffer_free(tmp); 2387275970Scy} 2388275970Scy 2389275970Scy 2390275970Scystatic void 2391275970Scytest_methods(void *ptr) 2392275970Scy{ 2393275970Scy const char **methods = event_get_supported_methods(); 2394275970Scy struct event_config *cfg = NULL; 2395275970Scy struct event_base *base = NULL; 2396275970Scy const char *backend; 2397275970Scy int n_methods = 0; 2398275970Scy 2399275970Scy tt_assert(methods); 2400275970Scy 2401275970Scy backend = methods[0]; 2402275970Scy while (*methods != NULL) { 2403275970Scy TT_BLATHER(("Support method: %s", *methods)); 2404275970Scy ++methods; 2405275970Scy ++n_methods; 2406275970Scy } 2407275970Scy 2408275970Scy cfg = event_config_new(); 2409275970Scy assert(cfg != NULL); 2410275970Scy 2411275970Scy tt_int_op(event_config_avoid_method(cfg, backend), ==, 0); 2412275970Scy event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV); 2413275970Scy 2414275970Scy base = event_base_new_with_config(cfg); 2415275970Scy if (n_methods > 1) { 2416275970Scy tt_assert(base); 2417275970Scy tt_str_op(backend, !=, event_base_get_method(base)); 2418275970Scy } else { 2419275970Scy tt_assert(base == NULL); 2420275970Scy } 2421275970Scy 2422275970Scyend: 2423275970Scy if (base) 2424275970Scy event_base_free(base); 2425275970Scy if (cfg) 2426275970Scy event_config_free(cfg); 2427275970Scy} 2428275970Scy 2429275970Scystatic void 2430275970Scytest_version(void *arg) 2431275970Scy{ 2432275970Scy const char *vstr; 2433275970Scy ev_uint32_t vint; 2434275970Scy int major, minor, patch, n; 2435275970Scy 2436275970Scy vstr = event_get_version(); 2437275970Scy vint = event_get_version_number(); 2438275970Scy 2439275970Scy tt_assert(vstr); 2440275970Scy tt_assert(vint); 2441275970Scy 2442275970Scy tt_str_op(vstr, ==, LIBEVENT_VERSION); 2443275970Scy tt_int_op(vint, ==, LIBEVENT_VERSION_NUMBER); 2444275970Scy 2445275970Scy n = sscanf(vstr, "%d.%d.%d", &major, &minor, &patch); 2446275970Scy tt_assert(3 == n); 2447275970Scy tt_int_op((vint&0xffffff00), ==, ((major<<24)|(minor<<16)|(patch<<8))); 2448275970Scyend: 2449275970Scy ; 2450275970Scy} 2451275970Scy 2452275970Scystatic void 2453275970Scytest_base_features(void *arg) 2454275970Scy{ 2455275970Scy struct event_base *base = NULL; 2456275970Scy struct event_config *cfg = NULL; 2457275970Scy 2458275970Scy cfg = event_config_new(); 2459275970Scy 2460275970Scy tt_assert(0 == event_config_require_features(cfg, EV_FEATURE_ET)); 2461275970Scy 2462275970Scy base = event_base_new_with_config(cfg); 2463275970Scy if (base) { 2464275970Scy tt_int_op(EV_FEATURE_ET, ==, 2465275970Scy event_base_get_features(base) & EV_FEATURE_ET); 2466275970Scy } else { 2467275970Scy base = event_base_new(); 2468275970Scy tt_int_op(0, ==, event_base_get_features(base) & EV_FEATURE_ET); 2469275970Scy } 2470275970Scy 2471275970Scyend: 2472275970Scy if (base) 2473275970Scy event_base_free(base); 2474275970Scy if (cfg) 2475275970Scy event_config_free(cfg); 2476275970Scy} 2477275970Scy 2478275970Scy#ifdef EVENT__HAVE_SETENV 2479275970Scy#define SETENV_OK 2480275970Scy#elif !defined(EVENT__HAVE_SETENV) && defined(EVENT__HAVE_PUTENV) 2481275970Scystatic void setenv(const char *k, const char *v, int o_) 2482275970Scy{ 2483275970Scy char b[256]; 2484275970Scy evutil_snprintf(b, sizeof(b), "%s=%s",k,v); 2485275970Scy putenv(b); 2486275970Scy} 2487275970Scy#define SETENV_OK 2488275970Scy#endif 2489275970Scy 2490275970Scy#ifdef EVENT__HAVE_UNSETENV 2491275970Scy#define UNSETENV_OK 2492275970Scy#elif !defined(EVENT__HAVE_UNSETENV) && defined(EVENT__HAVE_PUTENV) 2493275970Scystatic void unsetenv(const char *k) 2494275970Scy{ 2495275970Scy char b[256]; 2496275970Scy evutil_snprintf(b, sizeof(b), "%s=",k); 2497275970Scy putenv(b); 2498275970Scy} 2499275970Scy#define UNSETENV_OK 2500275970Scy#endif 2501275970Scy 2502275970Scy#if defined(SETENV_OK) && defined(UNSETENV_OK) 2503275970Scystatic void 2504275970Scymethodname_to_envvar(const char *mname, char *buf, size_t buflen) 2505275970Scy{ 2506275970Scy char *cp; 2507275970Scy evutil_snprintf(buf, buflen, "EVENT_NO%s", mname); 2508275970Scy for (cp = buf; *cp; ++cp) { 2509275970Scy *cp = EVUTIL_TOUPPER_(*cp); 2510275970Scy } 2511275970Scy} 2512275970Scy#endif 2513275970Scy 2514275970Scystatic void 2515275970Scytest_base_environ(void *arg) 2516275970Scy{ 2517275970Scy struct event_base *base = NULL; 2518275970Scy struct event_config *cfg = NULL; 2519275970Scy 2520275970Scy#if defined(SETENV_OK) && defined(UNSETENV_OK) 2521275970Scy const char **basenames; 2522275970Scy int i, n_methods=0; 2523275970Scy char varbuf[128]; 2524275970Scy const char *defaultname, *ignoreenvname; 2525275970Scy 2526275970Scy /* See if unsetenv works before we rely on it. */ 2527275970Scy setenv("EVENT_NOWAFFLES", "1", 1); 2528275970Scy unsetenv("EVENT_NOWAFFLES"); 2529275970Scy if (getenv("EVENT_NOWAFFLES") != NULL) { 2530275970Scy#ifndef EVENT__HAVE_UNSETENV 2531275970Scy TT_DECLARE("NOTE", ("Can't fake unsetenv; skipping test")); 2532275970Scy#else 2533275970Scy TT_DECLARE("NOTE", ("unsetenv doesn't work; skipping test")); 2534275970Scy#endif 2535275970Scy tt_skip(); 2536275970Scy } 2537275970Scy 2538275970Scy basenames = event_get_supported_methods(); 2539275970Scy for (i = 0; basenames[i]; ++i) { 2540275970Scy methodname_to_envvar(basenames[i], varbuf, sizeof(varbuf)); 2541275970Scy unsetenv(varbuf); 2542275970Scy ++n_methods; 2543275970Scy } 2544275970Scy 2545275970Scy base = event_base_new(); 2546275970Scy tt_assert(base); 2547275970Scy 2548275970Scy defaultname = event_base_get_method(base); 2549275970Scy TT_BLATHER(("default is <%s>", defaultname)); 2550275970Scy event_base_free(base); 2551275970Scy base = NULL; 2552275970Scy 2553275970Scy /* Can we disable the method with EVENT_NOfoo ? */ 2554275970Scy if (!strcmp(defaultname, "epoll (with changelist)")) { 2555275970Scy setenv("EVENT_NOEPOLL", "1", 1); 2556275970Scy ignoreenvname = "epoll"; 2557275970Scy } else { 2558275970Scy methodname_to_envvar(defaultname, varbuf, sizeof(varbuf)); 2559275970Scy setenv(varbuf, "1", 1); 2560275970Scy ignoreenvname = defaultname; 2561275970Scy } 2562275970Scy 2563275970Scy /* Use an empty cfg rather than NULL so a failure doesn't exit() */ 2564275970Scy cfg = event_config_new(); 2565275970Scy base = event_base_new_with_config(cfg); 2566275970Scy event_config_free(cfg); 2567275970Scy cfg = NULL; 2568275970Scy if (n_methods == 1) { 2569275970Scy tt_assert(!base); 2570275970Scy } else { 2571275970Scy tt_assert(base); 2572275970Scy tt_str_op(defaultname, !=, event_base_get_method(base)); 2573275970Scy event_base_free(base); 2574275970Scy base = NULL; 2575275970Scy } 2576275970Scy 2577275970Scy /* Can we disable looking at the environment with IGNORE_ENV ? */ 2578275970Scy cfg = event_config_new(); 2579275970Scy event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV); 2580275970Scy base = event_base_new_with_config(cfg); 2581275970Scy tt_assert(base); 2582275970Scy tt_str_op(ignoreenvname, ==, event_base_get_method(base)); 2583275970Scy#else 2584275970Scy tt_skip(); 2585275970Scy#endif 2586275970Scy 2587275970Scyend: 2588275970Scy if (base) 2589275970Scy event_base_free(base); 2590275970Scy if (cfg) 2591275970Scy event_config_free(cfg); 2592275970Scy} 2593275970Scy 2594275970Scystatic void 2595275970Scyread_called_once_cb(evutil_socket_t fd, short event, void *arg) 2596275970Scy{ 2597275970Scy tt_int_op(event, ==, EV_READ); 2598275970Scy called += 1; 2599275970Scyend: 2600275970Scy ; 2601275970Scy} 2602275970Scy 2603275970Scystatic void 2604275970Scytimeout_called_once_cb(evutil_socket_t fd, short event, void *arg) 2605275970Scy{ 2606275970Scy tt_int_op(event, ==, EV_TIMEOUT); 2607275970Scy called += 100; 2608275970Scyend: 2609275970Scy ; 2610275970Scy} 2611275970Scy 2612275970Scystatic void 2613275970Scyimmediate_called_twice_cb(evutil_socket_t fd, short event, void *arg) 2614275970Scy{ 2615275970Scy tt_int_op(event, ==, EV_TIMEOUT); 2616275970Scy called += 1000; 2617275970Scyend: 2618275970Scy ; 2619275970Scy} 2620275970Scy 2621275970Scystatic void 2622275970Scytest_event_once(void *ptr) 2623275970Scy{ 2624275970Scy struct basic_test_data *data = ptr; 2625275970Scy struct timeval tv; 2626275970Scy int r; 2627275970Scy 2628275970Scy tv.tv_sec = 0; 2629275970Scy tv.tv_usec = 50*1000; 2630275970Scy called = 0; 2631275970Scy r = event_base_once(data->base, data->pair[0], EV_READ, 2632275970Scy read_called_once_cb, NULL, NULL); 2633275970Scy tt_int_op(r, ==, 0); 2634275970Scy r = event_base_once(data->base, -1, EV_TIMEOUT, 2635275970Scy timeout_called_once_cb, NULL, &tv); 2636275970Scy tt_int_op(r, ==, 0); 2637275970Scy r = event_base_once(data->base, -1, 0, NULL, NULL, NULL); 2638275970Scy tt_int_op(r, <, 0); 2639275970Scy r = event_base_once(data->base, -1, EV_TIMEOUT, 2640275970Scy immediate_called_twice_cb, NULL, NULL); 2641275970Scy tt_int_op(r, ==, 0); 2642275970Scy tv.tv_sec = 0; 2643275970Scy tv.tv_usec = 0; 2644275970Scy r = event_base_once(data->base, -1, EV_TIMEOUT, 2645275970Scy immediate_called_twice_cb, NULL, &tv); 2646275970Scy tt_int_op(r, ==, 0); 2647275970Scy 2648275970Scy if (write(data->pair[1], TEST1, strlen(TEST1)+1) < 0) { 2649275970Scy tt_fail_perror("write"); 2650275970Scy } 2651275970Scy 2652275970Scy shutdown(data->pair[1], SHUT_WR); 2653275970Scy 2654275970Scy event_base_dispatch(data->base); 2655275970Scy 2656275970Scy tt_int_op(called, ==, 2101); 2657275970Scyend: 2658275970Scy ; 2659275970Scy} 2660275970Scy 2661275970Scystatic void 2662275970Scytest_event_once_never(void *ptr) 2663275970Scy{ 2664275970Scy struct basic_test_data *data = ptr; 2665275970Scy struct timeval tv; 2666275970Scy 2667275970Scy /* Have one trigger in 10 seconds (don't worry, because) */ 2668275970Scy tv.tv_sec = 10; 2669275970Scy tv.tv_usec = 0; 2670275970Scy called = 0; 2671275970Scy event_base_once(data->base, -1, EV_TIMEOUT, 2672275970Scy timeout_called_once_cb, NULL, &tv); 2673275970Scy 2674275970Scy /* But shut down the base in 75 msec. */ 2675275970Scy tv.tv_sec = 0; 2676275970Scy tv.tv_usec = 75*1000; 2677275970Scy event_base_loopexit(data->base, &tv); 2678275970Scy 2679275970Scy event_base_dispatch(data->base); 2680275970Scy 2681275970Scy tt_int_op(called, ==, 0); 2682275970Scyend: 2683275970Scy ; 2684275970Scy} 2685275970Scy 2686275970Scystatic void 2687275970Scytest_event_pending(void *ptr) 2688275970Scy{ 2689275970Scy struct basic_test_data *data = ptr; 2690275970Scy struct event *r=NULL, *w=NULL, *t=NULL; 2691275970Scy struct timeval tv, now, tv2; 2692275970Scy 2693275970Scy tv.tv_sec = 0; 2694275970Scy tv.tv_usec = 500 * 1000; 2695275970Scy r = event_new(data->base, data->pair[0], EV_READ, simple_read_cb, 2696275970Scy NULL); 2697275970Scy w = event_new(data->base, data->pair[1], EV_WRITE, simple_write_cb, 2698275970Scy NULL); 2699275970Scy t = evtimer_new(data->base, timeout_cb, NULL); 2700275970Scy 2701275970Scy tt_assert(r); 2702275970Scy tt_assert(w); 2703275970Scy tt_assert(t); 2704275970Scy 2705275970Scy evutil_gettimeofday(&now, NULL); 2706275970Scy event_add(r, NULL); 2707275970Scy event_add(t, &tv); 2708275970Scy 2709275970Scy tt_assert( event_pending(r, EV_READ, NULL)); 2710275970Scy tt_assert(!event_pending(w, EV_WRITE, NULL)); 2711275970Scy tt_assert(!event_pending(r, EV_WRITE, NULL)); 2712275970Scy tt_assert( event_pending(r, EV_READ|EV_WRITE, NULL)); 2713275970Scy tt_assert(!event_pending(r, EV_TIMEOUT, NULL)); 2714275970Scy tt_assert( event_pending(t, EV_TIMEOUT, NULL)); 2715275970Scy tt_assert( event_pending(t, EV_TIMEOUT, &tv2)); 2716275970Scy 2717275970Scy tt_assert(evutil_timercmp(&tv2, &now, >)); 2718275970Scy 2719275970Scy test_timeval_diff_eq(&now, &tv2, 500); 2720275970Scy 2721275970Scyend: 2722275970Scy if (r) { 2723275970Scy event_del(r); 2724275970Scy event_free(r); 2725275970Scy } 2726275970Scy if (w) { 2727275970Scy event_del(w); 2728275970Scy event_free(w); 2729275970Scy } 2730275970Scy if (t) { 2731275970Scy event_del(t); 2732275970Scy event_free(t); 2733275970Scy } 2734275970Scy} 2735275970Scy 2736275970Scy#ifndef _WIN32 2737275970Scy/* You can't do this test on windows, since dup2 doesn't work on sockets */ 2738275970Scy 2739275970Scystatic void 2740275970Scydfd_cb(evutil_socket_t fd, short e, void *data) 2741275970Scy{ 2742275970Scy *(int*)data = (int)e; 2743275970Scy} 2744275970Scy 2745275970Scy/* Regression test for our workaround for a fun epoll/linux related bug 2746275970Scy * where fd2 = dup(fd1); add(fd2); close(fd2); dup2(fd1,fd2); add(fd2) 2747275970Scy * will get you an EEXIST */ 2748275970Scystatic void 2749275970Scytest_dup_fd(void *arg) 2750275970Scy{ 2751275970Scy struct basic_test_data *data = arg; 2752275970Scy struct event_base *base = data->base; 2753275970Scy struct event *ev1=NULL, *ev2=NULL; 2754275970Scy int fd, dfd=-1; 2755275970Scy int ev1_got, ev2_got; 2756275970Scy 2757275970Scy tt_int_op(write(data->pair[0], "Hello world", 2758275970Scy strlen("Hello world")), >, 0); 2759275970Scy fd = data->pair[1]; 2760275970Scy 2761275970Scy dfd = dup(fd); 2762275970Scy tt_int_op(dfd, >=, 0); 2763275970Scy 2764275970Scy ev1 = event_new(base, fd, EV_READ|EV_PERSIST, dfd_cb, &ev1_got); 2765275970Scy ev2 = event_new(base, dfd, EV_READ|EV_PERSIST, dfd_cb, &ev2_got); 2766275970Scy ev1_got = ev2_got = 0; 2767275970Scy event_add(ev1, NULL); 2768275970Scy event_add(ev2, NULL); 2769275970Scy event_base_loop(base, EVLOOP_ONCE); 2770275970Scy tt_int_op(ev1_got, ==, EV_READ); 2771275970Scy tt_int_op(ev2_got, ==, EV_READ); 2772275970Scy 2773275970Scy /* Now close and delete dfd then dispatch. We need to do the 2774275970Scy * dispatch here so that when we add it later, we think there 2775275970Scy * was an intermediate delete. */ 2776275970Scy close(dfd); 2777275970Scy event_del(ev2); 2778275970Scy ev1_got = ev2_got = 0; 2779275970Scy event_base_loop(base, EVLOOP_ONCE); 2780275970Scy tt_want_int_op(ev1_got, ==, EV_READ); 2781275970Scy tt_int_op(ev2_got, ==, 0); 2782275970Scy 2783275970Scy /* Re-duplicate the fd. We need to get the same duplicated 2784275970Scy * value that we closed to provoke the epoll quirk. Also, we 2785275970Scy * need to change the events to write, or else the old lingering 2786275970Scy * read event will make the test pass whether the change was 2787275970Scy * successful or not. */ 2788275970Scy tt_int_op(dup2(fd, dfd), ==, dfd); 2789275970Scy event_free(ev2); 2790275970Scy ev2 = event_new(base, dfd, EV_WRITE|EV_PERSIST, dfd_cb, &ev2_got); 2791275970Scy event_add(ev2, NULL); 2792275970Scy ev1_got = ev2_got = 0; 2793275970Scy event_base_loop(base, EVLOOP_ONCE); 2794275970Scy tt_want_int_op(ev1_got, ==, EV_READ); 2795275970Scy tt_int_op(ev2_got, ==, EV_WRITE); 2796275970Scy 2797275970Scyend: 2798275970Scy if (ev1) 2799275970Scy event_free(ev1); 2800275970Scy if (ev2) 2801275970Scy event_free(ev2); 2802275970Scy if (dfd >= 0) 2803275970Scy close(dfd); 2804275970Scy} 2805275970Scy#endif 2806275970Scy 2807275970Scy#ifdef EVENT__DISABLE_MM_REPLACEMENT 2808275970Scystatic void 2809275970Scytest_mm_functions(void *arg) 2810275970Scy{ 2811275970Scy tinytest_set_test_skipped_(); 2812275970Scy} 2813275970Scy#else 2814275970Scystatic int 2815275970Scycheck_dummy_mem_ok(void *mem_) 2816275970Scy{ 2817275970Scy char *mem = mem_; 2818275970Scy mem -= 16; 2819275970Scy return !memcmp(mem, "{[<guardedram>]}", 16); 2820275970Scy} 2821275970Scy 2822275970Scystatic void * 2823275970Scydummy_malloc(size_t len) 2824275970Scy{ 2825275970Scy char *mem = malloc(len+16); 2826275970Scy memcpy(mem, "{[<guardedram>]}", 16); 2827275970Scy return mem+16; 2828275970Scy} 2829275970Scy 2830275970Scystatic void * 2831275970Scydummy_realloc(void *mem_, size_t len) 2832275970Scy{ 2833275970Scy char *mem = mem_; 2834275970Scy if (!mem) 2835275970Scy return dummy_malloc(len); 2836275970Scy tt_want(check_dummy_mem_ok(mem_)); 2837275970Scy mem -= 16; 2838275970Scy mem = realloc(mem, len+16); 2839275970Scy return mem+16; 2840275970Scy} 2841275970Scy 2842275970Scystatic void 2843275970Scydummy_free(void *mem_) 2844275970Scy{ 2845275970Scy char *mem = mem_; 2846275970Scy tt_want(check_dummy_mem_ok(mem_)); 2847275970Scy mem -= 16; 2848275970Scy free(mem); 2849275970Scy} 2850275970Scy 2851275970Scystatic void 2852275970Scytest_mm_functions(void *arg) 2853275970Scy{ 2854275970Scy struct event_base *b = NULL; 2855275970Scy struct event_config *cfg = NULL; 2856275970Scy event_set_mem_functions(dummy_malloc, dummy_realloc, dummy_free); 2857275970Scy cfg = event_config_new(); 2858275970Scy event_config_avoid_method(cfg, "Nonesuch"); 2859275970Scy b = event_base_new_with_config(cfg); 2860275970Scy tt_assert(b); 2861275970Scy tt_assert(check_dummy_mem_ok(b)); 2862275970Scyend: 2863275970Scy if (cfg) 2864275970Scy event_config_free(cfg); 2865275970Scy if (b) 2866275970Scy event_base_free(b); 2867275970Scy} 2868275970Scy#endif 2869275970Scy 2870275970Scystatic void 2871275970Scymany_event_cb(evutil_socket_t fd, short event, void *arg) 2872275970Scy{ 2873275970Scy int *calledp = arg; 2874275970Scy *calledp += 1; 2875275970Scy} 2876275970Scy 2877275970Scystatic void 2878275970Scytest_many_events(void *arg) 2879275970Scy{ 2880275970Scy /* Try 70 events that should all be ready at once. This will 2881275970Scy * exercise the "resize" code on most of the backends, and will make 2882275970Scy * sure that we can get past the 64-handle limit of some windows 2883275970Scy * functions. */ 2884275970Scy#define MANY 70 2885275970Scy 2886275970Scy struct basic_test_data *data = arg; 2887275970Scy struct event_base *base = data->base; 2888275970Scy int one_at_a_time = data->setup_data != NULL; 2889275970Scy evutil_socket_t sock[MANY]; 2890275970Scy struct event *ev[MANY]; 2891275970Scy int called[MANY]; 2892275970Scy int i; 2893275970Scy int loopflags = EVLOOP_NONBLOCK, evflags=0; 2894275970Scy if (one_at_a_time) { 2895275970Scy loopflags |= EVLOOP_ONCE; 2896275970Scy evflags = EV_PERSIST; 2897275970Scy } 2898275970Scy 2899275970Scy memset(sock, 0xff, sizeof(sock)); 2900275970Scy memset(ev, 0, sizeof(ev)); 2901275970Scy memset(called, 0, sizeof(called)); 2902275970Scy 2903275970Scy for (i = 0; i < MANY; ++i) { 2904275970Scy /* We need an event that will hit the backend, and that will 2905275970Scy * be ready immediately. "Send a datagram" is an easy 2906275970Scy * instance of that. */ 2907275970Scy sock[i] = socket(AF_INET, SOCK_DGRAM, 0); 2908275970Scy tt_assert(sock[i] >= 0); 2909275970Scy called[i] = 0; 2910275970Scy ev[i] = event_new(base, sock[i], EV_WRITE|evflags, 2911275970Scy many_event_cb, &called[i]); 2912275970Scy event_add(ev[i], NULL); 2913275970Scy if (one_at_a_time) 2914275970Scy event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE); 2915275970Scy } 2916275970Scy 2917275970Scy event_base_loop(base, loopflags); 2918275970Scy 2919275970Scy for (i = 0; i < MANY; ++i) { 2920275970Scy if (one_at_a_time) 2921275970Scy tt_int_op(called[i], ==, MANY - i + 1); 2922275970Scy else 2923275970Scy tt_int_op(called[i], ==, 1); 2924275970Scy } 2925275970Scy 2926275970Scyend: 2927275970Scy for (i = 0; i < MANY; ++i) { 2928275970Scy if (ev[i]) 2929275970Scy event_free(ev[i]); 2930275970Scy if (sock[i] >= 0) 2931275970Scy evutil_closesocket(sock[i]); 2932275970Scy } 2933275970Scy#undef MANY 2934275970Scy} 2935275970Scy 2936275970Scystatic void 2937275970Scytest_struct_event_size(void *arg) 2938275970Scy{ 2939275970Scy tt_int_op(event_get_struct_event_size(), <=, sizeof(struct event)); 2940275970Scyend: 2941275970Scy ; 2942275970Scy} 2943275970Scy 2944275970Scystatic void 2945275970Scytest_get_assignment(void *arg) 2946275970Scy{ 2947275970Scy struct basic_test_data *data = arg; 2948275970Scy struct event_base *base = data->base; 2949275970Scy struct event *ev1 = NULL; 2950275970Scy const char *str = "foo"; 2951275970Scy 2952275970Scy struct event_base *b; 2953275970Scy evutil_socket_t s; 2954275970Scy short what; 2955275970Scy event_callback_fn cb; 2956275970Scy void *cb_arg; 2957275970Scy 2958275970Scy ev1 = event_new(base, data->pair[1], EV_READ, dummy_read_cb, (void*)str); 2959275970Scy event_get_assignment(ev1, &b, &s, &what, &cb, &cb_arg); 2960275970Scy 2961275970Scy tt_ptr_op(b, ==, base); 2962275970Scy tt_int_op(s, ==, data->pair[1]); 2963275970Scy tt_int_op(what, ==, EV_READ); 2964275970Scy tt_ptr_op(cb, ==, dummy_read_cb); 2965275970Scy tt_ptr_op(cb_arg, ==, str); 2966275970Scy 2967275970Scy /* Now make sure this doesn't crash. */ 2968275970Scy event_get_assignment(ev1, NULL, NULL, NULL, NULL, NULL); 2969275970Scy 2970275970Scyend: 2971275970Scy if (ev1) 2972275970Scy event_free(ev1); 2973275970Scy} 2974275970Scy 2975275970Scystruct foreach_helper { 2976275970Scy int count; 2977275970Scy const struct event *ev; 2978275970Scy}; 2979275970Scy 2980275970Scystatic int 2981275970Scyforeach_count_cb(const struct event_base *base, const struct event *ev, void *arg) 2982275970Scy{ 2983275970Scy struct foreach_helper *h = event_get_callback_arg(ev); 2984275970Scy struct timeval *tv = arg; 2985275970Scy if (event_get_callback(ev) != timeout_cb) 2986275970Scy return 0; 2987275970Scy tt_ptr_op(event_get_base(ev), ==, base); 2988275970Scy tt_int_op(tv->tv_sec, ==, 10); 2989275970Scy h->ev = ev; 2990275970Scy h->count++; 2991275970Scy return 0; 2992275970Scyend: 2993275970Scy return -1; 2994275970Scy} 2995275970Scy 2996275970Scystatic int 2997275970Scyforeach_find_cb(const struct event_base *base, const struct event *ev, void *arg) 2998275970Scy{ 2999275970Scy const struct event **ev_out = arg; 3000275970Scy struct foreach_helper *h = event_get_callback_arg(ev); 3001275970Scy if (event_get_callback(ev) != timeout_cb) 3002275970Scy return 0; 3003275970Scy if (h->count == 99) { 3004275970Scy *ev_out = ev; 3005275970Scy return 101; 3006275970Scy } 3007275970Scy return 0; 3008275970Scy} 3009275970Scy 3010275970Scystatic void 3011275970Scytest_event_foreach(void *arg) 3012275970Scy{ 3013275970Scy struct basic_test_data *data = arg; 3014275970Scy struct event_base *base = data->base; 3015275970Scy struct event *ev[5]; 3016275970Scy struct foreach_helper visited[5]; 3017275970Scy int i; 3018275970Scy struct timeval ten_sec = {10,0}; 3019275970Scy const struct event *ev_found = NULL; 3020275970Scy 3021275970Scy for (i = 0; i < 5; ++i) { 3022275970Scy visited[i].count = 0; 3023275970Scy visited[i].ev = NULL; 3024275970Scy ev[i] = event_new(base, -1, 0, timeout_cb, &visited[i]); 3025275970Scy } 3026275970Scy 3027275970Scy tt_int_op(-1, ==, event_base_foreach_event(NULL, foreach_count_cb, NULL)); 3028275970Scy tt_int_op(-1, ==, event_base_foreach_event(base, NULL, NULL)); 3029275970Scy 3030275970Scy event_add(ev[0], &ten_sec); 3031275970Scy event_add(ev[1], &ten_sec); 3032275970Scy event_active(ev[1], EV_TIMEOUT, 1); 3033275970Scy event_active(ev[2], EV_TIMEOUT, 1); 3034275970Scy event_add(ev[3], &ten_sec); 3035275970Scy /* Don't touch ev[4]. */ 3036275970Scy 3037275970Scy tt_int_op(0, ==, event_base_foreach_event(base, foreach_count_cb, 3038275970Scy &ten_sec)); 3039275970Scy tt_int_op(1, ==, visited[0].count); 3040275970Scy tt_int_op(1, ==, visited[1].count); 3041275970Scy tt_int_op(1, ==, visited[2].count); 3042275970Scy tt_int_op(1, ==, visited[3].count); 3043275970Scy tt_ptr_op(ev[0], ==, visited[0].ev); 3044275970Scy tt_ptr_op(ev[1], ==, visited[1].ev); 3045275970Scy tt_ptr_op(ev[2], ==, visited[2].ev); 3046275970Scy tt_ptr_op(ev[3], ==, visited[3].ev); 3047275970Scy 3048275970Scy visited[2].count = 99; 3049275970Scy tt_int_op(101, ==, event_base_foreach_event(base, foreach_find_cb, 3050275970Scy &ev_found)); 3051275970Scy tt_ptr_op(ev_found, ==, ev[2]); 3052275970Scy 3053275970Scyend: 3054275970Scy for (i=0; i<5; ++i) { 3055275970Scy event_free(ev[i]); 3056275970Scy } 3057275970Scy} 3058275970Scy 3059275970Scystatic struct event_base *cached_time_base = NULL; 3060275970Scystatic int cached_time_reset = 0; 3061275970Scystatic int cached_time_sleep = 0; 3062275970Scystatic void 3063275970Scycache_time_cb(evutil_socket_t fd, short what, void *arg) 3064275970Scy{ 3065275970Scy struct timeval *tv = arg; 3066275970Scy tt_int_op(0, ==, event_base_gettimeofday_cached(cached_time_base, tv)); 3067275970Scy if (cached_time_sleep) { 3068275970Scy struct timeval delay = { 0, 30*1000 }; 3069275970Scy evutil_usleep_(&delay); 3070275970Scy } 3071275970Scy if (cached_time_reset) { 3072275970Scy event_base_update_cache_time(cached_time_base); 3073275970Scy } 3074275970Scyend: 3075275970Scy ; 3076275970Scy} 3077275970Scy 3078275970Scystatic void 3079275970Scytest_gettimeofday_cached(void *arg) 3080275970Scy{ 3081275970Scy struct basic_test_data *data = arg; 3082275970Scy struct event_config *cfg = NULL; 3083275970Scy struct event_base *base = NULL; 3084275970Scy struct timeval tv1, tv2, tv3, now; 3085275970Scy struct event *ev1=NULL, *ev2=NULL, *ev3=NULL; 3086275970Scy int cached_time_disable = strstr(data->setup_data, "disable") != NULL; 3087275970Scy 3088275970Scy cfg = event_config_new(); 3089275970Scy if (cached_time_disable) { 3090275970Scy event_config_set_flag(cfg, EVENT_BASE_FLAG_NO_CACHE_TIME); 3091275970Scy } 3092275970Scy cached_time_base = base = event_base_new_with_config(cfg); 3093275970Scy tt_assert(base); 3094275970Scy 3095275970Scy /* Try gettimeofday_cached outside of an event loop. */ 3096275970Scy evutil_gettimeofday(&now, NULL); 3097275970Scy tt_int_op(0, ==, event_base_gettimeofday_cached(NULL, &tv1)); 3098275970Scy tt_int_op(0, ==, event_base_gettimeofday_cached(base, &tv2)); 3099275970Scy tt_int_op(timeval_msec_diff(&tv1, &tv2), <, 10); 3100275970Scy tt_int_op(timeval_msec_diff(&tv1, &now), <, 10); 3101275970Scy 3102275970Scy cached_time_reset = strstr(data->setup_data, "reset") != NULL; 3103275970Scy cached_time_sleep = strstr(data->setup_data, "sleep") != NULL; 3104275970Scy 3105275970Scy ev1 = event_new(base, -1, 0, cache_time_cb, &tv1); 3106275970Scy ev2 = event_new(base, -1, 0, cache_time_cb, &tv2); 3107275970Scy ev3 = event_new(base, -1, 0, cache_time_cb, &tv3); 3108275970Scy 3109275970Scy event_active(ev1, EV_TIMEOUT, 1); 3110275970Scy event_active(ev2, EV_TIMEOUT, 1); 3111275970Scy event_active(ev3, EV_TIMEOUT, 1); 3112275970Scy 3113275970Scy event_base_dispatch(base); 3114275970Scy 3115275970Scy if (cached_time_reset && cached_time_sleep) { 3116275970Scy tt_int_op(labs(timeval_msec_diff(&tv1,&tv2)), >, 10); 3117275970Scy tt_int_op(labs(timeval_msec_diff(&tv2,&tv3)), >, 10); 3118275970Scy } else if (cached_time_disable && cached_time_sleep) { 3119275970Scy tt_int_op(labs(timeval_msec_diff(&tv1,&tv2)), >, 10); 3120275970Scy tt_int_op(labs(timeval_msec_diff(&tv2,&tv3)), >, 10); 3121275970Scy } else if (! cached_time_disable) { 3122275970Scy tt_assert(evutil_timercmp(&tv1, &tv2, ==)); 3123275970Scy tt_assert(evutil_timercmp(&tv2, &tv3, ==)); 3124275970Scy } 3125275970Scy 3126275970Scyend: 3127275970Scy if (ev1) 3128275970Scy event_free(ev1); 3129275970Scy if (ev2) 3130275970Scy event_free(ev2); 3131275970Scy if (ev3) 3132275970Scy event_free(ev3); 3133275970Scy if (base) 3134275970Scy event_base_free(base); 3135275970Scy if (cfg) 3136275970Scy event_config_free(cfg); 3137275970Scy} 3138275970Scy 3139275970Scystatic void 3140275970Scytabf_cb(evutil_socket_t fd, short what, void *arg) 3141275970Scy{ 3142275970Scy int *ptr = arg; 3143275970Scy *ptr = what; 3144275970Scy *ptr += 0x10000; 3145275970Scy} 3146275970Scy 3147275970Scystatic void 3148275970Scytest_active_by_fd(void *arg) 3149275970Scy{ 3150275970Scy struct basic_test_data *data = arg; 3151275970Scy struct event_base *base = data->base; 3152275970Scy struct event *ev1 = NULL, *ev2 = NULL, *ev3 = NULL, *ev4 = NULL; 3153275970Scy int e1,e2,e3,e4; 3154275970Scy#ifndef _WIN32 3155275970Scy struct event *evsig = NULL; 3156275970Scy int es; 3157275970Scy#endif 3158275970Scy struct timeval tenmin = { 600, 0 }; 3159275970Scy 3160275970Scy /* Ensure no crash on nonexistent FD. */ 3161275970Scy event_base_active_by_fd(base, 1000, EV_READ); 3162275970Scy 3163275970Scy /* Ensure no crash on bogus FD. */ 3164275970Scy event_base_active_by_fd(base, -1, EV_READ); 3165275970Scy 3166275970Scy /* Ensure no crash on nonexistent/bogus signal. */ 3167275970Scy event_base_active_by_signal(base, 1000); 3168275970Scy event_base_active_by_signal(base, -1); 3169275970Scy 3170275970Scy event_base_assert_ok_(base); 3171275970Scy 3172275970Scy e1 = e2 = e3 = e4 = 0; 3173275970Scy ev1 = event_new(base, data->pair[0], EV_READ, tabf_cb, &e1); 3174275970Scy ev2 = event_new(base, data->pair[0], EV_WRITE, tabf_cb, &e2); 3175275970Scy ev3 = event_new(base, data->pair[1], EV_READ, tabf_cb, &e3); 3176275970Scy ev4 = event_new(base, data->pair[1], EV_READ, tabf_cb, &e4); 3177275970Scy tt_assert(ev1); 3178275970Scy tt_assert(ev2); 3179275970Scy tt_assert(ev3); 3180275970Scy tt_assert(ev4); 3181275970Scy#ifndef _WIN32 3182275970Scy evsig = event_new(base, SIGHUP, EV_SIGNAL, tabf_cb, &es); 3183275970Scy tt_assert(evsig); 3184275970Scy event_add(evsig, &tenmin); 3185275970Scy#endif 3186275970Scy 3187275970Scy event_add(ev1, &tenmin); 3188275970Scy event_add(ev2, NULL); 3189275970Scy event_add(ev3, NULL); 3190275970Scy event_add(ev4, &tenmin); 3191275970Scy 3192275970Scy 3193275970Scy event_base_assert_ok_(base); 3194275970Scy 3195275970Scy /* Trigger 2, 3, 4 */ 3196275970Scy event_base_active_by_fd(base, data->pair[0], EV_WRITE); 3197275970Scy event_base_active_by_fd(base, data->pair[1], EV_READ); 3198275970Scy#ifndef _WIN32 3199275970Scy event_base_active_by_signal(base, SIGHUP); 3200275970Scy#endif 3201275970Scy 3202275970Scy event_base_assert_ok_(base); 3203275970Scy 3204275970Scy event_base_loop(base, EVLOOP_ONCE); 3205275970Scy 3206275970Scy tt_int_op(e1, ==, 0); 3207275970Scy tt_int_op(e2, ==, EV_WRITE | 0x10000); 3208275970Scy tt_int_op(e3, ==, EV_READ | 0x10000); 3209275970Scy /* Mask out EV_WRITE here, since it could be genuinely writeable. */ 3210275970Scy tt_int_op((e4 & ~EV_WRITE), ==, EV_READ | 0x10000); 3211275970Scy#ifndef _WIN32 3212275970Scy tt_int_op(es, ==, EV_SIGNAL | 0x10000); 3213275970Scy#endif 3214275970Scy 3215275970Scyend: 3216275970Scy if (ev1) 3217275970Scy event_free(ev1); 3218275970Scy if (ev2) 3219275970Scy event_free(ev2); 3220275970Scy if (ev3) 3221275970Scy event_free(ev3); 3222275970Scy if (ev4) 3223275970Scy event_free(ev4); 3224275970Scy#ifndef _WIN32 3225275970Scy if (evsig) 3226275970Scy event_free(evsig); 3227275970Scy#endif 3228275970Scy} 3229275970Scy 3230275970Scystruct testcase_t main_testcases[] = { 3231275970Scy /* Some converted-over tests */ 3232275970Scy { "methods", test_methods, TT_FORK, NULL, NULL }, 3233275970Scy { "version", test_version, 0, NULL, NULL }, 3234275970Scy BASIC(base_features, TT_FORK|TT_NO_LOGS), 3235275970Scy { "base_environ", test_base_environ, TT_FORK, NULL, NULL }, 3236275970Scy 3237275970Scy BASIC(event_base_new, TT_FORK|TT_NEED_SOCKETPAIR), 3238275970Scy BASIC(free_active_base, TT_FORK|TT_NEED_SOCKETPAIR), 3239275970Scy 3240275970Scy BASIC(manipulate_active_events, TT_FORK|TT_NEED_BASE), 3241275970Scy BASIC(event_new_selfarg, TT_FORK|TT_NEED_BASE), 3242275970Scy BASIC(event_assign_selfarg, TT_FORK|TT_NEED_BASE), 3243275970Scy BASIC(event_base_get_num_events, TT_FORK|TT_NEED_BASE), 3244275970Scy BASIC(event_base_get_max_events, TT_FORK|TT_NEED_BASE), 3245275970Scy 3246275970Scy BASIC(bad_assign, TT_FORK|TT_NEED_BASE|TT_NO_LOGS), 3247275970Scy BASIC(bad_reentrant, TT_FORK|TT_NEED_BASE|TT_NO_LOGS), 3248275970Scy BASIC(active_later, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 3249275970Scy BASIC(event_remove_timeout, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 3250275970Scy 3251275970Scy /* These are still using the old API */ 3252275970Scy LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE), 3253275970Scy { "persistent_timeout_jump", test_persistent_timeout_jump, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 3254275970Scy { "persistent_active_timeout", test_persistent_active_timeout, 3255275970Scy TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 3256275970Scy LEGACY(priorities, TT_FORK|TT_NEED_BASE), 3257275970Scy BASIC(priority_active_inversion, TT_FORK|TT_NEED_BASE), 3258275970Scy { "common_timeout", test_common_timeout, TT_FORK|TT_NEED_BASE, 3259275970Scy &basic_setup, NULL }, 3260275970Scy 3261275970Scy /* These legacy tests may not all need all of these flags. */ 3262275970Scy LEGACY(simpleread, TT_ISOLATED), 3263275970Scy LEGACY(simpleread_multiple, TT_ISOLATED), 3264275970Scy LEGACY(simplewrite, TT_ISOLATED), 3265275970Scy { "simpleclose", test_simpleclose, TT_FORK, &basic_setup, 3266275970Scy NULL }, 3267275970Scy LEGACY(multiple, TT_ISOLATED), 3268275970Scy LEGACY(persistent, TT_ISOLATED), 3269275970Scy LEGACY(combined, TT_ISOLATED), 3270275970Scy LEGACY(simpletimeout, TT_ISOLATED), 3271275970Scy LEGACY(loopbreak, TT_ISOLATED), 3272275970Scy LEGACY(loopexit, TT_ISOLATED), 3273275970Scy LEGACY(loopexit_multiple, TT_ISOLATED), 3274275970Scy LEGACY(nonpersist_readd, TT_ISOLATED), 3275275970Scy LEGACY(multiple_events_for_same_fd, TT_ISOLATED), 3276275970Scy LEGACY(want_only_once, TT_ISOLATED), 3277275970Scy { "event_once", test_event_once, TT_ISOLATED, &basic_setup, NULL }, 3278275970Scy { "event_once_never", test_event_once_never, TT_ISOLATED, &basic_setup, NULL }, 3279275970Scy { "event_pending", test_event_pending, TT_ISOLATED, &basic_setup, 3280275970Scy NULL }, 3281275970Scy#ifndef _WIN32 3282275970Scy { "dup_fd", test_dup_fd, TT_ISOLATED, &basic_setup, NULL }, 3283275970Scy#endif 3284275970Scy { "mm_functions", test_mm_functions, TT_FORK, NULL, NULL }, 3285275970Scy { "many_events", test_many_events, TT_ISOLATED, &basic_setup, NULL }, 3286275970Scy { "many_events_slow_add", test_many_events, TT_ISOLATED, &basic_setup, (void*)1 }, 3287275970Scy 3288275970Scy { "struct_event_size", test_struct_event_size, 0, NULL, NULL }, 3289275970Scy BASIC(get_assignment, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 3290275970Scy 3291275970Scy BASIC(event_foreach, TT_FORK|TT_NEED_BASE), 3292275970Scy { "gettimeofday_cached", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"" }, 3293275970Scy { "gettimeofday_cached_sleep", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep" }, 3294275970Scy { "gettimeofday_cached_reset", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep reset" }, 3295275970Scy { "gettimeofday_cached_disabled", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep disable" }, 3296275970Scy { "gettimeofday_cached_disabled_nosleep", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"disable" }, 3297275970Scy 3298275970Scy BASIC(active_by_fd, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR), 3299275970Scy 3300275970Scy#ifndef _WIN32 3301275970Scy LEGACY(fork, TT_ISOLATED), 3302275970Scy#endif 3303275970Scy END_OF_TESTCASES 3304275970Scy}; 3305275970Scy 3306275970Scystruct testcase_t evtag_testcases[] = { 3307275970Scy { "int", evtag_int_test, TT_FORK, NULL, NULL }, 3308275970Scy { "fuzz", evtag_fuzz, TT_FORK, NULL, NULL }, 3309275970Scy { "encoding", evtag_tag_encoding, TT_FORK, NULL, NULL }, 3310275970Scy { "peek", evtag_test_peek, 0, NULL, NULL }, 3311275970Scy 3312275970Scy END_OF_TESTCASES 3313275970Scy}; 3314275970Scy 3315275970Scystruct testcase_t signal_testcases[] = { 3316275970Scy#ifndef _WIN32 3317285612Sdelphij LEGACY(simplestsignal, TT_ISOLATED), 3318275970Scy LEGACY(simplesignal, TT_ISOLATED), 3319275970Scy LEGACY(multiplesignal, TT_ISOLATED), 3320275970Scy LEGACY(immediatesignal, TT_ISOLATED), 3321275970Scy LEGACY(signal_dealloc, TT_ISOLATED), 3322275970Scy LEGACY(signal_pipeloss, TT_ISOLATED), 3323275970Scy LEGACY(signal_switchbase, TT_ISOLATED|TT_NO_LOGS), 3324275970Scy LEGACY(signal_restore, TT_ISOLATED), 3325275970Scy LEGACY(signal_assert, TT_ISOLATED), 3326275970Scy LEGACY(signal_while_processing, TT_ISOLATED), 3327275970Scy#endif 3328275970Scy END_OF_TESTCASES 3329275970Scy}; 3330275970Scy 3331