bugfixes
[oweals/gnunet.git] / src / datastore / test_datastore_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2004, 2005, 2006, 2007, 2009 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 2, 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 datastore/test_datastore_api.c
22  * @brief Test for the datastore implementation.
23  * @author Christian Grothoff
24  *
25  * TODO:
26  * - test multiple values under same key
27  * - test "update"
28  * - test storage reservations
29  */
30
31 #include "platform.h"
32 #include "gnunet_util_lib.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_datastore_service.h"
35
36 #define VERBOSE GNUNET_YES
37
38 /**
39  * How long until we give up on transmitting the message?
40  */
41 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
42
43 #define ITERATIONS 256
44
45 static struct GNUNET_DATASTORE_Handle *datastore;
46
47 static struct GNUNET_TIME_Absolute now;
48
49 static int ok;
50
51
52 static size_t
53 get_size (int i)
54 {
55   return 8 * i;
56 }
57
58
59 static const void *
60 get_data (int i)
61 {
62   static char buf[60000]; 
63   memset (buf, i, 8 * i);
64   return buf;
65 }
66
67
68 static int
69 get_type(int i)
70 {
71   return i+1;
72 }
73
74
75 static int 
76 get_priority (int i)
77 {
78   return i+1;
79 }
80
81
82 static int
83 get_anonymity(int i)
84 {
85   return i;
86 }
87
88
89 static struct GNUNET_TIME_Absolute 
90 get_expiration (int i)
91 {
92   struct GNUNET_TIME_Absolute av;
93
94   av.value = now.value - i * 1000;
95   return av;
96 }
97
98 enum RunPhase
99   {
100     RP_DONE = 0,
101     RP_PUT,
102     RP_GET,
103     RP_DEL,
104     RP_DELVALIDATE
105   };
106
107
108 struct CpsRunContext
109 {
110   GNUNET_HashCode key;
111   int i;
112   int *iptr;
113   struct GNUNET_SCHEDULER_Handle *sched;
114   struct GNUNET_CONFIGURATION_Handle *cfg;
115   enum RunPhase phase;
116 };
117
118
119 static void
120 run_continuation (void *cls,
121                   const struct GNUNET_SCHEDULER_TaskContext *tc);
122
123
124 static void
125 check_success (void *cls,
126                int success,
127                const char *msg)
128 {
129   struct CpsRunContext *crc = cls;
130   if (GNUNET_OK != success)
131     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
132                 "%s\n", msg);
133   GNUNET_assert (GNUNET_OK == success);
134   GNUNET_SCHEDULER_add_continuation (crc->sched,
135                                      GNUNET_NO,
136                                      &run_continuation,
137                                      crc,
138                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
139 }
140
141
142 static void
143 check_failure (void *cls,
144                int success,
145                const char *msg)
146 {
147   struct CpsRunContext *crc = cls;
148   GNUNET_assert (GNUNET_OK != success);
149   GNUNET_assert (NULL != msg);
150   GNUNET_SCHEDULER_add_continuation (crc->sched,
151                                      GNUNET_NO,
152                                      &run_continuation,
153                                      crc,
154                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
155 }
156
157
158 static void 
159 check_value (void *cls,
160              const GNUNET_HashCode * key,
161              uint32_t size,
162              const void *data,
163              uint32_t type,
164              uint32_t priority,
165              uint32_t anonymity,
166              struct GNUNET_TIME_Absolute
167              expiration, uint64_t uid)
168 {
169   struct CpsRunContext *crc = cls;
170   int i;
171
172   if (key == NULL)
173     return;
174   i = crc->i;
175   GNUNET_assert (size == get_size (i));
176   GNUNET_assert (0 == memcmp (data, get_data(i), size));
177   GNUNET_assert (type == get_type (i));
178   GNUNET_assert (priority == get_priority (i));
179   GNUNET_assert (anonymity == get_anonymity(i));
180   GNUNET_assert (expiration.value == get_expiration(i).value);
181   GNUNET_SCHEDULER_add_continuation (crc->sched,
182                                      GNUNET_NO,
183                                      &run_continuation,
184                                      crc,
185                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
186 }
187
188
189 static void 
190 delete_value (void *cls,
191              const GNUNET_HashCode * key,
192              uint32_t size,
193              const void *data,
194              uint32_t type,
195              uint32_t priority,
196              uint32_t anonymity,
197              struct GNUNET_TIME_Absolute
198              expiration, uint64_t uid)
199 {
200   struct CpsRunContext *crc = cls;
201   if (key == NULL)
202     return;
203   GNUNET_DATASTORE_remove (datastore,
204                            key,
205                            size,
206                            data,
207                            &check_success,
208                            NULL,
209                            TIMEOUT);
210   ((int*)key)[0]++;
211   GNUNET_DATASTORE_remove (datastore,
212                            key,
213                            size,
214                            data,
215                            &check_failure,
216                            NULL,
217                            TIMEOUT);
218   GNUNET_SCHEDULER_add_continuation (crc->sched,
219                                      GNUNET_NO,
220                                      &run_continuation,
221                                      crc,
222                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
223 }
224
225
226
227 static void 
228 check_nothing (void *cls,
229              const GNUNET_HashCode * key,
230              uint32_t size,
231              const void *data,
232              uint32_t type,
233              uint32_t priority,
234              uint32_t anonymity,
235              struct GNUNET_TIME_Absolute
236              expiration, uint64_t uid)
237 {
238   struct CpsRunContext *crc = cls;
239   GNUNET_assert (key == NULL);
240   GNUNET_SCHEDULER_add_continuation (crc->sched,
241                                      GNUNET_NO,
242                                      &run_continuation,
243                                      crc,
244                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
245 }
246
247
248 static void
249 run_continuation (void *cls,
250                   const struct GNUNET_SCHEDULER_TaskContext *tc)
251 {
252   struct CpsRunContext *crc = cls;
253   ok = (int) crc->phase;
254   switch (crc->phase)
255     {
256     case RP_PUT:
257 #if VERBOSE
258       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
259                   "Executing `%s' number %u\n",
260                   "PUT",
261                   crc->i);
262 #endif
263       memset (&crc->key, ITERATIONS - crc->i, sizeof (GNUNET_HashCode));
264       GNUNET_DATASTORE_put (datastore,
265                             0,
266                             &crc->key,
267                             get_size (crc->i),
268                             get_data (crc->i),
269                             get_type (crc->i),
270                             get_priority (crc->i),
271                             get_anonymity (crc->i),
272                             get_expiration (crc->i),
273                             TIMEOUT,
274                             &check_success,
275                             crc);
276       crc->i++;
277       if (crc->i == ITERATIONS)
278         crc->phase = RP_GET;
279       break;
280     case RP_GET:
281       crc->i--;
282 #if VERBOSE
283       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
284                   "Executing `%s' number %u\n",
285                   "GET",
286                   crc->i);
287 #endif
288       memset (&crc->key, ITERATIONS - crc->i, sizeof (GNUNET_HashCode));
289       GNUNET_DATASTORE_get (datastore, 
290                             &crc->key,
291                             get_type (crc->i),
292                             &check_value,
293                             crc,
294                             TIMEOUT);
295       if (crc->i == 0)
296         {
297           crc->phase = RP_DEL;
298           crc->i = ITERATIONS;
299         }
300       break;
301     case RP_DEL:
302       crc->i--;
303 #if VERBOSE
304       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
305                   "Executing `%s' number %u\n",
306                   "DEL",
307                   crc->i);
308 #endif
309       memset (&crc->key, ITERATIONS - crc->i, sizeof (GNUNET_HashCode));
310       GNUNET_DATASTORE_get (datastore, 
311                             &crc->key,
312                             get_type (crc->i),
313                             &delete_value,
314                             crc,
315                             TIMEOUT);
316       if (crc->i == 0)
317         {
318           crc->phase = RP_DELVALIDATE;
319           crc->i = ITERATIONS;   
320         }
321       break;
322     case RP_DELVALIDATE:
323       crc->i--;
324 #if VERBOSE
325       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
326                   "Executing `%s' number %u\n",
327                   "DEL-VALIDATE",
328                   crc->i);
329 #endif
330       memset (&crc->key, ITERATIONS - crc->i, sizeof (GNUNET_HashCode));
331       GNUNET_DATASTORE_get (datastore, 
332                             &crc->key,
333                             get_type (crc->i),
334                             &check_nothing,
335                             crc,
336                             TIMEOUT);
337       if (crc->i == 0)
338         {
339           crc->phase = RP_DONE;   
340         }
341       break;
342   /* check reservations */
343   /* check update */
344   /* test multiple results */
345     case RP_DONE:
346 #if VERBOSE
347       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
348                   "Finished, disconnecting\n");
349 #endif
350       GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES);
351       ok = 0;
352     }
353 }
354
355
356 static void
357 run (void *cls,
358      struct GNUNET_SCHEDULER_Handle *sched,
359      char *const *args,
360      const char *cfgfile, struct GNUNET_CONFIGURATION_Handle *cfg)
361 {
362   struct CpsRunContext *crc;
363
364   crc = GNUNET_malloc(sizeof(struct CpsRunContext));
365   crc->sched = sched;
366   crc->cfg = cfg;
367   crc->phase = RP_PUT;
368   now.value = 1000000;
369   datastore = GNUNET_DATASTORE_connect (cfg, sched);
370   GNUNET_SCHEDULER_add_continuation (crc->sched,
371                                      GNUNET_NO,
372                                      &run_continuation,
373                                      crc,
374                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
375
376 }
377
378
379
380 static int
381 check ()
382 {
383   pid_t pid;
384   char *const argv[] = { "test-datastore-api",
385     "-c",
386     "test_datastore_api_data.conf",
387 #if VERBOSE
388     "-L", "DEBUG",
389 #endif
390     NULL
391   };
392   struct GNUNET_GETOPT_CommandLineOption options[] = {
393     GNUNET_GETOPT_OPTION_END
394   };
395   pid = GNUNET_OS_start_process ("gnunet-service-datastore",
396                                  "gnunet-service-datastore",
397 #if VERBOSE
398                                  "-L", "DEBUG",
399 #endif
400                                  "-c", "test_datastore_api_data.conf", NULL);
401   sleep (1);
402   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
403                       argv, "test-datastore-api", "nohelp",
404                       options, &run, NULL);
405   if (0 != PLIBC_KILL (pid, SIGTERM))
406     {
407       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
408       ok = 1;
409     }
410   GNUNET_OS_process_wait(pid);
411   if (ok != 0)
412     fprintf (stderr, "Missed some testcases: %u\n", ok);
413   return ok;
414 }
415
416 int
417 main (int argc, char *argv[])
418 {
419   int ret;
420
421   GNUNET_log_setup ("test-datastore-api",
422 #if VERBOSE
423                     "DEBUG",
424 #else
425                     "WARNING",
426 #endif
427                     NULL);
428   ret = check ();
429
430   return ret;
431 }
432
433
434
435 /* end of test_datastore_api.c */