7d98eefb01bae05ef5ee5168c7425a1047e57fca
[oweals/gnunet.git] / src / namestore / test_namestore_api_zone_iteration_specific_zone.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file namestore/test_namestore_api_zone_iteration.c
22  * @brief testcase for namestore_api.c zone iteration functionality
23  */
24 #include "platform.h"
25 #include "gnunet_common.h"
26 #include "gnunet_namestore_service.h"
27 #include "namestore.h"
28
29 #define VERBOSE GNUNET_NO
30
31 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
32
33 static struct GNUNET_NAMESTORE_Handle * nsh;
34
35 static GNUNET_SCHEDULER_TaskIdentifier endbadly_task;
36 static GNUNET_SCHEDULER_TaskIdentifier stopiteration_task;
37 static struct GNUNET_OS_Process *arm;
38
39 static struct GNUNET_CRYPTO_RsaPrivateKey * privkey;
40 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
41 static GNUNET_HashCode zone;
42
43 static struct GNUNET_CRYPTO_RsaPrivateKey * privkey2;
44 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey2;
45 static GNUNET_HashCode zone2;
46
47 static struct GNUNET_NAMESTORE_ZoneIterator *zi;
48 static int res;
49
50 struct GNUNET_CRYPTO_RsaSignature *sig_1;
51 char * s_name_1;
52 struct GNUNET_NAMESTORE_RecordData *s_rd_1;
53
54 struct GNUNET_CRYPTO_RsaSignature *sig_2;
55 char * s_name_2;
56 struct GNUNET_NAMESTORE_RecordData *s_rd_2;
57
58 struct GNUNET_CRYPTO_RsaSignature *sig_3;
59 char * s_name_3;
60 struct GNUNET_NAMESTORE_RecordData *s_rd_3;
61
62 static void
63 start_arm (const char *cfgname)
64 {
65   arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm",
66                                "gnunet-service-arm", "-c", cfgname,
67 #if VERBOSE_PEERS
68                                "-L", "DEBUG",
69 #else
70                                "-L", "ERROR",
71 #endif
72                                NULL);
73 }
74
75 static void
76 stop_arm ()
77 {
78   if (NULL != arm)
79   {
80     if (0 != GNUNET_OS_process_kill (arm, SIGTERM))
81       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
82     GNUNET_OS_process_wait (arm);
83     GNUNET_OS_process_close (arm);
84     arm = NULL;
85   }
86 }
87
88 /**
89  * Re-establish the connection to the service.
90  *
91  * @param cls handle to use to re-connect.
92  * @param tc scheduler context
93  */
94 static void
95 endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
96 {
97   if (stopiteration_task != GNUNET_SCHEDULER_NO_TASK)
98   {
99     GNUNET_SCHEDULER_cancel (stopiteration_task);
100     stopiteration_task = GNUNET_SCHEDULER_NO_TASK;
101   }
102
103   if (nsh != NULL)
104     GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES);
105   nsh = NULL;
106
107   GNUNET_free_non_null(sig_1);
108   GNUNET_free_non_null(sig_2);
109   GNUNET_free_non_null(s_name_1);
110   GNUNET_free_non_null(s_name_2);
111
112   if (s_rd_1 != NULL)
113   {
114     GNUNET_free ((void *)s_rd_1->data);
115     GNUNET_free (s_rd_1);
116   }
117   if (s_rd_2 != NULL)
118   {
119     GNUNET_free ((void *)s_rd_2->data);
120     GNUNET_free (s_rd_2);
121   }
122
123   if (privkey != NULL)
124     GNUNET_CRYPTO_rsa_key_free (privkey);
125   privkey = NULL;
126
127   if (NULL != arm)
128     stop_arm();
129
130   res = 1;
131 }
132
133
134 static void
135 end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
136 {
137   if (stopiteration_task != GNUNET_SCHEDULER_NO_TASK)
138   {
139     GNUNET_SCHEDULER_cancel (stopiteration_task);
140     stopiteration_task = GNUNET_SCHEDULER_NO_TASK;
141   }
142
143   if (endbadly_task != GNUNET_SCHEDULER_NO_TASK)
144   {
145     GNUNET_SCHEDULER_cancel (endbadly_task);
146     endbadly_task = GNUNET_SCHEDULER_NO_TASK;
147   }
148
149   if (privkey != NULL)
150     GNUNET_CRYPTO_rsa_key_free (privkey);
151   privkey = NULL;
152
153   GNUNET_free (sig_1);
154   GNUNET_free (sig_2);
155   GNUNET_free (s_name_1);
156   GNUNET_free (s_name_2);
157   if (s_rd_1 != NULL)
158   {
159     GNUNET_free ((void *)s_rd_1->data);
160     GNUNET_free (s_rd_1);
161   }
162   if (s_rd_2 != NULL)
163   {
164     GNUNET_free ((void *)s_rd_2->data);
165     GNUNET_free (s_rd_2);
166   }
167
168   if (nsh != NULL)
169     GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES);
170   nsh = NULL;
171
172
173   if (NULL != arm)
174     stop_arm();
175 }
176
177 void zone_proc (void *cls,
178                 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
179                 struct GNUNET_TIME_Absolute expire,
180                 const char *name,
181                 unsigned int rd_count,
182                 const struct GNUNET_NAMESTORE_RecordData *rd,
183                 const struct GNUNET_CRYPTO_RsaSignature *signature)
184 {
185   int failed = GNUNET_NO;
186   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for zone `%s'\n", GNUNET_h2s (&zone));
187   if ((zone_key == NULL) &&  (name == NULL))
188   {
189     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done\n");
190     GNUNET_SCHEDULER_add_now (&end, NULL);
191   }
192   else
193   {
194     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing results name %s \n", name);
195     if (0 == strcmp (name, s_name_1))
196     {
197       if (rd_count == 1)
198       {
199         if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_1))
200         {
201           failed = GNUNET_YES;
202           GNUNET_break (0);
203         }
204       }
205       else
206       {
207         failed = GNUNET_YES;
208         GNUNET_break (0);
209       }
210       if (0 != memcmp (signature, sig_1, sizeof (struct GNUNET_CRYPTO_RsaSignature)))
211       {
212         failed = GNUNET_YES;
213         GNUNET_break (0);
214       }
215     }
216     else if (0 == strcmp (name, s_name_2))
217     {
218       if (rd_count == 1)
219       {
220         if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_2))
221         {
222           failed = GNUNET_YES;
223           GNUNET_break (0);
224         }
225       }
226       else
227       {
228         failed = GNUNET_YES;
229         GNUNET_break (0);
230       }
231       if (0 != memcmp (signature, sig_2, sizeof (struct GNUNET_CRYPTO_RsaSignature)))
232       {
233         failed = GNUNET_YES;
234         GNUNET_break (0);
235       }
236     }
237     else
238     {
239       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result `%s'\n", name);
240       GNUNET_break (0);
241       GNUNET_SCHEDULER_add_now (&end, NULL);
242     }
243
244     if (failed == GNUNET_NO)
245     {
246       res --;
247       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n");
248       GNUNET_NAMESTORE_zone_iterator_next (zi);
249     }
250     else
251     {
252       GNUNET_break (0);
253       GNUNET_SCHEDULER_add_now (&end, NULL);
254     }
255   }
256 }
257
258 void
259 delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg)
260 {
261   char *afsdir;
262
263   if (GNUNET_OK ==
264       GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite",
265                                                "FILENAME", &afsdir))
266   {
267     if (GNUNET_OK == GNUNET_DISK_file_test (afsdir))
268       if (GNUNET_OK == GNUNET_DISK_file_test (afsdir))
269         if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir))
270           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir);
271    GNUNET_free (afsdir);
272   }
273
274 }
275
276 void
277 put_cont (void *cls, int32_t success, const char *emsg)
278 {
279   static int c = 0;
280
281   if (success == GNUNET_OK)
282   {
283     c++;
284     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c);
285   }
286   else
287   {
288     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records\n");
289     GNUNET_break (0);
290     GNUNET_SCHEDULER_cancel (endbadly_task);
291     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
292   }
293
294   if (c == 2)
295   {
296     res = 2;
297     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over zone `%s'\n",
298         GNUNET_h2s(&zone));
299     zi = GNUNET_NAMESTORE_zone_iteration_start(nsh,
300                                         &zone,
301                                         GNUNET_NAMESTORE_RF_NONE,
302                                         GNUNET_NAMESTORE_RF_NONE,
303                                         zone_proc,
304                                         &zone);
305     if (zi == NULL)
306     {
307       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n");
308       GNUNET_break (0);
309       GNUNET_SCHEDULER_cancel (endbadly_task);
310       endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
311     }
312   }
313 }
314
315 static struct GNUNET_NAMESTORE_RecordData *
316 create_record (int count)
317 {
318   int c;
319   struct GNUNET_NAMESTORE_RecordData * rd;
320   rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData));
321
322   for (c = 0; c < count; c++)
323   {
324     rd[c].expiration = GNUNET_TIME_absolute_get();
325     rd[c].record_type = 1111;
326     rd[c].data_size = 50;
327     rd[c].data = GNUNET_malloc(50);
328     memset ((char *) rd[c].data, 'a', 50);
329   }
330   return rd;
331 }
332
333 static void
334 run (void *cls, char *const *args, const char *cfgfile,
335      const struct GNUNET_CONFIGURATION_Handle *cfg)
336 {
337   delete_existing_db(cfg);
338   endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,&endbadly, NULL);
339
340   privkey = GNUNET_CRYPTO_rsa_key_create_from_file("hostkey");
341   GNUNET_assert (privkey != NULL);
342   GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey);
343   GNUNET_CRYPTO_hash(&pubkey, sizeof (pubkey), &zone);
344
345   privkey2 = GNUNET_CRYPTO_rsa_key_create_from_file("hostkey2");
346   GNUNET_assert (privkey2 != NULL);
347   GNUNET_CRYPTO_rsa_key_get_public(privkey2, &pubkey2);
348   GNUNET_CRYPTO_hash(&pubkey2, sizeof (pubkey), &zone2);
349
350
351   start_arm (cfgfile);
352   GNUNET_assert (arm != NULL);
353
354   nsh = GNUNET_NAMESTORE_connect (cfg);
355   GNUNET_break (NULL != nsh);
356
357   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n");
358
359   GNUNET_asprintf(&s_name_1, "dummy1");
360   s_rd_1 = create_record(1);
361   sig_1 = GNUNET_NAMESTORE_create_signature(privkey, s_name_1, s_rd_1, 1);
362   GNUNET_NAMESTORE_record_create(nsh, privkey, s_name_1, s_rd_1, &put_cont, NULL);
363
364
365   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n");
366   GNUNET_asprintf(&s_name_2, "dummy2");
367   s_rd_2 = create_record(1);
368
369   sig_2 = GNUNET_NAMESTORE_create_signature(privkey, s_name_2, s_rd_2, 1);
370   GNUNET_NAMESTORE_record_create(nsh, privkey, s_name_2, s_rd_2, &put_cont, NULL);
371
372   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n");
373   /* name in different zone */
374   GNUNET_asprintf(&s_name_3, "dummy3");
375   s_rd_3 = create_record(1);
376   sig_3 = GNUNET_NAMESTORE_create_signature(privkey, s_name_3, s_rd_3, 1);
377   GNUNET_NAMESTORE_record_put (nsh, &pubkey2, s_name_3, GNUNET_TIME_absolute_get_forever(), 1, s_rd_3, sig_3, &put_cont, NULL);
378 }
379
380 static int
381 check ()
382 {
383   static char *const argv[] = { "test_namestore_api_zone_iteration",
384     "-c",
385     "test_namestore_api.conf",
386 #if VERBOSE
387     "-L", "DEBUG",
388 #endif
389     NULL
390   };
391   static struct GNUNET_GETOPT_CommandLineOption options[] = {
392     GNUNET_GETOPT_OPTION_END
393   };
394
395   res = 1;
396   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test_namestore_api_zone_iteration",
397                       "nohelp", options, &run, &res);
398   return res;
399 }
400
401 int
402 main (int argc, char *argv[])
403 {
404   int ret;
405
406   ret = check ();
407
408   return ret;
409 }
410
411 /* end of test_namestore_api_zone_iteration.c */