aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/test_mq.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/test_mq.c')
-rw-r--r--src/lib/util/test_mq.c342
1 files changed, 342 insertions, 0 deletions
diff --git a/src/lib/util/test_mq.c b/src/lib/util/test_mq.c
new file mode 100644
index 000000000..522589daf
--- /dev/null
+++ b/src/lib/util/test_mq.c
@@ -0,0 +1,342 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/test_mq.c
23 * @brief tests for mq
24 * @author Florian Dold
25 * @author Christian Grothoff
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30
31#define NUM_TRANSMISSIONS 500
32
33/**
34 * How long does the receiver take per message?
35 */
36#define RECEIVER_THROTTLE GNUNET_TIME_relative_multiply ( \
37 GNUNET_TIME_UNIT_MILLISECONDS, 1)
38
39static unsigned int received_cnt;
40
41
42GNUNET_NETWORK_STRUCT_BEGIN
43
44struct MyMessage
45{
46 struct GNUNET_MessageHeader header;
47 uint32_t x GNUNET_PACKED;
48};
49
50GNUNET_NETWORK_STRUCT_END
51
52static int global_ret;
53
54static struct GNUNET_SCHEDULER_Task *tt;
55
56static struct GNUNET_SCHEDULER_Task *dt;
57
58static struct GNUNET_MQ_Handle *cmq;
59
60
61static void
62do_shutdown (void *cls)
63{
64 (void) cls;
65 if (NULL != tt)
66 {
67 GNUNET_SCHEDULER_cancel (tt);
68 tt = NULL;
69 }
70 if (NULL != cmq)
71 {
72 GNUNET_MQ_destroy (cmq);
73 cmq = NULL;
74 }
75}
76
77
78static void
79do_timeout (void *cls)
80{
81 (void) cls;
82 tt = NULL;
83 GNUNET_SCHEDULER_shutdown ();
84 global_ret = 1;
85}
86
87
88/**
89 * Generic error handler, called with the appropriate
90 * error code and the same closure specified at the creation of
91 * the message queue.
92 * Not every message queue implementation supports an error handler.
93 *
94 * @param cls closure
95 * @param error error code
96 */
97static void
98error_cb (void *cls,
99 enum GNUNET_MQ_Error error)
100{
101 GNUNET_break (0);
102 global_ret = 3;
103 GNUNET_SCHEDULER_shutdown ();
104}
105
106
107static void
108client_continue (void *cls)
109{
110 struct GNUNET_SERVICE_Client *c = cls;
111
112 dt = NULL;
113 GNUNET_SERVICE_client_continue (c);
114}
115
116
117static void
118handle_dummy (void *cls,
119 const struct MyMessage *msg)
120{
121 struct GNUNET_SERVICE_Client *c = cls;
122
123 GNUNET_assert (NULL == dt);
124 /* artificially make receiver slower than sender */
125 dt = GNUNET_SCHEDULER_add_delayed (RECEIVER_THROTTLE,
126 &client_continue,
127 c);
128 if (received_cnt != ntohl (msg->x))
129 {
130 GNUNET_break (0);
131 global_ret = 4;
132 GNUNET_SCHEDULER_shutdown ();
133 }
134 received_cnt++;
135}
136
137
138static void
139handle_dummy2 (void *cls,
140 const struct MyMessage *msg)
141{
142 struct GNUNET_SERVICE_Client *c = cls;
143
144 GNUNET_SERVICE_client_continue (c);
145 if (NUM_TRANSMISSIONS != received_cnt)
146 {
147 GNUNET_break (0);
148 global_ret = 5;
149 }
150 GNUNET_SCHEDULER_shutdown ();
151}
152
153
154/**
155 * Function called whenever MQ has sent a message.
156 */
157static void
158notify_sent_cb (void *cls)
159{
160 static unsigned int seen;
161 unsigned int *cnt = cls;
162
163 if (seen != *cnt)
164 {
165 GNUNET_break (0);
166 global_ret = 6;
167 GNUNET_SCHEDULER_shutdown ();
168 }
169 seen++;
170 GNUNET_free (cnt);
171}
172
173
174/**
175 * Start running the actual test.
176 *
177 * @param cls closure passed to #GNUNET_SERVICE_MAIN
178 * @param cfg configuration to use for this service
179 * @param sh handle to the newly create service
180 */
181static void
182run (void *cls,
183 const struct GNUNET_CONFIGURATION_Handle *cfg,
184 struct GNUNET_SERVICE_Handle *sh)
185{
186 struct GNUNET_MQ_MessageHandler ch[] = {
187 GNUNET_MQ_handler_end ()
188 };
189 struct GNUNET_MQ_Envelope *env;
190 struct MyMessage *m;
191
192 (void) cls;
193 (void) sh;
194 cmq = GNUNET_CLIENT_connect (cfg,
195 "test_client",
196 ch,
197 &error_cb,
198 NULL);
199 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
200 NULL);
201 tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
202 &do_timeout,
203 NULL);
204 for (unsigned int i = 0; i < NUM_TRANSMISSIONS; i++)
205 {
206 unsigned int *cnt;
207
208 cnt = GNUNET_new (unsigned int);
209 *cnt = i;
210 env = GNUNET_MQ_msg (m,
211 GNUNET_MESSAGE_TYPE_DUMMY);
212 GNUNET_MQ_notify_sent (env,
213 &notify_sent_cb,
214 cnt);
215 m->x = htonl (i);
216 GNUNET_MQ_send (cmq,
217 env);
218 }
219 env = GNUNET_MQ_msg (m,
220 GNUNET_MESSAGE_TYPE_DUMMY2);
221 GNUNET_MQ_send (cmq,
222 env);
223}
224
225
226/**
227 * Callback to be called when a client connects to the service.
228 *
229 * @param cls closure for the service
230 * @param c the new client that connected to the service
231 * @param mq the message queue used to send messages to the client
232 * @return the client-specific (`internal') closure
233 */
234static void *
235connect_cb (void *cls,
236 struct GNUNET_SERVICE_Client *c,
237 struct GNUNET_MQ_Handle *mq)
238{
239 (void) cls;
240 (void) mq;
241 return c;
242}
243
244
245/**
246 * Callback to be called when a client disconnected from the service
247 *
248 * @param cls closure for the service
249 * @param c the client that disconnected
250 * @param internal_cls the client-specific (`internal') closure
251 */
252static void
253disconnect_cb (void *cls,
254 struct GNUNET_SERVICE_Client *c,
255 void *internal_cls)
256{
257 (void) cls;
258 (void) c;
259 (void) internal_cls;
260}
261
262
263static void
264test1 ()
265{
266 struct GNUNET_MQ_Envelope *mqm;
267 struct MyMessage *mm;
268
269 mm = NULL;
270 mqm = NULL;
271
272 mqm = GNUNET_MQ_msg (mm,
273 GNUNET_MESSAGE_TYPE_DUMMY);
274 GNUNET_assert (NULL != mqm);
275 GNUNET_assert (NULL != mm);
276 GNUNET_assert (GNUNET_MESSAGE_TYPE_DUMMY == ntohs (mm->header.type));
277 GNUNET_assert (sizeof(struct MyMessage) == ntohs (mm->header.size));
278 GNUNET_MQ_discard (mqm);
279}
280
281
282static void
283test2 ()
284{
285 struct GNUNET_MQ_Envelope *mqm;
286 struct GNUNET_MessageHeader *mh;
287
288 mqm = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_DUMMY);
289 /* how could the above be checked? */
290
291 GNUNET_MQ_discard (mqm);
292
293 mqm = GNUNET_MQ_msg_header_extra (mh,
294 20,
295 GNUNET_MESSAGE_TYPE_DUMMY);
296 GNUNET_assert (GNUNET_MESSAGE_TYPE_DUMMY == ntohs (mh->type));
297 GNUNET_assert (sizeof(struct GNUNET_MessageHeader) + 20 == ntohs (mh->size));
298 GNUNET_MQ_discard (mqm);
299}
300
301
302int
303main (int argc, char **argv)
304{
305 char *test_argv[] = {
306 (char *) "test_client",
307 "-c",
308 "test_client_data.conf",
309 NULL
310 };
311 struct GNUNET_MQ_MessageHandler mh[] = {
312 GNUNET_MQ_hd_fixed_size (dummy,
313 GNUNET_MESSAGE_TYPE_DUMMY,
314 struct MyMessage,
315 NULL),
316 GNUNET_MQ_hd_fixed_size (dummy2,
317 GNUNET_MESSAGE_TYPE_DUMMY2,
318 struct MyMessage,
319 NULL),
320 GNUNET_MQ_handler_end ()
321 };
322
323 (void) argc;
324 (void) argv;
325 GNUNET_log_setup ("test-mq",
326 "INFO",
327 NULL);
328 test1 ();
329 test2 ();
330 if (0 !=
331 GNUNET_SERVICE_run_ (3,
332 test_argv,
333 "test_client",
334 GNUNET_SERVICE_OPTION_NONE,
335 &run,
336 &connect_cb,
337 &disconnect_cb,
338 NULL,
339 mh))
340 return 1;
341 return global_ret;
342}