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