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);
138 if (NULL == ctx->ports)
140 actx->ports = GNUNET_new_array (ctx->port_count,
141 struct GNUNET_CADET_Port *);
142 for (unsigned int i = 0; i < ctx->port_count; i++)
144 actx->ports[i] = GNUNET_CADET_open_port (h,
147 (void *) (long) actx->peer,
157 * Adapter function called to destroy a connection to
161 * @param op_result service handle returned from the connect adapter
164 cadet_disconnect_adapter (void *cls,
167 struct GNUNET_CADET_Handle *cadet = op_result;
168 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
170 if (NULL != actx->ports)
172 for (unsigned int i = 0; i < actx->ctx->port_count; i++)
174 GNUNET_CADET_close_port (actx->ports[i]);
175 actx->ports[i] = NULL;
177 GNUNET_free (actx->ports);
180 GNUNET_CADET_disconnect (cadet);
185 * Callback to be called when a service connect operation is completed.
187 * @param cls The callback closure from functions generating an operation.
188 * @param op The operation that has been finished.
189 * @param ca_result The service handle returned from
190 * GNUNET_TESTBED_ConnectAdapter() (cadet handle).
191 * @param emsg Error message in case the operation has failed.
192 * NULL if operation has executed successfully.
195 cadet_connect_cb (void *cls,
196 struct GNUNET_TESTBED_Operation *op,
200 struct GNUNET_CADET_TEST_Context *ctx = cls;
205 "Failed to connect to CADET service: %s\n",
207 GNUNET_SCHEDULER_shutdown ();
210 for (unsigned int i = 0; i < ctx->num_peers; i++)
211 if (op == ctx->ops[i])
213 ctx->cadets[i] = ca_result;
214 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
215 "...cadet %u connected\n",
218 for (unsigned int i = 0; i < ctx->num_peers; i++)
219 if (NULL == ctx->cadets[i])
220 return; /* still some CADET connections missing */
221 /* all CADET connections ready! */
222 ctx->app_main (ctx->app_main_cls,
231 GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
233 for (unsigned int i = 0; i < ctx->num_peers; i++)
235 GNUNET_assert (NULL != ctx->ops[i]);
236 GNUNET_TESTBED_operation_done (ctx->ops[i]);
239 GNUNET_free (ctx->ops);
240 GNUNET_free (ctx->cadets);
241 GNUNET_free (ctx->handlers);
243 GNUNET_SCHEDULER_shutdown ();
248 * Callback run when the testbed is ready (peers running and connected to
251 * @param cls Closure (context).
252 * @param h the run handle
253 * @param num_peers Number of peers that are running.
254 * @param peers Handles to each one of the @c num_peers peers.
255 * @param links_succeeded the number of overlay link connection attempts that
257 * @param links_failed the number of overlay link connection attempts that
261 cadet_test_run (void *cls,
262 struct GNUNET_TESTBED_RunHandle *h,
263 unsigned int num_peers,
264 struct GNUNET_TESTBED_Peer **peers,
265 unsigned int links_succeeded,
266 unsigned int links_failed)
268 struct GNUNET_CADET_TEST_Context *ctx = cls;
270 if (0 != links_failed)
272 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
273 "Some links failed (%u), ending\n",
277 if (num_peers != ctx->num_peers)
279 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
280 "Peers started %u/%u, ending\n",
285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
286 "Testbed up, %u peers and %u links\n",
290 for (unsigned int i = 0; i < num_peers; i++)
292 struct GNUNET_CADET_TEST_AdapterContext *newctx;
294 newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
297 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
298 "Connecting to cadet %u\n",
300 ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
305 &cadet_connect_adapter,
306 &cadet_disconnect_adapter,
308 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
316 * Run a test using the given name, configuration file and number of peers.
317 * All cadet callbacks will receive the peer number (long) as the closure.
319 * @param testname Name of the test (for logging).
320 * @param cfgfile Name of the configuration file.
321 * @param num_peers Number of peers to start.
322 * @param tmain Main function to run once the testbed is ready.
323 * @param tmain_cls Closure for @a tmain.
324 * @param connects Handler for incoming channels.
325 * @param window_changes Handler for the window size change notification.
326 * @param disconnects Cleaner for destroyed incoming channels.
327 * @param handlers Message handlers.
328 * @param ports Ports the peers offer, NULL-terminated.
331 GNUNET_CADET_TEST_ruN (const char *testname,
333 unsigned int num_peers,
334 GNUNET_CADET_TEST_AppMain tmain,
336 GNUNET_CADET_ConnectEventHandler connects,
337 GNUNET_CADET_WindowSizeEventHandler window_changes,
338 GNUNET_CADET_DisconnectEventHandler disconnects,
339 struct GNUNET_MQ_MessageHandler *handlers,
340 const struct GNUNET_HashCode **ports)
342 struct GNUNET_CADET_TEST_Context *ctx;
344 ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
345 ctx->num_peers = num_peers;
346 ctx->ops = GNUNET_new_array (num_peers,
347 struct GNUNET_TESTBED_Operation *);
348 ctx->cadets = GNUNET_new_array (num_peers,
349 struct GNUNET_CADET_Handle *);
350 ctx->app_main = tmain;
351 ctx->app_main_cls = tmain_cls;
352 ctx->connects = connects;
353 ctx->window_changes = window_changes;
354 ctx->disconnects = disconnects;
355 ctx->handlers = GNUNET_MQ_copy_handlers (handlers);
358 while (NULL != ctx->ports[ctx->port_count])
360 GNUNET_TESTBED_test_run (testname,
368 /* end of cadet_test_lib.c */