Annotation of embedaddon/libevent/test/regress.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: * 3. The name of the author may not be used to endorse or promote products
! 14: * derived from this software without specific prior written permission.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 26: */
! 27:
! 28: #ifdef WIN32
! 29: #include <winsock2.h>
! 30: #include <windows.h>
! 31: #endif
! 32:
! 33: #ifdef HAVE_CONFIG_H
! 34: #include "config.h"
! 35: #endif
! 36:
! 37: #include <sys/types.h>
! 38: #include <sys/stat.h>
! 39: #ifdef HAVE_SYS_TIME_H
! 40: #include <sys/time.h>
! 41: #endif
! 42: #include <sys/queue.h>
! 43: #ifndef WIN32
! 44: #include <sys/socket.h>
! 45: #include <sys/wait.h>
! 46: #include <signal.h>
! 47: #include <unistd.h>
! 48: #include <netdb.h>
! 49: #endif
! 50: #include <assert.h>
! 51: #include <fcntl.h>
! 52: #include <signal.h>
! 53: #include <stdlib.h>
! 54: #include <stdio.h>
! 55: #include <string.h>
! 56: #include <errno.h>
! 57:
! 58: #include "event.h"
! 59: #include "evutil.h"
! 60: #include "event-internal.h"
! 61: #include "log.h"
! 62:
! 63: #include "regress.h"
! 64: #ifndef WIN32
! 65: #include "regress.gen.h"
! 66: #endif
! 67:
! 68: int pair[2];
! 69: int test_ok;
! 70: static int called;
! 71: static char wbuf[4096];
! 72: static char rbuf[4096];
! 73: static int woff;
! 74: static int roff;
! 75: static int usepersist;
! 76: static struct timeval tset;
! 77: static struct timeval tcalled;
! 78: static struct event_base *global_base;
! 79:
! 80: #define TEST1 "this is a test"
! 81: #define SECONDS 1
! 82:
! 83: #ifndef SHUT_WR
! 84: #define SHUT_WR 1
! 85: #endif
! 86:
! 87: #ifdef WIN32
! 88: #define write(fd,buf,len) send((fd),(buf),(len),0)
! 89: #define read(fd,buf,len) recv((fd),(buf),(len),0)
! 90: #endif
! 91:
! 92: static void
! 93: simple_read_cb(int fd, short event, void *arg)
! 94: {
! 95: char buf[256];
! 96: int len;
! 97:
! 98: if (arg == NULL)
! 99: return;
! 100:
! 101: len = read(fd, buf, sizeof(buf));
! 102:
! 103: if (len) {
! 104: if (!called) {
! 105: if (event_add(arg, NULL) == -1)
! 106: exit(1);
! 107: }
! 108: } else if (called == 1)
! 109: test_ok = 1;
! 110:
! 111: called++;
! 112: }
! 113:
! 114: static void
! 115: simple_write_cb(int fd, short event, void *arg)
! 116: {
! 117: int len;
! 118:
! 119: if (arg == NULL)
! 120: return;
! 121:
! 122: len = write(fd, TEST1, strlen(TEST1) + 1);
! 123: if (len == -1)
! 124: test_ok = 0;
! 125: else
! 126: test_ok = 1;
! 127: }
! 128:
! 129: static void
! 130: multiple_write_cb(int fd, short event, void *arg)
! 131: {
! 132: struct event *ev = arg;
! 133: int len;
! 134:
! 135: len = 128;
! 136: if (woff + len >= sizeof(wbuf))
! 137: len = sizeof(wbuf) - woff;
! 138:
! 139: len = write(fd, wbuf + woff, len);
! 140: if (len == -1) {
! 141: fprintf(stderr, "%s: write\n", __func__);
! 142: if (usepersist)
! 143: event_del(ev);
! 144: return;
! 145: }
! 146:
! 147: woff += len;
! 148:
! 149: if (woff >= sizeof(wbuf)) {
! 150: shutdown(fd, SHUT_WR);
! 151: if (usepersist)
! 152: event_del(ev);
! 153: return;
! 154: }
! 155:
! 156: if (!usepersist) {
! 157: if (event_add(ev, NULL) == -1)
! 158: exit(1);
! 159: }
! 160: }
! 161:
! 162: static void
! 163: multiple_read_cb(int fd, short event, void *arg)
! 164: {
! 165: struct event *ev = arg;
! 166: int len;
! 167:
! 168: len = read(fd, rbuf + roff, sizeof(rbuf) - roff);
! 169: if (len == -1)
! 170: fprintf(stderr, "%s: read\n", __func__);
! 171: if (len <= 0) {
! 172: if (usepersist)
! 173: event_del(ev);
! 174: return;
! 175: }
! 176:
! 177: roff += len;
! 178: if (!usepersist) {
! 179: if (event_add(ev, NULL) == -1)
! 180: exit(1);
! 181: }
! 182: }
! 183:
! 184: static void
! 185: timeout_cb(int fd, short event, void *arg)
! 186: {
! 187: struct timeval tv;
! 188: int diff;
! 189:
! 190: evutil_gettimeofday(&tcalled, NULL);
! 191: if (evutil_timercmp(&tcalled, &tset, >))
! 192: evutil_timersub(&tcalled, &tset, &tv);
! 193: else
! 194: evutil_timersub(&tset, &tcalled, &tv);
! 195:
! 196: diff = tv.tv_sec*1000 + tv.tv_usec/1000 - SECONDS * 1000;
! 197: if (diff < 0)
! 198: diff = -diff;
! 199:
! 200: if (diff < 100)
! 201: test_ok = 1;
! 202: }
! 203:
! 204: #ifndef WIN32
! 205: static void
! 206: signal_cb_sa(int sig)
! 207: {
! 208: test_ok = 2;
! 209: }
! 210:
! 211: static void
! 212: signal_cb(int fd, short event, void *arg)
! 213: {
! 214: struct event *ev = arg;
! 215:
! 216: signal_del(ev);
! 217: test_ok = 1;
! 218: }
! 219: #endif
! 220:
! 221: struct both {
! 222: struct event ev;
! 223: int nread;
! 224: };
! 225:
! 226: static void
! 227: combined_read_cb(int fd, short event, void *arg)
! 228: {
! 229: struct both *both = arg;
! 230: char buf[128];
! 231: int len;
! 232:
! 233: len = read(fd, buf, sizeof(buf));
! 234: if (len == -1)
! 235: fprintf(stderr, "%s: read\n", __func__);
! 236: if (len <= 0)
! 237: return;
! 238:
! 239: both->nread += len;
! 240: if (event_add(&both->ev, NULL) == -1)
! 241: exit(1);
! 242: }
! 243:
! 244: static void
! 245: combined_write_cb(int fd, short event, void *arg)
! 246: {
! 247: struct both *both = arg;
! 248: char buf[128];
! 249: int len;
! 250:
! 251: len = sizeof(buf);
! 252: if (len > both->nread)
! 253: len = both->nread;
! 254:
! 255: len = write(fd, buf, len);
! 256: if (len == -1)
! 257: fprintf(stderr, "%s: write\n", __func__);
! 258: if (len <= 0) {
! 259: shutdown(fd, SHUT_WR);
! 260: return;
! 261: }
! 262:
! 263: both->nread -= len;
! 264: if (event_add(&both->ev, NULL) == -1)
! 265: exit(1);
! 266: }
! 267:
! 268: /* Test infrastructure */
! 269:
! 270: static int
! 271: setup_test(const char *name)
! 272: {
! 273:
! 274: fprintf(stdout, "%s", name);
! 275:
! 276: if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
! 277: fprintf(stderr, "%s: socketpair\n", __func__);
! 278: exit(1);
! 279: }
! 280:
! 281: #ifdef HAVE_FCNTL
! 282: if (fcntl(pair[0], F_SETFL, O_NONBLOCK) == -1)
! 283: fprintf(stderr, "fcntl(O_NONBLOCK)");
! 284:
! 285: if (fcntl(pair[1], F_SETFL, O_NONBLOCK) == -1)
! 286: fprintf(stderr, "fcntl(O_NONBLOCK)");
! 287: #endif
! 288:
! 289: test_ok = 0;
! 290: called = 0;
! 291: return (0);
! 292: }
! 293:
! 294: static int
! 295: cleanup_test(void)
! 296: {
! 297: #ifndef WIN32
! 298: close(pair[0]);
! 299: close(pair[1]);
! 300: #else
! 301: CloseHandle((HANDLE)pair[0]);
! 302: CloseHandle((HANDLE)pair[1]);
! 303: #endif
! 304: if (test_ok)
! 305: fprintf(stdout, "OK\n");
! 306: else {
! 307: fprintf(stdout, "FAILED\n");
! 308: exit(1);
! 309: }
! 310: test_ok = 0;
! 311: return (0);
! 312: }
! 313:
! 314: static void
! 315: test_registerfds(void)
! 316: {
! 317: int i, j;
! 318: int pair[2];
! 319: struct event read_evs[512];
! 320: struct event write_evs[512];
! 321:
! 322: struct event_base *base = event_base_new();
! 323:
! 324: fprintf(stdout, "Testing register fds: ");
! 325:
! 326: for (i = 0; i < 512; ++i) {
! 327: if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
! 328: /* run up to the limit of file descriptors */
! 329: break;
! 330: }
! 331: event_set(&read_evs[i], pair[0],
! 332: EV_READ|EV_PERSIST, simple_read_cb, NULL);
! 333: event_base_set(base, &read_evs[i]);
! 334: event_add(&read_evs[i], NULL);
! 335: event_set(&write_evs[i], pair[1],
! 336: EV_WRITE|EV_PERSIST, simple_write_cb, NULL);
! 337: event_base_set(base, &write_evs[i]);
! 338: event_add(&write_evs[i], NULL);
! 339:
! 340: /* just loop once */
! 341: event_base_loop(base, EVLOOP_ONCE);
! 342: }
! 343:
! 344: /* now delete everything */
! 345: for (j = 0; j < i; ++j) {
! 346: event_del(&read_evs[j]);
! 347: event_del(&write_evs[j]);
! 348: #ifndef WIN32
! 349: close(read_evs[j].ev_fd);
! 350: close(write_evs[j].ev_fd);
! 351: #else
! 352: CloseHandle((HANDLE)read_evs[j].ev_fd);
! 353: CloseHandle((HANDLE)write_evs[j].ev_fd);
! 354: #endif
! 355:
! 356: /* just loop once */
! 357: event_base_loop(base, EVLOOP_ONCE);
! 358: }
! 359:
! 360: event_base_free(base);
! 361:
! 362: fprintf(stdout, "OK\n");
! 363: }
! 364:
! 365: static void
! 366: test_simpleread(void)
! 367: {
! 368: struct event ev;
! 369:
! 370: /* Very simple read test */
! 371: setup_test("Simple read: ");
! 372:
! 373: write(pair[0], TEST1, strlen(TEST1)+1);
! 374: shutdown(pair[0], SHUT_WR);
! 375:
! 376: event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev);
! 377: if (event_add(&ev, NULL) == -1)
! 378: exit(1);
! 379: event_dispatch();
! 380:
! 381: cleanup_test();
! 382: }
! 383:
! 384: static void
! 385: test_simplewrite(void)
! 386: {
! 387: struct event ev;
! 388:
! 389: /* Very simple write test */
! 390: setup_test("Simple write: ");
! 391:
! 392: event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev);
! 393: if (event_add(&ev, NULL) == -1)
! 394: exit(1);
! 395: event_dispatch();
! 396:
! 397: cleanup_test();
! 398: }
! 399:
! 400: static void
! 401: test_multiple(void)
! 402: {
! 403: struct event ev, ev2;
! 404: int i;
! 405:
! 406: /* Multiple read and write test */
! 407: setup_test("Multiple read/write: ");
! 408: memset(rbuf, 0, sizeof(rbuf));
! 409: for (i = 0; i < sizeof(wbuf); i++)
! 410: wbuf[i] = i;
! 411:
! 412: roff = woff = 0;
! 413: usepersist = 0;
! 414:
! 415: event_set(&ev, pair[0], EV_WRITE, multiple_write_cb, &ev);
! 416: if (event_add(&ev, NULL) == -1)
! 417: exit(1);
! 418: event_set(&ev2, pair[1], EV_READ, multiple_read_cb, &ev2);
! 419: if (event_add(&ev2, NULL) == -1)
! 420: exit(1);
! 421: event_dispatch();
! 422:
! 423: if (roff == woff)
! 424: test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0;
! 425:
! 426: cleanup_test();
! 427: }
! 428:
! 429: static void
! 430: test_persistent(void)
! 431: {
! 432: struct event ev, ev2;
! 433: int i;
! 434:
! 435: /* Multiple read and write test with persist */
! 436: setup_test("Persist read/write: ");
! 437: memset(rbuf, 0, sizeof(rbuf));
! 438: for (i = 0; i < sizeof(wbuf); i++)
! 439: wbuf[i] = i;
! 440:
! 441: roff = woff = 0;
! 442: usepersist = 1;
! 443:
! 444: event_set(&ev, pair[0], EV_WRITE|EV_PERSIST, multiple_write_cb, &ev);
! 445: if (event_add(&ev, NULL) == -1)
! 446: exit(1);
! 447: event_set(&ev2, pair[1], EV_READ|EV_PERSIST, multiple_read_cb, &ev2);
! 448: if (event_add(&ev2, NULL) == -1)
! 449: exit(1);
! 450: event_dispatch();
! 451:
! 452: if (roff == woff)
! 453: test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0;
! 454:
! 455: cleanup_test();
! 456: }
! 457:
! 458: static void
! 459: test_combined(void)
! 460: {
! 461: struct both r1, r2, w1, w2;
! 462:
! 463: setup_test("Combined read/write: ");
! 464: memset(&r1, 0, sizeof(r1));
! 465: memset(&r2, 0, sizeof(r2));
! 466: memset(&w1, 0, sizeof(w1));
! 467: memset(&w2, 0, sizeof(w2));
! 468:
! 469: w1.nread = 4096;
! 470: w2.nread = 8192;
! 471:
! 472: event_set(&r1.ev, pair[0], EV_READ, combined_read_cb, &r1);
! 473: event_set(&w1.ev, pair[0], EV_WRITE, combined_write_cb, &w1);
! 474: event_set(&r2.ev, pair[1], EV_READ, combined_read_cb, &r2);
! 475: event_set(&w2.ev, pair[1], EV_WRITE, combined_write_cb, &w2);
! 476: if (event_add(&r1.ev, NULL) == -1)
! 477: exit(1);
! 478: if (event_add(&w1.ev, NULL))
! 479: exit(1);
! 480: if (event_add(&r2.ev, NULL))
! 481: exit(1);
! 482: if (event_add(&w2.ev, NULL))
! 483: exit(1);
! 484:
! 485: event_dispatch();
! 486:
! 487: if (r1.nread == 8192 && r2.nread == 4096)
! 488: test_ok = 1;
! 489:
! 490: cleanup_test();
! 491: }
! 492:
! 493: static void
! 494: test_simpletimeout(void)
! 495: {
! 496: struct timeval tv;
! 497: struct event ev;
! 498:
! 499: setup_test("Simple timeout: ");
! 500:
! 501: tv.tv_usec = 0;
! 502: tv.tv_sec = SECONDS;
! 503: evtimer_set(&ev, timeout_cb, NULL);
! 504: evtimer_add(&ev, &tv);
! 505:
! 506: evutil_gettimeofday(&tset, NULL);
! 507: event_dispatch();
! 508:
! 509: cleanup_test();
! 510: }
! 511:
! 512: #ifndef WIN32
! 513: extern struct event_base *current_base;
! 514:
! 515: static void
! 516: child_signal_cb(int fd, short event, void *arg)
! 517: {
! 518: struct timeval tv;
! 519: int *pint = arg;
! 520:
! 521: *pint = 1;
! 522:
! 523: tv.tv_usec = 500000;
! 524: tv.tv_sec = 0;
! 525: event_loopexit(&tv);
! 526: }
! 527:
! 528: static void
! 529: test_fork(void)
! 530: {
! 531: int status, got_sigchld = 0;
! 532: struct event ev, sig_ev;
! 533: pid_t pid;
! 534:
! 535: setup_test("After fork: ");
! 536:
! 537: write(pair[0], TEST1, strlen(TEST1)+1);
! 538:
! 539: event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev);
! 540: if (event_add(&ev, NULL) == -1)
! 541: exit(1);
! 542:
! 543: signal_set(&sig_ev, SIGCHLD, child_signal_cb, &got_sigchld);
! 544: signal_add(&sig_ev, NULL);
! 545:
! 546: if ((pid = fork()) == 0) {
! 547: /* in the child */
! 548: if (event_reinit(current_base) == -1) {
! 549: fprintf(stderr, "FAILED (reinit)\n");
! 550: exit(1);
! 551: }
! 552:
! 553: signal_del(&sig_ev);
! 554:
! 555: called = 0;
! 556:
! 557: event_dispatch();
! 558:
! 559: /* we do not send an EOF; simple_read_cb requires an EOF
! 560: * to set test_ok. we just verify that the callback was
! 561: * called. */
! 562: exit(test_ok != 0 || called != 2 ? -2 : 76);
! 563: }
! 564:
! 565: /* wait for the child to read the data */
! 566: sleep(1);
! 567:
! 568: write(pair[0], TEST1, strlen(TEST1)+1);
! 569:
! 570: if (waitpid(pid, &status, 0) == -1) {
! 571: fprintf(stderr, "FAILED (fork)\n");
! 572: exit(1);
! 573: }
! 574:
! 575: if (WEXITSTATUS(status) != 76) {
! 576: fprintf(stderr, "FAILED (exit): %d\n", WEXITSTATUS(status));
! 577: exit(1);
! 578: }
! 579:
! 580: /* test that the current event loop still works */
! 581: write(pair[0], TEST1, strlen(TEST1)+1);
! 582: shutdown(pair[0], SHUT_WR);
! 583:
! 584: event_dispatch();
! 585:
! 586: if (!got_sigchld) {
! 587: fprintf(stdout, "FAILED (sigchld)\n");
! 588: exit(1);
! 589: }
! 590:
! 591: signal_del(&sig_ev);
! 592:
! 593: cleanup_test();
! 594: }
! 595:
! 596: static void
! 597: test_simplesignal(void)
! 598: {
! 599: struct event ev;
! 600: struct itimerval itv;
! 601:
! 602: setup_test("Simple signal: ");
! 603: signal_set(&ev, SIGALRM, signal_cb, &ev);
! 604: signal_add(&ev, NULL);
! 605: /* find bugs in which operations are re-ordered */
! 606: signal_del(&ev);
! 607: signal_add(&ev, NULL);
! 608:
! 609: memset(&itv, 0, sizeof(itv));
! 610: itv.it_value.tv_sec = 1;
! 611: if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
! 612: goto skip_simplesignal;
! 613:
! 614: event_dispatch();
! 615: skip_simplesignal:
! 616: if (signal_del(&ev) == -1)
! 617: test_ok = 0;
! 618:
! 619: cleanup_test();
! 620: }
! 621:
! 622: static void
! 623: test_multiplesignal(void)
! 624: {
! 625: struct event ev_one, ev_two;
! 626: struct itimerval itv;
! 627:
! 628: setup_test("Multiple signal: ");
! 629:
! 630: signal_set(&ev_one, SIGALRM, signal_cb, &ev_one);
! 631: signal_add(&ev_one, NULL);
! 632:
! 633: signal_set(&ev_two, SIGALRM, signal_cb, &ev_two);
! 634: signal_add(&ev_two, NULL);
! 635:
! 636: memset(&itv, 0, sizeof(itv));
! 637: itv.it_value.tv_sec = 1;
! 638: if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
! 639: goto skip_simplesignal;
! 640:
! 641: event_dispatch();
! 642:
! 643: skip_simplesignal:
! 644: if (signal_del(&ev_one) == -1)
! 645: test_ok = 0;
! 646: if (signal_del(&ev_two) == -1)
! 647: test_ok = 0;
! 648:
! 649: cleanup_test();
! 650: }
! 651:
! 652: static void
! 653: test_immediatesignal(void)
! 654: {
! 655: struct event ev;
! 656:
! 657: test_ok = 0;
! 658: printf("Immediate signal: ");
! 659: signal_set(&ev, SIGUSR1, signal_cb, &ev);
! 660: signal_add(&ev, NULL);
! 661: raise(SIGUSR1);
! 662: event_loop(EVLOOP_NONBLOCK);
! 663: signal_del(&ev);
! 664: cleanup_test();
! 665: }
! 666:
! 667: static void
! 668: test_signal_dealloc(void)
! 669: {
! 670: /* make sure that signal_event is event_del'ed and pipe closed */
! 671: struct event ev;
! 672: struct event_base *base = event_init();
! 673: printf("Signal dealloc: ");
! 674: signal_set(&ev, SIGUSR1, signal_cb, &ev);
! 675: signal_add(&ev, NULL);
! 676: signal_del(&ev);
! 677: event_base_free(base);
! 678: /* If we got here without asserting, we're fine. */
! 679: test_ok = 1;
! 680: cleanup_test();
! 681: }
! 682:
! 683: static void
! 684: test_signal_pipeloss(void)
! 685: {
! 686: /* make sure that the base1 pipe is closed correctly. */
! 687: struct event_base *base1, *base2;
! 688: int pipe1;
! 689: test_ok = 0;
! 690: printf("Signal pipeloss: ");
! 691: base1 = event_init();
! 692: pipe1 = base1->sig.ev_signal_pair[0];
! 693: base2 = event_init();
! 694: event_base_free(base2);
! 695: event_base_free(base1);
! 696: if (close(pipe1) != -1 || errno!=EBADF) {
! 697: /* fd must be closed, so second close gives -1, EBADF */
! 698: printf("signal pipe not closed. ");
! 699: test_ok = 0;
! 700: } else {
! 701: test_ok = 1;
! 702: }
! 703: cleanup_test();
! 704: }
! 705:
! 706: /*
! 707: * make two bases to catch signals, use both of them. this only works
! 708: * for event mechanisms that use our signal pipe trick. kqueue handles
! 709: * signals internally, and all interested kqueues get all the signals.
! 710: */
! 711: static void
! 712: test_signal_switchbase(void)
! 713: {
! 714: struct event ev1, ev2;
! 715: struct event_base *base1, *base2;
! 716: int is_kqueue;
! 717: test_ok = 0;
! 718: printf("Signal switchbase: ");
! 719: base1 = event_init();
! 720: base2 = event_init();
! 721: is_kqueue = !strcmp(event_get_method(),"kqueue");
! 722: signal_set(&ev1, SIGUSR1, signal_cb, &ev1);
! 723: signal_set(&ev2, SIGUSR1, signal_cb, &ev2);
! 724: if (event_base_set(base1, &ev1) ||
! 725: event_base_set(base2, &ev2) ||
! 726: event_add(&ev1, NULL) ||
! 727: event_add(&ev2, NULL)) {
! 728: fprintf(stderr, "%s: cannot set base, add\n", __func__);
! 729: exit(1);
! 730: }
! 731:
! 732: test_ok = 0;
! 733: /* can handle signal before loop is called */
! 734: raise(SIGUSR1);
! 735: event_base_loop(base2, EVLOOP_NONBLOCK);
! 736: if (is_kqueue) {
! 737: if (!test_ok)
! 738: goto done;
! 739: test_ok = 0;
! 740: }
! 741: event_base_loop(base1, EVLOOP_NONBLOCK);
! 742: if (test_ok && !is_kqueue) {
! 743: test_ok = 0;
! 744:
! 745: /* set base1 to handle signals */
! 746: event_base_loop(base1, EVLOOP_NONBLOCK);
! 747: raise(SIGUSR1);
! 748: event_base_loop(base1, EVLOOP_NONBLOCK);
! 749: event_base_loop(base2, EVLOOP_NONBLOCK);
! 750: }
! 751: done:
! 752: event_base_free(base1);
! 753: event_base_free(base2);
! 754: cleanup_test();
! 755: }
! 756:
! 757: /*
! 758: * assert that a signal event removed from the event queue really is
! 759: * removed - with no possibility of it's parent handler being fired.
! 760: */
! 761: static void
! 762: test_signal_assert(void)
! 763: {
! 764: struct event ev;
! 765: struct event_base *base = event_init();
! 766: test_ok = 0;
! 767: printf("Signal handler assert: ");
! 768: /* use SIGCONT so we don't kill ourselves when we signal to nowhere */
! 769: signal_set(&ev, SIGCONT, signal_cb, &ev);
! 770: signal_add(&ev, NULL);
! 771: /*
! 772: * if signal_del() fails to reset the handler, it's current handler
! 773: * will still point to evsignal_handler().
! 774: */
! 775: signal_del(&ev);
! 776:
! 777: raise(SIGCONT);
! 778: /* only way to verify we were in evsignal_handler() */
! 779: if (base->sig.evsignal_caught)
! 780: test_ok = 0;
! 781: else
! 782: test_ok = 1;
! 783:
! 784: event_base_free(base);
! 785: cleanup_test();
! 786: return;
! 787: }
! 788:
! 789: /*
! 790: * assert that we restore our previous signal handler properly.
! 791: */
! 792: static void
! 793: test_signal_restore(void)
! 794: {
! 795: struct event ev;
! 796: struct event_base *base = event_init();
! 797: #ifdef HAVE_SIGACTION
! 798: struct sigaction sa;
! 799: #endif
! 800:
! 801: test_ok = 0;
! 802: printf("Signal handler restore: ");
! 803: #ifdef HAVE_SIGACTION
! 804: sa.sa_handler = signal_cb_sa;
! 805: sa.sa_flags = 0x0;
! 806: sigemptyset(&sa.sa_mask);
! 807: if (sigaction(SIGUSR1, &sa, NULL) == -1)
! 808: goto out;
! 809: #else
! 810: if (signal(SIGUSR1, signal_cb_sa) == SIG_ERR)
! 811: goto out;
! 812: #endif
! 813: signal_set(&ev, SIGUSR1, signal_cb, &ev);
! 814: signal_add(&ev, NULL);
! 815: signal_del(&ev);
! 816:
! 817: raise(SIGUSR1);
! 818: /* 1 == signal_cb, 2 == signal_cb_sa, we want our previous handler */
! 819: if (test_ok != 2)
! 820: test_ok = 0;
! 821: out:
! 822: event_base_free(base);
! 823: cleanup_test();
! 824: return;
! 825: }
! 826:
! 827: static void
! 828: signal_cb_swp(int sig, short event, void *arg)
! 829: {
! 830: called++;
! 831: if (called < 5)
! 832: raise(sig);
! 833: else
! 834: event_loopexit(NULL);
! 835: }
! 836: static void
! 837: timeout_cb_swp(int fd, short event, void *arg)
! 838: {
! 839: if (called == -1) {
! 840: struct timeval tv = {5, 0};
! 841:
! 842: called = 0;
! 843: evtimer_add((struct event *)arg, &tv);
! 844: raise(SIGUSR1);
! 845: return;
! 846: }
! 847: test_ok = 0;
! 848: event_loopexit(NULL);
! 849: }
! 850:
! 851: static void
! 852: test_signal_while_processing(void)
! 853: {
! 854: struct event_base *base = event_init();
! 855: struct event ev, ev_timer;
! 856: struct timeval tv = {0, 0};
! 857:
! 858: setup_test("Receiving a signal while processing other signal: ");
! 859:
! 860: called = -1;
! 861: test_ok = 1;
! 862: signal_set(&ev, SIGUSR1, signal_cb_swp, NULL);
! 863: signal_add(&ev, NULL);
! 864: evtimer_set(&ev_timer, timeout_cb_swp, &ev_timer);
! 865: evtimer_add(&ev_timer, &tv);
! 866: event_dispatch();
! 867:
! 868: event_base_free(base);
! 869: cleanup_test();
! 870: return;
! 871: }
! 872: #endif
! 873:
! 874: static void
! 875: test_free_active_base(void)
! 876: {
! 877: struct event_base *base1;
! 878: struct event ev1;
! 879: setup_test("Free active base: ");
! 880: base1 = event_init();
! 881: event_set(&ev1, pair[1], EV_READ, simple_read_cb, &ev1);
! 882: event_base_set(base1, &ev1);
! 883: event_add(&ev1, NULL);
! 884: /* event_del(&ev1); */
! 885: event_base_free(base1);
! 886: test_ok = 1;
! 887: cleanup_test();
! 888: }
! 889:
! 890: static void
! 891: test_event_base_new(void)
! 892: {
! 893: struct event_base *base;
! 894: struct event ev1;
! 895: setup_test("Event base new: ");
! 896:
! 897: write(pair[0], TEST1, strlen(TEST1)+1);
! 898: shutdown(pair[0], SHUT_WR);
! 899:
! 900: base = event_base_new();
! 901: event_set(&ev1, pair[1], EV_READ, simple_read_cb, &ev1);
! 902: event_base_set(base, &ev1);
! 903: event_add(&ev1, NULL);
! 904:
! 905: event_base_dispatch(base);
! 906:
! 907: event_base_free(base);
! 908: test_ok = 1;
! 909: cleanup_test();
! 910: }
! 911:
! 912: static void
! 913: test_loopexit(void)
! 914: {
! 915: struct timeval tv, tv_start, tv_end;
! 916: struct event ev;
! 917:
! 918: setup_test("Loop exit: ");
! 919:
! 920: tv.tv_usec = 0;
! 921: tv.tv_sec = 60*60*24;
! 922: evtimer_set(&ev, timeout_cb, NULL);
! 923: evtimer_add(&ev, &tv);
! 924:
! 925: tv.tv_usec = 0;
! 926: tv.tv_sec = 1;
! 927: event_loopexit(&tv);
! 928:
! 929: evutil_gettimeofday(&tv_start, NULL);
! 930: event_dispatch();
! 931: evutil_gettimeofday(&tv_end, NULL);
! 932: evutil_timersub(&tv_end, &tv_start, &tv_end);
! 933:
! 934: evtimer_del(&ev);
! 935:
! 936: if (tv.tv_sec < 2)
! 937: test_ok = 1;
! 938:
! 939: cleanup_test();
! 940: }
! 941:
! 942: static void
! 943: test_loopexit_multiple(void)
! 944: {
! 945: struct timeval tv;
! 946: struct event_base *base;
! 947:
! 948: setup_test("Loop Multiple exit: ");
! 949:
! 950: base = event_base_new();
! 951:
! 952: tv.tv_usec = 0;
! 953: tv.tv_sec = 1;
! 954: event_base_loopexit(base, &tv);
! 955:
! 956: tv.tv_usec = 0;
! 957: tv.tv_sec = 2;
! 958: event_base_loopexit(base, &tv);
! 959:
! 960: event_base_dispatch(base);
! 961:
! 962: event_base_free(base);
! 963:
! 964: test_ok = 1;
! 965:
! 966: cleanup_test();
! 967: }
! 968:
! 969: static void
! 970: break_cb(int fd, short events, void *arg)
! 971: {
! 972: test_ok = 1;
! 973: event_loopbreak();
! 974: }
! 975:
! 976: static void
! 977: fail_cb(int fd, short events, void *arg)
! 978: {
! 979: test_ok = 0;
! 980: }
! 981:
! 982: static void
! 983: test_loopbreak(void)
! 984: {
! 985: struct event ev1, ev2;
! 986: struct timeval tv;
! 987:
! 988: setup_test("Loop break: ");
! 989:
! 990: tv.tv_sec = 0;
! 991: tv.tv_usec = 0;
! 992: evtimer_set(&ev1, break_cb, NULL);
! 993: evtimer_add(&ev1, &tv);
! 994: evtimer_set(&ev2, fail_cb, NULL);
! 995: evtimer_add(&ev2, &tv);
! 996:
! 997: event_dispatch();
! 998:
! 999: evtimer_del(&ev1);
! 1000: evtimer_del(&ev2);
! 1001:
! 1002: cleanup_test();
! 1003: }
! 1004:
! 1005: static void
! 1006: test_evbuffer(void) {
! 1007:
! 1008: struct evbuffer *evb = evbuffer_new();
! 1009: setup_test("Testing Evbuffer: ");
! 1010:
! 1011: evbuffer_add_printf(evb, "%s/%d", "hello", 1);
! 1012:
! 1013: if (EVBUFFER_LENGTH(evb) == 7 &&
! 1014: strcmp((char*)EVBUFFER_DATA(evb), "hello/1") == 0)
! 1015: test_ok = 1;
! 1016:
! 1017: evbuffer_free(evb);
! 1018:
! 1019: cleanup_test();
! 1020: }
! 1021:
! 1022: static void
! 1023: test_evbuffer_readln(void)
! 1024: {
! 1025: struct evbuffer *evb = evbuffer_new();
! 1026: struct evbuffer *evb_tmp = evbuffer_new();
! 1027: const char *s;
! 1028: char *cp = NULL;
! 1029: size_t sz;
! 1030:
! 1031: #define tt_line_eq(content) \
! 1032: if (!cp || sz != strlen(content) || strcmp(cp, content)) { \
! 1033: fprintf(stdout, "FAILED\n"); \
! 1034: exit(1); \
! 1035: }
! 1036: #define tt_assert(expression) \
! 1037: if (!(expression)) { \
! 1038: fprintf(stdout, "FAILED\n"); \
! 1039: exit(1); \
! 1040: } \
! 1041:
! 1042: /* Test EOL_ANY. */
! 1043: fprintf(stdout, "Testing evbuffer_readln EOL_ANY: ");
! 1044:
! 1045: s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
! 1046: evbuffer_add(evb, s, strlen(s)+2);
! 1047: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
! 1048: tt_line_eq("complex silly newline");
! 1049: free(cp);
! 1050: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
! 1051: if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6)) {
! 1052: fprintf(stdout, "FAILED\n");
! 1053: exit(1);
! 1054: }
! 1055: if (evb->totallen == 0) {
! 1056: fprintf(stdout, "FAILED\n");
! 1057: exit(1);
! 1058: }
! 1059: s = "\nno newline";
! 1060: evbuffer_add(evb, s, strlen(s));
! 1061: free(cp);
! 1062: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
! 1063: tt_line_eq("");
! 1064: free(cp);
! 1065: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
! 1066: tt_assert(!cp);
! 1067: evbuffer_drain(evb, EVBUFFER_LENGTH(evb));
! 1068: tt_assert(EVBUFFER_LENGTH(evb) == 0);
! 1069:
! 1070: fprintf(stdout, "OK\n");
! 1071:
! 1072: /* Test EOL_CRLF */
! 1073: fprintf(stdout, "Testing evbuffer_readln EOL_CRLF: ");
! 1074:
! 1075: s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
! 1076: evbuffer_add(evb, s, strlen(s));
! 1077: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
! 1078: tt_line_eq("Line with\rin the middle");
! 1079: free(cp);
! 1080:
! 1081: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
! 1082: tt_line_eq("Line with good crlf");
! 1083: free(cp);
! 1084:
! 1085: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
! 1086: tt_line_eq("");
! 1087: free(cp);
! 1088:
! 1089: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
! 1090: tt_line_eq("final");
! 1091: s = "x";
! 1092: evbuffer_add(evb, s, 1);
! 1093: free(cp);
! 1094: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
! 1095: tt_assert(!cp);
! 1096:
! 1097: fprintf(stdout, "OK\n");
! 1098:
! 1099: /* Test CRLF_STRICT */
! 1100: fprintf(stdout, "Testing evbuffer_readln CRLF_STRICT: ");
! 1101:
! 1102: s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
! 1103: evbuffer_add(evb, s, strlen(s));
! 1104: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1105: tt_line_eq("x and a bad crlf\nand a good one");
! 1106: free(cp);
! 1107:
! 1108: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1109: tt_line_eq("");
! 1110: free(cp);
! 1111:
! 1112: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1113: tt_assert(!cp);
! 1114: evbuffer_add(evb, "\n", 1);
! 1115:
! 1116: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1117: tt_line_eq("More");
! 1118: free(cp);
! 1119: tt_assert(EVBUFFER_LENGTH(evb) == 0);
! 1120:
! 1121: s = "An internal CR\r is not an eol\r\nNor is a lack of one";
! 1122: evbuffer_add(evb, s, strlen(s));
! 1123: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1124: tt_line_eq("An internal CR\r is not an eol");
! 1125: free(cp);
! 1126:
! 1127: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1128: tt_assert(!cp);
! 1129:
! 1130: evbuffer_add(evb, "\r\n", 2);
! 1131: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1132: tt_line_eq("Nor is a lack of one");
! 1133: free(cp);
! 1134: tt_assert(EVBUFFER_LENGTH(evb) == 0);
! 1135:
! 1136: fprintf(stdout, "OK\n");
! 1137:
! 1138: /* Test LF */
! 1139: fprintf(stdout, "Testing evbuffer_readln LF: ");
! 1140:
! 1141: s = "An\rand a nl\n\nText";
! 1142: evbuffer_add(evb, s, strlen(s));
! 1143:
! 1144: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
! 1145: tt_line_eq("An\rand a nl");
! 1146: free(cp);
! 1147:
! 1148: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
! 1149: tt_line_eq("");
! 1150: free(cp);
! 1151:
! 1152: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
! 1153: tt_assert(!cp);
! 1154: free(cp);
! 1155: evbuffer_add(evb, "\n", 1);
! 1156: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
! 1157: tt_line_eq("Text");
! 1158: free(cp);
! 1159:
! 1160: fprintf(stdout, "OK\n");
! 1161:
! 1162: /* Test CRLF_STRICT - across boundaries */
! 1163: fprintf(stdout,
! 1164: "Testing evbuffer_readln CRLF_STRICT across boundaries: ");
! 1165:
! 1166: s = " and a bad crlf\nand a good one\r";
! 1167: evbuffer_add(evb_tmp, s, strlen(s));
! 1168: evbuffer_add_buffer(evb, evb_tmp);
! 1169: s = "\n\r";
! 1170: evbuffer_add(evb_tmp, s, strlen(s));
! 1171: evbuffer_add_buffer(evb, evb_tmp);
! 1172: s = "\nMore\r";
! 1173: evbuffer_add(evb_tmp, s, strlen(s));
! 1174: evbuffer_add_buffer(evb, evb_tmp);
! 1175:
! 1176: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1177: tt_line_eq(" and a bad crlf\nand a good one");
! 1178: free(cp);
! 1179:
! 1180: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1181: tt_line_eq("");
! 1182: free(cp);
! 1183:
! 1184: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1185: tt_assert(!cp);
! 1186: free(cp);
! 1187: evbuffer_add(evb, "\n", 1);
! 1188: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
! 1189: tt_line_eq("More");
! 1190: free(cp); cp = NULL;
! 1191: if (EVBUFFER_LENGTH(evb) != 0) {
! 1192: fprintf(stdout, "FAILED\n");
! 1193: exit(1);
! 1194: }
! 1195:
! 1196: fprintf(stdout, "OK\n");
! 1197:
! 1198: /* Test memory problem */
! 1199: fprintf(stdout, "Testing evbuffer_readln memory problem: ");
! 1200:
! 1201: s = "one line\ntwo line\nblue line";
! 1202: evbuffer_add(evb_tmp, s, strlen(s));
! 1203: evbuffer_add_buffer(evb, evb_tmp);
! 1204:
! 1205: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
! 1206: tt_line_eq("one line");
! 1207: free(cp); cp = NULL;
! 1208:
! 1209: cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
! 1210: tt_line_eq("two line");
! 1211: free(cp); cp = NULL;
! 1212:
! 1213: fprintf(stdout, "OK\n");
! 1214:
! 1215: test_ok = 1;
! 1216: evbuffer_free(evb);
! 1217: evbuffer_free(evb_tmp);
! 1218: if (cp) free(cp);
! 1219: }
! 1220:
! 1221: static void
! 1222: test_evbuffer_find(void)
! 1223: {
! 1224: u_char* p;
! 1225: const char* test1 = "1234567890\r\n";
! 1226: const char* test2 = "1234567890\r";
! 1227: #define EVBUFFER_INITIAL_LENGTH 256
! 1228: char test3[EVBUFFER_INITIAL_LENGTH];
! 1229: unsigned int i;
! 1230: struct evbuffer * buf = evbuffer_new();
! 1231:
! 1232: /* make sure evbuffer_find doesn't match past the end of the buffer */
! 1233: fprintf(stdout, "Testing evbuffer_find 1: ");
! 1234: evbuffer_add(buf, (u_char*)test1, strlen(test1));
! 1235: evbuffer_drain(buf, strlen(test1));
! 1236: evbuffer_add(buf, (u_char*)test2, strlen(test2));
! 1237: p = evbuffer_find(buf, (u_char*)"\r\n", 2);
! 1238: if (p == NULL) {
! 1239: fprintf(stdout, "OK\n");
! 1240: } else {
! 1241: fprintf(stdout, "FAILED\n");
! 1242: exit(1);
! 1243: }
! 1244:
! 1245: /*
! 1246: * drain the buffer and do another find; in r309 this would
! 1247: * read past the allocated buffer causing a valgrind error.
! 1248: */
! 1249: fprintf(stdout, "Testing evbuffer_find 2: ");
! 1250: evbuffer_drain(buf, strlen(test2));
! 1251: for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
! 1252: test3[i] = 'a';
! 1253: test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
! 1254: evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
! 1255: p = evbuffer_find(buf, (u_char *)"xy", 2);
! 1256: if (p == NULL) {
! 1257: printf("OK\n");
! 1258: } else {
! 1259: fprintf(stdout, "FAILED\n");
! 1260: exit(1);
! 1261: }
! 1262:
! 1263: /* simple test for match at end of allocated buffer */
! 1264: fprintf(stdout, "Testing evbuffer_find 3: ");
! 1265: p = evbuffer_find(buf, (u_char *)"ax", 2);
! 1266: if (p != NULL && strncmp((char*)p, "ax", 2) == 0) {
! 1267: printf("OK\n");
! 1268: } else {
! 1269: fprintf(stdout, "FAILED\n");
! 1270: exit(1);
! 1271: }
! 1272:
! 1273: evbuffer_free(buf);
! 1274: }
! 1275:
! 1276: /*
! 1277: * simple bufferevent test
! 1278: */
! 1279:
! 1280: static void
! 1281: readcb(struct bufferevent *bev, void *arg)
! 1282: {
! 1283: if (EVBUFFER_LENGTH(bev->input) == 8333) {
! 1284: bufferevent_disable(bev, EV_READ);
! 1285: test_ok++;
! 1286: }
! 1287: }
! 1288:
! 1289: static void
! 1290: writecb(struct bufferevent *bev, void *arg)
! 1291: {
! 1292: if (EVBUFFER_LENGTH(bev->output) == 0)
! 1293: test_ok++;
! 1294: }
! 1295:
! 1296: static void
! 1297: errorcb(struct bufferevent *bev, short what, void *arg)
! 1298: {
! 1299: test_ok = -2;
! 1300: }
! 1301:
! 1302: static void
! 1303: test_bufferevent(void)
! 1304: {
! 1305: struct bufferevent *bev1, *bev2;
! 1306: char buffer[8333];
! 1307: int i;
! 1308:
! 1309: setup_test("Bufferevent: ");
! 1310:
! 1311: bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL);
! 1312: bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL);
! 1313:
! 1314: bufferevent_disable(bev1, EV_READ);
! 1315: bufferevent_enable(bev2, EV_READ);
! 1316:
! 1317: for (i = 0; i < sizeof(buffer); i++)
! 1318: buffer[i] = i;
! 1319:
! 1320: bufferevent_write(bev1, buffer, sizeof(buffer));
! 1321:
! 1322: event_dispatch();
! 1323:
! 1324: bufferevent_free(bev1);
! 1325: bufferevent_free(bev2);
! 1326:
! 1327: if (test_ok != 2)
! 1328: test_ok = 0;
! 1329:
! 1330: cleanup_test();
! 1331: }
! 1332:
! 1333: /*
! 1334: * test watermarks and bufferevent
! 1335: */
! 1336:
! 1337: static void
! 1338: wm_readcb(struct bufferevent *bev, void *arg)
! 1339: {
! 1340: int len = EVBUFFER_LENGTH(bev->input);
! 1341: static int nread;
! 1342:
! 1343: assert(len >= 10 && len <= 20);
! 1344:
! 1345: evbuffer_drain(bev->input, len);
! 1346:
! 1347: nread += len;
! 1348: if (nread == 65000) {
! 1349: bufferevent_disable(bev, EV_READ);
! 1350: test_ok++;
! 1351: }
! 1352: }
! 1353:
! 1354: static void
! 1355: wm_writecb(struct bufferevent *bev, void *arg)
! 1356: {
! 1357: if (EVBUFFER_LENGTH(bev->output) == 0)
! 1358: test_ok++;
! 1359: }
! 1360:
! 1361: static void
! 1362: wm_errorcb(struct bufferevent *bev, short what, void *arg)
! 1363: {
! 1364: test_ok = -2;
! 1365: }
! 1366:
! 1367: static void
! 1368: test_bufferevent_watermarks(void)
! 1369: {
! 1370: struct bufferevent *bev1, *bev2;
! 1371: char buffer[65000];
! 1372: int i;
! 1373:
! 1374: setup_test("Bufferevent Watermarks: ");
! 1375:
! 1376: bev1 = bufferevent_new(pair[0], NULL, wm_writecb, wm_errorcb, NULL);
! 1377: bev2 = bufferevent_new(pair[1], wm_readcb, NULL, wm_errorcb, NULL);
! 1378:
! 1379: bufferevent_disable(bev1, EV_READ);
! 1380: bufferevent_enable(bev2, EV_READ);
! 1381:
! 1382: for (i = 0; i < sizeof(buffer); i++)
! 1383: buffer[i] = i;
! 1384:
! 1385: bufferevent_write(bev1, buffer, sizeof(buffer));
! 1386:
! 1387: /* limit the reading on the receiving bufferevent */
! 1388: bufferevent_setwatermark(bev2, EV_READ, 10, 20);
! 1389:
! 1390: event_dispatch();
! 1391:
! 1392: bufferevent_free(bev1);
! 1393: bufferevent_free(bev2);
! 1394:
! 1395: if (test_ok != 2)
! 1396: test_ok = 0;
! 1397:
! 1398: cleanup_test();
! 1399: }
! 1400:
! 1401: struct test_pri_event {
! 1402: struct event ev;
! 1403: int count;
! 1404: };
! 1405:
! 1406: static void
! 1407: test_priorities_cb(int fd, short what, void *arg)
! 1408: {
! 1409: struct test_pri_event *pri = arg;
! 1410: struct timeval tv;
! 1411:
! 1412: if (pri->count == 3) {
! 1413: event_loopexit(NULL);
! 1414: return;
! 1415: }
! 1416:
! 1417: pri->count++;
! 1418:
! 1419: evutil_timerclear(&tv);
! 1420: event_add(&pri->ev, &tv);
! 1421: }
! 1422:
! 1423: static void
! 1424: test_priorities(int npriorities)
! 1425: {
! 1426: char buf[32];
! 1427: struct test_pri_event one, two;
! 1428: struct timeval tv;
! 1429:
! 1430: evutil_snprintf(buf, sizeof(buf), "Testing Priorities %d: ", npriorities);
! 1431: setup_test(buf);
! 1432:
! 1433: event_base_priority_init(global_base, npriorities);
! 1434:
! 1435: memset(&one, 0, sizeof(one));
! 1436: memset(&two, 0, sizeof(two));
! 1437:
! 1438: timeout_set(&one.ev, test_priorities_cb, &one);
! 1439: if (event_priority_set(&one.ev, 0) == -1) {
! 1440: fprintf(stderr, "%s: failed to set priority", __func__);
! 1441: exit(1);
! 1442: }
! 1443:
! 1444: timeout_set(&two.ev, test_priorities_cb, &two);
! 1445: if (event_priority_set(&two.ev, npriorities - 1) == -1) {
! 1446: fprintf(stderr, "%s: failed to set priority", __func__);
! 1447: exit(1);
! 1448: }
! 1449:
! 1450: evutil_timerclear(&tv);
! 1451:
! 1452: if (event_add(&one.ev, &tv) == -1)
! 1453: exit(1);
! 1454: if (event_add(&two.ev, &tv) == -1)
! 1455: exit(1);
! 1456:
! 1457: event_dispatch();
! 1458:
! 1459: event_del(&one.ev);
! 1460: event_del(&two.ev);
! 1461:
! 1462: if (npriorities == 1) {
! 1463: if (one.count == 3 && two.count == 3)
! 1464: test_ok = 1;
! 1465: } else if (npriorities == 2) {
! 1466: /* Two is called once because event_loopexit is priority 1 */
! 1467: if (one.count == 3 && two.count == 1)
! 1468: test_ok = 1;
! 1469: } else {
! 1470: if (one.count == 3 && two.count == 0)
! 1471: test_ok = 1;
! 1472: }
! 1473:
! 1474: cleanup_test();
! 1475: }
! 1476:
! 1477: static void
! 1478: test_multiple_cb(int fd, short event, void *arg)
! 1479: {
! 1480: if (event & EV_READ)
! 1481: test_ok |= 1;
! 1482: else if (event & EV_WRITE)
! 1483: test_ok |= 2;
! 1484: }
! 1485:
! 1486: static void
! 1487: test_multiple_events_for_same_fd(void)
! 1488: {
! 1489: struct event e1, e2;
! 1490:
! 1491: setup_test("Multiple events for same fd: ");
! 1492:
! 1493: event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL);
! 1494: event_add(&e1, NULL);
! 1495: event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL);
! 1496: event_add(&e2, NULL);
! 1497: event_loop(EVLOOP_ONCE);
! 1498: event_del(&e2);
! 1499: write(pair[1], TEST1, strlen(TEST1)+1);
! 1500: event_loop(EVLOOP_ONCE);
! 1501: event_del(&e1);
! 1502:
! 1503: if (test_ok != 3)
! 1504: test_ok = 0;
! 1505:
! 1506: cleanup_test();
! 1507: }
! 1508:
! 1509: int evtag_decode_int(uint32_t *pnumber, struct evbuffer *evbuf);
! 1510: int evtag_encode_tag(struct evbuffer *evbuf, uint32_t number);
! 1511: int evtag_decode_tag(uint32_t *pnumber, struct evbuffer *evbuf);
! 1512:
! 1513: static void
! 1514: read_once_cb(int fd, short event, void *arg)
! 1515: {
! 1516: char buf[256];
! 1517: int len;
! 1518:
! 1519: len = read(fd, buf, sizeof(buf));
! 1520:
! 1521: if (called) {
! 1522: test_ok = 0;
! 1523: } else if (len) {
! 1524: /* Assumes global pair[0] can be used for writing */
! 1525: write(pair[0], TEST1, strlen(TEST1)+1);
! 1526: test_ok = 1;
! 1527: }
! 1528:
! 1529: called++;
! 1530: }
! 1531:
! 1532: static void
! 1533: test_want_only_once(void)
! 1534: {
! 1535: struct event ev;
! 1536: struct timeval tv;
! 1537:
! 1538: /* Very simple read test */
! 1539: setup_test("Want read only once: ");
! 1540:
! 1541: write(pair[0], TEST1, strlen(TEST1)+1);
! 1542:
! 1543: /* Setup the loop termination */
! 1544: evutil_timerclear(&tv);
! 1545: tv.tv_sec = 1;
! 1546: event_loopexit(&tv);
! 1547:
! 1548: event_set(&ev, pair[1], EV_READ, read_once_cb, &ev);
! 1549: if (event_add(&ev, NULL) == -1)
! 1550: exit(1);
! 1551: event_dispatch();
! 1552:
! 1553: cleanup_test();
! 1554: }
! 1555:
! 1556: #define TEST_MAX_INT 6
! 1557:
! 1558: static void
! 1559: evtag_int_test(void)
! 1560: {
! 1561: struct evbuffer *tmp = evbuffer_new();
! 1562: uint32_t integers[TEST_MAX_INT] = {
! 1563: 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000
! 1564: };
! 1565: uint32_t integer;
! 1566: int i;
! 1567:
! 1568: for (i = 0; i < TEST_MAX_INT; i++) {
! 1569: int oldlen, newlen;
! 1570: oldlen = EVBUFFER_LENGTH(tmp);
! 1571: encode_int(tmp, integers[i]);
! 1572: newlen = EVBUFFER_LENGTH(tmp);
! 1573: fprintf(stdout, "\t\tencoded 0x%08x with %d bytes\n",
! 1574: integers[i], newlen - oldlen);
! 1575: }
! 1576:
! 1577: for (i = 0; i < TEST_MAX_INT; i++) {
! 1578: if (evtag_decode_int(&integer, tmp) == -1) {
! 1579: fprintf(stderr, "decode %d failed", i);
! 1580: exit(1);
! 1581: }
! 1582: if (integer != integers[i]) {
! 1583: fprintf(stderr, "got %x, wanted %x",
! 1584: integer, integers[i]);
! 1585: exit(1);
! 1586: }
! 1587: }
! 1588:
! 1589: if (EVBUFFER_LENGTH(tmp) != 0) {
! 1590: fprintf(stderr, "trailing data");
! 1591: exit(1);
! 1592: }
! 1593: evbuffer_free(tmp);
! 1594:
! 1595: fprintf(stdout, "\t%s: OK\n", __func__);
! 1596: }
! 1597:
! 1598: static void
! 1599: evtag_fuzz(void)
! 1600: {
! 1601: u_char buffer[4096];
! 1602: struct evbuffer *tmp = evbuffer_new();
! 1603: struct timeval tv;
! 1604: int i, j;
! 1605:
! 1606: int not_failed = 0;
! 1607: for (j = 0; j < 100; j++) {
! 1608: for (i = 0; i < sizeof(buffer); i++)
! 1609: buffer[i] = rand();
! 1610: evbuffer_drain(tmp, -1);
! 1611: evbuffer_add(tmp, buffer, sizeof(buffer));
! 1612:
! 1613: if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1)
! 1614: not_failed++;
! 1615: }
! 1616:
! 1617: /* The majority of decodes should fail */
! 1618: if (not_failed >= 10) {
! 1619: fprintf(stderr, "evtag_unmarshal should have failed");
! 1620: exit(1);
! 1621: }
! 1622:
! 1623: /* Now insert some corruption into the tag length field */
! 1624: evbuffer_drain(tmp, -1);
! 1625: evutil_timerclear(&tv);
! 1626: tv.tv_sec = 1;
! 1627: evtag_marshal_timeval(tmp, 0, &tv);
! 1628: evbuffer_add(tmp, buffer, sizeof(buffer));
! 1629:
! 1630: EVBUFFER_DATA(tmp)[1] = 0xff;
! 1631: if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) {
! 1632: fprintf(stderr, "evtag_unmarshal_timeval should have failed");
! 1633: exit(1);
! 1634: }
! 1635:
! 1636: evbuffer_free(tmp);
! 1637:
! 1638: fprintf(stdout, "\t%s: OK\n", __func__);
! 1639: }
! 1640:
! 1641: static void
! 1642: evtag_tag_encoding(void)
! 1643: {
! 1644: struct evbuffer *tmp = evbuffer_new();
! 1645: uint32_t integers[TEST_MAX_INT] = {
! 1646: 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000
! 1647: };
! 1648: uint32_t integer;
! 1649: int i;
! 1650:
! 1651: for (i = 0; i < TEST_MAX_INT; i++) {
! 1652: int oldlen, newlen;
! 1653: oldlen = EVBUFFER_LENGTH(tmp);
! 1654: evtag_encode_tag(tmp, integers[i]);
! 1655: newlen = EVBUFFER_LENGTH(tmp);
! 1656: fprintf(stdout, "\t\tencoded 0x%08x with %d bytes\n",
! 1657: integers[i], newlen - oldlen);
! 1658: }
! 1659:
! 1660: for (i = 0; i < TEST_MAX_INT; i++) {
! 1661: if (evtag_decode_tag(&integer, tmp) == -1) {
! 1662: fprintf(stderr, "decode %d failed", i);
! 1663: exit(1);
! 1664: }
! 1665: if (integer != integers[i]) {
! 1666: fprintf(stderr, "got %x, wanted %x",
! 1667: integer, integers[i]);
! 1668: exit(1);
! 1669: }
! 1670: }
! 1671:
! 1672: if (EVBUFFER_LENGTH(tmp) != 0) {
! 1673: fprintf(stderr, "trailing data");
! 1674: exit(1);
! 1675: }
! 1676: evbuffer_free(tmp);
! 1677:
! 1678: fprintf(stdout, "\t%s: OK\n", __func__);
! 1679: }
! 1680:
! 1681: static void
! 1682: evtag_test(void)
! 1683: {
! 1684: fprintf(stdout, "Testing Tagging:\n");
! 1685:
! 1686: evtag_init();
! 1687: evtag_int_test();
! 1688: evtag_fuzz();
! 1689:
! 1690: evtag_tag_encoding();
! 1691:
! 1692: fprintf(stdout, "OK\n");
! 1693: }
! 1694:
! 1695: #ifndef WIN32
! 1696: static void
! 1697: rpc_test(void)
! 1698: {
! 1699: struct msg *msg, *msg2;
! 1700: struct kill *attack;
! 1701: struct run *run;
! 1702: struct evbuffer *tmp = evbuffer_new();
! 1703: struct timeval tv_start, tv_end;
! 1704: uint32_t tag;
! 1705: int i;
! 1706:
! 1707: fprintf(stdout, "Testing RPC: ");
! 1708:
! 1709: msg = msg_new();
! 1710: EVTAG_ASSIGN(msg, from_name, "niels");
! 1711: EVTAG_ASSIGN(msg, to_name, "phoenix");
! 1712:
! 1713: if (EVTAG_GET(msg, attack, &attack) == -1) {
! 1714: fprintf(stderr, "Failed to set kill message.\n");
! 1715: exit(1);
! 1716: }
! 1717:
! 1718: EVTAG_ASSIGN(attack, weapon, "feather");
! 1719: EVTAG_ASSIGN(attack, action, "tickle");
! 1720:
! 1721: evutil_gettimeofday(&tv_start, NULL);
! 1722: for (i = 0; i < 1000; ++i) {
! 1723: run = EVTAG_ADD(msg, run);
! 1724: if (run == NULL) {
! 1725: fprintf(stderr, "Failed to add run message.\n");
! 1726: exit(1);
! 1727: }
! 1728: EVTAG_ASSIGN(run, how, "very fast but with some data in it");
! 1729: EVTAG_ASSIGN(run, fixed_bytes,
! 1730: (unsigned char*)"012345678901234567890123");
! 1731: }
! 1732:
! 1733: if (msg_complete(msg) == -1) {
! 1734: fprintf(stderr, "Failed to make complete message.\n");
! 1735: exit(1);
! 1736: }
! 1737:
! 1738: evtag_marshal_msg(tmp, 0xdeaf, msg);
! 1739:
! 1740: if (evtag_peek(tmp, &tag) == -1) {
! 1741: fprintf(stderr, "Failed to peak tag.\n");
! 1742: exit (1);
! 1743: }
! 1744:
! 1745: if (tag != 0xdeaf) {
! 1746: fprintf(stderr, "Got incorrect tag: %0x.\n", tag);
! 1747: exit (1);
! 1748: }
! 1749:
! 1750: msg2 = msg_new();
! 1751: if (evtag_unmarshal_msg(tmp, 0xdeaf, msg2) == -1) {
! 1752: fprintf(stderr, "Failed to unmarshal message.\n");
! 1753: exit(1);
! 1754: }
! 1755:
! 1756: evutil_gettimeofday(&tv_end, NULL);
! 1757: evutil_timersub(&tv_end, &tv_start, &tv_end);
! 1758: fprintf(stderr, "(%.1f us/add) ",
! 1759: (float)tv_end.tv_sec/(float)i * 1000000.0 +
! 1760: tv_end.tv_usec / (float)i);
! 1761:
! 1762: if (!EVTAG_HAS(msg2, from_name) ||
! 1763: !EVTAG_HAS(msg2, to_name) ||
! 1764: !EVTAG_HAS(msg2, attack)) {
! 1765: fprintf(stderr, "Missing data structures.\n");
! 1766: exit(1);
! 1767: }
! 1768:
! 1769: if (EVTAG_LEN(msg2, run) != i) {
! 1770: fprintf(stderr, "Wrong number of run messages.\n");
! 1771: exit(1);
! 1772: }
! 1773:
! 1774: msg_free(msg);
! 1775: msg_free(msg2);
! 1776:
! 1777: evbuffer_free(tmp);
! 1778:
! 1779: fprintf(stdout, "OK\n");
! 1780: }
! 1781: #endif
! 1782:
! 1783: static void
! 1784: test_evutil_strtoll(void)
! 1785: {
! 1786: const char *s;
! 1787: char *endptr;
! 1788: setup_test("evutil_stroll: ");
! 1789: test_ok = 0;
! 1790:
! 1791: if (evutil_strtoll("5000000000", NULL, 10) != ((ev_int64_t)5000000)*1000)
! 1792: goto err;
! 1793: if (evutil_strtoll("-5000000000", NULL, 10) != ((ev_int64_t)5000000)*-1000)
! 1794: goto err;
! 1795: s = " 99999stuff";
! 1796: if (evutil_strtoll(s, &endptr, 10) != (ev_int64_t)99999)
! 1797: goto err;
! 1798: if (endptr != s+6)
! 1799: goto err;
! 1800: if (evutil_strtoll("foo", NULL, 10) != 0)
! 1801: goto err;
! 1802:
! 1803: test_ok = 1;
! 1804: err:
! 1805: cleanup_test();
! 1806: }
! 1807:
! 1808:
! 1809: int
! 1810: main (int argc, char **argv)
! 1811: {
! 1812: #ifdef WIN32
! 1813: WORD wVersionRequested;
! 1814: WSADATA wsaData;
! 1815: int err;
! 1816:
! 1817: wVersionRequested = MAKEWORD( 2, 2 );
! 1818:
! 1819: err = WSAStartup( wVersionRequested, &wsaData );
! 1820: #endif
! 1821:
! 1822: #ifndef WIN32
! 1823: if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
! 1824: return (1);
! 1825: #endif
! 1826: setvbuf(stdout, NULL, _IONBF, 0);
! 1827:
! 1828: /* Initalize the event library */
! 1829: global_base = event_init();
! 1830:
! 1831: test_registerfds();
! 1832:
! 1833: test_evutil_strtoll();
! 1834:
! 1835: /* use the global event base and need to be called first */
! 1836: test_priorities(1);
! 1837: test_priorities(2);
! 1838: test_priorities(3);
! 1839:
! 1840: test_evbuffer();
! 1841: test_evbuffer_find();
! 1842: test_evbuffer_readln();
! 1843:
! 1844: test_bufferevent();
! 1845: test_bufferevent_watermarks();
! 1846:
! 1847: test_free_active_base();
! 1848:
! 1849: test_event_base_new();
! 1850:
! 1851: http_suite();
! 1852:
! 1853: #ifndef WIN32
! 1854: rpc_suite();
! 1855: #endif
! 1856:
! 1857: dns_suite();
! 1858:
! 1859: #ifndef WIN32
! 1860: test_fork();
! 1861: #endif
! 1862:
! 1863: test_simpleread();
! 1864:
! 1865: test_simplewrite();
! 1866:
! 1867: test_multiple();
! 1868:
! 1869: test_persistent();
! 1870:
! 1871: test_combined();
! 1872:
! 1873: test_simpletimeout();
! 1874: #ifndef WIN32
! 1875: test_simplesignal();
! 1876: test_multiplesignal();
! 1877: test_immediatesignal();
! 1878: #endif
! 1879: test_loopexit();
! 1880: test_loopbreak();
! 1881:
! 1882: test_loopexit_multiple();
! 1883:
! 1884: test_multiple_events_for_same_fd();
! 1885:
! 1886: test_want_only_once();
! 1887:
! 1888: evtag_test();
! 1889:
! 1890: #ifndef WIN32
! 1891: rpc_test();
! 1892:
! 1893: test_signal_dealloc();
! 1894: test_signal_pipeloss();
! 1895: test_signal_switchbase();
! 1896: test_signal_restore();
! 1897: test_signal_assert();
! 1898: test_signal_while_processing();
! 1899: #endif
! 1900:
! 1901: return (0);
! 1902: }
! 1903:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>