style improvments wrt Mantis 1614 patch
[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  * TODO:
27  * - add timeout task
28  */
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_arm_service.h"
32 #include "gnunet_fs_service.h"
33
34 #define VERBOSE GNUNET_NO
35
36 #define START_ARM GNUNET_YES
37
38 static struct GNUNET_SCHEDULER_Handle *sched;
39
40 static struct PeerContext p1;
41
42 static GNUNET_HashCode nsid;
43
44 static struct GNUNET_FS_Uri *sks_expect_uri;
45
46 static struct GNUNET_FS_Uri *ksk_expect_uri;
47
48 static struct GNUNET_FS_Handle *fs;
49
50 static struct GNUNET_FS_SearchContext *sks_search;
51
52 static struct GNUNET_FS_SearchContext *ksk_search;
53
54 static int update_started;
55
56 static int err;
57
58 struct PeerContext
59 {
60   struct GNUNET_CONFIGURATION_Handle *cfg;
61 #if START_ARM
62   struct GNUNET_OS_Process *arm_proc;
63 #endif
64 };
65
66
67 static void
68 setup_peer (struct PeerContext *p, const char *cfgname)
69 {
70   p->cfg = GNUNET_CONFIGURATION_create ();
71 #if START_ARM
72   p->arm_proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
73                                         "gnunet-service-arm",
74 #if VERBOSE
75                                         "-L", "DEBUG",
76 #endif
77                                         "-c", cfgname, NULL);
78 #endif
79   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
80 }
81
82
83 static void
84 stop_arm (struct PeerContext *p)
85 {
86 #if START_ARM
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,
92               "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc));
93   GNUNET_OS_process_close (p->arm_proc);
94   p->arm_proc = NULL;
95 #endif
96   GNUNET_CONFIGURATION_destroy (p->cfg);
97 }
98
99
100 static void
101 abort_ksk_search_task (void *cls,
102                        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         }
112     }
113 }
114
115
116 static void
117 abort_sks_search_task (void *cls,
118                        const struct GNUNET_SCHEDULER_TaskContext *tc)
119 {
120   struct GNUNET_FS_Namespace *ns;
121
122   if (sks_search == NULL)
123     return;
124   GNUNET_FS_search_stop (sks_search); 
125   sks_search = NULL;
126   ns = GNUNET_FS_namespace_create (fs,
127                                    "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     }    
134 }
135
136
137 static void *
138 progress_cb (void *cls, 
139              const struct GNUNET_FS_ProgressInfo *event)
140 {
141   switch (event->status)
142     {
143     case GNUNET_FS_STATUS_SEARCH_RESULT:
144       if (sks_search == event->value.search.sc)
145         {
146           if (! GNUNET_FS_uri_test_equal (sks_expect_uri,
147                                           event->value.search.specifics.result.uri))
148             {
149               fprintf (stderr,
150                        "Wrong result for sks search!\n");
151               err = 1;
152             }
153           /* give system 1ms to initiate update search! */
154           GNUNET_SCHEDULER_add_delayed (sched,
155                                         GNUNET_TIME_UNIT_MILLISECONDS,
156                                         &abort_sks_search_task,
157                                         NULL);
158         }
159       else if (ksk_search == event->value.search.sc)
160         {
161           if (! GNUNET_FS_uri_test_equal (ksk_expect_uri,
162                                           event->value.search.specifics.result.uri))
163             {
164               fprintf (stderr,
165                        "Wrong result for ksk search!\n");
166               err = 1;
167             }
168           GNUNET_SCHEDULER_add_continuation (sched,
169                                              &abort_ksk_search_task,
170                                              NULL,
171                                              GNUNET_SCHEDULER_REASON_PREREQ_DONE);
172         }
173       else 
174         {
175           fprintf (stderr,
176                    "Unexpected search result received!\n");
177           GNUNET_break (0);
178         }
179       break;
180     case GNUNET_FS_STATUS_SEARCH_ERROR:
181       fprintf (stderr,
182                "Error searching file: %s\n",
183                event->value.search.specifics.error.message);
184       if (sks_search == event->value.search.sc)
185         GNUNET_SCHEDULER_add_continuation (sched,
186                                            &abort_sks_search_task,
187                                            NULL,
188                                            GNUNET_SCHEDULER_REASON_PREREQ_DONE);
189       else if (ksk_search == event->value.search.sc)
190         GNUNET_SCHEDULER_add_continuation (sched,
191                                            &abort_ksk_search_task,
192                                            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,
214                "Unexpected event: %d\n", 
215                event->status);
216       break;
217     }
218   return event->value.search.cctx;
219 }
220
221
222 static void
223 publish_cont (void *cls,
224               const struct GNUNET_FS_Uri *ksk_uri,
225               const char *emsg)
226 {
227   char *msg;
228   struct GNUNET_FS_Uri *sks_uri;
229   char sbuf[1024];
230   struct GNUNET_CRYPTO_HashAsciiEncoded enc;
231   
232   if (NULL != emsg)
233     {
234       fprintf (stderr, "Error publishing: %s\n", emsg);
235       err = 1;
236       GNUNET_FS_stop (fs);
237       return;
238     }  
239   GNUNET_CRYPTO_hash_to_enc (&nsid,
240                              &enc);
241   GNUNET_snprintf (sbuf,
242                    sizeof (sbuf),
243                    "gnunet://fs/sks/%s/this",
244                    &enc);
245   sks_uri = GNUNET_FS_uri_parse (sbuf, &msg);
246   if (msg != NULL)
247     {
248       fprintf (stderr, "failed to parse URI `%s': %s\n",
249                sbuf,
250                msg);
251       err = 1;
252       GNUNET_FS_stop (fs);
253       GNUNET_free (msg);
254       return;
255     }
256   ksk_search = GNUNET_FS_search_start (fs, ksk_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "ksk_search");
257   sks_search = GNUNET_FS_search_start (fs, sks_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "sks_search");
258   GNUNET_FS_uri_destroy (sks_uri);
259 }
260
261
262 static void
263 sks_cont (void *cls,
264           const struct GNUNET_FS_Uri *uri,
265           const char *emsg)
266 {
267   struct GNUNET_CONTAINER_MetaData *meta;
268   struct GNUNET_TIME_Absolute expiration;
269   struct GNUNET_FS_Uri *ksk_uri;
270   char * msg;
271
272   expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
273   meta = GNUNET_CONTAINER_meta_data_create ();
274   msg = NULL;
275   ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/ns-search", &msg);
276   GNUNET_assert (NULL == msg);
277   ksk_expect_uri = GNUNET_FS_uri_dup (uri);
278   GNUNET_FS_publish_ksk (fs,
279                          ksk_uri,
280                          meta,
281                          uri,
282                          expiration,
283                          1, 1,
284                          GNUNET_FS_PUBLISH_OPTION_NONE,
285                          &publish_cont,
286                          NULL);
287   GNUNET_FS_uri_destroy (ksk_uri);
288   GNUNET_CONTAINER_meta_data_destroy (meta);
289 }
290
291
292 static void
293 adv_cont (void *cls,
294           const struct GNUNET_FS_Uri *uri,
295           const char *emsg)
296 {
297   struct GNUNET_CONTAINER_MetaData *meta;
298   struct GNUNET_FS_Namespace *ns;
299   struct GNUNET_TIME_Absolute expiration;
300
301   if (NULL != emsg)
302     {
303       fprintf (stderr, "Error publishing: %s\n", emsg);
304       err = 1;
305       GNUNET_FS_stop (fs);
306       return;
307     }
308   expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
309   ns = GNUNET_FS_namespace_create (fs,
310                                    "testNamespace");
311   GNUNET_assert (NULL != ns);
312   meta = GNUNET_CONTAINER_meta_data_create ();
313   GNUNET_assert (NULL == emsg);
314   sks_expect_uri = GNUNET_FS_uri_dup (uri);
315   GNUNET_FS_publish_sks (fs,
316                          ns,
317                          "this",
318                          "next",
319                          meta,
320                          uri, /* FIXME: this is non-sense (use CHK URI!?) */
321                          expiration,
322                          1, 1,
323                          GNUNET_FS_PUBLISH_OPTION_NONE,
324                          &sks_cont,
325                          NULL);
326   GNUNET_CONTAINER_meta_data_destroy (meta);
327   GNUNET_FS_namespace_delete (ns, GNUNET_NO);
328 }
329
330
331 static void
332 ns_iterator (void *cls,
333              const char *name,
334              const GNUNET_HashCode *id)
335 {
336   int *ok = cls;
337
338   if (0 != strcmp (name,
339                    "testNamespace"))
340     return;
341   *ok = GNUNET_YES;
342   nsid = *id;
343 }
344
345
346 static void
347 testNamespace ()
348 {
349   struct GNUNET_FS_Namespace *ns;
350   struct GNUNET_TIME_Absolute expiration;
351   struct GNUNET_CONTAINER_MetaData *meta;
352   struct GNUNET_FS_Uri *ksk_uri;
353   int ok;
354
355   ns = GNUNET_FS_namespace_create (fs,
356                                    "testNamespace");
357   GNUNET_assert (NULL != ns);
358   ok = GNUNET_NO;
359   GNUNET_FS_namespace_list (fs, &ns_iterator, &ok);
360   if (GNUNET_NO == ok)
361     {
362       fprintf (stderr, "namespace_list failed to find namespace!\n");
363       GNUNET_FS_namespace_delete (ns, GNUNET_YES);
364       GNUNET_FS_stop (fs);
365       err = 1;
366       return;
367     }
368   expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
369   meta = GNUNET_CONTAINER_meta_data_create ();
370   ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/testnsa", NULL);
371   GNUNET_FS_namespace_advertise (fs,
372                                  ksk_uri,
373                                  ns,
374                                  meta,
375                                  1, 1,
376                                  expiration,                                       
377                                  "root",
378                                  &adv_cont, NULL);
379   GNUNET_FS_uri_destroy (ksk_uri);
380   GNUNET_FS_namespace_delete (ns, GNUNET_NO);
381   GNUNET_CONTAINER_meta_data_destroy (meta);
382 }
383
384
385 static void
386 run (void *cls,
387      struct GNUNET_SCHEDULER_Handle *s,
388      char *const *args,
389      const char *cfgfile,
390      const struct GNUNET_CONFIGURATION_Handle *cfg)
391 {
392   sched = s;
393   setup_peer (&p1, "test_fs_namespace_data.conf");
394   fs = GNUNET_FS_start (sched,
395                         cfg,
396                         "test-fs-namespace",
397                         &progress_cb,
398                         NULL,
399                         GNUNET_FS_FLAGS_NONE,
400                         GNUNET_FS_OPTIONS_END);
401   testNamespace ();
402 }
403
404
405 int
406 main (int argc, char *argv[])
407 {
408   char *const argvx[] = { 
409     "test-fs-namespace",
410     "-c",
411     "test_fs_namespace_data.conf",
412 #if VERBOSE
413     "-L", "DEBUG",
414 #endif
415     NULL
416   };
417   struct GNUNET_GETOPT_CommandLineOption options[] = {
418     GNUNET_GETOPT_OPTION_END
419   };
420
421   GNUNET_log_setup ("test_fs_namespace", 
422 #if VERBOSE
423                     "DEBUG",
424 #else
425                     "WARNING",
426 #endif
427                     NULL);
428   GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1,
429                       argvx, "test-fs-namespace",
430                       "nohelp", options, &run, NULL);
431   stop_arm (&p1);
432   if (GNUNET_YES != update_started)
433     {
434       fprintf (stderr,
435                "Update search never started!\n");
436       err = 1;
437     }
438   GNUNET_DISK_directory_remove ("/tmp/gnunet-test-fs-namespace/");
439   return err;
440 }
441
442
443 /* end of test_fs_namespace.c */