fixed broken api calls in test; fixed broken protocol
[oweals/gnunet.git] / src / cadet / cadet_test_lib.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012, 2017 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 cadet/cadet_test_lib.c
22  * @author Bartlomiej Polot
23  * @brief library for writing CADET tests
24  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "cadet_test_lib.h"
28 #include "gnunet_cadet_service.h"
29
30
31 /**
32  * Test context for a CADET Test.
33  */
34 struct GNUNET_CADET_TEST_Context
35 {
36   /**
37    * Array of running peers.
38    */
39   struct GNUNET_TESTBED_Peer **peers;
40
41   /**
42    * Array of handles to the CADET for each peer.
43    */
44   struct GNUNET_CADET_Handle **cadets;
45
46   /**
47    * Operation associated with the connection to the CADET.
48    */
49   struct GNUNET_TESTBED_Operation **ops;
50
51   /**
52    * Number of peers running, size of the arrays above.
53    */
54   unsigned int num_peers;
55
56   /**
57    * Main function of the test to run once all CADETs are available.
58    */
59   GNUNET_CADET_TEST_AppMain app_main;
60
61   /**
62    * Closure for 'app_main'.
63    */
64   void *app_main_cls;
65
66   /**
67    * Handler for incoming tunnels.
68    */
69   GNUNET_CADET_ConnectEventHandler connects;
70
71   /**
72    * Function called when the transmit window size changes.
73    */
74   GNUNET_CADET_WindowSizeEventHandler window_changes;
75
76   /**
77    * Cleaner for destroyed incoming tunnels.
78    */
79   GNUNET_CADET_DisconnectEventHandler disconnects;
80
81   /**
82    * Message handlers.
83    */
84   struct GNUNET_MQ_MessageHandler *handlers;
85
86   /**
87    * Application ports.
88    */
89   const struct GNUNET_HashCode **ports;
90
91   /**
92    * Number of ports in #ports.
93    */
94   unsigned int port_count;
95
96 };
97
98
99 /**
100  * Context for a cadet adapter callback.
101  */
102 struct GNUNET_CADET_TEST_AdapterContext
103 {
104   /**
105    * Peer number for the particular peer.
106    */
107   unsigned int peer;
108
109   /**
110    * Port handlers for open ports.
111    */
112   struct GNUNET_CADET_Port **ports;
113
114   /**
115    * General context.
116    */
117   struct GNUNET_CADET_TEST_Context *ctx;
118 };
119
120
121 /**
122  * Adapter function called to establish a connection to
123  * the CADET service.
124  *
125  * @param cls closure
126  * @param cfg configuration of the peer to connect to; will be available until
127  *          GNUNET_TESTBED_operation_done() is called on the operation returned
128  *          from GNUNET_TESTBED_service_connect()
129  * @return service handle to return in 'op_result', NULL on error
130  */
131 static void *
132 cadet_connect_adapter (void *cls,
133                        const struct GNUNET_CONFIGURATION_Handle *cfg)
134 {
135   struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
136   struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
137   struct GNUNET_CADET_Handle *h;
138
139   h = GNUNET_CADET_connect (cfg);
140   if (NULL == h)
141   {
142     GNUNET_break(0);
143     return NULL;
144   }
145   if (NULL == ctx->ports)
146     return h;
147   actx->ports = GNUNET_new_array (ctx->port_count,
148                                   struct GNUNET_CADET_Port *);
149   for (unsigned int i = 0; i < ctx->port_count; i++)
150   {
151     actx->ports[i] = GNUNET_CADET_open_port (h,
152                                              ctx->ports[i],
153                                              ctx->connects,
154                                              (void *) (long) actx->peer,
155                                              ctx->window_changes,
156                                              ctx->disconnects,
157                                              ctx->handlers);
158   }
159   return h;
160 }
161
162
163 /**
164  * Adapter function called to destroy a connection to
165  * the CADET service.
166  *
167  * @param cls closure
168  * @param op_result service handle returned from the connect adapter
169  */
170 static void
171 cadet_disconnect_adapter (void *cls,
172                           void *op_result)
173 {
174   struct GNUNET_CADET_Handle *cadet = op_result;
175   struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
176
177   if (NULL != actx->ports)
178   {
179     for (unsigned int i = 0; i < actx->ctx->port_count; i++)
180     {
181       GNUNET_CADET_close_port (actx->ports[i]);
182       actx->ports[i] = NULL;
183     }
184     GNUNET_free (actx->ports);
185   }
186   GNUNET_free (actx);
187   GNUNET_CADET_disconnect (cadet);
188 }
189
190
191 /**
192  * Callback to be called when a service connect operation is completed.
193  *
194  * @param cls The callback closure from functions generating an operation.
195  * @param op The operation that has been finished.
196  * @param ca_result The service handle returned from
197  *                  GNUNET_TESTBED_ConnectAdapter() (cadet handle).
198  * @param emsg Error message in case the operation has failed.
199  *             NULL if operation has executed successfully.
200  */
201 static void
202 cadet_connect_cb (void *cls,
203                  struct GNUNET_TESTBED_Operation *op,
204                  void *ca_result,
205                  const char *emsg)
206 {
207   struct GNUNET_CADET_TEST_Context *ctx = cls;
208
209   if (NULL != emsg)
210   {
211     fprintf (stderr,
212              "Failed to connect to CADET service: %s\n",
213              emsg);
214     GNUNET_SCHEDULER_shutdown ();
215     return;
216   }
217   for (unsigned int i = 0; i < ctx->num_peers; i++)
218     if (op == ctx->ops[i])
219     {
220       ctx->cadets[i] = ca_result;
221       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
222                   "...cadet %u connected\n",
223                   i);
224     }
225   for (unsigned int i = 0; i < ctx->num_peers; i++)
226     if (NULL == ctx->cadets[i])
227       return; /* still some CADET connections missing */
228   /* all CADET connections ready! */
229   ctx->app_main (ctx->app_main_cls,
230                  ctx,
231                  ctx->num_peers,
232                  ctx->peers,
233                  ctx->cadets);
234 }
235
236
237 void
238 GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
239 {
240   for (unsigned int i = 0; i < ctx->num_peers; i++)
241   {
242     GNUNET_assert (NULL != ctx->ops[i]);
243     GNUNET_TESTBED_operation_done (ctx->ops[i]);
244     ctx->ops[i] = NULL;
245   }
246   GNUNET_free (ctx->ops);
247   GNUNET_free (ctx->cadets);
248   GNUNET_free (ctx->handlers);
249   GNUNET_free (ctx);
250   GNUNET_SCHEDULER_shutdown ();
251 }
252
253
254 /**
255  * Callback run when the testbed is ready (peers running and connected to
256  * each other)
257  *
258  * @param cls Closure (context).
259  * @param h the run handle
260  * @param num_peers Number of peers that are running.
261  * @param peers Handles to each one of the @c num_peers peers.
262  * @param links_succeeded the number of overlay link connection attempts that
263  *          succeeded
264  * @param links_failed the number of overlay link connection attempts that
265  *          failed
266  */
267 static void
268 cadet_test_run (void *cls,
269                struct GNUNET_TESTBED_RunHandle *h,
270                unsigned int num_peers,
271                struct GNUNET_TESTBED_Peer **peers,
272                unsigned int links_succeeded,
273                unsigned int links_failed)
274 {
275   struct GNUNET_CADET_TEST_Context *ctx = cls;
276
277   if (0 != links_failed)
278   {
279     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
280                 "Some links failed (%u), ending\n",
281                 links_failed);
282     exit (77);
283   }
284   if  (num_peers != ctx->num_peers)
285   {
286     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
287                 "Peers started %u/%u, ending\n",
288                 num_peers,
289                 ctx->num_peers);
290     exit (1);
291   }
292   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
293               "Testbed up, %u peers and %u links\n",
294               num_peers,
295               links_succeeded);
296   ctx->peers = peers;
297   for (unsigned int i = 0; i < num_peers; i++)
298   {
299     struct GNUNET_CADET_TEST_AdapterContext *newctx;
300
301     newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
302     newctx->peer = i;
303     newctx->ctx = ctx;
304     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
305                 "Connecting to cadet %u\n",
306                 i);
307     ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
308                                                   peers[i],
309                                                   "cadet",
310                                                   &cadet_connect_cb,
311                                                   ctx,
312                                                   &cadet_connect_adapter,
313                                                   &cadet_disconnect_adapter,
314                                                   newctx);
315     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
316                 "op handle %p\n",
317                 ctx->ops[i]);
318   }
319 }
320
321
322 /**
323  * Run a test using the given name, configuration file and number of peers.
324  * All cadet callbacks will receive the peer number (long) as the closure.
325  *
326  * @param testname Name of the test (for logging).
327  * @param cfgfile Name of the configuration file.
328  * @param num_peers Number of peers to start.
329  * @param tmain Main function to run once the testbed is ready.
330  * @param tmain_cls Closure for @a tmain.
331  * @param connects Handler for incoming channels.
332  * @param window_changes Handler for the window size change notification.
333  * @param disconnects Cleaner for destroyed incoming channels.
334  * @param handlers Message handlers.
335  * @param ports Ports the peers offer, NULL-terminated.
336  */
337 void
338 GNUNET_CADET_TEST_ruN (const char *testname,
339                        const char *cfgfile,
340                        unsigned int num_peers,
341                        GNUNET_CADET_TEST_AppMain tmain,
342                        void *tmain_cls,
343                        GNUNET_CADET_ConnectEventHandler connects,
344                        GNUNET_CADET_WindowSizeEventHandler window_changes,
345                        GNUNET_CADET_DisconnectEventHandler disconnects,
346                        struct GNUNET_MQ_MessageHandler *handlers,
347                        const struct GNUNET_HashCode **ports)
348 {
349   struct GNUNET_CADET_TEST_Context *ctx;
350
351   ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
352   ctx->num_peers = num_peers;
353   ctx->ops = GNUNET_new_array (num_peers,
354                                struct GNUNET_TESTBED_Operation *);
355   ctx->cadets = GNUNET_new_array (num_peers,
356                                   struct GNUNET_CADET_Handle *);
357   ctx->app_main = tmain;
358   ctx->app_main_cls = tmain_cls;
359   ctx->connects = connects;
360   ctx->window_changes = window_changes;
361   ctx->disconnects = disconnects;
362   ctx->handlers = GNUNET_MQ_copy_handlers (handlers);
363   ctx->ports = ports;
364   ctx->port_count = 0;
365   while (NULL != ctx->ports[ctx->port_count])
366     ctx->port_count++;
367   GNUNET_TESTBED_test_run (testname,
368                            cfgfile,
369                            num_peers,
370                            0LL, NULL, NULL,
371                            &cadet_test_run,
372                            ctx);
373 }
374
375 /* end of cadet_test_lib.c */