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