LRN: Use GNUNET_EXTRA_LOGGING to manage compile-time logging calls
[oweals/gnunet.git] / src / fs / test_fs_namespace.c
1 /*
2      This file is part of GNUnet.
3      (C) 2005, 2006, 2008, 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 /**
22  * @file fs/test_fs_namespace.c
23  * @brief Test for fs_namespace.c
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_arm_service.h"
29 #include "gnunet_fs_service.h"
30
31 #define VERBOSE GNUNET_EXTRA_LOGGING
32
33 #define START_ARM GNUNET_YES
34
35 static struct PeerContext p1;
36
37 static GNUNET_HashCode nsid;
38
39 static struct GNUNET_FS_Uri *sks_expect_uri;
40
41 static struct GNUNET_FS_Uri *ksk_expect_uri;
42
43 static struct GNUNET_FS_Handle *fs;
44
45 static struct GNUNET_FS_SearchContext *sks_search;
46
47 static struct GNUNET_FS_SearchContext *ksk_search;
48
49 static GNUNET_SCHEDULER_TaskIdentifier kill_task;
50
51 static int update_started;
52
53 static int err;
54
55 struct PeerContext
56 {
57   struct GNUNET_CONFIGURATION_Handle *cfg;
58 #if START_ARM
59   struct GNUNET_OS_Process *arm_proc;
60 #endif
61 };
62
63
64 static void
65 setup_peer (struct PeerContext *p, const char *cfgname)
66 {
67   p->cfg = GNUNET_CONFIGURATION_create ();
68 #if START_ARM
69   p->arm_proc =
70       GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
71                                "gnunet-service-arm",
72 #if VERBOSE
73                                "-L", "DEBUG",
74 #endif
75                                "-c", cfgname, NULL);
76 #endif
77   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
78 }
79
80
81 static void
82 stop_arm (struct PeerContext *p)
83 {
84 #if START_ARM
85   if (NULL != p->arm_proc)
86   {
87     if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
88       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
89     if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK)
90       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
91     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n",
92                 GNUNET_OS_process_get_pid (p->arm_proc));
93     GNUNET_OS_process_close (p->arm_proc);
94     p->arm_proc = NULL;
95   }
96 #endif
97   GNUNET_CONFIGURATION_destroy (p->cfg);
98 }
99
100
101 static void
102 abort_ksk_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
103 {
104   if (ksk_search != NULL)
105   {
106     GNUNET_FS_search_stop (ksk_search);
107     ksk_search = NULL;
108     if (sks_search == NULL)
109     {
110       GNUNET_FS_stop (fs);
111       if (GNUNET_SCHEDULER_NO_TASK != kill_task)
112         GNUNET_SCHEDULER_cancel (kill_task);
113     }
114   }
115 }
116
117
118 static void
119 abort_sks_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
120 {
121   struct GNUNET_FS_Namespace *ns;
122
123   if (sks_search == NULL)
124     return;
125   GNUNET_FS_search_stop (sks_search);
126   sks_search = NULL;
127   ns = GNUNET_FS_namespace_create (fs, "testNamespace");
128   GNUNET_assert (NULL != ns);
129   GNUNET_assert (GNUNET_OK == GNUNET_FS_namespace_delete (ns, GNUNET_YES));
130   if (ksk_search == NULL)
131   {
132     GNUNET_FS_stop (fs);
133     if (GNUNET_SCHEDULER_NO_TASK != kill_task)
134       GNUNET_SCHEDULER_cancel (kill_task);
135   }
136 }
137
138
139 static void
140 do_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
141 {
142   fprintf (stderr, "Operation timed out\n");
143   kill_task = GNUNET_SCHEDULER_NO_TASK;
144   abort_sks_search_task (NULL, tc);
145   abort_ksk_search_task (NULL, tc);
146 }
147
148
149
150 static void *
151 progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event)
152 {
153   switch (event->status)
154   {
155   case GNUNET_FS_STATUS_SEARCH_RESULT:
156     if (sks_search == event->value.search.sc)
157     {
158       if (!GNUNET_FS_uri_test_equal
159           (sks_expect_uri, event->value.search.specifics.result.uri))
160       {
161         fprintf (stderr, "Wrong result for sks search!\n");
162         err = 1;
163       }
164       /* give system 1ms to initiate update search! */
165       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
166                                     &abort_sks_search_task, NULL);
167     }
168     else if (ksk_search == event->value.search.sc)
169     {
170       if (!GNUNET_FS_uri_test_equal
171           (ksk_expect_uri, event->value.search.specifics.result.uri))
172       {
173         fprintf (stderr, "Wrong result for ksk search!\n");
174         err = 1;
175       }
176       GNUNET_SCHEDULER_add_continuation (&abort_ksk_search_task, NULL,
177                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
178     }
179     else
180     {
181       fprintf (stderr, "Unexpected search result received!\n");
182       GNUNET_break (0);
183     }
184     break;
185   case GNUNET_FS_STATUS_SEARCH_ERROR:
186     fprintf (stderr, "Error searching file: %s\n",
187              event->value.search.specifics.error.message);
188     if (sks_search == event->value.search.sc)
189       GNUNET_SCHEDULER_add_continuation (&abort_sks_search_task, NULL,
190                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
191     else if (ksk_search == event->value.search.sc)
192       GNUNET_SCHEDULER_add_continuation (&abort_ksk_search_task, NULL,
193                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
194     else
195       GNUNET_break (0);
196     break;
197   case GNUNET_FS_STATUS_SEARCH_START:
198     GNUNET_assert ((NULL == event->value.search.cctx) ||
199                    (0 == strcmp ("sks_search", event->value.search.cctx)) ||
200                    (0 == strcmp ("ksk_search", event->value.search.cctx)));
201     if (NULL == event->value.search.cctx)
202     {
203       GNUNET_assert (0 == strcmp ("sks_search", event->value.search.pctx));
204       update_started = GNUNET_YES;
205     }
206     GNUNET_assert (1 == event->value.search.anonymity);
207     break;
208   case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
209     return NULL;
210   case GNUNET_FS_STATUS_SEARCH_STOPPED:
211     return NULL;
212   default:
213     fprintf (stderr, "Unexpected event: %d\n", event->status);
214     break;
215   }
216   return event->value.search.cctx;
217 }
218
219
220 static void
221 publish_cont (void *cls, const struct GNUNET_FS_Uri *ksk_uri, const char *emsg)
222 {
223   char *msg;
224   struct GNUNET_FS_Uri *sks_uri;
225   char sbuf[1024];
226   struct GNUNET_CRYPTO_HashAsciiEncoded enc;
227
228   if (NULL != emsg)
229   {
230     fprintf (stderr, "Error publishing: %s\n", emsg);
231     err = 1;
232     GNUNET_FS_stop (fs);
233     return;
234   }
235   GNUNET_CRYPTO_hash_to_enc (&nsid, &enc);
236   GNUNET_snprintf (sbuf, sizeof (sbuf), "gnunet://fs/sks/%s/this", &enc);
237   sks_uri = GNUNET_FS_uri_parse (sbuf, &msg);
238   if (msg != NULL)
239   {
240     fprintf (stderr, "failed to parse URI `%s': %s\n", sbuf, msg);
241     err = 1;
242     GNUNET_FS_stop (fs);
243     GNUNET_free (msg);
244     return;
245   }
246   ksk_search =
247       GNUNET_FS_search_start (fs, ksk_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE,
248                               "ksk_search");
249   sks_search =
250       GNUNET_FS_search_start (fs, sks_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE,
251                               "sks_search");
252   GNUNET_FS_uri_destroy (sks_uri);
253 }
254
255
256 static void
257 sks_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg)
258 {
259   struct GNUNET_CONTAINER_MetaData *meta;
260   struct GNUNET_FS_Uri *ksk_uri;
261   char *msg;
262   struct GNUNET_FS_BlockOptions bo;
263
264   meta = GNUNET_CONTAINER_meta_data_create ();
265   msg = NULL;
266   ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/ns-search", &msg);
267   GNUNET_assert (NULL == msg);
268   ksk_expect_uri = GNUNET_FS_uri_dup (uri);
269   bo.content_priority = 1;
270   bo.anonymity_level = 1;
271   bo.replication_level = 0;
272   bo.expiration_time =
273       GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
274   GNUNET_FS_publish_ksk (fs, ksk_uri, meta, uri, &bo,
275                          GNUNET_FS_PUBLISH_OPTION_NONE, &publish_cont, NULL);
276   GNUNET_FS_uri_destroy (ksk_uri);
277   GNUNET_CONTAINER_meta_data_destroy (meta);
278 }
279
280
281 static void
282 adv_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg)
283 {
284   struct GNUNET_CONTAINER_MetaData *meta;
285   struct GNUNET_FS_Namespace *ns;
286   struct GNUNET_FS_BlockOptions bo;
287
288   if (NULL != emsg)
289   {
290     fprintf (stderr, "Error publishing: %s\n", emsg);
291     err = 1;
292     GNUNET_FS_stop (fs);
293     return;
294   }
295   ns = GNUNET_FS_namespace_create (fs, "testNamespace");
296   GNUNET_assert (NULL != ns);
297   meta = GNUNET_CONTAINER_meta_data_create ();
298   GNUNET_assert (NULL == emsg);
299   sks_expect_uri = GNUNET_FS_uri_dup (uri);
300   bo.content_priority = 1;
301   bo.anonymity_level = 1;
302   bo.replication_level = 0;
303   bo.expiration_time =
304       GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
305   GNUNET_FS_publish_sks (fs, ns, "this", "next", meta, uri,     /* FIXME: this is non-sense (use CHK URI!?) */
306                          &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &sks_cont, NULL);
307   GNUNET_CONTAINER_meta_data_destroy (meta);
308   GNUNET_FS_namespace_delete (ns, GNUNET_NO);
309 }
310
311
312 static void
313 ns_iterator (void *cls, const char *name, const GNUNET_HashCode * id)
314 {
315   int *ok = cls;
316
317   if (0 != strcmp (name, "testNamespace"))
318     return;
319   *ok = GNUNET_YES;
320   nsid = *id;
321 }
322
323
324 static void
325 testNamespace ()
326 {
327   struct GNUNET_FS_Namespace *ns;
328   struct GNUNET_FS_BlockOptions bo;
329   struct GNUNET_CONTAINER_MetaData *meta;
330   struct GNUNET_FS_Uri *ksk_uri;
331   int ok;
332
333   ns = GNUNET_FS_namespace_create (fs, "testNamespace");
334   GNUNET_assert (NULL != ns);
335   ok = GNUNET_NO;
336   GNUNET_FS_namespace_list (fs, &ns_iterator, &ok);
337   if (GNUNET_NO == ok)
338   {
339     fprintf (stderr, "namespace_list failed to find namespace!\n");
340     GNUNET_FS_namespace_delete (ns, GNUNET_YES);
341     GNUNET_FS_stop (fs);
342     err = 1;
343     return;
344   }
345   meta = GNUNET_CONTAINER_meta_data_create ();
346   ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/testnsa", NULL);
347   bo.content_priority = 1;
348   bo.anonymity_level = 1;
349   bo.replication_level = 0;
350   bo.expiration_time =
351       GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
352   GNUNET_FS_namespace_advertise (fs, ksk_uri, ns, meta, &bo, "root", &adv_cont,
353                                  NULL);
354   kill_task =
355       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &do_timeout,
356                                     NULL);
357   GNUNET_FS_uri_destroy (ksk_uri);
358   GNUNET_FS_namespace_delete (ns, GNUNET_NO);
359   GNUNET_CONTAINER_meta_data_destroy (meta);
360 }
361
362
363 static void
364 run (void *cls, char *const *args, const char *cfgfile,
365      const struct GNUNET_CONFIGURATION_Handle *cfg)
366 {
367   setup_peer (&p1, "test_fs_namespace_data.conf");
368   fs = GNUNET_FS_start (cfg, "test-fs-namespace", &progress_cb, NULL,
369                         GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END);
370   testNamespace ();
371 }
372
373
374 int
375 main (int argc, char *argv[])
376 {
377   char *const argvx[] = {
378     "test-fs-namespace",
379     "-c",
380     "test_fs_namespace_data.conf",
381 #if VERBOSE
382     "-L", "DEBUG",
383 #endif
384     NULL
385   };
386   struct GNUNET_GETOPT_CommandLineOption options[] = {
387     GNUNET_GETOPT_OPTION_END
388   };
389
390   GNUNET_log_setup ("test_fs_namespace",
391 #if VERBOSE
392                     "DEBUG",
393 #else
394                     "WARNING",
395 #endif
396                     NULL);
397   GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx,
398                       "test-fs-namespace", "nohelp", options, &run, NULL);
399   stop_arm (&p1);
400   if (GNUNET_YES != update_started)
401   {
402     fprintf (stderr, "Update search never started!\n");
403     err = 1;
404   }
405   GNUNET_DISK_directory_remove ("/tmp/gnunet-test-fs-namespace/");
406   return err;
407 }
408
409
410 /* end of test_fs_namespace.c */