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