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