1 /* $NetBSD: regress_rpc.c,v 1.4 2017/01/31 23:17:40 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.4 2017/01/31 23:17:40 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 tt_assert(pool); 470 471 assert(evrpc_add_hook(pool, EVRPC_OUTPUT, rpc_hook_add_meta, NULL)); 472 assert(evrpc_add_hook(pool, EVRPC_INPUT, rpc_hook_remove_header, __UNCONST("output"))); 473 474 /* set up the basic message */ 475 msg = msg_new(); 476 tt_assert(msg); 477 EVTAG_ASSIGN(msg, from_name, "niels"); 478 EVTAG_ASSIGN(msg, to_name, "tester"); 479 480 xkill = kill_new(); 481 482 EVRPC_MAKE_REQUEST(Message, pool, msg, xkill, GotKillCb, NULL); 483 484 test_ok = 0; 485 486 event_dispatch(); 487 488 tt_assert(test_ok == 1); 489 490 /* we do it twice to make sure that reuse works correctly */ 491 kill_clear(xkill); 492 493 EVRPC_MAKE_REQUEST(Message, pool, msg, xkill, GotKillCb, NULL); 494 495 event_dispatch(); 496 497 tt_assert(test_ok == 2); 498 499 /* we do it trice to make sure other stuff works, too */ 500 kill_clear(xkill); 501 502 { 503 struct evrpc_request_wrapper *ctx = 504 EVRPC_MAKE_CTX(Message, msg, kill, 505 pool, msg, xkill, GotKillCb, NULL); 506 evrpc_make_request(ctx); 507 } 508 509 event_dispatch(); 510 511 rpc_teardown(base); 512 513 tt_assert(test_ok == 3); 514 515 end: 516 if (msg) 517 msg_free(msg); 518 if (xkill) 519 kill_free(xkill); 520 521 if (pool) 522 evrpc_pool_free(pool); 523 if (http) 524 evhttp_free(http); 525 526 need_input_hook = 0; 527 need_output_hook = 0; 528 } 529 530 /* 531 * We are testing that the second requests gets send over the same 532 * connection after the first RPCs completes. 533 */ 534 static void 535 rpc_basic_queued_client(void) 536 { 537 ev_uint16_t port; 538 struct evhttp *http = NULL; 539 struct evrpc_base *base = NULL; 540 struct evrpc_pool *pool = NULL; 541 struct msg *msg=NULL; 542 struct kill *kill_one=NULL, *kill_two=NULL; 543 544 rpc_setup(&http, &port, &base); 545 546 pool = rpc_pool_with_connection(port); 547 tt_assert(pool); 548 549 /* set up the basic message */ 550 msg = msg_new(); 551 tt_assert(msg); 552 EVTAG_ASSIGN(msg, from_name, "niels"); 553 EVTAG_ASSIGN(msg, to_name, "tester"); 554 555 kill_one = kill_new(); 556 kill_two = kill_new(); 557 558 EVRPC_MAKE_REQUEST(Message, pool, msg, kill_one, GotKillCbTwo, NULL); 559 EVRPC_MAKE_REQUEST(Message, pool, msg, kill_two, GotKillCb, NULL); 560 561 test_ok = 0; 562 563 event_dispatch(); 564 565 rpc_teardown(base); 566 567 tt_assert(test_ok == 2); 568 569 end: 570 if (msg) 571 msg_free(msg); 572 if (kill_one) 573 kill_free(kill_one); 574 if (kill_two) 575 kill_free(kill_two); 576 577 if (pool) 578 evrpc_pool_free(pool); 579 if (http) 580 evhttp_free(http); 581 } 582 583 static void 584 GotErrorCb(struct evrpc_status *status, 585 struct msg *msg, struct kill *xkill, void *arg) 586 { 587 if (status->error != EVRPC_STATUS_ERR_TIMEOUT) 588 goto done; 589 590 /* should never be complete but just to check */ 591 if (kill_complete(xkill) == 0) 592 goto done; 593 594 test_ok += 1; 595 596 done: 597 event_loopexit(NULL); 598 } 599 600 /* we just pause the rpc and continue it in the next callback */ 601 602 struct rpc_hook_ctx_ { 603 void *vbase; 604 void *ctx; 605 }; 606 607 static int hook_pause_cb_called=0; 608 609 static void 610 rpc_hook_pause_cb(evutil_socket_t fd, short what, void *arg) 611 { 612 struct rpc_hook_ctx_ *ctx = arg; 613 ++hook_pause_cb_called; 614 evrpc_resume_request(ctx->vbase, ctx->ctx, EVRPC_CONTINUE); 615 free(arg); 616 } 617 618 static int 619 rpc_hook_pause(void *ctx, struct evhttp_request *req, struct evbuffer *evbuf, 620 void *arg) 621 { 622 struct rpc_hook_ctx_ *tmp = malloc(sizeof(*tmp)); 623 struct timeval tv; 624 625 assert(tmp != NULL); 626 tmp->vbase = arg; 627 tmp->ctx = ctx; 628 629 memset(&tv, 0, sizeof(tv)); 630 event_once(-1, EV_TIMEOUT, rpc_hook_pause_cb, tmp, &tv); 631 return EVRPC_PAUSE; 632 } 633 634 static void 635 rpc_basic_client_with_pause(void) 636 { 637 ev_uint16_t port; 638 struct evhttp *http = NULL; 639 struct evrpc_base *base = NULL; 640 struct evrpc_pool *pool = NULL; 641 struct msg *msg = NULL; 642 struct kill *xkill= NULL; 643 644 rpc_setup(&http, &port, &base); 645 646 assert(evrpc_add_hook(base, EVRPC_INPUT, rpc_hook_pause, base)); 647 assert(evrpc_add_hook(base, EVRPC_OUTPUT, rpc_hook_pause, base)); 648 649 pool = rpc_pool_with_connection(port); 650 tt_assert(pool); 651 assert(evrpc_add_hook(pool, EVRPC_INPUT, rpc_hook_pause, pool)); 652 assert(evrpc_add_hook(pool, EVRPC_OUTPUT, rpc_hook_pause, pool)); 653 654 /* set up the basic message */ 655 msg = msg_new(); 656 tt_assert(msg); 657 EVTAG_ASSIGN(msg, from_name, "niels"); 658 EVTAG_ASSIGN(msg, to_name, "tester"); 659 660 xkill = kill_new(); 661 662 EVRPC_MAKE_REQUEST(Message, pool, msg, xkill, GotKillCb, NULL); 663 664 test_ok = 0; 665 666 event_dispatch(); 667 668 tt_int_op(test_ok, ==, 1); 669 tt_int_op(hook_pause_cb_called, ==, 4); 670 671 end: 672 if (base) 673 rpc_teardown(base); 674 675 if (msg) 676 msg_free(msg); 677 if (xkill) 678 kill_free(xkill); 679 680 if (pool) 681 evrpc_pool_free(pool); 682 if (http) 683 evhttp_free(http); 684 } 685 686 static void 687 rpc_client_timeout(void) 688 { 689 ev_uint16_t port; 690 struct evhttp *http = NULL; 691 struct evrpc_base *base = NULL; 692 struct evrpc_pool *pool = NULL; 693 struct msg *msg = NULL; 694 struct kill *xkill = NULL; 695 696 rpc_setup(&http, &port, &base); 697 698 pool = rpc_pool_with_connection(port); 699 tt_assert(pool); 700 701 /* set the timeout to 1 second. */ 702 evrpc_pool_set_timeout(pool, 1); 703 704 /* set up the basic message */ 705 msg = msg_new(); 706 tt_assert(msg); 707 EVTAG_ASSIGN(msg, from_name, "niels"); 708 EVTAG_ASSIGN(msg, to_name, "tester"); 709 710 xkill = kill_new(); 711 712 EVRPC_MAKE_REQUEST(NeverReply, pool, msg, xkill, GotErrorCb, NULL); 713 714 test_ok = 0; 715 716 event_dispatch(); 717 718 /* free the saved RPC structure up */ 719 EVRPC_REQUEST_DONE(saved_rpc); 720 721 rpc_teardown(base); 722 723 tt_assert(test_ok == 2); 724 725 end: 726 if (msg) 727 msg_free(msg); 728 if (xkill) 729 kill_free(xkill); 730 731 if (pool) 732 evrpc_pool_free(pool); 733 if (http) 734 evhttp_free(http); 735 } 736 737 static void 738 rpc_test(void) 739 { 740 struct msg *msg = NULL, *msg2 = NULL; 741 struct kill *attack = NULL; 742 struct run *run = NULL; 743 struct evbuffer *tmp = evbuffer_new(); 744 struct timeval tv_start, tv_end; 745 ev_uint32_t tag; 746 int i; 747 748 msg = msg_new(); 749 750 tt_assert(msg); 751 752 EVTAG_ASSIGN(msg, from_name, "niels"); 753 EVTAG_ASSIGN(msg, to_name, "phoenix"); 754 755 if (EVTAG_GET(msg, attack, &attack) == -1) { 756 tt_abort_msg("Failed to set kill message."); 757 } 758 759 EVTAG_ASSIGN(attack, weapon, "feather"); 760 EVTAG_ASSIGN(attack, action, "tickle"); 761 for (i = 0; i < 3; ++i) { 762 if (EVTAG_ARRAY_ADD_VALUE(attack, how_often, i) == NULL) { 763 tt_abort_msg("Failed to add how_often."); 764 } 765 } 766 767 evutil_gettimeofday(&tv_start, NULL); 768 for (i = 0; i < 1000; ++i) { 769 run = EVTAG_ARRAY_ADD(msg, run); 770 if (run == NULL) { 771 tt_abort_msg("Failed to add run message."); 772 } 773 EVTAG_ASSIGN(run, how, "very fast but with some data in it"); 774 EVTAG_ASSIGN(run, fixed_bytes, 775 __UNCONST("012345678901234567890123")); 776 777 if (EVTAG_ARRAY_ADD_VALUE( 778 run, notes, "this is my note") == NULL) { 779 tt_abort_msg("Failed to add note."); 780 } 781 if (EVTAG_ARRAY_ADD_VALUE(run, notes, "pps") == NULL) { 782 tt_abort_msg("Failed to add note"); 783 } 784 785 EVTAG_ASSIGN(run, large_number, 0xdead0a0bcafebeefLL); 786 EVTAG_ARRAY_ADD_VALUE(run, other_numbers, 0xdead0a0b); 787 EVTAG_ARRAY_ADD_VALUE(run, other_numbers, 0xbeefcafe); 788 } 789 790 if (msg_complete(msg) == -1) 791 tt_abort_msg("Failed to make complete message."); 792 793 evtag_marshal_msg(tmp, 0xdeaf, msg); 794 795 if (evtag_peek(tmp, &tag) == -1) 796 tt_abort_msg("Failed to peak tag."); 797 798 if (tag != 0xdeaf) 799 TT_DIE(("Got incorrect tag: %0x.", (unsigned)tag)); 800 801 msg2 = msg_new(); 802 if (evtag_unmarshal_msg(tmp, 0xdeaf, msg2) == -1) 803 tt_abort_msg("Failed to unmarshal message."); 804 805 evutil_gettimeofday(&tv_end, NULL); 806 evutil_timersub(&tv_end, &tv_start, &tv_end); 807 TT_BLATHER(("(%.1f us/add) ", 808 (float)tv_end.tv_sec/(float)i * 1000000.0 + 809 tv_end.tv_usec / (float)i)); 810 811 if (!EVTAG_HAS(msg2, from_name) || 812 !EVTAG_HAS(msg2, to_name) || 813 !EVTAG_HAS(msg2, attack)) { 814 tt_abort_msg("Missing data structures."); 815 } 816 817 if (EVTAG_GET(msg2, attack, &attack) == -1) { 818 tt_abort_msg("Could not get attack."); 819 } 820 821 if (EVTAG_ARRAY_LEN(msg2, run) != i) { 822 tt_abort_msg("Wrong number of run messages."); 823 } 824 825 /* get the very first run message */ 826 if (EVTAG_ARRAY_GET(msg2, run, 0, &run) == -1) { 827 tt_abort_msg("Failed to get run msg."); 828 } else { 829 /* verify the notes */ 830 char *note_one, *note_two; 831 ev_uint64_t large_number; 832 ev_uint32_t short_number; 833 834 if (EVTAG_ARRAY_LEN(run, notes) != 2) { 835 tt_abort_msg("Wrong number of note strings."); 836 } 837 838 if (EVTAG_ARRAY_GET(run, notes, 0, ¬e_one) == -1 || 839 EVTAG_ARRAY_GET(run, notes, 1, ¬e_two) == -1) { 840 tt_abort_msg("Could not get note strings."); 841 } 842 843 if (strcmp(note_one, "this is my note") || 844 strcmp(note_two, "pps")) { 845 tt_abort_msg("Incorrect note strings encoded."); 846 } 847 848 if (EVTAG_GET(run, large_number, &large_number) == -1 || 849 large_number != 0xdead0a0bcafebeefLL) { 850 tt_abort_msg("Incorrrect large_number."); 851 } 852 853 if (EVTAG_ARRAY_LEN(run, other_numbers) != 2) { 854 tt_abort_msg("Wrong number of other_numbers."); 855 } 856 857 if (EVTAG_ARRAY_GET( 858 run, other_numbers, 0, &short_number) == -1) { 859 tt_abort_msg("Could not get short number."); 860 } 861 tt_uint_op(short_number, ==, 0xdead0a0b); 862 863 } 864 tt_int_op(EVTAG_ARRAY_LEN(attack, how_often), ==, 3); 865 866 for (i = 0; i < 3; ++i) { 867 ev_uint32_t res; 868 if (EVTAG_ARRAY_GET(attack, how_often, i, &res) == -1) { 869 TT_DIE(("Cannot get %dth how_often msg.", i)); 870 } 871 if ((int)res != i) { 872 TT_DIE(("Wrong message encoded %d != %d", i, res)); 873 } 874 } 875 876 test_ok = 1; 877 end: 878 if (msg) 879 msg_free(msg); 880 if (msg2) 881 msg_free(msg2); 882 if (tmp) 883 evbuffer_free(tmp); 884 } 885 886 #define RPC_LEGACY(name) \ 887 { #name, run_legacy_test_fn, TT_FORK|TT_NEED_BASE|TT_LEGACY, \ 888 &legacy_setup, \ 889 rpc_##name } 890 #else 891 /* NO_PYTHON_EXISTS */ 892 893 #define RPC_LEGACY(name) \ 894 { #name, NULL, TT_SKIP, NULL, NULL } 895 896 #endif 897 898 struct testcase_t rpc_testcases[] = { 899 RPC_LEGACY(basic_test), 900 RPC_LEGACY(basic_message), 901 RPC_LEGACY(basic_client), 902 RPC_LEGACY(basic_queued_client), 903 RPC_LEGACY(basic_client_with_pause), 904 RPC_LEGACY(client_timeout), 905 RPC_LEGACY(test), 906 907 END_OF_TESTCASES, 908 }; 909