ipc/chromium/src/third_party/libevent/test/regress_rpc.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial