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