paragraph for gnunet devs that don't know how to use the web
[oweals/gnunet.git] / src / datastore / test_datastore_api_management.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2004, 2005, 2006, 2007, 2009, 2011 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 datastore/test_datastore_api_management.c
20  * @brief Test for the space management functions of the datastore implementation.
21  * @author Christian Grothoff
22  */
23 #include "platform.h"
24 #include "gnunet_util_lib.h"
25 #include "gnunet_protocols.h"
26 #include "gnunet_datastore_service.h"
27 #include "gnunet_datastore_plugin.h"
28 #include "gnunet_testing_lib.h"
29
30
31 /**
32  * How long until we give up on transmitting the message?
33  */
34 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
35
36 /**
37  * Number of iterations to run; must be large enough
38  * so that the quota will be exceeded!
39  */
40 #define ITERATIONS 5000
41
42 enum RunPhase
43 {
44   RP_PUT,
45   RP_GET,
46   RP_DONE,
47   RP_GET_FAIL
48 };
49
50
51 struct CpsRunContext
52 {
53   struct GNUNET_HashCode key;
54   int i;
55   int found;
56   const struct GNUNET_CONFIGURATION_Handle *cfg;
57   void *data;
58   enum RunPhase phase;
59 };
60
61
62 static struct GNUNET_DATASTORE_Handle *datastore;
63
64 static struct GNUNET_TIME_Absolute now;
65
66 static int ok;
67
68 static const char *plugin_name;
69
70
71 static size_t
72 get_size (int i)
73 {
74   return 8 + 8 * (i % 256);
75 }
76
77
78 static const void *
79 get_data (int i)
80 {
81   static char buf[60000];
82
83   memset (buf, i, 8 + 8 * (i % 256));
84   return buf;
85 }
86
87
88 static int
89 get_type (int i)
90 {
91   return 1;
92 }
93
94
95 static int
96 get_priority (int i)
97 {
98   return i + 1;
99 }
100
101
102 static int
103 get_anonymity (int i)
104 {
105   return i;
106 }
107
108
109 static struct GNUNET_TIME_Absolute
110 get_expiration (int i)
111 {
112   struct GNUNET_TIME_Absolute av;
113
114   av.abs_value_us = now.abs_value_us + i * 1000 * 1000LL;
115   return av;
116 }
117
118
119 static void
120 run_continuation (void *cls);
121
122
123 static void
124 check_success (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg)
125 {
126   struct CpsRunContext *crc = cls;
127
128   if (GNUNET_OK != success)
129     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", msg);
130   GNUNET_assert (GNUNET_OK == success);
131   GNUNET_free_non_null (crc->data);
132   crc->data = NULL;
133   GNUNET_SCHEDULER_add_now (&run_continuation, crc);
134 }
135
136
137 static void
138 check_value (void *cls,
139              const struct GNUNET_HashCode *key,
140              size_t size,
141              const void *data,
142              enum GNUNET_BLOCK_Type type,
143              uint32_t priority,
144              uint32_t anonymity,
145              uint32_t replication,
146              struct GNUNET_TIME_Absolute expiration,
147              uint64_t uid)
148 {
149   struct CpsRunContext *crc = cls;
150   int i;
151
152   if (NULL == key)
153   {
154     crc->phase = RP_GET_FAIL;
155     GNUNET_SCHEDULER_add_now (&run_continuation, crc);
156     return;
157   }
158   i = crc->i;
159   GNUNET_assert (size == get_size (i));
160   GNUNET_assert (0 == memcmp (data, get_data (i), size));
161   GNUNET_assert (type == get_type (i));
162   GNUNET_assert (priority == get_priority (i));
163   GNUNET_assert (anonymity == get_anonymity (i));
164   GNUNET_assert (expiration.abs_value_us == get_expiration (i).abs_value_us);
165   crc->i--;
166   if (crc->i == 0)
167     crc->phase = RP_DONE;
168   GNUNET_SCHEDULER_add_now (&run_continuation, crc);
169 }
170
171
172 static void
173 check_nothing (void *cls,
174                const struct GNUNET_HashCode *key,
175                size_t size,
176                const void *data,
177                enum GNUNET_BLOCK_Type type,
178                uint32_t priority,
179                uint32_t anonymity,
180                uint32_t replication,
181                struct GNUNET_TIME_Absolute expiration,
182                uint64_t uid)
183 {
184   struct CpsRunContext *crc = cls;
185
186   GNUNET_assert (key == NULL);
187   if (0 == --crc->i)
188     crc->phase = RP_DONE;
189   GNUNET_SCHEDULER_add_now (&run_continuation, crc);
190 }
191
192
193 static void
194 run_continuation (void *cls)
195 {
196   struct CpsRunContext *crc = cls;
197
198   ok = (int) crc->phase;
199   switch (crc->phase)
200   {
201   case RP_PUT:
202     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "PUT",
203                 crc->i);
204     GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
205     GNUNET_DATASTORE_put (datastore,
206                           0,
207                           &crc->key,
208                           get_size (crc->i),
209                           get_data (crc->i),
210                           get_type (crc->i),
211                           get_priority (crc->i),
212                           get_anonymity (crc->i),
213                           0,
214                           get_expiration (crc->i),
215                           1,
216                           1,
217                           &check_success, crc);
218     crc->i++;
219     if (crc->i == ITERATIONS)
220     {
221       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
222                   "Sleeping to give datastore time to clean up\n");
223       sleep (1);
224       crc->phase = RP_GET;
225       crc->i--;
226     }
227     break;
228   case RP_GET:
229     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "GET",
230                 crc->i);
231     GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
232     GNUNET_DATASTORE_get_key (datastore,
233                               0,
234                               false,
235                               &crc->key,
236                               get_type (crc->i),
237                               1,
238                               1,
239                               &check_value,
240                               crc);
241     break;
242   case RP_GET_FAIL:
243     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "GET(f)",
244                 crc->i);
245     GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
246     GNUNET_DATASTORE_get_key (datastore,
247                               0,
248                               false,
249                               &crc->key,
250                               get_type (crc->i),
251                               1,
252                               1,
253                               &check_nothing,
254                               crc);
255     break;
256   case RP_DONE:
257     GNUNET_assert (0 == crc->i);
258     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished, disconnecting\n");
259     GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES);
260     GNUNET_free (crc);
261     ok = 0;
262   }
263 }
264
265
266 static void
267 run_tests (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg)
268 {
269   struct CpsRunContext *crc = cls;
270
271   if (success != GNUNET_YES)
272   {
273     FPRINTF (stderr,
274              "Test 'put' operation failed with error `%s' database likely not setup, skipping test.\n",
275              msg);
276     GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES);
277     GNUNET_free (crc);
278     return;
279   }
280   GNUNET_SCHEDULER_add_now (&run_continuation, crc);
281 }
282
283
284 static void
285 run (void *cls,
286      const struct GNUNET_CONFIGURATION_Handle *cfg,
287      struct GNUNET_TESTING_Peer *peer)
288 {
289   struct CpsRunContext *crc;
290   static struct GNUNET_HashCode zkey;
291
292   crc = GNUNET_new (struct CpsRunContext);
293   crc->cfg = cfg;
294   crc->phase = RP_PUT;
295   now = GNUNET_TIME_absolute_get ();
296   datastore = GNUNET_DATASTORE_connect (cfg);
297   if (NULL ==
298       GNUNET_DATASTORE_put (datastore,
299                             0,
300                             &zkey,
301                             4,
302                             "TEST",
303                             GNUNET_BLOCK_TYPE_TEST,
304                             0, 0, 0,
305                             GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_SECONDS),
306                             0,
307                             1,
308                             &run_tests,
309                             crc))
310   {
311     FPRINTF (stderr, "%s",  "Test 'put' operation failed.\n");
312     GNUNET_free (crc);
313     ok = 1;
314   }
315 }
316
317
318 /**
319  * Function called when disk utilization changes, does nothing.
320  *
321  * @param cls closure
322  * @param delta change in utilization
323  */
324 static void
325 ignore_payload_cb (void *cls,
326                    int delta)
327 {
328   /* do nothing */
329 }
330
331
332 /**
333  * check if plugin is actually working
334  */
335 static int
336 test_plugin (const char *cfg_name)
337 {
338   char libname[128];
339   struct GNUNET_CONFIGURATION_Handle *cfg;
340   struct GNUNET_DATASTORE_PluginFunctions *api;
341   struct GNUNET_DATASTORE_PluginEnvironment env;
342
343   cfg = GNUNET_CONFIGURATION_create ();
344   if (GNUNET_OK !=
345       GNUNET_CONFIGURATION_load (cfg,
346                                  cfg_name))
347   {
348     GNUNET_CONFIGURATION_destroy (cfg);
349     fprintf (stderr,
350              "Failed to load configuration %s\n",
351              cfg_name);
352     return 1;
353   }
354   memset (&env, 0, sizeof (env));
355   env.cfg = cfg;
356   env.duc = &ignore_payload_cb;
357   GNUNET_snprintf (libname,
358                    sizeof (libname),
359                    "libgnunet_plugin_datastore_%s",
360                    plugin_name);
361   api = GNUNET_PLUGIN_load (libname, &env);
362   if (NULL == api)
363   {
364     GNUNET_CONFIGURATION_destroy (cfg);
365     fprintf (stderr,
366              "Failed to load plugin `%s'\n",
367              libname);
368     return 77;
369   }
370   GNUNET_PLUGIN_unload (libname, api);
371   GNUNET_CONFIGURATION_destroy (cfg);
372   return 0;
373 }
374
375
376 int
377 main (int argc, char *argv[])
378 {
379   char cfg_name[128];
380   int ret;
381
382   plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
383   GNUNET_snprintf (cfg_name,
384                    sizeof (cfg_name),
385                    "test_datastore_api_data_%s.conf",
386                    plugin_name);
387   ret = test_plugin (cfg_name);
388   if (0 != ret)
389     return ret;
390   if (0 !=
391       GNUNET_TESTING_peer_run ("test-gnunet-datastore-management",
392                                cfg_name,
393                                &run,
394                                NULL))
395     return 1;
396   return ok;
397 }
398
399 /* end of test_datastore_api_management.c */