convert sqlite peerstore to using libgnunetsq
[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
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.
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      General Public License for more details.
14
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.
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   unsigned int i;
139
140   h = GNUNET_CADET_connect (cfg);
141   if (NULL == ctx->ports)
142     return h;
143
144   actx->ports = GNUNET_new_array (ctx->port_count, struct GNUNET_CADET_Port *);
145   for (i = 0; i < ctx->port_count; i++)
146   {
147     actx->ports[i] = GNUNET_CADET_open_port (h,
148                                              ctx->ports[i],
149                                              ctx->connects,
150                                              (void *) (long) actx->peer,
151                                              ctx->window_changes,
152                                              ctx->disconnects,
153                                              ctx->handlers);
154   }
155   return h;
156 }
157
158
159 /**
160  * Adapter function called to destroy a connection to
161  * the CADET service.
162  *
163  * @param cls closure
164  * @param op_result service handle returned from the connect adapter
165  */
166 static void
167 cadet_disconnect_adapter (void *cls,
168                          void *op_result)
169 {
170   struct GNUNET_CADET_Handle *cadet = op_result;
171   struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
172
173   if (NULL != actx->ports)
174   {
175     for (int i = 0; i < actx->ctx->port_count; i++)
176     {
177       GNUNET_CADET_close_port (actx->ports[i]);
178       actx->ports[i] = NULL;
179     }
180     GNUNET_free (actx->ports);
181   }
182   GNUNET_free (actx);
183   GNUNET_CADET_disconnect (cadet);
184 }
185
186
187 /**
188  * Callback to be called when a service connect operation is completed.
189  *
190  * @param cls The callback closure from functions generating an operation.
191  * @param op The operation that has been finished.
192  * @param ca_result The service handle returned from
193  *                  GNUNET_TESTBED_ConnectAdapter() (cadet handle).
194  * @param emsg Error message in case the operation has failed.
195  *             NULL if operation has executed successfully.
196  */
197 static void
198 cadet_connect_cb (void *cls,
199                  struct GNUNET_TESTBED_Operation *op,
200                  void *ca_result,
201                  const char *emsg)
202 {
203   struct GNUNET_CADET_TEST_Context *ctx = cls;
204   unsigned int i;
205
206   if (NULL != emsg)
207   {
208     fprintf (stderr, "Failed to connect to CADET service: %s\n",
209              emsg);
210     GNUNET_SCHEDULER_shutdown ();
211     return;
212   }
213   for (i = 0; i < ctx->num_peers; i++)
214     if (op == ctx->ops[i])
215     {
216       ctx->cadets[i] = ca_result;
217       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i);
218     }
219   for (i = 0; i < ctx->num_peers; i++)
220     if (NULL == ctx->cadets[i])
221       return; /* still some CADET connections missing */
222   /* all CADET connections ready! */
223   ctx->app_main (ctx->app_main_cls,
224                  ctx,
225                  ctx->num_peers,
226                  ctx->peers,
227                  ctx->cadets);
228 }
229
230
231 void
232 GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
233 {
234   unsigned int i;
235
236   for (i = 0; i < ctx->num_peers; i++)
237   {
238     GNUNET_assert (NULL != ctx->ops[i]);
239     GNUNET_TESTBED_operation_done (ctx->ops[i]);
240     ctx->ops[i] = NULL;
241   }
242   GNUNET_free (ctx->ops);
243   GNUNET_free (ctx->cadets);
244   GNUNET_free (ctx);
245   GNUNET_SCHEDULER_shutdown ();
246 }
247
248
249 /**
250  * Callback run when the testbed is ready (peers running and connected to
251  * each other)
252  *
253  * @param cls Closure (context).
254  * @param h the run handle
255  * @param num_peers Number of peers that are running.
256  * @param peers Handles to each one of the @c num_peers peers.
257  * @param links_succeeded the number of overlay link connection attempts that
258  *          succeeded
259  * @param links_failed the number of overlay link connection attempts that
260  *          failed
261  */
262 static void
263 cadet_test_run (void *cls,
264                struct GNUNET_TESTBED_RunHandle *h,
265                unsigned int num_peers,
266                struct GNUNET_TESTBED_Peer **peers,
267                unsigned int links_succeeded,
268                unsigned int links_failed)
269 {
270   struct GNUNET_CADET_TEST_Context *ctx = cls;
271   unsigned int i;
272
273   if (0 != links_failed)
274   {
275     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Some links failed (%u), ending\n",
276                 links_failed);
277     exit (2);
278   }
279
280   if  (num_peers != ctx->num_peers)
281   {
282     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n",
283                 num_peers, ctx->num_peers);
284     exit (1);
285   }
286
287   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
288               "Testbed up, %u peers and %u links\n",
289               num_peers, links_succeeded);
290   ctx->peers = peers;
291   for (i = 0; i < num_peers; i++)
292   {
293     struct GNUNET_CADET_TEST_AdapterContext *newctx;
294     newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
295     newctx->peer = i;
296     newctx->ctx = ctx;
297     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to cadet %u\n", i);
298     ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
299                                                   peers[i],
300                                                   "cadet",
301                                                   &cadet_connect_cb,
302                                                   ctx,
303                                                   &cadet_connect_adapter,
304                                                   &cadet_disconnect_adapter,
305                                                   newctx);
306     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "op handle %p\n", ctx->ops[i]);
307   }
308 }
309
310
311 /**
312  * Run a test using the given name, configuration file and number of peers.
313  * All cadet callbacks will receive the peer number (long) as the closure.
314  *
315  * @param testname Name of the test (for logging).
316  * @param cfgfile Name of the configuration file.
317  * @param num_peers Number of peers to start.
318  * @param tmain Main function to run once the testbed is ready.
319  * @param tmain_cls Closure for @a tmain.
320  * @param connects Handler for incoming channels.
321  * @param window_changes Handler for the window size change notification.
322  * @param disconnects Cleaner for destroyed incoming channels.
323  * @param handlers Message handlers.
324  * @param ports Ports the peers offer, NULL-terminated.
325  */
326 void
327 GNUNET_CADET_TEST_ruN (const char *testname,
328                        const char *cfgfile,
329                        unsigned int num_peers,
330                        GNUNET_CADET_TEST_AppMain tmain,
331                        void *tmain_cls,
332                        GNUNET_CADET_ConnectEventHandler connects,
333                        GNUNET_CADET_WindowSizeEventHandler window_changes,
334                        GNUNET_CADET_DisconnectEventHandler disconnects,
335                        struct GNUNET_MQ_MessageHandler *handlers,
336                        const struct GNUNET_HashCode **ports)
337 {
338   struct GNUNET_CADET_TEST_Context *ctx;
339
340   ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
341   ctx->num_peers = num_peers;
342   ctx->ops = GNUNET_new_array (num_peers, struct GNUNET_TESTBED_Operation *);
343   ctx->cadets = GNUNET_new_array (num_peers, struct GNUNET_CADET_Handle *);
344   ctx->app_main = tmain;
345   ctx->app_main_cls = tmain_cls;
346   ctx->connects = connects;
347   ctx->window_changes = window_changes;
348   ctx->disconnects = disconnects;
349   ctx->handlers = GNUNET_MQ_copy_handlers (handlers);
350   ctx->ports = ports;
351   ctx->port_count = 0;
352   while (NULL != ctx->ports[ctx->port_count])
353     ctx->port_count++;
354
355   GNUNET_TESTBED_test_run (testname,
356                            cfgfile,
357                            num_peers,
358                            0LL, NULL, NULL,
359                            &cadet_test_run, ctx);
360 }
361
362 /* end of cadet_test_lib.c */