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