79208636f212fed3bf9db2c0f1b7120df5210eb9
[oweals/gnunet.git] / src / dht / dht_test_lib.c
1 /*
2      This file is part of GNUnet.
3      Copyright (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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20 /**
21  * @file dht/dht_test_lib.c
22  * @author Christian Grothoff
23  * @brief library for writing DHT tests
24  */
25 #include "platform.h"
26 #include "dht_test_lib.h"
27
28 /**
29  * Test context for a DHT Test.
30  */
31 struct GNUNET_DHT_TEST_Context
32 {
33   /**
34    * Array of running peers.
35    */
36   struct GNUNET_TESTBED_Peer **peers;
37
38   /**
39    * Array of handles to the DHT for each peer.
40    */
41   struct GNUNET_DHT_Handle **dhts;
42
43   /**
44    * Operation associated with the connection to the DHT.
45    */
46   struct GNUNET_TESTBED_Operation **ops;
47
48   /**
49    * Main function of the test to run once all DHTs are available.
50    */
51   GNUNET_DHT_TEST_AppMain app_main;
52
53   /**
54    * Closure for 'app_main'.
55    */
56   void *app_main_cls;
57
58   /**
59    * Number of peers running, size of the arrays above.
60    */
61   unsigned int num_peers;
62
63 };
64
65
66 /**
67  * Adapter function called to establish a connection to
68  * the DHT service.
69  *
70  * @param cls closure
71  * @param cfg configuration of the peer to connect to; will be available until
72  *          GNUNET_TESTBED_operation_done() is called on the operation returned
73  *          from GNUNET_TESTBED_service_connect()
74  * @return service handle to return in 'op_result', NULL on error
75  */
76 static void *
77 dht_connect_adapter (void *cls,
78                      const struct GNUNET_CONFIGURATION_Handle *cfg)
79 {
80   return GNUNET_DHT_connect (cfg, 16);
81 }
82
83
84 /**
85  * Adapter function called to destroy a connection to
86  * the DHT service.
87  *
88  * @param cls closure
89  * @param op_result service handle returned from the connect adapter
90  */
91 static void
92 dht_disconnect_adapter (void *cls,
93                         void *op_result)
94 {
95   struct GNUNET_DHT_Handle *dht = op_result;
96
97   GNUNET_DHT_disconnect (dht);
98 }
99
100
101 /**
102  * Callback to be called when a service connect operation is completed
103  *
104  * @param cls the callback closure from functions generating an operation
105  * @param op the operation that has been finished
106  * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
107  * @param emsg error message in case the operation has failed; will be NULL if
108  *          operation has executed successfully.
109  */
110 static void
111 dht_connect_cb (void *cls,
112                 struct GNUNET_TESTBED_Operation *op,
113                 void *ca_result,
114                 const char *emsg)
115 {
116   struct GNUNET_DHT_TEST_Context *ctx = cls;
117   unsigned int i;
118
119   if (NULL != emsg)
120   {
121     fprintf (stderr, "Failed to connect to DHT service: %s\n",
122              emsg);
123     GNUNET_SCHEDULER_shutdown ();
124     return;
125   }
126   for (i=0;i<ctx->num_peers;i++)
127     if (op == ctx->ops[i])
128       ctx->dhts[i] = ca_result;
129   for (i=0;i<ctx->num_peers;i++)
130     if (NULL == ctx->dhts[i])
131       return; /* still some DHT connections missing */
132   /* all DHT connections ready! */
133   ctx->app_main (ctx->app_main_cls,
134                  ctx,
135                  ctx->num_peers,
136                  ctx->peers,
137                  ctx->dhts);            
138 }
139
140
141 /**
142  * Clean up the testbed.
143  *
144  * @param ctx handle for the testbed
145  */
146 void
147 GNUNET_DHT_TEST_cleanup (struct GNUNET_DHT_TEST_Context *ctx)
148 {
149   unsigned int i;
150
151   for (i=0;i<ctx->num_peers;i++)
152     GNUNET_TESTBED_operation_done (ctx->ops[i]);
153   GNUNET_free (ctx->ops);
154   GNUNET_free (ctx->dhts);
155   GNUNET_free (ctx);
156   GNUNET_SCHEDULER_shutdown ();
157 }
158
159
160 static void
161 dht_test_run (void *cls,
162              struct GNUNET_TESTBED_RunHandle *h,
163               unsigned int num_peers,
164               struct GNUNET_TESTBED_Peer **peers,
165               unsigned int links_succeeded,
166               unsigned int links_failed)
167 {
168   struct GNUNET_DHT_TEST_Context *ctx = cls;
169   unsigned int i;
170
171   GNUNET_assert (num_peers == ctx->num_peers);
172   ctx->peers = peers;
173   for (i=0;i<num_peers;i++)
174     ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
175                                                   peers[i],
176                                                   "dht",
177                                                   &dht_connect_cb,
178                                                   ctx,
179                                                   &dht_connect_adapter,
180                                                   &dht_disconnect_adapter,
181                                                   ctx);
182 }
183
184
185 /**
186  * Run a test using the given name, configuration file and number of
187  * peers.
188  *
189  * @param testname name of the test (for logging)
190  * @param cfgname name of the configuration file
191  * @param num_peers number of peers to start
192  * @param tmain main function to run once the testbed is ready
193  * @param tmain_cls closure for 'tmain'
194  */
195 void
196 GNUNET_DHT_TEST_run (const char *testname,
197                      const char *cfgname,
198                      unsigned int num_peers,
199                      GNUNET_DHT_TEST_AppMain tmain,
200                      void *tmain_cls)
201 {
202   struct GNUNET_DHT_TEST_Context *ctx;
203
204   ctx = GNUNET_new (struct GNUNET_DHT_TEST_Context);
205   ctx->num_peers = num_peers;
206   ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *));
207   ctx->dhts = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_Handle *));
208   ctx->app_main = tmain;
209   ctx->app_main_cls = tmain_cls;
210   (void) GNUNET_TESTBED_test_run (testname,
211                                   cfgname,
212                                   num_peers,
213                                   0LL, NULL, NULL,
214                                   &dht_test_run, ctx);
215 }
216
217 /* end of dht_test_lib.c */