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