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