2 This file is part of GNUnet.
3 Copyright (C) 2012, 2017 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU 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.
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.
16 * @file cadet/cadet_test_lib.c
17 * @author Bartlomiej Polot
18 * @brief library for writing CADET tests
21 #include "gnunet_util_lib.h"
22 #include "cadet_test_lib.h"
23 #include "gnunet_cadet_service.h"
27 * Test context for a CADET Test.
29 struct GNUNET_CADET_TEST_Context
32 * Array of running peers.
34 struct GNUNET_TESTBED_Peer **peers;
37 * Array of handles to the CADET for each peer.
39 struct GNUNET_CADET_Handle **cadets;
42 * Operation associated with the connection to the CADET.
44 struct GNUNET_TESTBED_Operation **ops;
47 * Number of peers running, size of the arrays above.
49 unsigned int num_peers;
52 * Main function of the test to run once all CADETs are available.
54 GNUNET_CADET_TEST_AppMain app_main;
57 * Closure for 'app_main'.
62 * Handler for incoming tunnels.
64 GNUNET_CADET_ConnectEventHandler connects;
67 * Function called when the transmit window size changes.
69 GNUNET_CADET_WindowSizeEventHandler window_changes;
72 * Cleaner for destroyed incoming tunnels.
74 GNUNET_CADET_DisconnectEventHandler disconnects;
79 struct GNUNET_MQ_MessageHandler *handlers;
84 const struct GNUNET_HashCode **ports;
87 * Number of ports in #ports.
89 unsigned int port_count;
95 * Context for a cadet adapter callback.
97 struct GNUNET_CADET_TEST_AdapterContext
100 * Peer number for the particular peer.
105 * Port handlers for open ports.
107 struct GNUNET_CADET_Port **ports;
112 struct GNUNET_CADET_TEST_Context *ctx;
117 * Adapter function called to establish a connection to
121 * @param cfg configuration of the peer to connect to; will be available until
122 * GNUNET_TESTBED_operation_done() is called on the operation returned
123 * from GNUNET_TESTBED_service_connect()
124 * @return service handle to return in 'op_result', NULL on error
127 cadet_connect_adapter (void *cls,
128 const struct GNUNET_CONFIGURATION_Handle *cfg)
130 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
131 struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
132 struct GNUNET_CADET_Handle *h;
134 h = GNUNET_CADET_connect (cfg);
135 if (NULL == ctx->ports)
137 actx->ports = GNUNET_new_array (ctx->port_count,
138 struct GNUNET_CADET_Port *);
139 for (unsigned int i = 0; i < ctx->port_count; i++)
141 actx->ports[i] = GNUNET_CADET_open_port (h,
144 (void *) (long) actx->peer,
154 * Adapter function called to destroy a connection to
158 * @param op_result service handle returned from the connect adapter
161 cadet_disconnect_adapter (void *cls,
164 struct GNUNET_CADET_Handle *cadet = op_result;
165 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
167 if (NULL != actx->ports)
169 for (unsigned int i = 0; i < actx->ctx->port_count; i++)
171 GNUNET_CADET_close_port (actx->ports[i]);
172 actx->ports[i] = NULL;
174 GNUNET_free (actx->ports);
177 GNUNET_CADET_disconnect (cadet);
182 * Callback to be called when a service connect operation is completed.
184 * @param cls The callback closure from functions generating an operation.
185 * @param op The operation that has been finished.
186 * @param ca_result The service handle returned from
187 * GNUNET_TESTBED_ConnectAdapter() (cadet handle).
188 * @param emsg Error message in case the operation has failed.
189 * NULL if operation has executed successfully.
192 cadet_connect_cb (void *cls,
193 struct GNUNET_TESTBED_Operation *op,
197 struct GNUNET_CADET_TEST_Context *ctx = cls;
202 "Failed to connect to CADET service: %s\n",
204 GNUNET_SCHEDULER_shutdown ();
207 for (unsigned int i = 0; i < ctx->num_peers; i++)
208 if (op == ctx->ops[i])
210 ctx->cadets[i] = ca_result;
211 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
212 "...cadet %u connected\n",
215 for (unsigned int i = 0; i < ctx->num_peers; i++)
216 if (NULL == ctx->cadets[i])
217 return; /* still some CADET connections missing */
218 /* all CADET connections ready! */
219 ctx->app_main (ctx->app_main_cls,
228 GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
230 for (unsigned int i = 0; i < ctx->num_peers; i++)
232 GNUNET_assert (NULL != ctx->ops[i]);
233 GNUNET_TESTBED_operation_done (ctx->ops[i]);
236 GNUNET_free (ctx->ops);
237 GNUNET_free (ctx->cadets);
238 GNUNET_free (ctx->handlers);
240 GNUNET_SCHEDULER_shutdown ();
245 * Callback run when the testbed is ready (peers running and connected to
248 * @param cls Closure (context).
249 * @param h the run handle
250 * @param num_peers Number of peers that are running.
251 * @param peers Handles to each one of the @c num_peers peers.
252 * @param links_succeeded the number of overlay link connection attempts that
254 * @param links_failed the number of overlay link connection attempts that
258 cadet_test_run (void *cls,
259 struct GNUNET_TESTBED_RunHandle *h,
260 unsigned int num_peers,
261 struct GNUNET_TESTBED_Peer **peers,
262 unsigned int links_succeeded,
263 unsigned int links_failed)
265 struct GNUNET_CADET_TEST_Context *ctx = cls;
267 if (0 != links_failed)
269 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
270 "Some links failed (%u), ending\n",
274 if (num_peers != ctx->num_peers)
276 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
277 "Peers started %u/%u, ending\n",
282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
283 "Testbed up, %u peers and %u links\n",
287 for (unsigned int i = 0; i < num_peers; i++)
289 struct GNUNET_CADET_TEST_AdapterContext *newctx;
291 newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
294 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
295 "Connecting to cadet %u\n",
297 ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
302 &cadet_connect_adapter,
303 &cadet_disconnect_adapter,
305 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
313 * Run a test using the given name, configuration file and number of peers.
314 * All cadet callbacks will receive the peer number (long) as the closure.
316 * @param testname Name of the test (for logging).
317 * @param cfgfile Name of the configuration file.
318 * @param num_peers Number of peers to start.
319 * @param tmain Main function to run once the testbed is ready.
320 * @param tmain_cls Closure for @a tmain.
321 * @param connects Handler for incoming channels.
322 * @param window_changes Handler for the window size change notification.
323 * @param disconnects Cleaner for destroyed incoming channels.
324 * @param handlers Message handlers.
325 * @param ports Ports the peers offer, NULL-terminated.
328 GNUNET_CADET_TEST_ruN (const char *testname,
330 unsigned int num_peers,
331 GNUNET_CADET_TEST_AppMain tmain,
333 GNUNET_CADET_ConnectEventHandler connects,
334 GNUNET_CADET_WindowSizeEventHandler window_changes,
335 GNUNET_CADET_DisconnectEventHandler disconnects,
336 struct GNUNET_MQ_MessageHandler *handlers,
337 const struct GNUNET_HashCode **ports)
339 struct GNUNET_CADET_TEST_Context *ctx;
341 ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
342 ctx->num_peers = num_peers;
343 ctx->ops = GNUNET_new_array (num_peers,
344 struct GNUNET_TESTBED_Operation *);
345 ctx->cadets = GNUNET_new_array (num_peers,
346 struct GNUNET_CADET_Handle *);
347 ctx->app_main = tmain;
348 ctx->app_main_cls = tmain_cls;
349 ctx->connects = connects;
350 ctx->window_changes = window_changes;
351 ctx->disconnects = disconnects;
352 ctx->handlers = GNUNET_MQ_copy_handlers (handlers);
355 while (NULL != ctx->ports[ctx->port_count])
357 GNUNET_TESTBED_test_run (testname,
365 /* end of cadet_test_lib.c */