cleaner stats
[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   pid_t arm_pid;
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_pid = 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 != PLIBC_KILL (p->arm_pid, SIGTERM))
88     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
89   if (GNUNET_OS_process_wait(p->arm_pid) != GNUNET_OK)
90     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
91   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
92               "ARM process %u stopped\n", p->arm_pid);
93 #endif
94   GNUNET_CONFIGURATION_destroy (p->cfg);
95 }
96
97
98 static void
99 abort_ksk_search_task (void *cls,
100                        const struct GNUNET_SCHEDULER_TaskContext *tc)
101 {
102   if (ksk_search != NULL)
103     {
104       GNUNET_FS_search_stop (ksk_search);
105       ksk_search = NULL;
106       if (sks_search == NULL)
107         {
108           GNUNET_FS_stop (fs);
109         }
110     }
111 }
112
113
114 static void
115 abort_sks_search_task (void *cls,
116                        const struct GNUNET_SCHEDULER_TaskContext *tc)
117 {
118   struct GNUNET_FS_Namespace *ns;
119
120   if (sks_search == NULL)
121     return;
122   GNUNET_FS_search_stop (sks_search); 
123   sks_search = NULL;
124   ns = GNUNET_FS_namespace_create (fs,
125                                    "testNamespace");
126   GNUNET_assert (NULL != ns);
127   GNUNET_assert (GNUNET_OK == GNUNET_FS_namespace_delete (ns, GNUNET_YES));
128   if (ksk_search == NULL)
129     {
130       GNUNET_FS_stop (fs);
131     }    
132 }
133
134
135 static void *
136 progress_cb (void *cls, 
137              const struct GNUNET_FS_ProgressInfo *event)
138 {
139   switch (event->status)
140     {
141     case GNUNET_FS_STATUS_SEARCH_RESULT:
142       if (sks_search == event->value.search.sc)
143         {
144           if (! GNUNET_FS_uri_test_equal (sks_expect_uri,
145                                           event->value.search.specifics.result.uri))
146             {
147               fprintf (stderr,
148                        "Wrong result for sks search!\n");
149               err = 1;
150             }
151           /* give system 1ms to initiate update search! */
152           GNUNET_SCHEDULER_add_delayed (sched,
153                                         GNUNET_TIME_UNIT_MILLISECONDS,
154                                         &abort_sks_search_task,
155                                         NULL);
156         }
157       else if (ksk_search == event->value.search.sc)
158         {
159           if (! GNUNET_FS_uri_test_equal (ksk_expect_uri,
160                                           event->value.search.specifics.result.uri))
161             {
162               fprintf (stderr,
163                        "Wrong result for ksk search!\n");
164               err = 1;
165             }
166           GNUNET_SCHEDULER_add_continuation (sched,
167                                              &abort_ksk_search_task,
168                                              NULL,
169                                              GNUNET_SCHEDULER_REASON_PREREQ_DONE);
170         }
171       else 
172         {
173           fprintf (stderr,
174                    "Unexpected search result received!\n");
175           GNUNET_break (0);
176         }
177       break;
178     case GNUNET_FS_STATUS_SEARCH_ERROR:
179       fprintf (stderr,
180                "Error searching file: %s\n",
181                event->value.search.specifics.error.message);
182       if (sks_search == event->value.search.sc)
183         GNUNET_SCHEDULER_add_continuation (sched,
184                                            &abort_sks_search_task,
185                                            NULL,
186                                            GNUNET_SCHEDULER_REASON_PREREQ_DONE);
187       else if (ksk_search == event->value.search.sc)
188         GNUNET_SCHEDULER_add_continuation (sched,
189                                            &abort_ksk_search_task,
190                                            NULL,
191                                            GNUNET_SCHEDULER_REASON_PREREQ_DONE);
192       else
193         GNUNET_break (0);
194       break;
195     case GNUNET_FS_STATUS_SEARCH_START:
196       GNUNET_assert ( (NULL == event->value.search.cctx) ||
197                       (0 == strcmp ("sks_search", event->value.search.cctx)) ||
198                       (0 == strcmp ("ksk_search", event->value.search.cctx)));
199       if (NULL == event->value.search.cctx)
200         {
201           GNUNET_assert (0 == strcmp ("sks_search", event->value.search.pctx));
202           update_started = GNUNET_YES;
203         }
204       GNUNET_assert (1 == event->value.search.anonymity);
205       break;
206     case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
207       return NULL;
208     case GNUNET_FS_STATUS_SEARCH_STOPPED:
209       return NULL;
210     default:
211       fprintf (stderr,
212                "Unexpected event: %d\n", 
213                event->status);
214       break;
215     }
216   return event->value.search.cctx;
217 }
218
219
220 static void
221 publish_cont (void *cls,
222               const struct GNUNET_FS_Uri *ksk_uri,
223               const char *emsg)
224 {
225   char *msg;
226   struct GNUNET_FS_Uri *sks_uri;
227   char sbuf[1024];
228   struct GNUNET_CRYPTO_HashAsciiEncoded enc;
229   
230   if (NULL != emsg)
231     {
232       fprintf (stderr, "Error publishing: %s\n", emsg);
233       err = 1;
234       GNUNET_FS_stop (fs);
235       return;
236     }  
237   GNUNET_CRYPTO_hash_to_enc (&nsid,
238                              &enc);
239   GNUNET_snprintf (sbuf,
240                    sizeof (sbuf),
241                    "gnunet://fs/sks/%s/this",
242                    &enc);
243   sks_uri = GNUNET_FS_uri_parse (sbuf, &msg);
244   if (msg != NULL)
245     {
246       fprintf (stderr, "failed to parse URI `%s': %s\n",
247                sbuf,
248                msg);
249       err = 1;
250       GNUNET_FS_stop (fs);
251       GNUNET_free (msg);
252       return;
253     }
254   ksk_search = GNUNET_FS_search_start (fs, ksk_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "ksk_search");
255   sks_search = GNUNET_FS_search_start (fs, sks_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "sks_search");
256   GNUNET_FS_uri_destroy (sks_uri);
257 }
258
259
260 static void
261 sks_cont (void *cls,
262           const struct GNUNET_FS_Uri *uri,
263           const char *emsg)
264 {
265   struct GNUNET_CONTAINER_MetaData *meta;
266   struct GNUNET_TIME_Absolute expiration;
267   struct GNUNET_FS_Uri *ksk_uri;
268   char * msg;
269
270   expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
271   meta = GNUNET_CONTAINER_meta_data_create ();
272   msg = NULL;
273   ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/ns-search", &msg);
274   GNUNET_assert (NULL == msg);
275   ksk_expect_uri = GNUNET_FS_uri_dup (uri);
276   GNUNET_FS_publish_ksk (fs,
277                          ksk_uri,
278                          meta,
279                          uri,
280                          expiration,
281                          1, 1,
282                          GNUNET_FS_PUBLISH_OPTION_NONE,
283                          &publish_cont,
284                          NULL);
285   GNUNET_FS_uri_destroy (ksk_uri);
286   GNUNET_CONTAINER_meta_data_destroy (meta);
287 }
288
289
290 static void
291 adv_cont (void *cls,
292           const struct GNUNET_FS_Uri *uri,
293           const char *emsg)
294 {
295   struct GNUNET_CONTAINER_MetaData *meta;
296   struct GNUNET_FS_Namespace *ns;
297   struct GNUNET_TIME_Absolute expiration;
298
299   if (NULL != emsg)
300     {
301       fprintf (stderr, "Error publishing: %s\n", emsg);
302       err = 1;
303       GNUNET_FS_stop (fs);
304       return;
305     }
306   expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
307   ns = GNUNET_FS_namespace_create (fs,
308                                    "testNamespace");
309   GNUNET_assert (NULL != ns);
310   meta = GNUNET_CONTAINER_meta_data_create ();
311   GNUNET_assert (NULL == emsg);
312   sks_expect_uri = GNUNET_FS_uri_dup (uri);
313   GNUNET_FS_publish_sks (fs,
314                          ns,
315                          "this",
316                          "next",
317                          meta,
318                          uri, /* FIXME: this is non-sense (use CHK URI!?) */
319                          expiration,
320                          1, 1,
321                          GNUNET_FS_PUBLISH_OPTION_NONE,
322                          &sks_cont,
323                          NULL);
324   GNUNET_CONTAINER_meta_data_destroy (meta);
325   GNUNET_FS_namespace_delete (ns, GNUNET_NO);
326 }
327
328
329 static void
330 ns_iterator (void *cls,
331              const char *name,
332              const GNUNET_HashCode *id)
333 {
334   int *ok = cls;
335
336   if (0 != strcmp (name,
337                    "testNamespace"))
338     return;
339   *ok = GNUNET_YES;
340   nsid = *id;
341 }
342
343
344 static void
345 testNamespace ()
346 {
347   struct GNUNET_FS_Namespace *ns;
348   struct GNUNET_TIME_Absolute expiration;
349   struct GNUNET_CONTAINER_MetaData *meta;
350   struct GNUNET_FS_Uri *ksk_uri;
351   int ok;
352
353   ns = GNUNET_FS_namespace_create (fs,
354                                    "testNamespace");
355   GNUNET_assert (NULL != ns);
356   ok = GNUNET_NO;
357   GNUNET_FS_namespace_list (fs, &ns_iterator, &ok);
358   if (GNUNET_NO == ok)
359     {
360       fprintf (stderr, "namespace_list failed to find namespace!\n");
361       GNUNET_FS_namespace_delete (ns, GNUNET_YES);
362       GNUNET_FS_stop (fs);
363       err = 1;
364       return;
365     }
366   expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
367   meta = GNUNET_CONTAINER_meta_data_create ();
368   ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/testnsa", NULL);
369   GNUNET_FS_namespace_advertise (fs,
370                                  ksk_uri,
371                                  ns,
372                                  meta,
373                                  1, 1,
374                                  expiration,                                       
375                                  "root",
376                                  &adv_cont, NULL);
377   GNUNET_FS_uri_destroy (ksk_uri);
378   GNUNET_FS_namespace_delete (ns, GNUNET_NO);
379   GNUNET_CONTAINER_meta_data_destroy (meta);
380 }
381
382
383 static void
384 run (void *cls,
385      struct GNUNET_SCHEDULER_Handle *s,
386      char *const *args,
387      const char *cfgfile,
388      const struct GNUNET_CONFIGURATION_Handle *cfg)
389 {
390   sched = s;
391   setup_peer (&p1, "test_fs_namespace_data.conf");
392   fs = GNUNET_FS_start (sched,
393                         cfg,
394                         "test-fs-namespace",
395                         &progress_cb,
396                         NULL,
397                         GNUNET_FS_FLAGS_NONE,
398                         GNUNET_FS_OPTIONS_END);
399   testNamespace ();
400 }
401
402
403 int
404 main (int argc, char *argv[])
405 {
406   char *const argvx[] = { 
407     "test-fs-namespace",
408     "-c",
409     "test_fs_namespace_data.conf",
410 #if VERBOSE
411     "-L", "DEBUG",
412 #endif
413     NULL
414   };
415   struct GNUNET_GETOPT_CommandLineOption options[] = {
416     GNUNET_GETOPT_OPTION_END
417   };
418
419   GNUNET_log_setup ("test_fs_namespace", 
420 #if VERBOSE
421                     "DEBUG",
422 #else
423                     "WARNING",
424 #endif
425                     NULL);
426   GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1,
427                       argvx, "test-fs-namespace",
428                       "nohelp", options, &run, NULL);
429   stop_arm (&p1);
430   if (GNUNET_YES != update_started)
431     {
432       fprintf (stderr,
433                "Update search never started!\n");
434       err = 1;
435     }
436   GNUNET_DISK_directory_remove ("/tmp/gnunet-test-fs-namespace/");
437   return err;
438 }
439
440
441 /* end of test_fs_namespace.c */