1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/test/regress_rpc.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,898 @@ 1.4 +/* 1.5 + * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 1.6 + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 1.7 + * 1.8 + * Redistribution and use in source and binary forms, with or without 1.9 + * modification, are permitted provided that the following conditions 1.10 + * are met: 1.11 + * 1. Redistributions of source code must retain the above copyright 1.12 + * notice, this list of conditions and the following disclaimer. 1.13 + * 2. Redistributions in binary form must reproduce the above copyright 1.14 + * notice, this list of conditions and the following disclaimer in the 1.15 + * documentation and/or other materials provided with the distribution. 1.16 + * 3. The name of the author may not be used to endorse or promote products 1.17 + * derived from this software without specific prior written permission. 1.18 + * 1.19 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.20 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.21 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.22 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1.23 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1.24 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.25 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.26 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.27 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.28 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.29 + */ 1.30 + 1.31 +/* The old tests here need assertions to work. */ 1.32 +#undef NDEBUG 1.33 + 1.34 +#ifdef WIN32 1.35 +#include <winsock2.h> 1.36 +#include <windows.h> 1.37 +#endif 1.38 + 1.39 +#include "event2/event-config.h" 1.40 + 1.41 +#include <sys/types.h> 1.42 +#include <sys/stat.h> 1.43 +#ifdef _EVENT_HAVE_SYS_TIME_H 1.44 +#include <sys/time.h> 1.45 +#endif 1.46 +#include <sys/queue.h> 1.47 +#ifndef WIN32 1.48 +#include <sys/socket.h> 1.49 +#include <signal.h> 1.50 +#include <unistd.h> 1.51 +#include <netdb.h> 1.52 +#endif 1.53 +#include <fcntl.h> 1.54 +#include <stdlib.h> 1.55 +#include <stdio.h> 1.56 +#include <string.h> 1.57 +#include <errno.h> 1.58 +#include <assert.h> 1.59 + 1.60 +#include "event2/buffer.h" 1.61 +#include "event2/event.h" 1.62 +#include "event2/event_compat.h" 1.63 +#include "event2/http.h" 1.64 +#include "event2/http_compat.h" 1.65 +#include "event2/http_struct.h" 1.66 +#include "event2/rpc.h" 1.67 +#include "event2/rpc.h" 1.68 +#include "event2/rpc_struct.h" 1.69 +#include "event2/tag.h" 1.70 +#include "log-internal.h" 1.71 + 1.72 +#include "regress.gen.h" 1.73 + 1.74 +#include "regress.h" 1.75 +#include "regress_testutils.h" 1.76 + 1.77 +#ifndef NO_PYTHON_EXISTS 1.78 + 1.79 +static struct evhttp * 1.80 +http_setup(ev_uint16_t *pport) 1.81 +{ 1.82 + struct evhttp *myhttp; 1.83 + ev_uint16_t port; 1.84 + struct evhttp_bound_socket *sock; 1.85 + 1.86 + myhttp = evhttp_new(NULL); 1.87 + if (!myhttp) 1.88 + event_errx(1, "Could not start web server"); 1.89 + 1.90 + /* Try a few different ports */ 1.91 + sock = evhttp_bind_socket_with_handle(myhttp, "127.0.0.1", 0); 1.92 + if (!sock) 1.93 + event_errx(1, "Couldn't open web port"); 1.94 + 1.95 + port = regress_get_socket_port(evhttp_bound_socket_get_fd(sock)); 1.96 + 1.97 + *pport = port; 1.98 + return (myhttp); 1.99 +} 1.100 + 1.101 +EVRPC_HEADER(Message, msg, kill) 1.102 +EVRPC_HEADER(NeverReply, msg, kill) 1.103 + 1.104 +EVRPC_GENERATE(Message, msg, kill) 1.105 +EVRPC_GENERATE(NeverReply, msg, kill) 1.106 + 1.107 +static int need_input_hook = 0; 1.108 +static int need_output_hook = 0; 1.109 + 1.110 +static void 1.111 +MessageCb(EVRPC_STRUCT(Message)* rpc, void *arg) 1.112 +{ 1.113 + struct kill* kill_reply = rpc->reply; 1.114 + 1.115 + if (need_input_hook) { 1.116 + struct evhttp_request* req = EVRPC_REQUEST_HTTP(rpc); 1.117 + const char *header = evhttp_find_header( 1.118 + req->input_headers, "X-Hook"); 1.119 + assert(header); 1.120 + assert(strcmp(header, "input") == 0); 1.121 + } 1.122 + 1.123 + /* we just want to fill in some non-sense */ 1.124 + EVTAG_ASSIGN(kill_reply, weapon, "dagger"); 1.125 + EVTAG_ASSIGN(kill_reply, action, "wave around like an idiot"); 1.126 + 1.127 + /* no reply to the RPC */ 1.128 + EVRPC_REQUEST_DONE(rpc); 1.129 +} 1.130 + 1.131 +static EVRPC_STRUCT(NeverReply) *saved_rpc; 1.132 + 1.133 +static void 1.134 +NeverReplyCb(EVRPC_STRUCT(NeverReply)* rpc, void *arg) 1.135 +{ 1.136 + test_ok += 1; 1.137 + saved_rpc = rpc; 1.138 +} 1.139 + 1.140 +static void 1.141 +rpc_setup(struct evhttp **phttp, ev_uint16_t *pport, struct evrpc_base **pbase) 1.142 +{ 1.143 + ev_uint16_t port; 1.144 + struct evhttp *http = NULL; 1.145 + struct evrpc_base *base = NULL; 1.146 + 1.147 + http = http_setup(&port); 1.148 + base = evrpc_init(http); 1.149 + 1.150 + EVRPC_REGISTER(base, Message, msg, kill, MessageCb, NULL); 1.151 + EVRPC_REGISTER(base, NeverReply, msg, kill, NeverReplyCb, NULL); 1.152 + 1.153 + *phttp = http; 1.154 + *pport = port; 1.155 + *pbase = base; 1.156 + 1.157 + need_input_hook = 0; 1.158 + need_output_hook = 0; 1.159 +} 1.160 + 1.161 +static void 1.162 +rpc_teardown(struct evrpc_base *base) 1.163 +{ 1.164 + assert(EVRPC_UNREGISTER(base, Message) == 0); 1.165 + assert(EVRPC_UNREGISTER(base, NeverReply) == 0); 1.166 + 1.167 + evrpc_free(base); 1.168 +} 1.169 + 1.170 +static void 1.171 +rpc_postrequest_failure(struct evhttp_request *req, void *arg) 1.172 +{ 1.173 + if (req->response_code != HTTP_SERVUNAVAIL) { 1.174 + 1.175 + fprintf(stderr, "FAILED (response code)\n"); 1.176 + exit(1); 1.177 + } 1.178 + 1.179 + test_ok = 1; 1.180 + event_loopexit(NULL); 1.181 +} 1.182 + 1.183 +/* 1.184 + * Test a malformed payload submitted as an RPC 1.185 + */ 1.186 + 1.187 +static void 1.188 +rpc_basic_test(void) 1.189 +{ 1.190 + ev_uint16_t port; 1.191 + struct evhttp *http = NULL; 1.192 + struct evrpc_base *base = NULL; 1.193 + struct evhttp_connection *evcon = NULL; 1.194 + struct evhttp_request *req = NULL; 1.195 + 1.196 + rpc_setup(&http, &port, &base); 1.197 + 1.198 + evcon = evhttp_connection_new("127.0.0.1", port); 1.199 + tt_assert(evcon); 1.200 + 1.201 + /* 1.202 + * At this point, we want to schedule an HTTP POST request 1.203 + * server using our make request method. 1.204 + */ 1.205 + 1.206 + req = evhttp_request_new(rpc_postrequest_failure, NULL); 1.207 + tt_assert(req); 1.208 + 1.209 + /* Add the information that we care about */ 1.210 + evhttp_add_header(req->output_headers, "Host", "somehost"); 1.211 + evbuffer_add_printf(req->output_buffer, "Some Nonsense"); 1.212 + 1.213 + if (evhttp_make_request(evcon, req, 1.214 + EVHTTP_REQ_POST, 1.215 + "/.rpc.Message") == -1) { 1.216 + tt_abort(); 1.217 + } 1.218 + 1.219 + test_ok = 0; 1.220 + 1.221 + event_dispatch(); 1.222 + 1.223 + evhttp_connection_free(evcon); 1.224 + 1.225 + rpc_teardown(base); 1.226 + 1.227 + tt_assert(test_ok == 1); 1.228 + 1.229 +end: 1.230 + evhttp_free(http); 1.231 +} 1.232 + 1.233 +static void 1.234 +rpc_postrequest_done(struct evhttp_request *req, void *arg) 1.235 +{ 1.236 + struct kill* kill_reply = NULL; 1.237 + 1.238 + if (req->response_code != HTTP_OK) { 1.239 + fprintf(stderr, "FAILED (response code)\n"); 1.240 + exit(1); 1.241 + } 1.242 + 1.243 + kill_reply = kill_new(); 1.244 + 1.245 + if ((kill_unmarshal(kill_reply, req->input_buffer)) == -1) { 1.246 + fprintf(stderr, "FAILED (unmarshal)\n"); 1.247 + exit(1); 1.248 + } 1.249 + 1.250 + kill_free(kill_reply); 1.251 + 1.252 + test_ok = 1; 1.253 + event_loopexit(NULL); 1.254 +} 1.255 + 1.256 +static void 1.257 +rpc_basic_message(void) 1.258 +{ 1.259 + ev_uint16_t port; 1.260 + struct evhttp *http = NULL; 1.261 + struct evrpc_base *base = NULL; 1.262 + struct evhttp_connection *evcon = NULL; 1.263 + struct evhttp_request *req = NULL; 1.264 + struct msg *msg; 1.265 + 1.266 + rpc_setup(&http, &port, &base); 1.267 + 1.268 + evcon = evhttp_connection_new("127.0.0.1", port); 1.269 + tt_assert(evcon); 1.270 + 1.271 + /* 1.272 + * At this point, we want to schedule an HTTP POST request 1.273 + * server using our make request method. 1.274 + */ 1.275 + 1.276 + req = evhttp_request_new(rpc_postrequest_done, NULL); 1.277 + if (req == NULL) { 1.278 + fprintf(stdout, "FAILED\n"); 1.279 + exit(1); 1.280 + } 1.281 + 1.282 + /* Add the information that we care about */ 1.283 + evhttp_add_header(req->output_headers, "Host", "somehost"); 1.284 + 1.285 + /* set up the basic message */ 1.286 + msg = msg_new(); 1.287 + EVTAG_ASSIGN(msg, from_name, "niels"); 1.288 + EVTAG_ASSIGN(msg, to_name, "tester"); 1.289 + msg_marshal(req->output_buffer, msg); 1.290 + msg_free(msg); 1.291 + 1.292 + if (evhttp_make_request(evcon, req, 1.293 + EVHTTP_REQ_POST, 1.294 + "/.rpc.Message") == -1) { 1.295 + fprintf(stdout, "FAILED\n"); 1.296 + exit(1); 1.297 + } 1.298 + 1.299 + test_ok = 0; 1.300 + 1.301 + event_dispatch(); 1.302 + 1.303 + evhttp_connection_free(evcon); 1.304 + 1.305 + rpc_teardown(base); 1.306 + 1.307 +end: 1.308 + evhttp_free(http); 1.309 +} 1.310 + 1.311 +static struct evrpc_pool * 1.312 +rpc_pool_with_connection(ev_uint16_t port) 1.313 +{ 1.314 + struct evhttp_connection *evcon; 1.315 + struct evrpc_pool *pool; 1.316 + 1.317 + pool = evrpc_pool_new(NULL); 1.318 + assert(pool != NULL); 1.319 + 1.320 + evcon = evhttp_connection_new("127.0.0.1", port); 1.321 + assert(evcon != NULL); 1.322 + 1.323 + evrpc_pool_add_connection(pool, evcon); 1.324 + 1.325 + return (pool); 1.326 +} 1.327 + 1.328 +static void 1.329 +GotKillCb(struct evrpc_status *status, 1.330 + struct msg *msg, struct kill *kill, void *arg) 1.331 +{ 1.332 + char *weapon; 1.333 + char *action; 1.334 + 1.335 + if (need_output_hook) { 1.336 + struct evhttp_request *req = status->http_req; 1.337 + const char *header = evhttp_find_header( 1.338 + req->input_headers, "X-Pool-Hook"); 1.339 + assert(header); 1.340 + assert(strcmp(header, "ran") == 0); 1.341 + } 1.342 + 1.343 + if (status->error != EVRPC_STATUS_ERR_NONE) 1.344 + goto done; 1.345 + 1.346 + if (EVTAG_GET(kill, weapon, &weapon) == -1) { 1.347 + fprintf(stderr, "get weapon\n"); 1.348 + goto done; 1.349 + } 1.350 + if (EVTAG_GET(kill, action, &action) == -1) { 1.351 + fprintf(stderr, "get action\n"); 1.352 + goto done; 1.353 + } 1.354 + 1.355 + if (strcmp(weapon, "dagger")) 1.356 + goto done; 1.357 + 1.358 + if (strcmp(action, "wave around like an idiot")) 1.359 + goto done; 1.360 + 1.361 + test_ok += 1; 1.362 + 1.363 +done: 1.364 + event_loopexit(NULL); 1.365 +} 1.366 + 1.367 +static void 1.368 +GotKillCbTwo(struct evrpc_status *status, 1.369 + struct msg *msg, struct kill *kill, void *arg) 1.370 +{ 1.371 + char *weapon; 1.372 + char *action; 1.373 + 1.374 + if (status->error != EVRPC_STATUS_ERR_NONE) 1.375 + goto done; 1.376 + 1.377 + if (EVTAG_GET(kill, weapon, &weapon) == -1) { 1.378 + fprintf(stderr, "get weapon\n"); 1.379 + goto done; 1.380 + } 1.381 + if (EVTAG_GET(kill, action, &action) == -1) { 1.382 + fprintf(stderr, "get action\n"); 1.383 + goto done; 1.384 + } 1.385 + 1.386 + if (strcmp(weapon, "dagger")) 1.387 + goto done; 1.388 + 1.389 + if (strcmp(action, "wave around like an idiot")) 1.390 + goto done; 1.391 + 1.392 + test_ok += 1; 1.393 + 1.394 +done: 1.395 + if (test_ok == 2) 1.396 + event_loopexit(NULL); 1.397 +} 1.398 + 1.399 +static int 1.400 +rpc_hook_add_header(void *ctx, struct evhttp_request *req, 1.401 + struct evbuffer *evbuf, void *arg) 1.402 +{ 1.403 + const char *hook_type = arg; 1.404 + if (strcmp("input", hook_type) == 0) 1.405 + evhttp_add_header(req->input_headers, "X-Hook", hook_type); 1.406 + else 1.407 + evhttp_add_header(req->output_headers, "X-Hook", hook_type); 1.408 + 1.409 + assert(evrpc_hook_get_connection(ctx) != NULL); 1.410 + 1.411 + return (EVRPC_CONTINUE); 1.412 +} 1.413 + 1.414 +static int 1.415 +rpc_hook_add_meta(void *ctx, struct evhttp_request *req, 1.416 + struct evbuffer *evbuf, void *arg) 1.417 +{ 1.418 + evrpc_hook_add_meta(ctx, "meta", "test", 5); 1.419 + 1.420 + assert(evrpc_hook_get_connection(ctx) != NULL); 1.421 + 1.422 + return (EVRPC_CONTINUE); 1.423 +} 1.424 + 1.425 +static int 1.426 +rpc_hook_remove_header(void *ctx, struct evhttp_request *req, 1.427 + struct evbuffer *evbuf, void *arg) 1.428 +{ 1.429 + const char *header = evhttp_find_header(req->input_headers, "X-Hook"); 1.430 + void *data = NULL; 1.431 + size_t data_len = 0; 1.432 + 1.433 + assert(header != NULL); 1.434 + assert(strcmp(header, arg) == 0); 1.435 + 1.436 + evhttp_remove_header(req->input_headers, "X-Hook"); 1.437 + evhttp_add_header(req->input_headers, "X-Pool-Hook", "ran"); 1.438 + 1.439 + assert(evrpc_hook_find_meta(ctx, "meta", &data, &data_len) == 0); 1.440 + assert(data != NULL); 1.441 + assert(data_len == 5); 1.442 + 1.443 + assert(evrpc_hook_get_connection(ctx) != NULL); 1.444 + 1.445 + return (EVRPC_CONTINUE); 1.446 +} 1.447 + 1.448 +static void 1.449 +rpc_basic_client(void) 1.450 +{ 1.451 + ev_uint16_t port; 1.452 + struct evhttp *http = NULL; 1.453 + struct evrpc_base *base = NULL; 1.454 + struct evrpc_pool *pool = NULL; 1.455 + struct msg *msg = NULL; 1.456 + struct kill *kill = NULL; 1.457 + 1.458 + rpc_setup(&http, &port, &base); 1.459 + 1.460 + need_input_hook = 1; 1.461 + need_output_hook = 1; 1.462 + 1.463 + assert(evrpc_add_hook(base, EVRPC_INPUT, rpc_hook_add_header, (void*)"input") 1.464 + != NULL); 1.465 + assert(evrpc_add_hook(base, EVRPC_OUTPUT, rpc_hook_add_header, (void*)"output") 1.466 + != NULL); 1.467 + 1.468 + pool = rpc_pool_with_connection(port); 1.469 + 1.470 + assert(evrpc_add_hook(pool, EVRPC_OUTPUT, rpc_hook_add_meta, NULL)); 1.471 + assert(evrpc_add_hook(pool, EVRPC_INPUT, rpc_hook_remove_header, (void*)"output")); 1.472 + 1.473 + /* set up the basic message */ 1.474 + msg = msg_new(); 1.475 + EVTAG_ASSIGN(msg, from_name, "niels"); 1.476 + EVTAG_ASSIGN(msg, to_name, "tester"); 1.477 + 1.478 + kill = kill_new(); 1.479 + 1.480 + EVRPC_MAKE_REQUEST(Message, pool, msg, kill, GotKillCb, NULL); 1.481 + 1.482 + test_ok = 0; 1.483 + 1.484 + event_dispatch(); 1.485 + 1.486 + tt_assert(test_ok == 1); 1.487 + 1.488 + /* we do it twice to make sure that reuse works correctly */ 1.489 + kill_clear(kill); 1.490 + 1.491 + EVRPC_MAKE_REQUEST(Message, pool, msg, kill, GotKillCb, NULL); 1.492 + 1.493 + event_dispatch(); 1.494 + 1.495 + tt_assert(test_ok == 2); 1.496 + 1.497 + /* we do it trice to make sure other stuff works, too */ 1.498 + kill_clear(kill); 1.499 + 1.500 + { 1.501 + struct evrpc_request_wrapper *ctx = 1.502 + EVRPC_MAKE_CTX(Message, msg, kill, 1.503 + pool, msg, kill, GotKillCb, NULL); 1.504 + evrpc_make_request(ctx); 1.505 + } 1.506 + 1.507 + event_dispatch(); 1.508 + 1.509 + rpc_teardown(base); 1.510 + 1.511 + tt_assert(test_ok == 3); 1.512 + 1.513 +end: 1.514 + if (msg) 1.515 + msg_free(msg); 1.516 + if (kill) 1.517 + kill_free(kill); 1.518 + 1.519 + if (pool) 1.520 + evrpc_pool_free(pool); 1.521 + if (http) 1.522 + evhttp_free(http); 1.523 + 1.524 + need_input_hook = 0; 1.525 + need_output_hook = 0; 1.526 +} 1.527 + 1.528 +/* 1.529 + * We are testing that the second requests gets send over the same 1.530 + * connection after the first RPCs completes. 1.531 + */ 1.532 +static void 1.533 +rpc_basic_queued_client(void) 1.534 +{ 1.535 + ev_uint16_t port; 1.536 + struct evhttp *http = NULL; 1.537 + struct evrpc_base *base = NULL; 1.538 + struct evrpc_pool *pool = NULL; 1.539 + struct msg *msg=NULL; 1.540 + struct kill *kill_one=NULL, *kill_two=NULL; 1.541 + 1.542 + rpc_setup(&http, &port, &base); 1.543 + 1.544 + pool = rpc_pool_with_connection(port); 1.545 + 1.546 + /* set up the basic message */ 1.547 + msg = msg_new(); 1.548 + EVTAG_ASSIGN(msg, from_name, "niels"); 1.549 + EVTAG_ASSIGN(msg, to_name, "tester"); 1.550 + 1.551 + kill_one = kill_new(); 1.552 + kill_two = kill_new(); 1.553 + 1.554 + EVRPC_MAKE_REQUEST(Message, pool, msg, kill_one, GotKillCbTwo, NULL); 1.555 + EVRPC_MAKE_REQUEST(Message, pool, msg, kill_two, GotKillCb, NULL); 1.556 + 1.557 + test_ok = 0; 1.558 + 1.559 + event_dispatch(); 1.560 + 1.561 + rpc_teardown(base); 1.562 + 1.563 + tt_assert(test_ok == 2); 1.564 + 1.565 +end: 1.566 + if (msg) 1.567 + msg_free(msg); 1.568 + if (kill_one) 1.569 + kill_free(kill_one); 1.570 + if (kill_two) 1.571 + kill_free(kill_two); 1.572 + 1.573 + if (pool) 1.574 + evrpc_pool_free(pool); 1.575 + if (http) 1.576 + evhttp_free(http); 1.577 +} 1.578 + 1.579 +static void 1.580 +GotErrorCb(struct evrpc_status *status, 1.581 + struct msg *msg, struct kill *kill, void *arg) 1.582 +{ 1.583 + if (status->error != EVRPC_STATUS_ERR_TIMEOUT) 1.584 + goto done; 1.585 + 1.586 + /* should never be complete but just to check */ 1.587 + if (kill_complete(kill) == 0) 1.588 + goto done; 1.589 + 1.590 + test_ok += 1; 1.591 + 1.592 +done: 1.593 + event_loopexit(NULL); 1.594 +} 1.595 + 1.596 +/* we just pause the rpc and continue it in the next callback */ 1.597 + 1.598 +struct _rpc_hook_ctx { 1.599 + void *vbase; 1.600 + void *ctx; 1.601 +}; 1.602 + 1.603 +static int hook_pause_cb_called=0; 1.604 + 1.605 +static void 1.606 +rpc_hook_pause_cb(evutil_socket_t fd, short what, void *arg) 1.607 +{ 1.608 + struct _rpc_hook_ctx *ctx = arg; 1.609 + ++hook_pause_cb_called; 1.610 + evrpc_resume_request(ctx->vbase, ctx->ctx, EVRPC_CONTINUE); 1.611 + free(arg); 1.612 +} 1.613 + 1.614 +static int 1.615 +rpc_hook_pause(void *ctx, struct evhttp_request *req, struct evbuffer *evbuf, 1.616 + void *arg) 1.617 +{ 1.618 + struct _rpc_hook_ctx *tmp = malloc(sizeof(*tmp)); 1.619 + struct timeval tv; 1.620 + 1.621 + assert(tmp != NULL); 1.622 + tmp->vbase = arg; 1.623 + tmp->ctx = ctx; 1.624 + 1.625 + memset(&tv, 0, sizeof(tv)); 1.626 + event_once(-1, EV_TIMEOUT, rpc_hook_pause_cb, tmp, &tv); 1.627 + return EVRPC_PAUSE; 1.628 +} 1.629 + 1.630 +static void 1.631 +rpc_basic_client_with_pause(void) 1.632 +{ 1.633 + ev_uint16_t port; 1.634 + struct evhttp *http = NULL; 1.635 + struct evrpc_base *base = NULL; 1.636 + struct evrpc_pool *pool = NULL; 1.637 + struct msg *msg = NULL; 1.638 + struct kill *kill= NULL; 1.639 + 1.640 + rpc_setup(&http, &port, &base); 1.641 + 1.642 + assert(evrpc_add_hook(base, EVRPC_INPUT, rpc_hook_pause, base)); 1.643 + assert(evrpc_add_hook(base, EVRPC_OUTPUT, rpc_hook_pause, base)); 1.644 + 1.645 + pool = rpc_pool_with_connection(port); 1.646 + 1.647 + assert(evrpc_add_hook(pool, EVRPC_INPUT, rpc_hook_pause, pool)); 1.648 + assert(evrpc_add_hook(pool, EVRPC_OUTPUT, rpc_hook_pause, pool)); 1.649 + 1.650 + /* set up the basic message */ 1.651 + msg = msg_new(); 1.652 + EVTAG_ASSIGN(msg, from_name, "niels"); 1.653 + EVTAG_ASSIGN(msg, to_name, "tester"); 1.654 + 1.655 + kill = kill_new(); 1.656 + 1.657 + EVRPC_MAKE_REQUEST(Message, pool, msg, kill, GotKillCb, NULL); 1.658 + 1.659 + test_ok = 0; 1.660 + 1.661 + event_dispatch(); 1.662 + 1.663 + tt_int_op(test_ok, ==, 1); 1.664 + tt_int_op(hook_pause_cb_called, ==, 4); 1.665 + 1.666 +end: 1.667 + if (base) 1.668 + rpc_teardown(base); 1.669 + 1.670 + if (msg) 1.671 + msg_free(msg); 1.672 + if (kill) 1.673 + kill_free(kill); 1.674 + 1.675 + if (pool) 1.676 + evrpc_pool_free(pool); 1.677 + if (http) 1.678 + evhttp_free(http); 1.679 +} 1.680 + 1.681 +static void 1.682 +rpc_client_timeout(void) 1.683 +{ 1.684 + ev_uint16_t port; 1.685 + struct evhttp *http = NULL; 1.686 + struct evrpc_base *base = NULL; 1.687 + struct evrpc_pool *pool = NULL; 1.688 + struct msg *msg = NULL; 1.689 + struct kill *kill = NULL; 1.690 + 1.691 + rpc_setup(&http, &port, &base); 1.692 + 1.693 + pool = rpc_pool_with_connection(port); 1.694 + 1.695 + /* set the timeout to 5 seconds */ 1.696 + evrpc_pool_set_timeout(pool, 5); 1.697 + 1.698 + /* set up the basic message */ 1.699 + msg = msg_new(); 1.700 + EVTAG_ASSIGN(msg, from_name, "niels"); 1.701 + EVTAG_ASSIGN(msg, to_name, "tester"); 1.702 + 1.703 + kill = kill_new(); 1.704 + 1.705 + EVRPC_MAKE_REQUEST(NeverReply, pool, msg, kill, GotErrorCb, NULL); 1.706 + 1.707 + test_ok = 0; 1.708 + 1.709 + event_dispatch(); 1.710 + 1.711 + /* free the saved RPC structure up */ 1.712 + EVRPC_REQUEST_DONE(saved_rpc); 1.713 + 1.714 + rpc_teardown(base); 1.715 + 1.716 + tt_assert(test_ok == 2); 1.717 + 1.718 +end: 1.719 + if (msg) 1.720 + msg_free(msg); 1.721 + if (kill) 1.722 + kill_free(kill); 1.723 + 1.724 + if (pool) 1.725 + evrpc_pool_free(pool); 1.726 + if (http) 1.727 + evhttp_free(http); 1.728 +} 1.729 + 1.730 +static void 1.731 +rpc_test(void) 1.732 +{ 1.733 + struct msg *msg = NULL, *msg2 = NULL; 1.734 + struct kill *attack = NULL; 1.735 + struct run *run = NULL; 1.736 + struct evbuffer *tmp = evbuffer_new(); 1.737 + struct timeval tv_start, tv_end; 1.738 + ev_uint32_t tag; 1.739 + int i; 1.740 + 1.741 + msg = msg_new(); 1.742 + 1.743 + tt_assert(msg); 1.744 + 1.745 + EVTAG_ASSIGN(msg, from_name, "niels"); 1.746 + EVTAG_ASSIGN(msg, to_name, "phoenix"); 1.747 + 1.748 + if (EVTAG_GET(msg, attack, &attack) == -1) { 1.749 + tt_abort_msg("Failed to set kill message."); 1.750 + } 1.751 + 1.752 + EVTAG_ASSIGN(attack, weapon, "feather"); 1.753 + EVTAG_ASSIGN(attack, action, "tickle"); 1.754 + for (i = 0; i < 3; ++i) { 1.755 + if (EVTAG_ARRAY_ADD_VALUE(attack, how_often, i) == NULL) { 1.756 + tt_abort_msg("Failed to add how_often."); 1.757 + } 1.758 + } 1.759 + 1.760 + evutil_gettimeofday(&tv_start, NULL); 1.761 + for (i = 0; i < 1000; ++i) { 1.762 + run = EVTAG_ARRAY_ADD(msg, run); 1.763 + if (run == NULL) { 1.764 + tt_abort_msg("Failed to add run message."); 1.765 + } 1.766 + EVTAG_ASSIGN(run, how, "very fast but with some data in it"); 1.767 + EVTAG_ASSIGN(run, fixed_bytes, 1.768 + (ev_uint8_t*)"012345678901234567890123"); 1.769 + 1.770 + if (EVTAG_ARRAY_ADD_VALUE( 1.771 + run, notes, "this is my note") == NULL) { 1.772 + tt_abort_msg("Failed to add note."); 1.773 + } 1.774 + if (EVTAG_ARRAY_ADD_VALUE(run, notes, "pps") == NULL) { 1.775 + tt_abort_msg("Failed to add note"); 1.776 + } 1.777 + 1.778 + EVTAG_ASSIGN(run, large_number, 0xdead0a0bcafebeefLL); 1.779 + EVTAG_ARRAY_ADD_VALUE(run, other_numbers, 0xdead0a0b); 1.780 + EVTAG_ARRAY_ADD_VALUE(run, other_numbers, 0xbeefcafe); 1.781 + } 1.782 + 1.783 + if (msg_complete(msg) == -1) 1.784 + tt_abort_msg("Failed to make complete message."); 1.785 + 1.786 + evtag_marshal_msg(tmp, 0xdeaf, msg); 1.787 + 1.788 + if (evtag_peek(tmp, &tag) == -1) 1.789 + tt_abort_msg("Failed to peak tag."); 1.790 + 1.791 + if (tag != 0xdeaf) 1.792 + TT_DIE(("Got incorrect tag: %0x.", (unsigned)tag)); 1.793 + 1.794 + msg2 = msg_new(); 1.795 + if (evtag_unmarshal_msg(tmp, 0xdeaf, msg2) == -1) 1.796 + tt_abort_msg("Failed to unmarshal message."); 1.797 + 1.798 + evutil_gettimeofday(&tv_end, NULL); 1.799 + evutil_timersub(&tv_end, &tv_start, &tv_end); 1.800 + TT_BLATHER(("(%.1f us/add) ", 1.801 + (float)tv_end.tv_sec/(float)i * 1000000.0 + 1.802 + tv_end.tv_usec / (float)i)); 1.803 + 1.804 + if (!EVTAG_HAS(msg2, from_name) || 1.805 + !EVTAG_HAS(msg2, to_name) || 1.806 + !EVTAG_HAS(msg2, attack)) { 1.807 + tt_abort_msg("Missing data structures."); 1.808 + } 1.809 + 1.810 + if (EVTAG_GET(msg2, attack, &attack) == -1) { 1.811 + tt_abort_msg("Could not get attack."); 1.812 + } 1.813 + 1.814 + if (EVTAG_ARRAY_LEN(msg2, run) != i) { 1.815 + tt_abort_msg("Wrong number of run messages."); 1.816 + } 1.817 + 1.818 + /* get the very first run message */ 1.819 + if (EVTAG_ARRAY_GET(msg2, run, 0, &run) == -1) { 1.820 + tt_abort_msg("Failed to get run msg."); 1.821 + } else { 1.822 + /* verify the notes */ 1.823 + char *note_one, *note_two; 1.824 + ev_uint64_t large_number; 1.825 + ev_uint32_t short_number; 1.826 + 1.827 + if (EVTAG_ARRAY_LEN(run, notes) != 2) { 1.828 + tt_abort_msg("Wrong number of note strings."); 1.829 + } 1.830 + 1.831 + if (EVTAG_ARRAY_GET(run, notes, 0, ¬e_one) == -1 || 1.832 + EVTAG_ARRAY_GET(run, notes, 1, ¬e_two) == -1) { 1.833 + tt_abort_msg("Could not get note strings."); 1.834 + } 1.835 + 1.836 + if (strcmp(note_one, "this is my note") || 1.837 + strcmp(note_two, "pps")) { 1.838 + tt_abort_msg("Incorrect note strings encoded."); 1.839 + } 1.840 + 1.841 + if (EVTAG_GET(run, large_number, &large_number) == -1 || 1.842 + large_number != 0xdead0a0bcafebeefLL) { 1.843 + tt_abort_msg("Incorrrect large_number."); 1.844 + } 1.845 + 1.846 + if (EVTAG_ARRAY_LEN(run, other_numbers) != 2) { 1.847 + tt_abort_msg("Wrong number of other_numbers."); 1.848 + } 1.849 + 1.850 + if (EVTAG_ARRAY_GET( 1.851 + run, other_numbers, 0, &short_number) == -1) { 1.852 + tt_abort_msg("Could not get short number."); 1.853 + } 1.854 + tt_uint_op(short_number, ==, 0xdead0a0b); 1.855 + 1.856 + } 1.857 + tt_int_op(EVTAG_ARRAY_LEN(attack, how_often), ==, 3); 1.858 + 1.859 + for (i = 0; i < 3; ++i) { 1.860 + ev_uint32_t res; 1.861 + if (EVTAG_ARRAY_GET(attack, how_often, i, &res) == -1) { 1.862 + TT_DIE(("Cannot get %dth how_often msg.", i)); 1.863 + } 1.864 + if ((int)res != i) { 1.865 + TT_DIE(("Wrong message encoded %d != %d", i, res)); 1.866 + } 1.867 + } 1.868 + 1.869 + test_ok = 1; 1.870 +end: 1.871 + if (msg) 1.872 + msg_free(msg); 1.873 + if (msg2) 1.874 + msg_free(msg2); 1.875 + if (tmp) 1.876 + evbuffer_free(tmp); 1.877 +} 1.878 + 1.879 +#define RPC_LEGACY(name) \ 1.880 + { #name, run_legacy_test_fn, TT_FORK|TT_NEED_BASE|TT_LEGACY, \ 1.881 + &legacy_setup, \ 1.882 + rpc_##name } 1.883 +#else 1.884 +/* NO_PYTHON_EXISTS */ 1.885 + 1.886 +#define RPC_LEGACY(name) \ 1.887 + { #name, NULL, TT_SKIP, NULL, NULL } 1.888 + 1.889 +#endif 1.890 + 1.891 +struct testcase_t rpc_testcases[] = { 1.892 + RPC_LEGACY(basic_test), 1.893 + RPC_LEGACY(basic_message), 1.894 + RPC_LEGACY(basic_client), 1.895 + RPC_LEGACY(basic_queued_client), 1.896 + RPC_LEGACY(basic_client_with_pause), 1.897 + RPC_LEGACY(client_timeout), 1.898 + RPC_LEGACY(test), 1.899 + 1.900 + END_OF_TESTCASES, 1.901 +};