uncrustify as demanded.
[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(GNUNET_TIME_UNIT_HOURS).abs_value_us;
326       rd[c].record_type = TEST_RECORD_TYPE;
327       rd[c].data_size = 50;
328       rd[c].data = GNUNET_malloc(50);
329       rd[c].flags = 0;
330       memset((char *)rd[c].data, 'a', 50);
331     }
332   return rd;
333 }
334
335
336 /**
337  * Callback called from the zone iterator when we iterate over
338  * the empty zone.  Check that we got no records and then
339  * start the actual tests by filling the zone.
340  */
341 static void
342 empty_zone_proc(void *cls,
343                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
344                 const char *label,
345                 unsigned int rd_count,
346                 const struct GNUNET_GNSRECORD_Data *rd)
347 {
348   GNUNET_assert(nsh == cls);
349   if (NULL != zone)
350     {
351       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
352                  _("Expected empty zone but received zone private key\n"));
353       GNUNET_break(0);
354       GNUNET_SCHEDULER_shutdown();
355       res = 1;
356       return;
357     }
358   if ((NULL != label) || (NULL != rd) || (0 != rd_count))
359     {
360       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
361                  _("Expected no zone content but received data\n"));
362       GNUNET_break(0);
363       GNUNET_SCHEDULER_shutdown();
364       res = 1;
365       return;
366     }
367   GNUNET_assert(0);
368 }
369
370
371 static void
372 empty_zone_end(void *cls)
373 {
374   char *hostkey_file;
375
376   zi = NULL;
377   GNUNET_asprintf(&hostkey_file,
378                   "zonefiles%s%s",
379                   DIR_SEPARATOR_STR,
380                   "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey");
381   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
382              "Using zonekey file `%s' \n",
383              hostkey_file);
384   privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file);
385   GNUNET_free(hostkey_file);
386   GNUNET_assert(privkey != NULL);
387
388   GNUNET_asprintf(&hostkey_file,
389                   "zonefiles%s%s",
390                   DIR_SEPARATOR_STR,
391                   "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey");
392   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
393              "Using zonekey file `%s' \n",
394              hostkey_file);
395   privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file);
396   GNUNET_free(hostkey_file);
397   GNUNET_assert(privkey2 != NULL);
398
399   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n");
400
401   GNUNET_asprintf(&s_name_1, "dummy1");
402   s_rd_1 = create_record(1);
403   GNUNET_NAMESTORE_records_store(nsh,
404                                  privkey,
405                                  s_name_1,
406                                  1, s_rd_1,
407                                  &put_cont,
408                                  NULL);
409   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
410              "Created record 2 \n");
411   GNUNET_asprintf(&s_name_2, "dummy2");
412   s_rd_2 = create_record(1);
413   GNUNET_NAMESTORE_records_store(nsh,
414                                  privkey,
415                                  s_name_2,
416                                  1, s_rd_2,
417                                  &put_cont,
418                                  NULL);
419   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
420              "Created record 3\n");
421   /* name in different zone */
422   GNUNET_asprintf(&s_name_3, "dummy3");
423   s_rd_3 = create_record(1);
424   GNUNET_NAMESTORE_records_store(nsh,
425                                  privkey2,
426                                  s_name_3,
427                                  1,
428                                  s_rd_3,
429                                  &put_cont,
430                                  NULL);
431 }
432
433
434 static void
435 run(void *cls,
436     const struct GNUNET_CONFIGURATION_Handle *cfg,
437     struct GNUNET_TESTING_Peer *peer)
438 {
439   endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,
440                                                &endbadly,
441                                                NULL);
442   GNUNET_SCHEDULER_add_shutdown(&end,
443                                 NULL);
444
445   nsh = GNUNET_NAMESTORE_connect(cfg);
446   GNUNET_break(NULL != nsh);
447   /* first, iterate over empty namestore */
448   zi = GNUNET_NAMESTORE_zone_iteration_start(nsh,
449                                              NULL,
450                                              &fail_cb,
451                                              NULL,
452                                              &empty_zone_proc,
453                                              nsh,
454                                              &empty_zone_end,
455                                              NULL);
456   if (NULL == zi)
457     {
458       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
459                  "Failed to create zone iterator\n");
460       GNUNET_break(0);
461       res = 1;
462       GNUNET_SCHEDULER_shutdown();
463     }
464 }
465
466
467 #include "test_common.c"
468
469
470 int
471 main(int argc, char *argv[])
472 {
473   const char *plugin_name;
474   char *cfg_name;
475
476   SETUP_CFG(plugin_name, cfg_name);
477   res = 1;
478   if (0 !=
479       GNUNET_TESTING_peer_run("test-namestore-api-zone-iteration",
480                               cfg_name,
481                               &run,
482                               NULL))
483     {
484       res = 1;
485     }
486   GNUNET_DISK_purge_cfg_dir(cfg_name,
487                             "GNUNET_TEST_HOME");
488   GNUNET_free(cfg_name);
489   return res;
490 }
491
492
493 /* end of test_namestore_api_zone_iteration.c */