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