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