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