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