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 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.
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.
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/>.
19 * @file cadet/cadet_test_lib.c
20 * @author Bartlomiej Polot
21 * @brief library for writing CADET tests
24 #include "gnunet_util_lib.h"
25 #include "cadet_test_lib.h"
26 #include "gnunet_cadet_service.h"
30 * Test context for a CADET Test.
32 struct GNUNET_CADET_TEST_Context
35 * Array of running peers.
37 struct GNUNET_TESTBED_Peer **peers;
40 * Array of handles to the CADET for each peer.
42 struct GNUNET_CADET_Handle **cadets;
45 * Operation associated with the connection to the CADET.
47 struct GNUNET_TESTBED_Operation **ops;
50 * Number of peers running, size of the arrays above.
52 unsigned int num_peers;
55 * Main function of the test to run once all CADETs are available.
57 GNUNET_CADET_TEST_AppMain app_main;
60 * Closure for 'app_main'.
65 * Handler for incoming tunnels.
67 GNUNET_CADET_ConnectEventHandler connects;
70 * Function called when the transmit window size changes.
72 GNUNET_CADET_WindowSizeEventHandler window_changes;
75 * Cleaner for destroyed incoming tunnels.
77 GNUNET_CADET_DisconnectEventHandler disconnects;
82 struct GNUNET_MQ_MessageHandler *handlers;
87 const struct GNUNET_HashCode **ports;
90 * Number of ports in #ports.
92 unsigned int port_count;
98 * Context for a cadet adapter callback.
100 struct GNUNET_CADET_TEST_AdapterContext
103 * Peer number for the particular peer.
108 * Port handlers for open ports.
110 struct GNUNET_CADET_Port **ports;
115 struct GNUNET_CADET_TEST_Context *ctx;
120 * Adapter function called to establish a connection to
124 * @param cfg configuration of the peer to connect to; will be available until
125 * GNUNET_TESTBED_operation_done() is called on the operation returned
126 * from GNUNET_TESTBED_service_connect()
127 * @return service handle to return in 'op_result', NULL on error
130 cadet_connect_adapter (void *cls,
131 const struct GNUNET_CONFIGURATION_Handle *cfg)
133 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
134 struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
135 struct GNUNET_CADET_Handle *h;
137 h = GNUNET_CADET_connect (cfg);
143 if (NULL == ctx->ports)
145 actx->ports = GNUNET_new_array (ctx->port_count,
146 struct GNUNET_CADET_Port *);
147 for (unsigned int i = 0; i < ctx->port_count; i++)
149 actx->ports[i] = GNUNET_CADET_open_port (h,
152 (void *) (long) actx->peer,
162 * Adapter function called to destroy a connection to
166 * @param op_result service handle returned from the connect adapter
169 cadet_disconnect_adapter (void *cls,
172 struct GNUNET_CADET_Handle *cadet = op_result;
173 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
175 if (NULL != actx->ports)
177 for (unsigned int i = 0; i < actx->ctx->port_count; i++)
179 GNUNET_CADET_close_port (actx->ports[i]);
180 actx->ports[i] = NULL;
182 GNUNET_free (actx->ports);
185 GNUNET_CADET_disconnect (cadet);
190 * Callback to be called when a service connect operation is completed.
192 * @param cls The callback closure from functions generating an operation.
193 * @param op The operation that has been finished.
194 * @param ca_result The service handle returned from
195 * GNUNET_TESTBED_ConnectAdapter() (cadet handle).
196 * @param emsg Error message in case the operation has failed.
197 * NULL if operation has executed successfully.
200 cadet_connect_cb (void *cls,
201 struct GNUNET_TESTBED_Operation *op,
205 struct GNUNET_CADET_TEST_Context *ctx = cls;
210 "Failed to connect to CADET service: %s\n",
212 GNUNET_SCHEDULER_shutdown ();
215 for (unsigned int i = 0; i < ctx->num_peers; i++)
216 if (op == ctx->ops[i])
218 ctx->cadets[i] = ca_result;
219 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
220 "...cadet %u connected\n",
223 for (unsigned int i = 0; i < ctx->num_peers; i++)
224 if (NULL == ctx->cadets[i])
225 return; /* still some CADET connections missing */
226 /* all CADET connections ready! */
227 ctx->app_main (ctx->app_main_cls,
236 GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
238 for (unsigned int i = 0; i < ctx->num_peers; i++)
240 GNUNET_assert (NULL != ctx->ops[i]);
241 GNUNET_TESTBED_operation_done (ctx->ops[i]);
244 GNUNET_free (ctx->ops);
245 GNUNET_free (ctx->cadets);
246 GNUNET_free (ctx->handlers);
248 GNUNET_SCHEDULER_shutdown ();
253 * Callback run when the testbed is ready (peers running and connected to
256 * @param cls Closure (context).
257 * @param h the run handle
258 * @param num_peers Number of peers that are running.
259 * @param peers Handles to each one of the @c num_peers peers.
260 * @param links_succeeded the number of overlay link connection attempts that
262 * @param links_failed the number of overlay link connection attempts that
266 cadet_test_run (void *cls,
267 struct GNUNET_TESTBED_RunHandle *h,
268 unsigned int num_peers,
269 struct GNUNET_TESTBED_Peer **peers,
270 unsigned int links_succeeded,
271 unsigned int links_failed)
273 struct GNUNET_CADET_TEST_Context *ctx = cls;
275 if (0 != links_failed)
277 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
278 "Some links failed (%u), ending\n",
282 if (num_peers != ctx->num_peers)
284 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
285 "Peers started %u/%u, ending\n",
290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
291 "Testbed up, %u peers and %u links\n",
295 for (unsigned int i = 0; i < num_peers; i++)
297 struct GNUNET_CADET_TEST_AdapterContext *newctx;
299 newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
302 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
303 "Connecting to cadet %u\n",
305 ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
310 &cadet_connect_adapter,
311 &cadet_disconnect_adapter,
313 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
321 * Run a test using the given name, configuration file and number of peers.
322 * All cadet callbacks will receive the peer number (long) as the closure.
324 * @param testname Name of the test (for logging).
325 * @param cfgfile Name of the configuration file.
326 * @param num_peers Number of peers to start.
327 * @param tmain Main function to run once the testbed is ready.
328 * @param tmain_cls Closure for @a tmain.
329 * @param connects Handler for incoming channels.
330 * @param window_changes Handler for the window size change notification.
331 * @param disconnects Cleaner for destroyed incoming channels.
332 * @param handlers Message handlers.
333 * @param ports Ports the peers offer, NULL-terminated.
336 GNUNET_CADET_TEST_ruN (const char *testname,
338 unsigned int num_peers,
339 GNUNET_CADET_TEST_AppMain tmain,
341 GNUNET_CADET_ConnectEventHandler connects,
342 GNUNET_CADET_WindowSizeEventHandler window_changes,
343 GNUNET_CADET_DisconnectEventHandler disconnects,
344 struct GNUNET_MQ_MessageHandler *handlers,
345 const struct GNUNET_HashCode **ports)
347 struct GNUNET_CADET_TEST_Context *ctx;
349 ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
350 ctx->num_peers = num_peers;
351 ctx->ops = GNUNET_new_array (num_peers,
352 struct GNUNET_TESTBED_Operation *);
353 ctx->cadets = GNUNET_new_array (num_peers,
354 struct GNUNET_CADET_Handle *);
355 ctx->app_main = tmain;
356 ctx->app_main_cls = tmain_cls;
357 ctx->connects = connects;
358 ctx->window_changes = window_changes;
359 ctx->disconnects = disconnects;
360 ctx->handlers = GNUNET_MQ_copy_handlers (handlers);
363 while (NULL != ctx->ports[ctx->port_count])
365 GNUNET_TESTBED_test_run (testname,
373 /* end of cadet_test_lib.c */