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