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