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