renaming GNUNET_TIME_relative_get_forever and GNUNET_TIME_absolute_get_forever method...
[oweals/gnunet.git] / src / namestore / test_namestore_api_lookup_specific_type.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.c
22  * @brief testcase for namestore_api.c
23  */
24 #include "platform.h"
25 #include "gnunet_common.h"
26 #include "gnunet_namestore_service.h"
27 #include "namestore.h"
28 #include "gnunet_signatures.h"
29
30 #define VERBOSE GNUNET_NO
31
32 #define RECORDS 5
33 #define TEST_RECORD_TYPE 1234
34 #define TEST_RECORD_DATALEN 123
35 #define TEST_RECORD_DATA 'a'
36
37 #define TEST_RECORD_LOOKUP_TYPE_NOT_EXISTING 11111
38 #define TEST_RECORD_LOOKUP_TYPE_EXISTING 22222
39
40 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
41
42 static struct GNUNET_NAMESTORE_Handle * nsh;
43
44 static GNUNET_SCHEDULER_TaskIdentifier endbadly_task;
45 static struct GNUNET_OS_Process *arm;
46
47 static struct GNUNET_CRYPTO_RsaPrivateKey * privkey;
48 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
49 struct GNUNET_CRYPTO_RsaSignature *s_signature;
50 static struct GNUNET_CRYPTO_ShortHashCode s_zone;
51 struct GNUNET_NAMESTORE_RecordData *s_rd;
52 static char *s_name;
53
54
55
56 static int res;
57
58 static void
59 start_arm (const char *cfgname)
60 {
61   arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm",
62                                "gnunet-service-arm", "-c", cfgname,
63 #if VERBOSE_PEERS
64                                "-L", "DEBUG",
65 #else
66                                "-L", "ERROR",
67 #endif
68                                NULL);
69 }
70
71 static void
72 stop_arm ()
73 {
74   if (NULL != arm)
75   {
76     if (0 != GNUNET_OS_process_kill (arm, SIGTERM))
77       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
78     GNUNET_OS_process_wait (arm);
79     GNUNET_OS_process_destroy (arm);
80     arm = NULL;
81   }
82 }
83
84 /**
85  * Re-establish the connection to the service.
86  *
87  * @param cls handle to use to re-connect.
88  * @param tc scheduler context
89  */
90 static void
91 endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
92 {
93   if (nsh != NULL)
94     GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES);
95   nsh = NULL;
96
97   if (privkey != NULL)
98     GNUNET_CRYPTO_rsa_key_free (privkey);
99   privkey = NULL;
100
101   if (NULL != arm)
102     stop_arm();
103
104   res = 1;
105 }
106
107
108 static void
109 end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
110 {
111   if (endbadly_task != GNUNET_SCHEDULER_NO_TASK)
112   {
113     GNUNET_SCHEDULER_cancel (endbadly_task);
114     endbadly_task = GNUNET_SCHEDULER_NO_TASK;
115   }
116
117   int c;
118   for (c = 0; c < RECORDS; c++)
119   {
120     GNUNET_free_non_null((void *) s_rd[c].data);
121   }
122   GNUNET_free (s_rd);
123
124   if (privkey != NULL)
125     GNUNET_CRYPTO_rsa_key_free (privkey);
126   privkey = NULL;
127
128   if (nsh != NULL)
129     GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES);
130   nsh = NULL;
131
132   if (NULL != arm)
133     stop_arm();
134 }
135
136
137 void name_lookup_existing_record_type (void *cls,
138                             const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
139                             struct GNUNET_TIME_Absolute expire,
140                             const char *n,
141                             unsigned int rd_count,
142                             const struct GNUNET_NAMESTORE_RecordData *rd,
143                             const struct GNUNET_CRYPTO_RsaSignature *signature)
144 {
145   int failed = GNUNET_NO;
146
147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned %u records\n", rd_count);
148
149   if ((NULL == n) || (0 != memcmp(zone_key, &pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))))
150   {
151     GNUNET_break(0);
152     failed = GNUNET_YES;
153   }
154   if ((NULL == n) || (0 != strcmp(n, s_name)))
155   {
156     GNUNET_break(0);
157     failed = GNUNET_YES;
158   }
159   if (1 != rd_count)
160   {
161     GNUNET_break(0);
162     failed = GNUNET_YES;
163   }
164   if (NULL == rd)
165   {
166     GNUNET_break(0);
167     failed = GNUNET_YES;
168   }
169   if (NULL != signature)
170   {
171     GNUNET_break(0);
172     failed = GNUNET_YES;
173   }
174
175   if (failed == GNUNET_YES)
176   {
177     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned invalid response\n");
178     res = 1;
179   }
180   else
181   {
182    res = 0;
183   }
184
185   GNUNET_SCHEDULER_add_now(&end, NULL);
186 }
187
188
189 void name_lookup_non_existing_record_type (void *cls,
190                             const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
191                             struct GNUNET_TIME_Absolute expire,
192                             const char *n,
193                             unsigned int rd_count,
194                             const struct GNUNET_NAMESTORE_RecordData *rd,
195                             const struct GNUNET_CRYPTO_RsaSignature *signature)
196 {
197   int failed = GNUNET_NO;
198   /* We expect zone key != NULL, name != NULL, rd_count 0, rd NULL, signature NULL */
199   if (NULL == zone_key)
200   {
201     GNUNET_break(0);
202     failed = GNUNET_YES;
203   }
204   if (NULL == n)
205   {
206     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name %s!\n", n);
207     GNUNET_break(0);
208     failed = GNUNET_YES;
209   }
210   if (0 != rd_count)
211   {
212     GNUNET_break(0);
213     failed = GNUNET_YES;
214   }
215   if (NULL != rd)
216   {
217     GNUNET_break(0);
218     failed = GNUNET_YES;
219   }
220   if (NULL != signature)
221   {
222     GNUNET_break(0);
223     failed = GNUNET_YES;
224   }
225
226   if ((rd_count == 1) && (rd != NULL))
227   {
228     if (GNUNET_NO == GNUNET_NAMESTORE_records_cmp(rd, &rd[RECORDS-1]))
229     {
230       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Records are not equal!\n");
231       failed = GNUNET_YES;
232     }
233     else
234     {
235       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Records are equal!\n");
236     }
237   }
238
239   if (failed == GNUNET_YES)
240   {
241     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned invalid response\n");
242     res = 1;
243
244   }
245   else
246   {
247    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned valid response\n");
248    GNUNET_NAMESTORE_lookup_record (nsh, &s_zone, s_name, TEST_RECORD_LOOKUP_TYPE_EXISTING, &name_lookup_existing_record_type, NULL);
249    res = 0;
250   }
251 }
252
253 void
254 put_cont (void *cls, int32_t success, const char *emsg)
255 {
256   char * name = cls;
257
258   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
259   if (success == GNUNET_OK)
260   {
261     res = 0;
262     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up non-existing record type %u for name `%s'\n", TEST_RECORD_LOOKUP_TYPE_NOT_EXISTING, name);
263     GNUNET_NAMESTORE_lookup_record (nsh, &s_zone, name, TEST_RECORD_LOOKUP_TYPE_NOT_EXISTING, &name_lookup_non_existing_record_type, NULL);
264   }
265   else
266   {
267     res = 1;
268     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name);
269     GNUNET_SCHEDULER_add_now(&end, NULL);
270   }
271 }
272
273 static struct GNUNET_NAMESTORE_RecordData *
274 create_record (int count)
275 {
276   int c;
277   struct GNUNET_NAMESTORE_RecordData * rd;
278   rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData));
279
280   for (c = 0; c < RECORDS-1; c++)
281   {
282     rd[c].expiration = GNUNET_TIME_UNIT_ZERO_ABS;
283     rd[c].record_type = 1;
284     rd[c].data_size = TEST_RECORD_DATALEN;
285     rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN);
286     memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN);
287   }
288
289   rd[c].expiration = GNUNET_TIME_absolute_get();
290   rd[c].record_type = TEST_RECORD_LOOKUP_TYPE_EXISTING;
291   rd[c].data_size = TEST_RECORD_DATALEN;
292   rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN);
293   memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN);
294
295
296   return rd;
297 }
298
299 void
300 delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg)
301 {
302   char *afsdir;
303
304   if (GNUNET_OK ==
305       GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite",
306                                                "FILENAME", &afsdir))
307   {
308     if (GNUNET_OK == GNUNET_DISK_file_test (afsdir))
309       if (GNUNET_OK == GNUNET_DISK_file_test (afsdir))
310         if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir))
311           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir);
312    GNUNET_free (afsdir);
313   }
314
315 }
316
317 static void
318 run (void *cls, char *const *args, const char *cfgfile,
319      const struct GNUNET_CONFIGURATION_Handle *cfg)
320 {
321   delete_existing_db(cfg);
322   endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL);
323
324   size_t rd_ser_len;
325
326   /* load privat key */
327   char *hostkey_file;
328   GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR,
329       "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey");
330   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file);
331   privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file);
332   GNUNET_free (hostkey_file);
333   GNUNET_assert (privkey != NULL);
334   /* get public key */
335   GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey);
336
337   /* create record */
338   s_name = "dummy.dummy.gnunet";
339   s_rd = create_record (RECORDS);
340
341   rd_ser_len = GNUNET_NAMESTORE_records_get_size(RECORDS, s_rd);
342   char rd_ser[rd_ser_len];
343   GNUNET_NAMESTORE_records_serialize(RECORDS, s_rd, rd_ser_len, rd_ser);
344
345   /* sign */
346   s_signature = GNUNET_NAMESTORE_create_signature(privkey, s_rd[RECORDS -1].expiration, s_name, s_rd, RECORDS);
347
348   /* create random zone hash */
349   GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &s_zone);
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_break (s_rd != NULL);
358   GNUNET_break (s_name != NULL);
359
360   GNUNET_NAMESTORE_record_put (nsh, &pubkey, s_name,
361                               GNUNET_TIME_UNIT_FOREVER_ABS,
362                               RECORDS, s_rd, s_signature, put_cont, s_name);
363
364
365
366 }
367
368 static int
369 check ()
370 {
371   static char *const argv[] = { "test-namestore-api",
372     "-c",
373     "test_namestore_api.conf",
374 #if VERBOSE
375     "-L", "DEBUG",
376 #endif
377     NULL
378   };
379   static struct GNUNET_GETOPT_CommandLineOption options[] = {
380     GNUNET_GETOPT_OPTION_END
381   };
382
383   res = 1;
384   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api",
385                       "nohelp", options, &run, &res);
386   return res;
387 }
388
389 int
390 main (int argc, char *argv[])
391 {
392   int ret;
393
394   ret = check ();
395   GNUNET_free (s_signature);
396   return ret;
397 }
398
399 /* end of test_namestore_api.c */