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