1 /* 2 * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 3 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 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 /* The old tests here need assertions to work. */ 29 #undef NDEBUG 30 31 #ifdef _WIN32 32 #include <winsock2.h> 33 #include <windows.h> 34 #endif 35 36 #include "event2/event-config.h" 37 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #ifdef EVENT__HAVE_SYS_TIME_H 41 #include <sys/time.h> 42 #endif 43 #include <sys/queue.h> 44 #ifndef _WIN32 45 #include <sys/socket.h> 46 #include <signal.h> 47 #include <unistd.h> 48 #include <netdb.h> 49 #endif 50 #include <fcntl.h> 51 #include <stdlib.h> 52 #include <stdio.h> 53 #include <string.h> 54 #include <errno.h> 55 #include <assert.h> 56 57 #include "event2/buffer.h" 58 #include "event2/event.h" 59 #include "event2/event_compat.h" 60 #include "event2/http.h" 61 #include "event2/http_compat.h" 62 #include "event2/http_struct.h" 63 #include "event2/rpc.h" 64 #include "event2/rpc.h" 65 #include "event2/rpc_struct.h" 66 #include "event2/tag.h" 67 #include "log-internal.h" 68 69 #include "regress.gen.h" 70 71 #include "regress.h" 72 #include "regress_testutils.h" 73 74 #ifndef NO_PYTHON_EXISTS 75 76 static struct evhttp * 77 http_setup(ev_uint16_t *pport) 78 { 79 struct evhttp *myhttp; 80 ev_uint16_t port; 81 struct evhttp_bound_socket *sock; 82 83 myhttp = evhttp_new(NULL); 84 if (!myhttp) 85 event_errx(1, "Could not start web server"); 86 87 /* Try a few different ports */ 88 sock = evhttp_bind_socket_with_handle(myhttp, "127.0.0.1", 0); 89 if (!sock) 90 event_errx(1, "Couldn't open web port"); 91 92 port = regress_get_socket_port(evhttp_bound_socket_get_fd(sock)); 93 94 *pport = port; 95 return (myhttp); 96 } 97 98 EVRPC_HEADER(Message, msg, kill) 99 EVRPC_HEADER(NeverReply, msg, kill) 100 101 EVRPC_GENERATE(Message, msg, kill) 102 EVRPC_GENERATE(NeverReply, msg, kill) 103 104 static int need_input_hook = 0; 105 static int need_output_hook = 0; 106 107 static void 108 MessageCb(EVRPC_STRUCT(Message)* rpc, void *arg) 109 { 110 struct kill* kill_reply = rpc->reply; 111 112 if (need_input_hook) { 113 struct evhttp_request* req = EVRPC_REQUEST_HTTP(rpc); 114 const char *header = evhttp_find_header( 115 req->input_headers, "X-Hook"); 116 assert(header); 117 assert(strcmp(header, "input") == 0); 118 } 119 120 /* we just want to fill in some non-sense */ 121 EVTAG_ASSIGN(kill_reply, weapon, "dagger"); 122 EVTAG_ASSIGN(kill_reply, action, "wave around like an idiot"); 123 124 /* no reply to the RPC */ 125 EVRPC_REQUEST_DONE(rpc); 126 } 127 128 static EVRPC_STRUCT(NeverReply) *saved_rpc; 129 130 static void 131 NeverReplyCb(EVRPC_STRUCT(NeverReply)* rpc, void *arg) 132 { 133 test_ok += 1; 134 saved_rpc = rpc; 135 } 136 137 static void 138 rpc_setup(struct evhttp **phttp, ev_uint16_t *pport, struct evrpc_base **pbase) 139 { 140 ev_uint16_t port; 141 struct evhttp *http = NULL; 142 struct evrpc_base *base = NULL; 143 144 http = http_setup(&port); 145 base = evrpc_init(http); 146 147 EVRPC_REGISTER(base, Message, msg, kill, MessageCb, NULL); 148 EVRPC_REGISTER(base, NeverReply, msg, kill, NeverReplyCb, NULL); 149 150 *phttp = http; 151 *pport = port; 152 *pbase = base; 153 154 need_input_hook = 0; 155 need_output_hook = 0; 156 } 157 158 static void 159 rpc_teardown(struct evrpc_base *base) 160 { 161 assert(EVRPC_UNREGISTER(base, Message) == 0); 162 assert(EVRPC_UNREGISTER(base, NeverReply) == 0); 163 164 evrpc_free(base); 165 } 166 167 static void 168 rpc_postrequest_failure(struct evhttp_request *req, void *arg) 169 { 170 if (req->response_code != HTTP_SERVUNAVAIL) { 171 172 fprintf(stderr, "FAILED (response code)\n"); 173 exit(1); 174 } 175 176 test_ok = 1; 177 event_loopexit(NULL); 178 } 179 180 /* 181 * Test a malformed payload submitted as an RPC 182 */ 183 184 static void 185 rpc_basic_test(void) 186 { 187 ev_uint16_t port; 188 struct evhttp *http = NULL; 189 struct evrpc_base *base = NULL; 190 struct evhttp_connection *evcon = NULL; 191 struct evhttp_request *req = NULL; 192 193 rpc_setup(&http, &port, &base); 194 195 evcon = evhttp_connection_new("127.0.0.1", port); 196 tt_assert(evcon); 197 198 /* 199 * At this point, we want to schedule an HTTP POST request 200 * server using our make request method. 201 */ 202 203 req = evhttp_request_new(rpc_postrequest_failure, NULL); 204 tt_assert(req); 205 206 /* Add the information that we care about */ 207 evhttp_add_header(req->output_headers, "Host", "somehost"); 208 evbuffer_add_printf(req->output_buffer, "Some Nonsense"); 209 210 if (evhttp_make_request(evcon, req, 211 EVHTTP_REQ_POST, 212 "/.rpc.Message") == -1) { 213 tt_abort(); 214 } 215 216 test_ok = 0; 217 218 event_dispatch(); 219 220 evhttp_connection_free(evcon); 221 222 rpc_teardown(base); 223 224 tt_assert(test_ok == 1); 225 226 end: 227 evhttp_free(http); 228 } 229 230 static void 231 rpc_postrequest_done(struct evhttp_request *req, void *arg) 232 { 233 struct kill* kill_reply = NULL; 234 235 if (req->response_code != HTTP_OK) { 236 fprintf(stderr, "FAILED (response code)\n"); 237 exit(1); 238 } 239 240 kill_reply = kill_new(); 241 242 if ((kill_unmarshal(kill_reply, req->input_buffer)) == -1) { 243 fprintf(stderr, "FAILED (unmarshal)\n"); 244 exit(1); 245 } 246 247 kill_free(kill_reply); 248 249 test_ok = 1; 250 event_loopexit(NULL); 251 } 252 253 static void 254 rpc_basic_message(void) 255 { 256 ev_uint16_t port; 257 struct evhttp *http = NULL; 258 struct evrpc_base *base = NULL; 259 struct evhttp_connection *evcon = NULL; 260 struct evhttp_request *req = NULL; 261 struct msg *msg; 262 263 rpc_setup(&http, &port, &base); 264 265 evcon = evhttp_connection_new("127.0.0.1", port); 266 tt_assert(evcon); 267 268 /* 269 * At this point, we want to schedule an HTTP POST request 270 * server using our make request method. 271 */ 272 273 req = evhttp_request_new(rpc_postrequest_done, NULL); 274 if (req == NULL) { 275 fprintf(stdout, "FAILED\n"); 276 exit(1); 277 } 278 279 /* Add the information that we care about */ 280 evhttp_add_header(req->output_headers, "Host", "somehost"); 281 282 /* set up the basic message */ 283 msg = msg_new(); 284 EVTAG_ASSIGN(msg, from_name, "niels"); 285 EVTAG_ASSIGN(msg, to_name, "tester"); 286 msg_marshal(req->output_buffer, msg); 287 msg_free(msg); 288 289 if (evhttp_make_request(evcon, req, 290 EVHTTP_REQ_POST, 291 "/.rpc.Message") == -1) { 292 fprintf(stdout, "FAILED\n"); 293 exit(1); 294 } 295 296 test_ok = 0; 297 298 event_dispatch(); 299 300 evhttp_connection_free(evcon); 301 302 rpc_teardown(base); 303 304 end: 305 evhttp_free(http); 306 } 307 308 static struct evrpc_pool * 309 rpc_pool_with_connection(ev_uint16_t port) 310 { 311 struct evhttp_connection *evcon; 312 struct evrpc_pool *pool; 313 314 pool = evrpc_pool_new(NULL); 315 assert(pool != NULL); 316 317 evcon = evhttp_connection_new("127.0.0.1", port); 318 assert(evcon != NULL); 319 320 evrpc_pool_add_connection(pool, evcon); 321 322 return (pool); 323 } 324 325 static void 326 GotKillCb(struct evrpc_status *status, 327 struct msg *msg, struct kill *kill, void *arg) 328 { 329 char *weapon; 330 char *action; 331 332 if (need_output_hook) { 333 struct evhttp_request *req = status->http_req; 334 const char *header = evhttp_find_header( 335 req->input_headers, "X-Pool-Hook"); 336 assert(header); 337 assert(strcmp(header, "ran") == 0); 338 } 339 340 if (status->error != EVRPC_STATUS_ERR_NONE) 341 goto done; 342 343 if (EVTAG_GET(kill, weapon, &weapon) == -1) { 344 fprintf(stderr, "get weapon\n"); 345 goto done; 346 } 347 if (EVTAG_GET(kill, action, &action) == -1) { 348 fprintf(stderr, "get action\n"); 349 goto done; 350 } 351 352 if (strcmp(weapon, "dagger")) 353 goto done; 354 355 if (strcmp(action, "wave around like an idiot")) 356 goto done; 357 358 test_ok += 1; 359 360 done: 361 event_loopexit(NULL); 362 } 363 364 static void 365 GotKillCbTwo(struct evrpc_status *status, 366 struct msg *msg, struct kill *kill, void *arg) 367 { 368 char *weapon; 369 char *action; 370 371 if (status->error != EVRPC_STATUS_ERR_NONE) 372 goto done; 373 374 if (EVTAG_GET(kill, weapon, &weapon) == -1) { 375 fprintf(stderr, "get weapon\n"); 376 goto done; 377 } 378 if (EVTAG_GET(kill, action, &action) == -1) { 379 fprintf(stderr, "get action\n"); 380 goto done; 381 } 382 383 if (strcmp(weapon, "dagger")) 384 goto done; 385 386 if (strcmp(action, "wave around like an idiot")) 387 goto done; 388 389 test_ok += 1; 390 391 done: 392 if (test_ok == 2) 393 event_loopexit(NULL); 394 } 395 396 static int 397 rpc_hook_add_header(void *ctx, struct evhttp_request *req, 398 struct evbuffer *evbuf, void *arg) 399 { 400 const char *hook_type = arg; 401 if (strcmp("input", hook_type) == 0) 402 evhttp_add_header(req->input_headers, "X-Hook", hook_type); 403 else 404 evhttp_add_header(req->output_headers, "X-Hook", hook_type); 405 406 assert(evrpc_hook_get_connection(ctx) != NULL); 407 408 return (EVRPC_CONTINUE); 409 } 410 411 static int 412 rpc_hook_add_meta(void *ctx, struct evhttp_request *req, 413 struct evbuffer *evbuf, void *arg) 414 { 415 evrpc_hook_add_meta(ctx, "meta", "test", 5); 416 417 assert(evrpc_hook_get_connection(ctx) != NULL); 418 419 return (EVRPC_CONTINUE); 420 } 421 422 static int 423 rpc_hook_remove_header(void *ctx, struct evhttp_request *req, 424 struct evbuffer *evbuf, void *arg) 425 { 426 const char *header = evhttp_find_header(req->input_headers, "X-Hook"); 427 void *data = NULL; 428 size_t data_len = 0; 429 430 assert(header != NULL); 431 assert(strcmp(header, arg) == 0); 432 433 evhttp_remove_header(req->input_headers, "X-Hook"); 434 evhttp_add_header(req->input_headers, "X-Pool-Hook", "ran"); 435 436 assert(evrpc_hook_find_meta(ctx, "meta", &data, &data_len) == 0); 437 assert(data != NULL); 438 assert(data_len == 5); 439 440 assert(evrpc_hook_get_connection(ctx) != NULL); 441 442 return (EVRPC_CONTINUE); 443 } 444 445 static void 446 rpc_basic_client(void) 447 { 448 ev_uint16_t port; 449 struct evhttp *http = NULL; 450 struct evrpc_base *base = NULL; 451 struct evrpc_pool *pool = NULL; 452 struct msg *msg = NULL; 453 struct kill *kill = NULL; 454 455 rpc_setup(&http, &port, &base); 456 457 need_input_hook = 1; 458 need_output_hook = 1; 459 460 assert(evrpc_add_hook(base, EVRPC_INPUT, rpc_hook_add_header, (void*)"input") 461 != NULL); 462 assert(evrpc_add_hook(base, EVRPC_OUTPUT, rpc_hook_add_header, (void*)"output") 463 != NULL); 464 465 pool = rpc_pool_with_connection(port); 466 tt_assert(pool); 467 468 assert(evrpc_add_hook(pool, EVRPC_OUTPUT, rpc_hook_add_meta, NULL)); 469 assert(evrpc_add_hook(pool, EVRPC_INPUT, rpc_hook_remove_header, (void*)"output")); 470 471 /* set up the basic message */ 472 msg = msg_new(); 473 tt_assert(msg); 474 EVTAG_ASSIGN(msg, from_name, "niels"); 475 EVTAG_ASSIGN(msg, to_name, "tester"); 476 477 kill = kill_new(); 478 479 EVRPC_MAKE_REQUEST(Message, pool, msg, kill, GotKillCb, NULL); 480 481 test_ok = 0; 482 483 event_dispatch(); 484 485 tt_assert(test_ok == 1); 486 487 /* we do it twice to make sure that reuse works correctly */ 488 kill_clear(kill); 489 490 EVRPC_MAKE_REQUEST(Message, pool, msg, kill, GotKillCb, NULL); 491 492 event_dispatch(); 493 494 tt_assert(test_ok == 2); 495 496 /* we do it trice to make sure other stuff works, too */ 497 kill_clear(kill); 498 499 { 500 struct evrpc_request_wrapper *ctx = 501 EVRPC_MAKE_CTX(Message, msg, kill, 502 pool, msg, kill, GotKillCb, NULL); 503 evrpc_make_request(ctx); 504 } 505 506 event_dispatch(); 507 508 rpc_teardown(base); 509 510 tt_assert(test_ok == 3); 511 512 end: 513 if (msg) 514 msg_free(msg); 515 if (kill) 516 kill_free(kill); 517 518 if (pool) 519 evrpc_pool_free(pool); 520 if (http) 521 evhttp_free(http); 522 523 need_input_hook = 0; 524 need_output_hook = 0; 525 } 526 527 /* 528 * We are testing that the second requests gets send over the same 529 * connection after the first RPCs completes. 530 */ 531 static void 532 rpc_basic_queued_client(void) 533 { 534 ev_uint16_t port; 535 struct evhttp *http = NULL; 536 struct evrpc_base *base = NULL; 537 struct evrpc_pool *pool = NULL; 538 struct msg *msg=NULL; 539 struct kill *kill_one=NULL, *kill_two=NULL; 540 541 rpc_setup(&http, &port, &base); 542 543 pool = rpc_pool_with_connection(port); 544 tt_assert(pool); 545 546 /* set up the basic message */ 547 msg = msg_new(); 548 tt_assert(msg); 549 EVTAG_ASSIGN(msg, from_name, "niels"); 550 EVTAG_ASSIGN(msg, to_name, "tester"); 551 552 kill_one = kill_new(); 553 kill_two = kill_new(); 554 555 EVRPC_MAKE_REQUEST(Message, pool, msg, kill_one, GotKillCbTwo, NULL); 556 EVRPC_MAKE_REQUEST(Message, pool, msg, kill_two, GotKillCb, NULL); 557 558 test_ok = 0; 559 560 event_dispatch(); 561 562 rpc_teardown(base); 563 564 tt_assert(test_ok == 2); 565 566 end: 567 if (msg) 568 msg_free(msg); 569 if (kill_one) 570 kill_free(kill_one); 571 if (kill_two) 572 kill_free(kill_two); 573 574 if (pool) 575 evrpc_pool_free(pool); 576 if (http) 577 evhttp_free(http); 578 } 579 580 static void 581 GotErrorCb(struct evrpc_status *status, 582 struct msg *msg, struct kill *kill, void *arg) 583 { 584 if (status->error != EVRPC_STATUS_ERR_TIMEOUT) 585 goto done; 586 587 /* should never be complete but just to check */ 588 if (kill_complete(kill) == 0) 589 goto done; 590 591 test_ok += 1; 592 593 done: 594 event_loopexit(NULL); 595 } 596 597 /* we just pause the rpc and continue it in the next callback */ 598 599 struct rpc_hook_ctx_ { 600 void *vbase; 601 void *ctx; 602 }; 603 604 static int hook_pause_cb_called=0; 605 606 static void 607 rpc_hook_pause_cb(evutil_socket_t fd, short what, void *arg) 608 { 609 struct rpc_hook_ctx_ *ctx = arg; 610 ++hook_pause_cb_called; 611 evrpc_resume_request(ctx->vbase, ctx->ctx, EVRPC_CONTINUE); 612 free(arg); 613 } 614 615 static int 616 rpc_hook_pause(void *ctx, struct evhttp_request *req, struct evbuffer *evbuf, 617 void *arg) 618 { 619 struct rpc_hook_ctx_ *tmp = malloc(sizeof(*tmp)); 620 struct timeval tv; 621 622 assert(tmp != NULL); 623 tmp->vbase = arg; 624 tmp->ctx = ctx; 625 626 memset(&tv, 0, sizeof(tv)); 627 event_once(-1, EV_TIMEOUT, rpc_hook_pause_cb, tmp, &tv); 628 return EVRPC_PAUSE; 629 } 630 631 static void 632 rpc_basic_client_with_pause(void) 633 { 634 ev_uint16_t port; 635 struct evhttp *http = NULL; 636 struct evrpc_base *base = NULL; 637 struct evrpc_pool *pool = NULL; 638 struct msg *msg = NULL; 639 struct kill *kill= NULL; 640 641 rpc_setup(&http, &port, &base); 642 643 assert(evrpc_add_hook(base, EVRPC_INPUT, rpc_hook_pause, base)); 644 assert(evrpc_add_hook(base, EVRPC_OUTPUT, rpc_hook_pause, base)); 645 646 pool = rpc_pool_with_connection(port); 647 tt_assert(pool); 648 assert(evrpc_add_hook(pool, EVRPC_INPUT, rpc_hook_pause, pool)); 649 assert(evrpc_add_hook(pool, EVRPC_OUTPUT, rpc_hook_pause, pool)); 650 651 /* set up the basic message */ 652 msg = msg_new(); 653 tt_assert(msg); 654 EVTAG_ASSIGN(msg, from_name, "niels"); 655 EVTAG_ASSIGN(msg, to_name, "tester"); 656 657 kill = kill_new(); 658 659 EVRPC_MAKE_REQUEST(Message, pool, msg, kill, GotKillCb, NULL); 660 661 test_ok = 0; 662 663 event_dispatch(); 664 665 tt_int_op(test_ok, ==, 1); 666 tt_int_op(hook_pause_cb_called, ==, 4); 667 668 end: 669 if (base) 670 rpc_teardown(base); 671 672 if (msg) 673 msg_free(msg); 674 if (kill) 675 kill_free(kill); 676 677 if (pool) 678 evrpc_pool_free(pool); 679 if (http) 680 evhttp_free(http); 681 } 682 683 static void 684 rpc_client_timeout(void) 685 { 686 ev_uint16_t port; 687 struct evhttp *http = NULL; 688 struct evrpc_base *base = NULL; 689 struct evrpc_pool *pool = NULL; 690 struct msg *msg = NULL; 691 struct kill *kill = NULL; 692 693 rpc_setup(&http, &port, &base); 694 695 pool = rpc_pool_with_connection(port); 696 tt_assert(pool); 697 698 /* set the timeout to 1 second. */ 699 evrpc_pool_set_timeout(pool, 1); 700 701 /* set up the basic message */ 702 msg = msg_new(); 703 tt_assert(msg); 704 EVTAG_ASSIGN(msg, from_name, "niels"); 705 EVTAG_ASSIGN(msg, to_name, "tester"); 706 707 kill = kill_new(); 708 709 EVRPC_MAKE_REQUEST(NeverReply, pool, msg, kill, GotErrorCb, NULL); 710 711 test_ok = 0; 712 713 event_dispatch(); 714 715 /* free the saved RPC structure up */ 716 EVRPC_REQUEST_DONE(saved_rpc); 717 718 rpc_teardown(base); 719 720 tt_assert(test_ok == 2); 721 722 end: 723 if (msg) 724 msg_free(msg); 725 if (kill) 726 kill_free(kill); 727 728 if (pool) 729 evrpc_pool_free(pool); 730 if (http) 731 evhttp_free(http); 732 } 733 734 static void 735 rpc_test(void) 736 { 737 struct msg *msg = NULL, *msg2 = NULL; 738 struct kill *attack = NULL; 739 struct run *run = NULL; 740 struct evbuffer *tmp = evbuffer_new(); 741 struct timeval tv_start, tv_end; 742 ev_uint32_t tag; 743 int i; 744 745 msg = msg_new(); 746 747 tt_assert(msg); 748 749 EVTAG_ASSIGN(msg, from_name, "niels"); 750 EVTAG_ASSIGN(msg, to_name, "phoenix"); 751 752 if (EVTAG_GET(msg, attack, &attack) == -1) { 753 tt_abort_msg("Failed to set kill message."); 754 } 755 756 EVTAG_ASSIGN(attack, weapon, "feather"); 757 EVTAG_ASSIGN(attack, action, "tickle"); 758 for (i = 0; i < 3; ++i) { 759 if (EVTAG_ARRAY_ADD_VALUE(attack, how_often, i) == NULL) { 760 tt_abort_msg("Failed to add how_often."); 761 } 762 } 763 764 evutil_gettimeofday(&tv_start, NULL); 765 for (i = 0; i < 1000; ++i) { 766 run = EVTAG_ARRAY_ADD(msg, run); 767 if (run == NULL) { 768 tt_abort_msg("Failed to add run message."); 769 } 770 EVTAG_ASSIGN(run, how, "very fast but with some data in it"); 771 EVTAG_ASSIGN(run, fixed_bytes, 772 (ev_uint8_t*)"012345678901234567890123"); 773 774 if (EVTAG_ARRAY_ADD_VALUE( 775 run, notes, "this is my note") == NULL) { 776 tt_abort_msg("Failed to add note."); 777 } 778 if (EVTAG_ARRAY_ADD_VALUE(run, notes, "pps") == NULL) { 779 tt_abort_msg("Failed to add note"); 780 } 781 782 EVTAG_ASSIGN(run, large_number, 0xdead0a0bcafebeefLL); 783 EVTAG_ARRAY_ADD_VALUE(run, other_numbers, 0xdead0a0b); 784 EVTAG_ARRAY_ADD_VALUE(run, other_numbers, 0xbeefcafe); 785 } 786 787 if (msg_complete(msg) == -1) 788 tt_abort_msg("Failed to make complete message."); 789 790 evtag_marshal_msg(tmp, 0xdeaf, msg); 791 792 if (evtag_peek(tmp, &tag) == -1) 793 tt_abort_msg("Failed to peak tag."); 794 795 if (tag != 0xdeaf) 796 TT_DIE(("Got incorrect tag: %0x.", (unsigned)tag)); 797 798 msg2 = msg_new(); 799 if (evtag_unmarshal_msg(tmp, 0xdeaf, msg2) == -1) 800 tt_abort_msg("Failed to unmarshal message."); 801 802 evutil_gettimeofday(&tv_end, NULL); 803 evutil_timersub(&tv_end, &tv_start, &tv_end); 804 TT_BLATHER(("(%.1f us/add) ", 805 (float)tv_end.tv_sec/(float)i * 1000000.0 + 806 tv_end.tv_usec / (float)i)); 807 808 if (!EVTAG_HAS(msg2, from_name) || 809 !EVTAG_HAS(msg2, to_name) || 810 !EVTAG_HAS(msg2, attack)) { 811 tt_abort_msg("Missing data structures."); 812 } 813 814 if (EVTAG_GET(msg2, attack, &attack) == -1) { 815 tt_abort_msg("Could not get attack."); 816 } 817 818 if (EVTAG_ARRAY_LEN(msg2, run) != i) { 819 tt_abort_msg("Wrong number of run messages."); 820 } 821 822 /* get the very first run message */ 823 if (EVTAG_ARRAY_GET(msg2, run, 0, &run) == -1) { 824 tt_abort_msg("Failed to get run msg."); 825 } else { 826 /* verify the notes */ 827 char *note_one, *note_two; 828 ev_uint64_t large_number; 829 ev_uint32_t short_number; 830 831 if (EVTAG_ARRAY_LEN(run, notes) != 2) { 832 tt_abort_msg("Wrong number of note strings."); 833 } 834 835 if (EVTAG_ARRAY_GET(run, notes, 0, ¬e_one) == -1 || 836 EVTAG_ARRAY_GET(run, notes, 1, ¬e_two) == -1) { 837 tt_abort_msg("Could not get note strings."); 838 } 839 840 if (strcmp(note_one, "this is my note") || 841 strcmp(note_two, "pps")) { 842 tt_abort_msg("Incorrect note strings encoded."); 843 } 844 845 if (EVTAG_GET(run, large_number, &large_number) == -1 || 846 large_number != 0xdead0a0bcafebeefLL) { 847 tt_abort_msg("Incorrrect large_number."); 848 } 849 850 if (EVTAG_ARRAY_LEN(run, other_numbers) != 2) { 851 tt_abort_msg("Wrong number of other_numbers."); 852 } 853 854 if (EVTAG_ARRAY_GET( 855 run, other_numbers, 0, &short_number) == -1) { 856 tt_abort_msg("Could not get short number."); 857 } 858 tt_uint_op(short_number, ==, 0xdead0a0b); 859 860 } 861 tt_int_op(EVTAG_ARRAY_LEN(attack, how_often), ==, 3); 862 863 for (i = 0; i < 3; ++i) { 864 ev_uint32_t res; 865 if (EVTAG_ARRAY_GET(attack, how_often, i, &res) == -1) { 866 TT_DIE(("Cannot get %dth how_often msg.", i)); 867 } 868 if ((int)res != i) { 869 TT_DIE(("Wrong message encoded %d != %d", i, res)); 870 } 871 } 872 873 test_ok = 1; 874 end: 875 if (msg) 876 msg_free(msg); 877 if (msg2) 878 msg_free(msg2); 879 if (tmp) 880 evbuffer_free(tmp); 881 } 882 883 #define RPC_LEGACY(name) \ 884 { #name, run_legacy_test_fn, TT_FORK|TT_NEED_BASE|TT_LEGACY, \ 885 &legacy_setup, \ 886 rpc_##name } 887 #else 888 /* NO_PYTHON_EXISTS */ 889 890 #define RPC_LEGACY(name) \ 891 { #name, NULL, TT_SKIP, NULL, NULL } 892 893 #endif 894 895 struct testcase_t rpc_testcases[] = { 896 RPC_LEGACY(basic_test), 897 RPC_LEGACY(basic_message), 898 RPC_LEGACY(basic_client), 899 RPC_LEGACY(basic_queued_client), 900 RPC_LEGACY(basic_client_with_pause), 901 RPC_LEGACY(client_timeout), 902 RPC_LEGACY(test), 903 904 END_OF_TESTCASES, 905 }; 906