- Tests did not clean up: TEST_HOME with namestore db was not removed after test
[oweals/gnunet.git] / src / namestore / test_namestore_api_lookup_shadow_filter.c
1 /*
2      This file is part of GNUnet.
3      (C) 2012 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_lookup_shadow_filter.c
22  * @brief testcase for namestore_api.c: store a record with short expiration
23  *      and a shadow record, perform lookup:
24  *      - when active record is valid, expect only active record
25  *      - when active record is expired, expect shadow record only
26  */
27 #include "platform.h"
28 #include "gnunet_namecache_service.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_testing_lib.h"
31
32 #define TEST_NAME "dummy.dummy.gnunet"
33 #define TEST_RECORD_TYPE 1234
34 #define TEST_RECORD_DATALEN 123
35 #define TEST_RECORD_DATA 'a'
36 #define TEST_SHADOW_RECORD_DATA 'b'
37
38 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
39 #define EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
40
41 static struct GNUNET_NAMESTORE_Handle *nsh;
42
43 static struct GNUNET_NAMECACHE_Handle *nch;
44
45 static GNUNET_SCHEDULER_TaskIdentifier endbadly_task;
46
47 static GNUNET_SCHEDULER_TaskIdentifier delayed_lookup_task;
48
49 static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
50
51 static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
52
53 static int res;
54
55 static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
56
57 static struct GNUNET_NAMECACHE_QueueEntry *ncqe;
58
59 static struct GNUNET_NAMECACHE_QueueEntry *ncqe_shadow;
60
61 static struct GNUNET_GNSRECORD_Data records[2];
62
63 static struct GNUNET_TIME_Absolute record_expiration;
64
65 static struct GNUNET_HashCode derived_hash;
66
67 static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
68
69 static char *directory;
70
71 static void
72 cleanup ()
73 {
74   if (NULL != nsh)
75   {
76     GNUNET_NAMESTORE_disconnect (nsh);
77     nsh = NULL;
78   }
79   if (NULL != nch)
80   {
81     GNUNET_NAMECACHE_disconnect (nch);
82     nch = NULL;
83   }
84   if (NULL != privkey)
85   {
86     GNUNET_free (privkey);
87     privkey = NULL;
88   }
89   if (NULL != directory)
90   {
91       GNUNET_DISK_directory_remove (directory);
92       GNUNET_free (directory);
93   }
94   GNUNET_SCHEDULER_shutdown ();
95 }
96
97
98 /**
99  * Re-establish the connection to the service.
100  *
101  * @param cls handle to use to re-connect.
102  * @param tc scheduler context
103  */
104 static void
105 endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
106 {
107   if (GNUNET_SCHEDULER_NO_TASK != delayed_lookup_task)
108   {
109     GNUNET_SCHEDULER_cancel (delayed_lookup_task);
110     delayed_lookup_task = GNUNET_SCHEDULER_NO_TASK;
111   }
112   if (NULL != nsqe)
113   {
114     GNUNET_NAMESTORE_cancel (nsqe);
115     nsqe = NULL;
116   }
117   if (NULL != ncqe)
118   {
119     GNUNET_NAMECACHE_cancel (ncqe);
120     ncqe = NULL;
121   }
122   cleanup ();
123   res = 1;
124 }
125
126
127 static void
128 end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
129 {
130   cleanup ();
131   res = 0;
132 }
133
134
135 static void
136 rd_decrypt_cb (void *cls,
137                unsigned int rd_count,
138                const struct GNUNET_GNSRECORD_Data *rd)
139 {
140   struct GNUNET_GNSRECORD_Data *expected_rd = cls;
141   char rd_cmp_data[TEST_RECORD_DATALEN];
142
143   if (1 != rd_count)
144   {
145     GNUNET_SCHEDULER_add_now (&endbadly, NULL);
146     GNUNET_break (0);
147     return;
148   }
149   if (NULL == rd)
150   {
151     GNUNET_SCHEDULER_add_now (&endbadly, NULL);
152     GNUNET_break (0);
153     return;
154   }
155   if (expected_rd == &records[0])
156   {
157     /* Expecting active record */
158     memset (rd_cmp_data, TEST_RECORD_DATA, TEST_RECORD_DATALEN);
159     if (TEST_RECORD_TYPE != rd[0].record_type)
160     {
161       GNUNET_SCHEDULER_add_now (&endbadly, NULL);
162       GNUNET_break (0);
163       return;
164     }
165     if (TEST_RECORD_DATALEN != rd[0].data_size)
166     {
167       GNUNET_SCHEDULER_add_now (&endbadly, NULL);
168       GNUNET_break (0);
169       return;
170     }
171     if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN))
172     {
173       GNUNET_SCHEDULER_add_now (&endbadly, NULL);
174       GNUNET_break (0);
175       return;
176     }
177     if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags))
178     {
179       GNUNET_SCHEDULER_add_now (&endbadly, NULL);
180       GNUNET_break (0);
181       return;
182     }
183     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
184                 "Block was decrypted successfully with active record\n");
185   }
186   if (expected_rd == &records[1])
187   {
188     /* Expecting shadow record  but without shadow flag*/
189     memset (rd_cmp_data, TEST_SHADOW_RECORD_DATA, TEST_RECORD_DATALEN);
190     if (TEST_RECORD_TYPE != rd[0].record_type)
191     {
192       GNUNET_SCHEDULER_add_now (&endbadly, NULL);
193       GNUNET_break (0);
194       return;
195     }
196     if (TEST_RECORD_DATALEN != rd[0].data_size)
197     {
198       GNUNET_SCHEDULER_add_now (&endbadly, NULL);
199       GNUNET_break (0);
200       return;
201     }
202     if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN))
203     {
204       GNUNET_SCHEDULER_add_now (&endbadly, NULL);
205       GNUNET_break (0);
206       return;
207     }
208     if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags))
209     {
210       GNUNET_SCHEDULER_add_now (&endbadly, NULL);
211       GNUNET_break (0);
212       return;
213     }
214     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
215                 "Block was decrypted successfully with former shadow record \n");
216     GNUNET_SCHEDULER_add_now (&end, NULL );
217   }
218 }
219
220
221 static void
222 name_lookup_active_proc (void *cls,
223                   const struct GNUNET_GNSRECORD_Block *block)
224 {
225   struct GNUNET_GNSRECORD_Data *expected_rd = cls;
226   GNUNET_assert (NULL != expected_rd);
227
228   ncqe = NULL;
229   ncqe_shadow = NULL;
230   if (endbadly_task != GNUNET_SCHEDULER_NO_TASK)
231   {
232     GNUNET_SCHEDULER_cancel (endbadly_task);
233     endbadly_task = GNUNET_SCHEDULER_NO_TASK;
234   }
235
236   if (NULL == block)
237   {
238     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
239               _("Namestore returned no block\n"));
240     if (endbadly_task != GNUNET_SCHEDULER_NO_TASK)
241       GNUNET_SCHEDULER_cancel (endbadly_task);
242     endbadly_task =  GNUNET_SCHEDULER_add_now (&endbadly, NULL);
243     return;
244   }
245
246   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
247               "Namestore returned block, decrypting \n");
248   GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt(block,
249                 &pubkey, TEST_NAME, &rd_decrypt_cb, expected_rd));
250 }
251
252 static void
253 name_lookup_shadow (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
254 {
255   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
256               "Performing lookup for shadow record \n");
257   delayed_lookup_task = GNUNET_SCHEDULER_NO_TASK;
258   ncqe_shadow = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash,
259       &name_lookup_active_proc, &records[1]);
260 }
261
262
263 static void
264 put_cont (void *cls, int32_t success, const char *emsg)
265 {
266   nsqe = NULL;
267
268   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
269               "Name store added record for `%s': %s\n",
270               TEST_NAME,
271               (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
272
273   /* Create derived hash */
274   GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey);
275   GNUNET_GNSRECORD_query_from_public_key (&pubkey, TEST_NAME, &derived_hash);
276
277   if (0 == GNUNET_TIME_absolute_get_remaining(record_expiration).rel_value_us )
278   {
279     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
280                 "Test to too long to store records, cannot run test!\n");
281     GNUNET_SCHEDULER_add_now (&end, NULL );
282     return;
283   }
284   /* Lookup active record now */
285   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
286               "Performing lookup for active record \n");
287   ncqe = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash,
288                                         &name_lookup_active_proc, &records[0]);
289
290   delayed_lookup_task = GNUNET_SCHEDULER_add_delayed (EXPIRATION, &name_lookup_shadow, NULL);
291 }
292
293
294 static void
295 run (void *cls,
296      const struct GNUNET_CONFIGURATION_Handle *cfg,
297      struct GNUNET_TESTING_Peer *peer)
298 {
299   char *hostkey_file;
300
301   directory = NULL;
302   GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory);
303
304   endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
305                                                 &endbadly, NULL);
306   GNUNET_asprintf (&hostkey_file,
307                    "zonefiles%s%s",
308                    DIR_SEPARATOR_STR,
309                    "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey");
310   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file);
311   privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file);
312   GNUNET_free (hostkey_file);
313   GNUNET_assert (privkey != NULL);
314   GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey);
315
316   record_expiration = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), EXPIRATION);
317   records[0].expiration_time = record_expiration.abs_value_us;
318   records[0].record_type = TEST_RECORD_TYPE;
319   records[0].data_size = TEST_RECORD_DATALEN;
320   records[0].data = GNUNET_malloc (TEST_RECORD_DATALEN);
321   records[0].flags = GNUNET_GNSRECORD_RF_NONE;
322   memset ((char *) records[0].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN);
323
324   records[1].expiration_time = GNUNET_TIME_absolute_get().abs_value_us + 1000000000;
325   records[1].record_type = TEST_RECORD_TYPE;
326   records[1].data_size = TEST_RECORD_DATALEN;
327   records[1].data = GNUNET_malloc (TEST_RECORD_DATALEN);
328   records[1].flags = GNUNET_GNSRECORD_RF_SHADOW_RECORD;
329   memset ((char *) records[1].data, TEST_SHADOW_RECORD_DATA, TEST_RECORD_DATALEN);
330
331   nsh = GNUNET_NAMESTORE_connect (cfg);
332   nch = GNUNET_NAMECACHE_connect (cfg);
333   GNUNET_break (NULL != nsh);
334   GNUNET_break (NULL != nch);
335   nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, TEST_NAME,
336                                       2, records, &put_cont, NULL);
337   if (NULL == nsqe)
338   {
339     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
340               _("Namestore cannot store no block\n"));
341   }
342
343   GNUNET_free ((void *) records[0].data);
344   GNUNET_free ((void *) records[1].data);
345 }
346
347
348 int
349 main (int argc, char *argv[])
350 {
351   res = 1;
352   if (0 !=
353       GNUNET_TESTING_peer_run ("test-namestore-api",
354                                "test_namestore_api.conf",
355                                &run,
356                                NULL))
357     return 1;
358   return res;
359 }
360
361
362 /* end of test_namestore_api_lookup_shadow_filter.c */