2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 * @file transport-testing-main.c
22 * @brief convenience main function for tests
23 * @author Christian Grothoff
25 #include "transport-testing.h"
29 * Closure for #connect_cb.
31 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList
36 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *next;
41 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *prev;
44 * Overall context we are in.
46 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
49 * Connect request this is about.
51 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cr;
54 * Peer being connected.
56 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1;
59 * Peer being connected.
61 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
67 * Shutdown function for the test. Stops all peers.
69 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
72 do_shutdown (void *cls)
74 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
75 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl;
77 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
78 "Testcase shutting down\n");
79 if (NULL != ccc->shutdown_task)
80 ccc->shutdown_task (ccc->shutdown_task_cls);
81 if (NULL != ccc->timeout_task)
83 GNUNET_SCHEDULER_cancel (ccc->timeout_task);
84 ccc->timeout_task = NULL;
86 while (NULL != (crl = ccc->crl_head))
88 GNUNET_CONTAINER_DLL_remove (ccc->crl_head,
91 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (crl->cr);
94 for (unsigned int i=0;i<ccc->num_peers;i++)
96 if (NULL != ccc->p[i])
98 GNUNET_TRANSPORT_TESTING_stop_peer (ccc->p[i]);
106 * Testcase hit timeout, shut it down with error.
108 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
111 do_timeout (void *cls)
113 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
115 ccc->timeout_task = NULL;
116 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
117 "Testcase timed out\n");
118 ccc->global_ret = GNUNET_SYSERR;
119 GNUNET_SCHEDULER_shutdown ();
124 * Internal data structure. Closure for
125 * #connect_cb, #disconnect_cb, #my_nc and #start_cb.
126 * Allows us to identify which peer this is about.
128 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext
131 * Overall context of the callback.
133 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
136 * Offset of the peer this is about.
143 * Function called when we connected two peers.
144 * Once we have gotten to the clique, launch
145 * test-specific logic.
147 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *`
150 connect_cb (void *cls)
152 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl = cls;
153 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = crl->ccc;
155 GNUNET_CONTAINER_DLL_remove (ccc->crl_head,
159 char *p1_c = GNUNET_strdup (GNUNET_i2s (&crl->p1->id));
161 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
162 "Peers connected: %u (%s) <-> %u (%s)\n",
166 GNUNET_i2s (&crl->p2->id));
170 if (NULL == ccc->crl_head)
172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
173 "All connections UP, launching custom test logic.\n");
174 GNUNET_SCHEDULER_add_now (ccc->connect_continuation,
175 ccc->connect_continuation_cls);
181 * Find peer by peer ID.
183 * @param ccc context to search
184 * @param peer peer to look for
185 * @return NULL if @a peer was not found
187 struct GNUNET_TRANSPORT_TESTING_PeerContext *
188 GNUNET_TRANSPORT_TESTING_find_peer (struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc,
189 const struct GNUNET_PeerIdentity *peer)
191 for (unsigned int i=0;i<ccc->num_peers;i++)
192 if ( (NULL != ccc->p[i]) &&
202 * Wrapper around peers connecting. Calls client's nc function.
204 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
205 * @param peer peer we got connected to
209 const struct GNUNET_PeerIdentity *peer)
211 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
212 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
223 * Wrapper around peers disconnecting. Calls client's nd function.
225 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
226 * @param peer peer we got disconnected from
230 const struct GNUNET_PeerIdentity *peer)
232 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
233 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
243 * Wrapper around receiving data. Calls client's rec function.
245 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
246 * @param peer peer we got a message from
247 * @param message message we received
251 const struct GNUNET_PeerIdentity *peer,
252 const struct GNUNET_MessageHeader *message)
254 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
255 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
257 if (NULL != ccc->rec)
266 * Function called once we have successfully launched a peer.
267 * Once all peers have been launched, we connect all of them
270 * @param p peer that was launched (redundant, kill ASAP)
271 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
274 start_cb (struct GNUNET_TRANSPORT_TESTING_PeerContext *p,
277 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
278 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
281 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
282 "Peer %u (`%s') started\n",
284 GNUNET_i2s (&p->id));
285 if (ccc->started != ccc->num_peers)
288 for (unsigned int i=0;i<ccc->num_peers;i++)
289 for (unsigned int j=i+1;j<ccc->num_peers;j++)
291 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl;
293 crl = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequestList);
294 GNUNET_CONTAINER_DLL_insert (ccc->crl_head,
301 char *sender_c = GNUNET_strdup (GNUNET_i2s (&ccc->p[0]->id));
303 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
304 "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n",
308 GNUNET_i2s (&ccc->p[1]->id));
309 GNUNET_free (sender_c);
311 crl->cr = GNUNET_TRANSPORT_TESTING_connect_peers (ccc->p[i],
320 * Function run from #GNUNET_TRANSPORT_TESTING_connect_check
321 * once the scheduler is up. Should launch the peers and
322 * then in the continuations try to connect them.
324 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
325 * @param args ignored
326 * @param cfgfile ignored
327 * @param cfg configuration
330 connect_check_run (void *cls,
333 const struct GNUNET_CONFIGURATION_Handle *cfg)
335 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
339 ccc->timeout_task = GNUNET_SCHEDULER_add_delayed (ccc->timeout,
342 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
345 for (unsigned int i=0;i<ccc->num_peers;i++)
347 ccc->p[i] = GNUNET_TRANSPORT_TESTING_start_peer (ccc->tth,
355 if (NULL == ccc->p[i])
360 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
361 "Fail! Could not start peers!\n");
362 GNUNET_SCHEDULER_shutdown ();
368 * Common implementation of the #GNUNET_TRANSPORT_TESTING_CheckCallback.
369 * Starts and connects the two peers, then invokes the
370 * `connect_continuation` from @a cls. Sets up a timeout to
371 * abort the test, and a shutdown handler to clean up properly
374 * @param cls closure of type `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
375 * @param tth_ initialized testing handle
376 * @param test_plugin_ name of the plugin
377 * @param test_name_ name of the test
378 * @param num_peers number of entries in the @a cfg_file array
379 * @param cfg_files array of names of configuration files for the peers
380 * @return #GNUNET_SYSERR on error
383 GNUNET_TRANSPORT_TESTING_connect_check (void *cls,
384 struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
385 const char *test_plugin_,
386 const char *test_name_,
387 unsigned int num_peers,
390 static struct GNUNET_GETOPT_CommandLineOption options[] = {
391 GNUNET_GETOPT_OPTION_END
393 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
394 struct GNUNET_TRANSPORT_TESTING_PeerContext *p[num_peers];
395 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext ip[num_peers];
399 (char *) ccc->config_file,
403 ccc->num_peers = num_peers;
404 ccc->cfg_files = cfg_files;
405 ccc->test_plugin = test_plugin_;
406 ccc->test_name = test_name_;
408 ccc->global_ret = GNUNET_OK;
411 for (unsigned int i=0;i<num_peers;i++)
416 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
423 return ccc->global_ret;
428 * Setup testcase. Calls @a check with the data the test needs.
430 * @param argv0 binary name (argv[0])
431 * @param filename source file name (__FILE__)
432 * @param num_peers number of peers to start
433 * @param check main function to run
434 * @param check_cls closure for @a check
435 * @return #GNUNET_OK on success
438 GNUNET_TRANSPORT_TESTING_main_ (const char *argv0,
439 const char *filename,
440 unsigned int num_peers,
441 GNUNET_TRANSPORT_TESTING_CheckCallback check,
444 struct GNUNET_TRANSPORT_TESTING_Handle *tth;
448 char *cfg_names[num_peers];
452 test_name = GNUNET_TRANSPORT_TESTING_get_test_name (argv0);
453 GNUNET_log_setup (test_name,
456 test_source = GNUNET_TRANSPORT_TESTING_get_test_source_name (filename);
457 test_plugin = GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv0,
459 for (unsigned int i=0;i<num_peers;i++)
460 cfg_names[i] = GNUNET_TRANSPORT_TESTING_get_config_name (argv0,
462 tth = GNUNET_TRANSPORT_TESTING_init ();
469 ret = check (check_cls,
475 GNUNET_TRANSPORT_TESTING_done (tth);
477 for (unsigned int i=0;i<num_peers;i++)
478 GNUNET_free (cfg_names[i]);
479 GNUNET_free (test_source);
480 GNUNET_free (test_plugin);
481 GNUNET_free (test_name);
485 /* end of transport-testing-main.c */