glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / namestore / test_namestore_api_zone_iteration_nick.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 it
6      under the terms of the GNU Affero 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: iterate all 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 ZONE_NICK_1 "nick1"
28 #define ZONE_NICK_2 "nick2"
29
30 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
31
32
33 static struct GNUNET_NAMESTORE_Handle * nsh;
34
35 static struct GNUNET_SCHEDULER_Task * endbadly_task;
36
37 static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey;
38
39 static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey2;
40
41 static struct GNUNET_NAMESTORE_ZoneIterator *zi;
42
43 static int res;
44
45 static int returned_records;
46
47 static char * s_name_1;
48
49 static struct GNUNET_GNSRECORD_Data *s_rd_1;
50
51 static char * s_name_2;
52
53 static struct GNUNET_GNSRECORD_Data *s_rd_2;
54
55 static char * s_name_3;
56
57 static struct GNUNET_GNSRECORD_Data *s_rd_3;
58
59 static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
60
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   {
78     GNUNET_NAMESTORE_disconnect (nsh);
79     nsh = NULL;
80   }
81   GNUNET_free_non_null(s_name_1);
82   GNUNET_free_non_null(s_name_2);
83   GNUNET_free_non_null(s_name_3);
84
85   if (s_rd_1 != NULL)
86   {
87     GNUNET_free ((void *)s_rd_1->data);
88     GNUNET_free (s_rd_1);
89   }
90   if (s_rd_2 != NULL)
91   {
92     GNUNET_free ((void *)s_rd_2->data);
93     GNUNET_free (s_rd_2);
94   }
95   if (s_rd_3 != NULL)
96   {
97     GNUNET_free ((void *)s_rd_3->data);
98     GNUNET_free (s_rd_3);
99   }
100
101   if (privkey != NULL)
102     GNUNET_free (privkey);
103   privkey = NULL;
104
105   if (privkey2 != NULL)
106     GNUNET_free (privkey2);
107   privkey2 = NULL;
108   res = 1;
109 }
110
111
112 static void
113 end (void *cls)
114 {
115   if (NULL != zi)
116   {
117     GNUNET_NAMESTORE_zone_iteration_stop (zi);
118     zi = NULL;
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 int
159 check_zone_1 (const char *label, unsigned int rd_count,
160     const struct GNUNET_GNSRECORD_Data *rd)
161 {
162   int failed = GNUNET_NO;
163   int c;
164   for (c = 0; c< rd_count ; c++)
165   {
166     if (rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK)
167         if (0 != strcmp (rd[c].data, ZONE_NICK_1))
168         {
169           GNUNET_break (0);
170           return GNUNET_YES;
171         }
172   }
173   return failed;
174 }
175
176 static int
177 check_zone_2 (const char *label,
178            unsigned int rd_count,
179            const struct GNUNET_GNSRECORD_Data *rd)
180 {
181   int failed = GNUNET_NO;
182   int c;
183
184   for (c = 0; c< rd_count ; c++)
185   {
186     if (rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK)
187         if (0 != strcmp (rd[c].data, ZONE_NICK_2))
188         {
189           GNUNET_break (0);
190           return GNUNET_YES;
191         }
192   }
193
194   return failed;
195 }
196
197
198 static void
199 zone_proc_end (void *cls)
200 {
201   zi = NULL;
202   res = 0;
203   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
204               "Received last result, iteration done after receing %u results\n",
205               returned_records);
206   GNUNET_SCHEDULER_add_now (&end, NULL);
207 }
208
209
210 static void
211 zone_proc (void *cls,
212            const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
213            const char *label,
214            unsigned int rd_count,
215            const struct GNUNET_GNSRECORD_Data *rd)
216 {
217   int failed = GNUNET_NO;
218
219   GNUNET_assert (NULL != zone);
220   if (0 == memcmp (zone, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
221   {
222     failed = check_zone_1 (label, rd_count, rd);
223     if (GNUNET_YES == failed)
224       GNUNET_break (0);
225   }
226   else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
227   {
228     failed = check_zone_2 (label, rd_count, rd);
229     if (GNUNET_YES == failed)
230       GNUNET_break (0);
231   }
232   else
233   {
234     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
235                 "Received invalid zone\n");
236     failed = GNUNET_YES;
237     GNUNET_break (0);
238   }
239
240   if (failed == GNUNET_NO)
241   {
242     returned_records ++;
243     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
244                 "Telling namestore to send the next result\n");
245     GNUNET_NAMESTORE_zone_iterator_next (zi,
246                                          1);
247   }
248   else
249   {
250     GNUNET_break (0);
251     res = 1;
252     GNUNET_SCHEDULER_add_now (&end, NULL);
253   }
254 }
255
256
257 static void
258 fail_cb (void *cls)
259 {
260   GNUNET_assert (0);
261 }
262
263
264 static void
265 put_cont (void *cls,
266           int32_t success,
267           const char *emsg)
268 {
269   static int c = 0;
270
271   if (success == GNUNET_OK)
272   {
273     c++;
274     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c);
275   }
276   else
277   {
278     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n",
279                 emsg);
280     GNUNET_break (0);
281     if (NULL != endbadly_task)
282         GNUNET_SCHEDULER_cancel (endbadly_task);
283     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
284     return;
285   }
286
287   if (c == 3)
288   {
289     res = 1;
290     returned_records = 0;
291     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over all zones \n");
292     zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
293                                                 NULL,
294                                                 &fail_cb,
295                                                 NULL,
296                                                 &zone_proc,
297                                                 NULL,
298                                                 &zone_proc_end,
299                                                 NULL);
300     if (zi == NULL)
301     {
302       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n");
303       GNUNET_break (0);
304       if (NULL != endbadly_task)
305         GNUNET_SCHEDULER_cancel (endbadly_task);
306       endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
307       return;
308     }
309   }
310 }
311
312
313 static struct GNUNET_GNSRECORD_Data *
314 create_record (unsigned int count)
315 {
316   struct GNUNET_GNSRECORD_Data * rd;
317
318   rd = GNUNET_new_array (count,
319                          struct GNUNET_GNSRECORD_Data);
320   for (unsigned int c = 0; c < count; c++)
321   {
322     rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us;
323     rd[c].record_type = TEST_RECORD_TYPE;
324     rd[c].data_size = 50;
325     rd[c].data = GNUNET_malloc(50);
326     rd[c].flags = 0;
327     memset ((char *) rd[c].data, 'a', 50);
328   }
329   return rd;
330 }
331
332
333 static void
334 nick_2_cont (void *cls,
335              int32_t success,
336              const char *emsg)
337 {
338   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
339               "Nick added : %s\n",
340               (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
341
342   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n");
343
344   GNUNET_asprintf(&s_name_1, "dummy1");
345   s_rd_1 = create_record(1);
346   GNUNET_NAMESTORE_records_store (nsh, privkey, s_name_1,
347                                   1, s_rd_1,
348                                   &put_cont, NULL);
349
350   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
351               "Created record 2 \n");
352   GNUNET_asprintf(&s_name_2, "dummy2");
353   s_rd_2 = create_record(1);
354   GNUNET_NAMESTORE_records_store (nsh, privkey, s_name_2,
355                                   1, s_rd_2, &put_cont, NULL);
356
357   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
358               "Created record 3\n");
359
360   /* name in different zone */
361   GNUNET_asprintf(&s_name_3, "dummy3");
362   s_rd_3 = create_record(1);
363   GNUNET_NAMESTORE_records_store (nsh, privkey2, s_name_3,
364                                   1, s_rd_3,
365                                   &put_cont, NULL);
366 }
367
368
369 static void
370 nick_1_cont (void *cls, int32_t success, const char *emsg)
371 {
372   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
373               "Nick 1 added : %s\n",
374               (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
375
376   nsqe = GNUNET_NAMESTORE_set_nick (nsh, privkey2, ZONE_NICK_2, &nick_2_cont, &privkey2);
377   if (NULL == nsqe)
378   {
379     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
380               _("Namestore cannot store no block\n"));
381   }
382 }
383
384
385 /**
386  * Callback called from the zone iterator when we iterate over
387  * the empty zone.  Check that we got no records and then
388  * start the actual tests by filling the zone.
389  */
390 static void
391 empty_zone_proc (void *cls,
392                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
393                  const char *label,
394                  unsigned int rd_count,
395                  const struct GNUNET_GNSRECORD_Data *rd)
396 {
397   GNUNET_assert (nsh == cls);
398
399   if (NULL != zone)
400   {
401     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
402                 _("Expected empty zone but received zone private key\n"));
403     GNUNET_break (0);
404     if (endbadly_task != NULL)
405       GNUNET_SCHEDULER_cancel (endbadly_task);
406     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
407     return;
408   }
409   if ((NULL != label) || (NULL != rd) || (0 != rd_count))
410   {
411     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
412                 _("Expected no zone content but received data\n"));
413     GNUNET_break (0);
414     if (endbadly_task != NULL)
415       GNUNET_SCHEDULER_cancel (endbadly_task);
416     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
417     return;
418   }
419   GNUNET_assert (0);
420 }
421
422
423 static void
424 empty_zone_end (void *cls)
425 {
426   GNUNET_assert (nsh == cls);
427   zi = NULL;
428   privkey = GNUNET_CRYPTO_ecdsa_key_create ();
429   GNUNET_assert (privkey != NULL);
430   privkey2 = GNUNET_CRYPTO_ecdsa_key_create ();
431   GNUNET_assert (privkey2 != NULL);
432
433   nsqe = GNUNET_NAMESTORE_set_nick (nsh,
434                                     privkey,
435                                     ZONE_NICK_1,
436                                     &nick_1_cont,
437                                     &privkey);
438   if (NULL == nsqe)
439   {
440     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
441               _("Namestore cannot store no block\n"));
442   }
443
444 }
445
446
447 static void
448 run (void *cls,
449      const struct GNUNET_CONFIGURATION_Handle *cfg,
450      struct GNUNET_TESTING_Peer *peer)
451 {
452   endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
453                                                 &endbadly,
454                                                 NULL);
455   nsh = GNUNET_NAMESTORE_connect (cfg);
456   GNUNET_break (NULL != nsh);
457
458   /* first, iterate over empty namestore */
459   zi = GNUNET_NAMESTORE_zone_iteration_start(nsh,
460                                              NULL,
461                                              &fail_cb,
462                                              NULL,
463                                              &empty_zone_proc,
464                                              nsh,
465                                              &empty_zone_end,
466                                              nsh);
467   if (NULL == zi)
468   {
469     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
470                 "Failed to create zone iterator\n");
471     GNUNET_break (0);
472     GNUNET_SCHEDULER_cancel (endbadly_task);
473     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
474   }
475 }
476
477
478 int
479 main (int argc, char *argv[])
480 {
481   const char *plugin_name;
482   char *cfg_name;
483
484   plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
485   GNUNET_asprintf (&cfg_name,
486                    "test_namestore_api_%s.conf",
487                    plugin_name);
488   res = 1;
489   GNUNET_DISK_purge_cfg_dir (cfg_name,
490                              "GNUNET_TEST_HOME");
491   if (0 !=
492       GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration-nick",
493                                cfg_name,
494                                &run,
495                                NULL))
496   {
497     res = 1;
498   }
499   GNUNET_DISK_purge_cfg_dir (cfg_name,
500                              "GNUNET_TEST_HOME");
501   GNUNET_free (cfg_name);
502   return res;
503 }
504
505
506 /* end of test_namestore_api_zone_iteration.c */