error handling
[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 == GNUNET_memcmp (zone,
164                           privkey))
165   {
166     if (0 == strcmp (label, s_name_1))
167     {
168       if (rd_count == 1)
169       {
170         if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1))
171         {
172           failed = GNUNET_YES;
173           GNUNET_break (0);
174         }
175       }
176       else
177       {
178         failed = GNUNET_YES;
179         GNUNET_break (0);
180       }
181     }
182     else if (0 == strcmp (label, s_name_2))
183     {
184       if (rd_count == 1)
185       {
186         if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2))
187         {
188           failed = GNUNET_YES;
189           GNUNET_break (0);
190         }
191       }
192       else
193       {
194         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
195                     "Received invalid record count\n");
196         failed = GNUNET_YES;
197         GNUNET_break (0);
198       }
199     }
200     else
201     {
202       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
203                   "Comparing result failed: got name `%s' for first zone\n",
204                   label);
205       failed = GNUNET_YES;
206       GNUNET_break (0);
207     }
208   }
209   else if (0 == GNUNET_memcmp (zone,
210                                privkey2))
211   {
212     if (0 == strcmp (label, s_name_3))
213     {
214       if (rd_count == 1)
215       {
216         if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_3))
217         {
218           failed = GNUNET_YES;
219           GNUNET_break (0);
220         }
221       }
222       else
223       {
224         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225                     "Received invalid record count\n");
226         failed = GNUNET_YES;
227         GNUNET_break (0);
228       }
229     }
230     else
231     {
232       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
233                   "Comparing result failed: got name `%s' for first zone\n",
234                   label);
235       failed = GNUNET_YES;
236       GNUNET_break (0);
237     }
238   }
239   else
240   {
241     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
242                 "Received invalid zone\n");
243     failed = GNUNET_YES;
244     GNUNET_break (0);
245   }
246
247   if (failed == GNUNET_NO)
248   {
249     returned_records++;
250     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
251                 "Telling namestore to send the next result\n");
252     GNUNET_NAMESTORE_zone_iterator_next (zi,
253                                          1);
254   }
255   else
256   {
257     GNUNET_break (0);
258     GNUNET_SCHEDULER_shutdown ();
259     res = 1;
260   }
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,
275                 "Created record %u \n",
276                 c);
277   }
278   else
279   {
280     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
281                 "Failed to created records: `%s'\n",
282                 emsg);
283     GNUNET_break (0);
284     GNUNET_SCHEDULER_shutdown ();
285     res = 1;
286     return;
287   }
288
289   if (c == 3)
290   {
291     res = 1;
292     returned_records = 0;
293     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
294                 "All records created, starting iteration over all zones \n");
295     zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
296                                                 NULL,
297                                                 &fail_cb,
298                                                 NULL,
299                                                 &zone_proc,
300                                                 NULL,
301                                                 &zone_end,
302                                                 NULL);
303     if (zi == NULL)
304     {
305       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
306                   "Failed to create zone iterator\n");
307       GNUNET_break (0);
308       GNUNET_SCHEDULER_shutdown ();
309       res = 1;
310       return;
311     }
312   }
313 }
314
315
316 static struct GNUNET_GNSRECORD_Data *
317 create_record (unsigned int count)
318 {
319   struct GNUNET_GNSRECORD_Data *rd;
320
321   rd = GNUNET_new_array (count,
322                          struct GNUNET_GNSRECORD_Data);
323   for (unsigned int c = 0; c < count; c++)
324   {
325     rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (
326       GNUNET_TIME_UNIT_HOURS).abs_value_us;
327     rd[c].record_type = TEST_RECORD_TYPE;
328     rd[c].data_size = 50;
329     rd[c].data = GNUNET_malloc (50);
330     rd[c].flags = 0;
331     memset ((char *) rd[c].data, 'a', 50);
332   }
333   return rd;
334 }
335
336
337 /**
338  * Callback called from the zone iterator when we iterate over
339  * the empty zone.  Check that we got no records and then
340  * start the actual tests by filling the zone.
341  */
342 static void
343 empty_zone_proc (void *cls,
344                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
345                  const char *label,
346                  unsigned int rd_count,
347                  const struct GNUNET_GNSRECORD_Data *rd)
348 {
349   GNUNET_assert (nsh == cls);
350   if (NULL != zone)
351   {
352     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
353                 _ ("Expected empty zone but received zone private key\n"));
354     GNUNET_break (0);
355     GNUNET_SCHEDULER_shutdown ();
356     res = 1;
357     return;
358   }
359   if ((NULL != label) || (NULL != rd) || (0 != rd_count))
360   {
361     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
362                 _ ("Expected no zone content but received data\n"));
363     GNUNET_break (0);
364     GNUNET_SCHEDULER_shutdown ();
365     res = 1;
366     return;
367   }
368   GNUNET_assert (0);
369 }
370
371
372 static void
373 empty_zone_end (void *cls)
374 {
375   char *hostkey_file;
376
377   zi = NULL;
378   GNUNET_asprintf (&hostkey_file,
379                    "zonefiles%s%s",
380                    DIR_SEPARATOR_STR,
381                    "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey");
382   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
383               "Using zonekey file `%s' \n",
384               hostkey_file);
385   privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file);
386   GNUNET_free (hostkey_file);
387   GNUNET_assert (privkey != NULL);
388
389   GNUNET_asprintf (&hostkey_file,
390                    "zonefiles%s%s",
391                    DIR_SEPARATOR_STR,
392                    "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey");
393   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
394               "Using zonekey file `%s' \n",
395               hostkey_file);
396   privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file);
397   GNUNET_free (hostkey_file);
398   GNUNET_assert (privkey2 != NULL);
399
400   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n");
401
402   GNUNET_asprintf (&s_name_1, "dummy1");
403   s_rd_1 = create_record (1);
404   GNUNET_NAMESTORE_records_store (nsh,
405                                   privkey,
406                                   s_name_1,
407                                   1, s_rd_1,
408                                   &put_cont,
409                                   NULL);
410   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
411               "Created record 2 \n");
412   GNUNET_asprintf (&s_name_2, "dummy2");
413   s_rd_2 = create_record (1);
414   GNUNET_NAMESTORE_records_store (nsh,
415                                   privkey,
416                                   s_name_2,
417                                   1, s_rd_2,
418                                   &put_cont,
419                                   NULL);
420   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
421               "Created record 3\n");
422   /* name in different zone */
423   GNUNET_asprintf (&s_name_3, "dummy3");
424   s_rd_3 = create_record (1);
425   GNUNET_NAMESTORE_records_store (nsh,
426                                   privkey2,
427                                   s_name_3,
428                                   1,
429                                   s_rd_3,
430                                   &put_cont,
431                                   NULL);
432 }
433
434
435 static void
436 run (void *cls,
437      const struct GNUNET_CONFIGURATION_Handle *cfg,
438      struct GNUNET_TESTING_Peer *peer)
439 {
440   endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
441                                                 &endbadly,
442                                                 NULL);
443   GNUNET_SCHEDULER_add_shutdown (&end,
444                                  NULL);
445
446   nsh = GNUNET_NAMESTORE_connect (cfg);
447   GNUNET_break (NULL != nsh);
448   /* first, iterate over empty namestore */
449   zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
450                                               NULL,
451                                               &fail_cb,
452                                               NULL,
453                                               &empty_zone_proc,
454                                               nsh,
455                                               &empty_zone_end,
456                                               NULL);
457   if (NULL == zi)
458   {
459     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
460                 "Failed to create zone iterator\n");
461     GNUNET_break (0);
462     res = 1;
463     GNUNET_SCHEDULER_shutdown ();
464   }
465 }
466
467
468 #include "test_common.c"
469
470
471 int
472 main (int argc, char *argv[])
473 {
474   const char *plugin_name;
475   char *cfg_name;
476
477   SETUP_CFG (plugin_name, cfg_name);
478   res = 1;
479   if (0 !=
480       GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration",
481                                cfg_name,
482                                &run,
483                                NULL))
484   {
485     res = 1;
486   }
487   GNUNET_DISK_purge_cfg_dir (cfg_name,
488                              "GNUNET_TEST_HOME");
489   GNUNET_free (cfg_name);
490   return res;
491 }
492
493
494 /* end of test_namestore_api_zone_iteration.c */