aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport-testing-main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/transport-testing-main.c')
-rw-r--r--src/transport/transport-testing-main.c613
1 files changed, 0 insertions, 613 deletions
diff --git a/src/transport/transport-testing-main.c b/src/transport/transport-testing-main.c
deleted file mode 100644
index 20c58eeee..000000000
--- a/src/transport/transport-testing-main.c
+++ /dev/null
@@ -1,613 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016 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 * @file transport-testing-main.c
22 * @brief convenience main function for tests
23 * @author Christian Grothoff
24 */
25#include "transport-testing.h"
26
27
28/**
29 * Closure for #connect_cb.
30 */
31struct GNUNET_TRANSPORT_TESTING_ConnectRequestList
32{
33 /**
34 * Stored in a DLL.
35 */
36 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *next;
37
38 /**
39 * Stored in a DLL.
40 */
41 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *prev;
42
43 /**
44 * Overall context we are in.
45 */
46 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
47
48 /**
49 * Connect request this is about.
50 */
51 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cr;
52
53 /**
54 * Peer being connected.
55 */
56 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1;
57
58 /**
59 * Peer being connected.
60 */
61 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
62};
63
64
65/**
66 * Shutdown function for the test. Stops all peers.
67 *
68 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
69 */
70static void
71do_shutdown (void *cls)
72{
73 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
74 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl;
75
76 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
77 "Testcase shutting down\n");
78 if (NULL != ccc->shutdown_task)
79 ccc->shutdown_task (ccc->shutdown_task_cls);
80 if (NULL != ccc->timeout_task)
81 {
82 GNUNET_SCHEDULER_cancel (ccc->timeout_task);
83 ccc->timeout_task = NULL;
84 }
85 if (NULL != ccc->connect_task)
86 {
87 GNUNET_SCHEDULER_cancel (ccc->connect_task);
88 ccc->connect_task = NULL;
89 }
90 while (NULL != (crl = ccc->crl_head))
91 {
92 GNUNET_CONTAINER_DLL_remove (ccc->crl_head,
93 ccc->crl_tail,
94 crl);
95 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (crl->cr);
96 GNUNET_free (crl);
97 }
98 for (unsigned int i = 0; i < ccc->num_peers; i++)
99 {
100 if (NULL != ccc->p[i])
101 {
102 GNUNET_TRANSPORT_TESTING_stop_peer (ccc->p[i]);
103 ccc->p[i] = NULL;
104 }
105 }
106}
107
108
109/**
110 * Testcase hit timeout, shut it down with error.
111 *
112 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
113 */
114static void
115do_timeout (void *cls)
116{
117 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
118
119 ccc->timeout_task = NULL;
120 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
121 "Testcase timed out\n");
122 ccc->global_ret = GNUNET_SYSERR;
123 GNUNET_SCHEDULER_shutdown ();
124}
125
126
127/**
128 * Internal data structure. Closure for
129 * #connect_cb, #disconnect_cb, #my_nc and #start_cb.
130 * Allows us to identify which peer this is about.
131 */
132struct GNUNET_TRANSPORT_TESTING_InternalPeerContext
133{
134 /**
135 * Overall context of the callback.
136 */
137 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
138
139 /**
140 * Offset of the peer this is about.
141 */
142 unsigned int off;
143};
144
145
146/**
147 * Information tracked per connected peer.
148 */
149struct ConnectPairInfo
150{
151 /**
152 * Peer this is about.
153 */
154 const struct GNUNET_PeerIdentity *sender;
155
156 /**
157 * Information about the receiving peer.
158 */
159 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi;
160};
161
162
163/**
164 * Function called when we connected two peers. Once we have gotten
165 * to the clique, launch test-specific logic.
166 *
167 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *`
168 */
169static void
170connect_cb (void *cls)
171{
172 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl = cls;
173 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = crl->ccc;
174
175 GNUNET_CONTAINER_DLL_remove (ccc->crl_head,
176 ccc->crl_tail,
177 crl);
178 {
179 char *p1_c = GNUNET_strdup (GNUNET_i2s (&crl->p1->id));
180
181 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
182 "Peers connected: %u (%s) <-> %u (%s)\n",
183 crl->p1->no,
184 p1_c,
185 crl->p2->no,
186 GNUNET_i2s (&crl->p2->id));
187 GNUNET_free (p1_c);
188 GNUNET_free (crl);
189 }
190 if (NULL == ccc->crl_head)
191 {
192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
193 "All connections UP, launching custom test logic.\n");
194 GNUNET_SCHEDULER_add_now (ccc->connect_continuation,
195 ccc->connect_continuation_cls);
196 }
197}
198
199
200/**
201 * Find peer by peer ID.
202 *
203 * @param ccc context to search
204 * @param peer peer to look for
205 * @return NULL if @a peer was not found
206 */
207struct GNUNET_TRANSPORT_TESTING_PeerContext *
208GNUNET_TRANSPORT_TESTING_find_peer (struct
209 GNUNET_TRANSPORT_TESTING_ConnectCheckContext
210 *ccc,
211 const struct GNUNET_PeerIdentity *peer)
212{
213 for (unsigned int i = 0; i < ccc->num_peers; i++)
214 if ((NULL != ccc->p[i]) &&
215 (0 == memcmp (peer,
216 &ccc->p[i]->id,
217 sizeof(*peer))))
218 return ccc->p[i];
219 return NULL;
220}
221
222
223/**
224 * Wrapper around peers connecting. Calls client's nc function.
225 *
226 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
227 * @param peer peer we got connected to
228 * @param mq message queue for transmissions to @a peer
229 * @return closure for message handlers
230 */
231static void *
232my_nc (void *cls,
233 const struct GNUNET_PeerIdentity *peer,
234 struct GNUNET_MQ_Handle *mq)
235{
236 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
237 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
238 struct ConnectPairInfo *cpi;
239
240 if (NULL != ccc->nc)
241 ccc->nc (ccc->cls,
242 ccc->p[ipi->off],
243 peer);
244 cpi = GNUNET_new (struct ConnectPairInfo);
245 cpi->ipi = ipi;
246 cpi->sender = peer; /* valid until disconnect */
247 return cpi;
248}
249
250
251/**
252 * Wrapper around peers disconnecting. Calls client's nd function.
253 *
254 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
255 * @param peer peer we got disconnected from
256 * @param custom_cls return value from @my_nc
257 */
258static void
259my_nd (void *cls,
260 const struct GNUNET_PeerIdentity *peer,
261 void *custom_cls)
262{
263 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
264 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
265 struct ConnectPairInfo *cpi = custom_cls;
266
267 if (NULL != ccc->nd)
268 ccc->nd (ccc->cls,
269 ccc->p[ipi->off],
270 peer);
271 GNUNET_free (cpi);
272}
273
274
275/**
276 * Wrapper around receiving data. Calls client's rec function.
277 *
278 * @param cls our `struct ConnectPairInfo *`
279 * @param message message we received
280 * @return #GNUNET_OK (all messages are fine)
281 */
282static int
283check_test (void *cls,
284 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
285{
286 return GNUNET_OK;
287}
288
289
290/**
291 * Wrapper around receiving data. Calls client's rec function.
292 *
293 * @param cls our `struct ConnectPairInfo *`
294 * @param message message we received
295 */
296static void
297handle_test (void *cls,
298 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
299{
300 struct ConnectPairInfo *cpi = cls;
301 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cpi->ipi;
302 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
303
304 if (NULL != ccc->rec)
305 ccc->rec (ccc->cls,
306 ccc->p[ipi->off],
307 cpi->sender,
308 message);
309}
310
311
312/**
313 * Wrapper around receiving data. Calls client's rec function.
314 *
315 * @param cls our `struct ConnectPairInfo *`
316 * @param message message we received
317 * @return #GNUNET_OK (all messages are fine)
318 */
319static int
320check_test2 (void *cls,
321 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
322{
323 return GNUNET_OK;
324}
325
326
327/**
328 * Wrapper around receiving data. Calls client's rec function.
329 *
330 * @param cls our `struct ConnectPairInfo *`
331 * @param message message we received
332 */
333static void
334handle_test2 (void *cls,
335 const struct GNUNET_TRANSPORT_TESTING_TestMessage *message)
336{
337 struct ConnectPairInfo *cpi = cls;
338 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cpi->ipi;
339 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
340
341 if (NULL != ccc->rec)
342 ccc->rec (ccc->cls,
343 ccc->p[ipi->off],
344 cpi->sender,
345 message);
346}
347
348
349/**
350 * Connect the peers as a clique.
351 *
352 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
353 */
354static void
355do_connect (void *cls)
356{
357 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
358
359 ccc->connect_task = NULL;
360 for (unsigned int i = 0; i < ccc->num_peers; i++)
361 for (unsigned int j = (ccc->bi_directional ? 0 : i + 1); j < ccc->num_peers;
362 j++)
363 {
364 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl;
365
366 if (i == j)
367 continue;
368 crl = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequestList);
369 GNUNET_CONTAINER_DLL_insert (ccc->crl_head,
370 ccc->crl_tail,
371 crl);
372 crl->ccc = ccc;
373 crl->p1 = ccc->p[i];
374 crl->p2 = ccc->p[j];
375 {
376 char *sender_c = GNUNET_strdup (GNUNET_i2s (&ccc->p[0]->id));
377
378 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
379 "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n",
380 ccc->p[0]->no,
381 sender_c,
382 ccc->p[1]->no,
383 GNUNET_i2s (&ccc->p[1]->id));
384 GNUNET_free (sender_c);
385 }
386 crl->cr = GNUNET_TRANSPORT_TESTING_connect_peers (ccc->p[i],
387 ccc->p[j],
388 &connect_cb,
389 crl);
390 }
391}
392
393
394/**
395 * Function called once we have successfully launched a peer.
396 * Once all peers have been launched, we connect all of them
397 * in a clique.
398 *
399 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
400 */
401static void
402start_cb (void *cls)
403{
404 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
405 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
406 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = ccc->p[ipi->off];
407
408 ccc->started++;
409 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
410 "Peer %u (`%s') started\n",
411 p->no,
412 GNUNET_i2s (&p->id));
413 if (ccc->started != ccc->num_peers)
414 return;
415 if (NULL != ccc->pre_connect_task)
416 {
417 /* Run the custom per-connect job, then give it a second to
418 go into effect before we continue connecting peers. */
419 ccc->pre_connect_task (ccc->pre_connect_task_cls);
420 ccc->connect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
421 &do_connect,
422 ccc);
423 }
424 else
425 {
426 do_connect (ccc);
427 }
428}
429
430
431/**
432 * Function run from #GNUNET_TRANSPORT_TESTING_connect_check
433 * once the scheduler is up. Should launch the peers and
434 * then in the continuations try to connect them.
435 *
436 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
437 * @param args ignored
438 * @param cfgfile ignored
439 * @param cfg configuration
440 */
441static void
442connect_check_run (void *cls,
443 char *const *args,
444 const char *cfgfile,
445 const struct GNUNET_CONFIGURATION_Handle *cfg)
446{
447 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
448 int ok;
449
450 ccc->cfg = cfg;
451 ccc->timeout_task = GNUNET_SCHEDULER_add_delayed (ccc->timeout,
452 &do_timeout,
453 ccc);
454 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
455 ccc);
456 ok = GNUNET_OK;
457 for (unsigned int i = 0; i < ccc->num_peers; i++)
458 {
459 struct GNUNET_MQ_MessageHandler handlers[] = {
460 GNUNET_MQ_hd_var_size (test,
461 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
462 struct GNUNET_TRANSPORT_TESTING_TestMessage,
463 NULL),
464 GNUNET_MQ_hd_var_size (test2,
465 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE2,
466 struct GNUNET_TRANSPORT_TESTING_TestMessage,
467 NULL),
468 GNUNET_MQ_handler_end ()
469 };
470 ccc->p[i] = GNUNET_TRANSPORT_TESTING_start_peer (ccc->tth,
471 ccc->cfg_files[i],
472 i + 1,
473 handlers,
474 &my_nc,
475 &my_nd,
476 &ccc->ip[i],
477 &start_cb,
478 &ccc->ip[i]);
479 if (NULL == ccc->p[i])
480 ok = GNUNET_SYSERR;
481 }
482 if (GNUNET_OK != ok)
483 {
484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
485 "Fail! Could not start peers!\n");
486 GNUNET_SCHEDULER_shutdown ();
487 }
488}
489
490
491/**
492 * Common implementation of the #GNUNET_TRANSPORT_TESTING_CheckCallback.
493 * Starts and connects the two peers, then invokes the
494 * `connect_continuation` from @a cls. Sets up a timeout to
495 * abort the test, and a shutdown handler to clean up properly
496 * on exit.
497 *
498 * @param cls closure of type `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
499 * @param tth_ initialized testing handle
500 * @param test_plugin_ name of the plugin
501 * @param test_name_ name of the test
502 * @param num_peers number of entries in the @a cfg_file array
503 * @param cfg_files array of names of configuration files for the peers
504 * @return #GNUNET_SYSERR on error
505 */
506int
507GNUNET_TRANSPORT_TESTING_connect_check (void *cls,
508 struct GNUNET_TRANSPORT_TESTING_Handle *
509 tth_,
510 const char *test_plugin_,
511 const char *test_name_,
512 unsigned int num_peers,
513 char *cfg_files[])
514{
515 static struct GNUNET_GETOPT_CommandLineOption options[] = {
516 GNUNET_GETOPT_OPTION_END
517 };
518 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
519 struct GNUNET_TRANSPORT_TESTING_PeerContext *p[num_peers];
520 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext ip[num_peers];
521 char *argv[] = {
522 (char *) test_name_,
523 "-c",
524 (char *) ccc->config_file,
525 NULL
526 };
527
528 ccc->num_peers = num_peers;
529 ccc->cfg_files = cfg_files;
530 ccc->test_plugin = test_plugin_;
531 ccc->test_name = test_name_;
532 ccc->tth = tth_;
533 ccc->global_ret = GNUNET_OK;
534 ccc->p = p;
535 ccc->ip = ip;
536 for (unsigned int i = 0; i < num_peers; i++)
537 {
538 ip[i].off = i;
539 ip[i].ccc = ccc;
540 }
541 if (GNUNET_OK !=
542 GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1,
543 argv,
544 test_name_,
545 "nohelp",
546 options,
547 &connect_check_run,
548 ccc))
549 return GNUNET_SYSERR;
550 return ccc->global_ret;
551}
552
553
554/**
555 * Setup testcase. Calls @a check with the data the test needs.
556 *
557 * @param argv0 binary name (argv[0])
558 * @param filename source file name (__FILE__)
559 * @param num_peers number of peers to start
560 * @param check main function to run
561 * @param check_cls closure for @a check
562 * @return #GNUNET_OK on success
563 */
564int
565GNUNET_TRANSPORT_TESTING_main_ (const char *argv0,
566 const char *filename,
567 unsigned int num_peers,
568 GNUNET_TRANSPORT_TESTING_CheckCallback check,
569 void *check_cls)
570{
571 struct GNUNET_TRANSPORT_TESTING_Handle *tth;
572 char *test_name;
573 char *test_source;
574 char *test_plugin;
575 char *cfg_names[num_peers];
576 int ret;
577
578 ret = GNUNET_OK;
579 test_name = GNUNET_TRANSPORT_TESTING_get_test_name (argv0);
580 GNUNET_log_setup (test_name,
581 "WARNING",
582 NULL);
583 test_source = GNUNET_TRANSPORT_TESTING_get_test_source_name (filename);
584 test_plugin = GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv0,
585 test_source);
586 for (unsigned int i = 0; i < num_peers; i++)
587 cfg_names[i] = GNUNET_TRANSPORT_TESTING_get_config_name (argv0,
588 i + 1);
589 tth = GNUNET_TRANSPORT_TESTING_init ();
590 if (NULL == tth)
591 {
592 ret = GNUNET_SYSERR;
593 }
594 else
595 {
596 ret = check (check_cls,
597 tth,
598 test_plugin,
599 test_name,
600 num_peers,
601 cfg_names);
602 GNUNET_TRANSPORT_TESTING_done (tth);
603 }
604 for (unsigned int i = 0; i < num_peers; i++)
605 GNUNET_free (cfg_names[i]);
606 GNUNET_free (test_source);
607 GNUNET_free (test_plugin);
608 GNUNET_free (test_name);
609 return ret;
610}
611
612
613/* end of transport-testing-main.c */