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