psycstore
[oweals/gnunet.git] / src / namestore / test_namestore_api_zone_iteration_specific_zone.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013 GNUnet e.V.
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 3, 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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20 /**
21  * @file namestore/test_namestore_api_zone_iteration_specific_zone.c
22  * @brief testcase for zone iteration functionality: iterate over a specific zone
23  * @author Matthias Wachs
24  */
25 #include "platform.h"
26 #include "gnunet_namestore_service.h"
27 #include "gnunet_testing_lib.h"
28 #include "namestore.h"
29
30
31 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
32
33
34 static struct GNUNET_NAMESTORE_Handle * nsh;
35
36 static struct GNUNET_SCHEDULER_Task * endbadly_task;
37
38 static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey;
39
40 static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey2;
41
42 static struct GNUNET_NAMESTORE_ZoneIterator *zi;
43
44 static int res;
45
46 static int returned_records;
47
48 static char * s_name_1;
49
50 static struct GNUNET_GNSRECORD_Data *s_rd_1;
51
52 static char * s_name_2;
53
54 static struct GNUNET_GNSRECORD_Data *s_rd_2;
55
56 static char * s_name_3;
57
58 static struct GNUNET_GNSRECORD_Data *s_rd_3;
59
60 static char *directory;
61
62 /**
63  * Re-establish the connection to the service.
64  *
65  * @param cls handle to use to re-connect.
66  * @param tc scheduler context
67  */
68 static void
69 endbadly (void *cls)
70 {
71   if (NULL != zi)
72   {
73     GNUNET_NAMESTORE_zone_iteration_stop (zi);
74     zi = NULL;
75   }
76   if (nsh != NULL)
77     GNUNET_NAMESTORE_disconnect (nsh);
78   nsh = NULL;
79
80   GNUNET_free_non_null(s_name_1);
81   GNUNET_free_non_null(s_name_2);
82   GNUNET_free_non_null(s_name_3);
83
84   if (s_rd_1 != NULL)
85   {
86     GNUNET_free ((void *)s_rd_1->data);
87     GNUNET_free (s_rd_1);
88   }
89   if (s_rd_2 != NULL)
90   {
91     GNUNET_free ((void *)s_rd_2->data);
92     GNUNET_free (s_rd_2);
93   }
94   if (s_rd_3 != NULL)
95   {
96     GNUNET_free ((void *)s_rd_3->data);
97     GNUNET_free (s_rd_3);
98   }
99
100   if (privkey != NULL)
101     GNUNET_free (privkey);
102   privkey = NULL;
103
104   if (privkey2 != NULL)
105     GNUNET_free (privkey2);
106   privkey2 = NULL;
107   res = 1;
108 }
109
110
111 static void
112 end (void *cls)
113 {
114   if (NULL != zi)
115   {
116     GNUNET_NAMESTORE_zone_iteration_stop (zi);
117     zi = NULL;
118   }
119
120   if (endbadly_task != NULL)
121   {
122     GNUNET_SCHEDULER_cancel (endbadly_task);
123     endbadly_task = NULL;
124   }
125
126   if (privkey != NULL)
127     GNUNET_free (privkey);
128   privkey = NULL;
129
130   if (privkey2 != NULL)
131     GNUNET_free (privkey2);
132   privkey2 = NULL;
133
134   GNUNET_free (s_name_1);
135   GNUNET_free (s_name_2);
136   GNUNET_free (s_name_3);
137   if (s_rd_1 != NULL)
138   {
139     GNUNET_free ((void *)s_rd_1->data);
140     GNUNET_free (s_rd_1);
141   }
142   if (s_rd_2 != NULL)
143   {
144     GNUNET_free ((void *)s_rd_2->data);
145     GNUNET_free (s_rd_2);
146   }
147   if (s_rd_3 != NULL)
148   {
149     GNUNET_free ((void *)s_rd_3->data);
150     GNUNET_free (s_rd_3);
151   }
152   if (nsh != NULL)
153     GNUNET_NAMESTORE_disconnect (nsh);
154   nsh = NULL;
155 }
156
157
158 static void
159 fail_cb (void *cls)
160 {
161   GNUNET_assert (0);
162 }
163
164
165 static void
166 zone_proc (void *cls,
167            const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
168            const char *label,
169            unsigned int rd_count,
170            const struct GNUNET_GNSRECORD_Data *rd)
171 {
172   int failed = GNUNET_NO;
173
174   GNUNET_assert (NULL != zone);
175   if (0 == memcmp (zone,
176                    privkey,
177                    sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
178   {
179     if (0 == strcmp (label, s_name_1))
180     {
181       if (rd_count == 1)
182       {
183         if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1))
184         {
185           failed = GNUNET_YES;
186           GNUNET_break (0);
187         }
188       }
189       else
190       {
191         failed = GNUNET_YES;
192         GNUNET_break (0);
193       }
194     }
195     else if (0 == strcmp (label, s_name_2))
196     {
197       if (rd_count == 1)
198       {
199         if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_2))
200         {
201           failed = GNUNET_YES;
202           GNUNET_break (0);
203         }
204       }
205       else
206       {
207         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
208                     "Received invalid record count\n");
209         failed = GNUNET_YES;
210         GNUNET_break (0);
211       }
212     }
213     else
214     {
215       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
216                   "Comparing result failed: got name `%s' for first zone\n",
217                   label);
218       failed = GNUNET_YES;
219       GNUNET_break (0);
220     }
221   }
222   else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
223   {
224     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225                 "Received data for not requested zone\n");
226     failed = GNUNET_YES;
227     GNUNET_break (0);
228   }
229   else
230   {
231     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232                 "Received invalid zone\n");
233     failed = GNUNET_YES;
234     GNUNET_break (0);
235   }
236   if (failed == GNUNET_NO)
237   {
238     returned_records ++;
239     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
240                 "Telling namestore to send the next result\n");
241     GNUNET_NAMESTORE_zone_iterator_next (zi);
242   }
243   else
244   {
245     GNUNET_break (0);
246     GNUNET_SCHEDULER_add_now (&end, NULL);
247   }
248 }
249
250
251 static void
252 zone_proc_end (void *cls)
253 {
254   GNUNET_break (2 == returned_records);
255   if (2 == returned_records)
256   {
257     res = 0; /* Last iteraterator callback, we are done */
258     zi = NULL;
259   }
260   else
261     res = 1;
262
263   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
264               "Received last result, iteration done after receing %u results\n",
265               returned_records);
266   GNUNET_SCHEDULER_add_now (&end, NULL);
267 }
268
269
270 static void
271 put_cont (void *cls, int32_t success, const char *emsg)
272 {
273   static int c = 0;
274
275   if (success == GNUNET_OK)
276   {
277     c++;
278     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
279                 "Created record %u \n", c);
280   }
281   else
282   {
283     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
284                 "Failed to created records: `%s'\n",
285                 emsg);
286     GNUNET_break (0);
287     if (NULL != endbadly_task)
288         GNUNET_SCHEDULER_cancel (endbadly_task);
289     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
290     return;
291   }
292
293   if (c == 3)
294   {
295     res = 1;
296     returned_records = 0;
297     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
298                 "All records created, starting iteration over all zones \n");
299     zi = GNUNET_NAMESTORE_zone_iteration_start(nsh,
300                                                privkey,
301                                                &fail_cb,
302                                                NULL,
303                                                &zone_proc,
304                                                NULL,
305                                                &zone_proc_end,
306                                                NULL);
307     if (zi == NULL)
308     {
309       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
310                   "Failed to create zone iterator\n");
311       GNUNET_break (0);
312       if (NULL != endbadly_task)
313         GNUNET_SCHEDULER_cancel (endbadly_task);
314       endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
315       return;
316     }
317   }
318 }
319
320
321 static struct GNUNET_GNSRECORD_Data *
322 create_record (unsigned int count)
323 {
324   unsigned int c;
325   struct GNUNET_GNSRECORD_Data * rd;
326
327   rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data));
328   for (c = 0; c < count; c++)
329   {
330     rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us;
331     rd[c].record_type = 1111;
332     rd[c].data_size = 50;
333     rd[c].data = GNUNET_malloc(50);
334     rd[c].flags = 0;
335     memset ((char *) rd[c].data, 'a', 50);
336   }
337   return rd;
338 }
339
340
341 /**
342  * Callback called from the zone iterator when we iterate over
343  * the empty zone.  Check that we got no records and then
344  * start the actual tests by filling the zone.
345  */
346 static void
347 empty_zone_proc (void *cls,
348                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
349                  const char *label,
350                  unsigned int rd_count,
351                  const struct GNUNET_GNSRECORD_Data *rd)
352 {
353   GNUNET_assert (nsh == cls);
354   if (NULL != zone)
355   {
356     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
357                 _("Expected empty zone but received zone private key\n"));
358     GNUNET_break (0);
359     if (endbadly_task != NULL)
360       GNUNET_SCHEDULER_cancel (endbadly_task);
361     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
362     return;
363   }
364   if ((NULL != label) || (NULL != rd) || (0 != rd_count))
365   {
366     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
367                 _("Expected no zone content but received data\n"));
368     GNUNET_break (0);
369     if (endbadly_task != NULL)
370       GNUNET_SCHEDULER_cancel (endbadly_task);
371     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
372     return;
373   }
374   GNUNET_assert (0);
375 }
376
377
378 static void
379 empty_zone_proc_end (void *cls)
380 {
381   char *hostkey_file;
382
383   zi = NULL;
384   GNUNET_asprintf (&hostkey_file,
385                    "zonefiles%s%s",
386                    DIR_SEPARATOR_STR,
387                    "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey");
388   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
389               "Using zonekey file `%s'\n",
390               hostkey_file);
391   privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file);
392   GNUNET_free (hostkey_file);
393   GNUNET_assert (privkey != NULL);
394
395   GNUNET_asprintf(&hostkey_file,
396                   "zonefiles%s%s",
397                   DIR_SEPARATOR_STR,
398                   "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey");
399   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
400               "Using zonekey file `%s' \n",
401               hostkey_file);
402   privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file);
403   GNUNET_free (hostkey_file);
404   GNUNET_assert (privkey2 != NULL);
405
406   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
407               "Created record 1\n");
408
409   GNUNET_asprintf(&s_name_1, "dummy1");
410   s_rd_1 = create_record (1);
411   GNUNET_NAMESTORE_records_store (nsh,
412                                   privkey,
413                                   s_name_1,
414                                   1,
415                                   s_rd_1,
416                                   &put_cont,
417                                   NULL);
418
419   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
420               "Created record 2 \n");
421   GNUNET_asprintf(&s_name_2, "dummy2");
422   s_rd_2 = create_record (1);
423   GNUNET_NAMESTORE_records_store (nsh,
424                                   privkey,
425                                   s_name_2,
426                                   1,
427                                   s_rd_2,
428                                   &put_cont,
429                                   NULL);
430
431   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
432               "Created record 3\n");
433
434   /* name in different zone */
435   GNUNET_asprintf(&s_name_3, "dummy3");
436   s_rd_3 = create_record (1);
437   GNUNET_NAMESTORE_records_store (nsh,
438                                   privkey2,
439                                   s_name_3,
440                                   1, s_rd_3,
441                                   &put_cont,
442                                   NULL);
443 }
444
445
446 static void
447 run (void *cls,
448      const struct GNUNET_CONFIGURATION_Handle *cfg,
449      struct GNUNET_TESTING_Peer *peer)
450 {
451   directory = NULL;
452   GNUNET_assert (GNUNET_OK ==
453                  GNUNET_CONFIGURATION_get_value_string (cfg,
454                                                         "PATHS",
455                                                         "GNUNET_TEST_HOME",
456                                                         &directory));
457   GNUNET_DISK_directory_remove (directory);
458
459   endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
460                                                 &endbadly,
461                                                 NULL);
462   nsh = GNUNET_NAMESTORE_connect (cfg);
463   GNUNET_break (NULL != nsh);
464   /* first, iterate over empty namestore */
465   zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
466                                               NULL,
467                                               &fail_cb,
468                                               NULL,
469                                               &empty_zone_proc,
470                                               nsh,
471                                               &empty_zone_proc_end,
472                                               nsh);
473   if (NULL == zi)
474   {
475     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
476                 "Failed to create zone iterator\n");
477     GNUNET_break (0);
478     GNUNET_SCHEDULER_cancel (endbadly_task);
479     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
480   }
481 }
482
483
484 int
485 main (int argc, char *argv[])
486 {
487   res = 1;
488   if (0 !=
489       GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration",
490                                "test_namestore_api.conf",
491                                &run,
492                                NULL))
493   {
494     res = 1;
495   }
496   if (NULL != directory)
497   {
498       GNUNET_DISK_directory_remove (directory);
499       GNUNET_free (directory);
500   }
501   return res;
502 }
503
504 /* end of test_namestore_api_zone_iteration_specific_zone.c */