improving datastore API
[oweals/gnunet.git] / src / datastore / test_datastore_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2004, 2005, 2006, 2007 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
26 #include "platform.h"
27 #include "gnunet_util.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_sqstore_service.h"
30 #include "core.h"
31
32 #define ASSERT(x) do { if (! (x)) { printf("Error at %s:%d\n", __FILE__, __LINE__); goto FAILURE;} } while (0)
33
34 static GNUNET_CronTime now;
35
36 static GNUNET_DatastoreValue *
37 initValue (int i)
38 {
39   GNUNET_DatastoreValue *value;
40
41   value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + 8 * i);
42   value->size = htonl (sizeof (GNUNET_DatastoreValue) + 8 * i);
43   value->type = htonl (i);
44   value->priority = htonl (i + 1);
45   value->anonymity_level = htonl (i);
46   value->expiration_time = GNUNET_htonll (now - i * GNUNET_CRON_SECONDS);
47   memset (&value[1], i, 8 * i);
48   return value;
49 }
50
51 static int
52 checkValue (const GNUNET_HashCode * key,
53             const GNUNET_DatastoreValue * val, void *closure,
54             unsigned long long uid)
55 {
56   int i;
57   int ret;
58   GNUNET_DatastoreValue *value;
59
60   i = *(int *) closure;
61   value = initValue (i);
62   if ((value->size == val->size) &&
63       (0 == memcmp (val, value, ntohl (val->size))))
64     ret = GNUNET_OK;
65   else
66     {
67       /*
68          printf("Wanted: %u, %llu; got %u, %llu - %d\n",
69          ntohl(value->size), GNUNET_ntohll(value->expiration_time),
70          ntohl(val->size), GNUNET_ntohll(val->expiration_time),
71          memcmp(val, value, ntohl(val->size))); */
72       ret = GNUNET_SYSERR;
73     }
74   GNUNET_free (value);
75   return ret;
76 }
77
78 static int
79 iterateUp (const GNUNET_HashCode * key, const GNUNET_DatastoreValue * val,
80            int *closure, unsigned long long uid)
81 {
82   int ret;
83
84   ret = checkValue (key, val, closure, uid);
85   (*closure) += 2;
86   return ret;
87 }
88
89 static int
90 iterateDown (const GNUNET_HashCode * key,
91              const GNUNET_DatastoreValue * val, int *closure,
92              unsigned long long uid)
93 {
94   int ret;
95
96   (*closure) -= 2;
97   ret = checkValue (key, val, closure, uid);
98   return ret;
99 }
100
101 static int
102 iterateDelete (const GNUNET_HashCode * key,
103                const GNUNET_DatastoreValue * val, void *closure,
104                unsigned long long uid)
105 {
106   return GNUNET_NO;
107 }
108
109 static int
110 iteratePriority (const GNUNET_HashCode * key,
111                  const GNUNET_DatastoreValue * val,
112                  GNUNET_SQstore_ServiceAPI * api, unsigned long long uid)
113 {
114   api->update (uid, 4, 0);
115   return GNUNET_OK;
116 }
117
118 static int
119 priorityCheck (const GNUNET_HashCode * key,
120                const GNUNET_DatastoreValue * val, int *closure,
121                unsigned long long uid)
122 {
123   int id;
124
125   id = (*closure);
126   if (id + 1 == ntohl (val->priority))
127     return GNUNET_OK;
128   fprintf (stderr,
129            "Wrong priority, wanted %u got %u\n", id + 1,
130            ntohl (val->priority));
131   return GNUNET_SYSERR;
132 }
133
134 static int
135 multipleCheck (const GNUNET_HashCode * key,
136                const GNUNET_DatastoreValue * val,
137                GNUNET_DatastoreValue ** last, unsigned long long uid)
138 {
139   if (*last != NULL)
140     {
141       if (((*last)->size == val->size) &&
142           (0 == memcmp (*last, val, ntohl (val->size))))
143         return GNUNET_SYSERR;   /* duplicate! */
144       GNUNET_free (*last);
145     }
146   *last = GNUNET_malloc (ntohl (val->size));
147   memcpy (*last, val, ntohl (val->size));
148   return GNUNET_OK;
149 }
150
151
152 /**
153  * Add testcode here!
154  */
155 static int
156 test (GNUNET_SQstore_ServiceAPI * api)
157 {
158   GNUNET_DatastoreValue *value;
159   GNUNET_HashCode key;
160   unsigned long long oldSize;
161   int i;
162
163   now = 1000000;
164   oldSize = api->getSize ();
165   for (i = 0; i < 256; i++)
166     {
167       value = initValue (i);
168       memset (&key, 256 - i, sizeof (GNUNET_HashCode));
169       ASSERT (GNUNET_OK == api->put (&key, value));
170       GNUNET_free (value);
171     }
172   ASSERT (oldSize < api->getSize ());
173   for (i = 255; i >= 0; i--)
174     {
175       memset (&key, 256 - i, sizeof (GNUNET_HashCode));
176       ASSERT (1 == api->get (&key, NULL, i, &checkValue, (void *) &i));
177     }
178   ASSERT (256 ==
179           api->iterateLowPriority (GNUNET_ECRS_BLOCKTYPE_ANY, NULL, NULL));
180   ASSERT (256 ==
181           api->iterateExpirationTime (GNUNET_ECRS_BLOCKTYPE_ANY, NULL, NULL));
182   for (i = 255; i >= 0; i--)
183     {
184       memset (&key, 256 - i, sizeof (GNUNET_HashCode));
185       ASSERT (1 == api->get (&key, NULL, i, &checkValue, (void *) &i));
186     }
187
188   oldSize = api->getSize ();
189   for (i = 255; i >= 0; i -= 2)
190     {
191       memset (&key, 256 - i, sizeof (GNUNET_HashCode));
192       value = initValue (i);
193       if (1 != api->get (&key, NULL, 0, &iterateDelete, NULL))
194         {
195           GNUNET_free (value);
196           ASSERT (0);
197         }
198       GNUNET_free (value);
199     }
200   ASSERT (oldSize > api->getSize ());
201   i = 0;
202   ASSERT (128 == api->iterateLowPriority (GNUNET_ECRS_BLOCKTYPE_ANY,
203                                           (GNUNET_DatastoreValueIterator) &
204                                           iterateUp, &i));
205   ASSERT (256 == i);
206   ASSERT (128 == api->iterateExpirationTime (GNUNET_ECRS_BLOCKTYPE_ANY,
207                                              (GNUNET_DatastoreValueIterator) &
208                                              iterateDown, &i));
209   ASSERT (0 == i);
210   ASSERT (128 == api->iterateExpirationTime (GNUNET_ECRS_BLOCKTYPE_ANY,
211                                              (GNUNET_DatastoreValueIterator) &
212                                              iterateDelete, api));
213   i = 0;
214   ASSERT (0 ==
215           api->iterateExpirationTime (GNUNET_ECRS_BLOCKTYPE_ANY,
216                                       (GNUNET_DatastoreValueIterator) &
217                                       iterateDown, &i));
218   i = 42;
219   value = initValue (i);
220   memset (&key, 256 - i, sizeof (GNUNET_HashCode));
221   api->put (&key, value);
222   ASSERT (1 == api->iterateExpirationTime (GNUNET_ECRS_BLOCKTYPE_ANY,
223                                            (GNUNET_DatastoreValueIterator) &
224                                            priorityCheck, &i));
225   ASSERT (1 == api->iterateExpirationTime (GNUNET_ECRS_BLOCKTYPE_ANY,
226                                            (GNUNET_DatastoreValueIterator) &
227                                            priorityCheck, &i));
228   ASSERT (1 ==
229           api->iterateAllNow ((GNUNET_DatastoreValueIterator) &
230                               iteratePriority, api));
231   i += 4;
232   ASSERT (1 == api->iterateExpirationTime (GNUNET_ECRS_BLOCKTYPE_ANY,
233                                            (GNUNET_DatastoreValueIterator) &
234                                            priorityCheck, &i));
235   GNUNET_free (value);
236
237   /* test multiple results */
238   value = initValue (i + 1);
239   api->put (&key, value);
240   GNUNET_free (value);
241
242   value = NULL;
243   ASSERT (2 == api->iterateExpirationTime (GNUNET_ECRS_BLOCKTYPE_ANY,
244                                            (GNUNET_DatastoreValueIterator) &
245                                            multipleCheck, &value));
246   GNUNET_free (value);
247   ASSERT (2 ==
248           api->iterateAllNow ((GNUNET_DatastoreValueIterator) & iterateDelete,
249                               api));
250   ASSERT (0 ==
251           api->iterateExpirationTime (GNUNET_ECRS_BLOCKTYPE_ANY, NULL, NULL));
252   api->drop ();
253
254   return GNUNET_OK;
255
256 FAILURE:
257   api->drop ();
258   return GNUNET_SYSERR;
259 }
260
261 int
262 main (int argc, char *argv[])
263 {
264   GNUNET_SQstore_ServiceAPI *api;
265   int ok;
266   struct GNUNET_GC_Configuration *cfg;
267   struct GNUNET_CronManager *cron;
268
269   cfg = GNUNET_GC_create ();
270   if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
271     {
272       GNUNET_GC_free (cfg);
273       return -1;
274     }
275   cron = GNUNET_cron_create (NULL);
276   GNUNET_CORE_init (NULL, cfg, cron, NULL);
277   api = GNUNET_CORE_request_service ("sqstore");
278   if (api != NULL)
279     {
280       ok = test (api);
281       GNUNET_CORE_release_service (api);
282     }
283   else
284     ok = GNUNET_SYSERR;
285   GNUNET_CORE_done ();
286   GNUNET_cron_destroy (cron);
287   GNUNET_GC_free (cfg);
288   if (ok == GNUNET_SYSERR)
289     return 1;
290   return 0;
291 }
292
293 /* end of test_datastore_api.c */