more code cleanup, better error handing in tests
[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 == memcmp (zone,
146                    privkey,
147                    sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
148   {
149     if (0 == strcmp (label, s_name_1))
150     {
151       if (rd_count == 1)
152       {
153         if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1))
154         {
155           failed = GNUNET_YES;
156           GNUNET_break (0);
157         }
158       }
159       else
160       {
161         failed = GNUNET_YES;
162         GNUNET_break (0);
163       }
164     }
165     else if (0 == strcmp (label, s_name_2))
166     {
167       if (rd_count == 1)
168       {
169         if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_2))
170         {
171           failed = GNUNET_YES;
172           GNUNET_break (0);
173         }
174       }
175       else
176       {
177         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
178                     "Received invalid record count\n");
179         failed = GNUNET_YES;
180         GNUNET_break (0);
181       }
182     }
183     else
184     {
185       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
186                   "Comparing result failed: got name `%s' for first zone\n",
187                   label);
188       failed = GNUNET_YES;
189       GNUNET_break (0);
190     }
191   }
192   else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
193   {
194     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
195                 "Received data for not requested zone\n");
196     failed = GNUNET_YES;
197     GNUNET_break (0);
198   }
199   else
200   {
201     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
202                 "Received invalid zone\n");
203     failed = GNUNET_YES;
204     GNUNET_break (0);
205   }
206   if (failed == GNUNET_NO)
207   {
208     returned_records ++;
209     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
210                 "Telling namestore to send the next result\n");
211     GNUNET_NAMESTORE_zone_iterator_next (zi,
212                                          1);
213   }
214   else
215   {
216     GNUNET_break (0);
217     res = 2;
218     GNUNET_SCHEDULER_shutdown ();
219   }
220 }
221
222
223 static void
224 zone_proc_end (void *cls)
225 {
226   zi = NULL;
227   GNUNET_break (2 == returned_records);
228   if (2 == returned_records)
229   {
230     res = 0; /* Last iteraterator callback, we are done */
231   }
232   else
233   {
234     res = 1;
235   }
236
237   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
238               "Received last result, iteration done after receing %u results\n",
239               returned_records);
240   GNUNET_SCHEDULER_shutdown ();
241 }
242
243
244 static void
245 put_cont (void *cls,
246           int32_t success,
247           const char *emsg)
248 {
249   static int c = 0;
250
251   if (success == GNUNET_OK)
252   {
253     c++;
254     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
255                 "Created record %u \n", c);
256   }
257   else
258   {
259     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
260                 "Failed to created records: `%s'\n",
261                 emsg);
262     GNUNET_break (0);
263     res = 2;
264     GNUNET_SCHEDULER_shutdown ();
265     return;
266   }
267
268   if (c == 3)
269   {
270     res = 1;
271     returned_records = 0;
272     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
273                 "All records created, starting iteration over all zones \n");
274     zi = GNUNET_NAMESTORE_zone_iteration_start(nsh,
275                                                privkey,
276                                                &fail_cb,
277                                                NULL,
278                                                &zone_proc,
279                                                NULL,
280                                                &zone_proc_end,
281                                                NULL);
282     if (zi == NULL)
283     {
284       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
285                   "Failed to create zone iterator\n");
286       GNUNET_break (0);
287       res = 2;
288       GNUNET_SCHEDULER_shutdown ();
289       return;
290     }
291   }
292 }
293
294
295 static struct GNUNET_GNSRECORD_Data *
296 create_record (unsigned int count)
297 {
298   struct GNUNET_GNSRECORD_Data *rd;
299
300   rd = GNUNET_new_array (count,
301                          struct GNUNET_GNSRECORD_Data);
302   for (unsigned int c = 0; c < count; c++)
303   {
304     rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (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 ("test-namestore-api-zone-iteration-specific-zone",
445                                cfg_name,
446                                &run,
447                                NULL))
448   {
449     res = 1;
450   }
451   GNUNET_DISK_purge_cfg_dir (cfg_name,
452                              "GNUNET_TEST_HOME");
453   GNUNET_free (cfg_name);
454   return res;
455 }
456
457 /* end of test_namestore_api_zone_iteration_specific_zone.c */