- adapt first test to mesh test lib
[oweals/gnunet.git] / src / mesh / mesh_test_lib.c
1 /*
2      This file is part of GNUnet.
3      (C) 2012 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file mesh/mesh_test_lib.c
22  * @author Bartlomiej Polot
23  * @brief library for writing MESH tests
24  */
25 #include "platform.h"
26 #include "mesh_test_lib.h"
27 #include "gnunet_mesh_service.h"
28
29 /**
30  * Test context for a MESH Test.
31  */
32 struct GNUNET_MESH_TEST_Context
33 {
34   /**
35    * Array of running peers.
36    */
37   struct GNUNET_TESTBED_Peer **peers;
38
39   /**
40    * Array of handles to the MESH for each peer.
41    */
42   struct GNUNET_MESH_Handle **meshes;
43
44   /**
45    * Operation associated with the connection to the MESH.
46    */
47   struct GNUNET_TESTBED_Operation **ops;
48
49   /**
50    * Main function of the test to run once all MESHs are available.
51    */
52   GNUNET_MESH_TEST_AppMain app_main;
53   
54   /**
55    * Closure for 'app_main'.
56    */
57   void *app_main_cls;
58
59   /**
60    * Number of peers running, size of the arrays above.
61    */
62   unsigned int num_peers;
63
64   /**
65    * Handler for incoming tunnels.
66    */
67   GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
68
69   /**
70    * Cleaner for destroyed incoming tunnels.
71    */
72   GNUNET_MESH_TunnelEndHandler *cleaner;
73
74   /**
75    * Message handlers.
76    */
77   struct GNUNET_MESH_MessageHandler* handlers;
78
79   /**
80    * Application types.
81    */
82   const GNUNET_MESH_ApplicationType* stypes;
83
84 };
85
86
87 /**
88  * Context for a mesh adapter callback.
89  */
90 struct GNUNET_MESH_TEST_AdapterContext
91 {
92   /**
93    * Peer number for the particular peer.
94    */
95   unsigned int peer;
96
97   /**
98    * General context.
99    */
100   struct GNUNET_MESH_TEST_Context *ctx;
101 };
102
103
104 /**
105  * Adapter function called to establish a connection to
106  * the MESH service.
107  *
108  * @param cls closure
109  * @param cfg configuration of the peer to connect to; will be available until
110  *          GNUNET_TESTBED_operation_done() is called on the operation returned
111  *          from GNUNET_TESTBED_service_connect()
112  * @return service handle to return in 'op_result', NULL on error
113  */
114 static void *
115 mesh_connect_adapter (void *cls,
116                       const struct GNUNET_CONFIGURATION_Handle *cfg)
117 {
118   struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
119   struct GNUNET_MESH_TEST_Context *ctx = actx->ctx;
120   struct GNUNET_MESH_Handle *h;
121
122   h = GNUNET_MESH_connect (cfg,
123                            (void *) (long) actx->peer,
124                            ctx->new_tunnel,
125                            ctx->cleaner,
126                            ctx->handlers,
127                            ctx->stypes);
128   return h;
129 }
130
131
132 /**
133  * Adapter function called to destroy a connection to
134  * the MESH service.
135  *
136  * @param cls closure
137  * @param op_result service handle returned from the connect adapter
138  */
139 static void 
140 mesh_disconnect_adapter (void *cls,
141                          void *op_result)
142 {
143   struct GNUNET_MESH_Handle *mesh = op_result;
144   struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
145
146   GNUNET_free (actx);
147   GNUNET_MESH_disconnect (mesh);
148 }
149
150
151 /**
152  * Callback to be called when a service connect operation is completed.
153  *
154  * @param cls The callback closure from functions generating an operation.
155  * @param op The operation that has been finished.
156  * @param ca_result The service handle returned from 
157  *                  GNUNET_TESTBED_ConnectAdapter() (mesh handle).
158  * @param emsg Error message in case the operation has failed.
159  *             NULL if operation has executed successfully.
160  */
161 static void 
162 mesh_connect_cb (void *cls,
163                  struct GNUNET_TESTBED_Operation *op,
164                  void *ca_result,
165                  const char *emsg)
166 {
167   struct GNUNET_MESH_TEST_Context *ctx = cls;
168   unsigned int i;
169  
170   if (NULL != emsg)
171   {
172     fprintf (stderr, "Failed to connect to MESH service: %s\n",
173              emsg);
174     GNUNET_SCHEDULER_shutdown ();
175     return;
176   }
177   for (i = 0; i < ctx->num_peers; i++)
178     if (op == ctx->ops[i])
179       ctx->meshes[i] = ca_result;
180   for (i = 0; i < ctx->num_peers; i++)
181     if (NULL == ctx->meshes[i])
182       return; /* still some MESH connections missing */
183   /* all MESH connections ready! */
184   ctx->app_main (ctx->app_main_cls,
185                  ctx,
186                  ctx->num_peers,
187                  ctx->peers,
188                  ctx->meshes);
189 }
190
191
192 /**
193  * Clean up the testbed.
194  *
195  * @param ctx handle for the testbed
196  */
197 void
198 GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx)
199 {
200   unsigned int i;
201
202   for (i = 0; i < ctx->num_peers; i++)
203     GNUNET_TESTBED_operation_done (ctx->ops[i]);
204   GNUNET_free (ctx->ops);
205   GNUNET_free (ctx->meshes);
206   GNUNET_free (ctx);
207   GNUNET_SCHEDULER_shutdown ();
208 }
209
210
211 /**
212  * Callback run when the testbed is ready (peers running and connected to
213  * each other)
214  * 
215  * @param cls Closure (context).
216  * @param num_peers Number of peers that are running.
217  * @param peers Handles to each one of the @c num_peers peers.
218  */
219 static void
220 mesh_test_run (void *cls,
221                unsigned int num_peers,
222                struct GNUNET_TESTBED_Peer **peers)
223 {
224   struct GNUNET_MESH_TEST_Context *ctx = cls;
225   unsigned int i;
226
227   GNUNET_assert (num_peers == ctx->num_peers);
228   ctx->peers = peers;
229   for (i = 0; i < num_peers; i++)
230   {
231     struct GNUNET_MESH_TEST_AdapterContext *newctx;
232     newctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_AdapterContext));
233     newctx->peer = i;
234     newctx->ctx = ctx;
235     ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
236                                                   peers[i],
237                                                   "mesh",
238                                                   &mesh_connect_cb,
239                                                   ctx,
240                                                   &mesh_connect_adapter,
241                                                   &mesh_disconnect_adapter,
242                                                   newctx);
243   }
244 }
245
246
247 /**
248  * Run a test using the given name, configuration file and number of
249  * peers.
250  * All mesh callbacks will receive the peer number as the closure.
251  *
252  * @param testname Name of the test (for logging).
253  * @param cfgname Name of the configuration file.
254  * @param num_peers Number of peers to start.
255  * @param tmain Main function to run once the testbed is ready.
256  * @param tmain_cls Closure for 'tmain'.
257  * @param new_tunnel Handler for incoming tunnels.
258  * @param cleaner Cleaner for destroyed incoming tunnels.
259  * @param handlers Message handlers.
260  * @param stypes Application types.
261  */
262 void 
263 GNUNET_MESH_TEST_run (const char *testname,
264                       const char *cfgname,
265                       unsigned int num_peers,
266                       GNUNET_MESH_TEST_AppMain tmain,
267                       void *tmain_cls,
268                       GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
269                       GNUNET_MESH_TunnelEndHandler cleaner,
270                       struct GNUNET_MESH_MessageHandler* handlers,
271                       const GNUNET_MESH_ApplicationType* stypes)
272 {
273   struct GNUNET_MESH_TEST_Context *ctx;
274   
275   ctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_Context));
276   ctx->num_peers = num_peers;
277   ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *));
278   ctx->meshes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_MESH_Handle *));
279   ctx->app_main = tmain;
280   ctx->app_main_cls = tmain_cls;
281   ctx->new_tunnel = new_tunnel;
282   ctx->cleaner = cleaner;
283   ctx->handlers = handlers;
284   ctx->stypes = stypes;
285   GNUNET_TESTBED_test_run (testname,
286                            cfgname,
287                            num_peers,
288                            0LL, NULL, NULL,
289                            &mesh_test_run, ctx);
290 }
291
292 /* end of mesh_test_lib.c */