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