big scheduler refactoring, expect some issues
[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 PeerContext p1;
39
40 static GNUNET_HashCode nsid;
41
42 static struct GNUNET_FS_Uri *sks_expect_uri;
43
44 static struct GNUNET_FS_Uri *ksk_expect_uri;
45
46 static struct GNUNET_FS_Handle *fs;
47
48 static struct GNUNET_FS_SearchContext *sks_search;
49
50 static struct GNUNET_FS_SearchContext *ksk_search;
51
52 static int update_started;
53
54 static int err;
55
56 struct PeerContext
57 {
58   struct GNUNET_CONFIGURATION_Handle *cfg;
59 #if START_ARM
60   struct GNUNET_OS_Process *arm_proc;
61 #endif
62 };
63
64
65 static void
66 setup_peer (struct PeerContext *p, const char *cfgname)
67 {
68   p->cfg = GNUNET_CONFIGURATION_create ();
69 #if START_ARM
70   p->arm_proc = 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 (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
86     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
87   if (GNUNET_OS_process_wait(p->arm_proc) != GNUNET_OK)
88     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
89   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
90               "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc));
91   GNUNET_OS_process_close (p->arm_proc);
92   p->arm_proc = NULL;
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 (GNUNET_TIME_UNIT_MILLISECONDS,
153                                         &abort_sks_search_task,
154                                         NULL);
155         }
156       else if (ksk_search == event->value.search.sc)
157         {
158           if (! GNUNET_FS_uri_test_equal (ksk_expect_uri,
159                                           event->value.search.specifics.result.uri))
160             {
161               fprintf (stderr,
162                        "Wrong result for ksk search!\n");
163               err = 1;
164             }
165           GNUNET_SCHEDULER_add_continuation (&abort_ksk_search_task,
166                                              NULL,
167                                              GNUNET_SCHEDULER_REASON_PREREQ_DONE);
168         }
169       else 
170         {
171           fprintf (stderr,
172                    "Unexpected search result received!\n");
173           GNUNET_break (0);
174         }
175       break;
176     case GNUNET_FS_STATUS_SEARCH_ERROR:
177       fprintf (stderr,
178                "Error searching file: %s\n",
179                event->value.search.specifics.error.message);
180       if (sks_search == event->value.search.sc)
181         GNUNET_SCHEDULER_add_continuation (&abort_sks_search_task,
182                                            NULL,
183                                            GNUNET_SCHEDULER_REASON_PREREQ_DONE);
184       else if (ksk_search == event->value.search.sc)
185         GNUNET_SCHEDULER_add_continuation (&abort_ksk_search_task,
186                                            NULL,
187                                            GNUNET_SCHEDULER_REASON_PREREQ_DONE);
188       else
189         GNUNET_break (0);
190       break;
191     case GNUNET_FS_STATUS_SEARCH_START:
192       GNUNET_assert ( (NULL == event->value.search.cctx) ||
193                       (0 == strcmp ("sks_search", event->value.search.cctx)) ||
194                       (0 == strcmp ("ksk_search", event->value.search.cctx)));
195       if (NULL == event->value.search.cctx)
196         {
197           GNUNET_assert (0 == strcmp ("sks_search", event->value.search.pctx));
198           update_started = GNUNET_YES;
199         }
200       GNUNET_assert (1 == event->value.search.anonymity);
201       break;
202     case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
203       return NULL;
204     case GNUNET_FS_STATUS_SEARCH_STOPPED:
205       return NULL;
206     default:
207       fprintf (stderr,
208                "Unexpected event: %d\n", 
209                event->status);
210       break;
211     }
212   return event->value.search.cctx;
213 }
214
215
216 static void
217 publish_cont (void *cls,
218               const struct GNUNET_FS_Uri *ksk_uri,
219               const char *emsg)
220 {
221   char *msg;
222   struct GNUNET_FS_Uri *sks_uri;
223   char sbuf[1024];
224   struct GNUNET_CRYPTO_HashAsciiEncoded enc;
225   
226   if (NULL != emsg)
227     {
228       fprintf (stderr, "Error publishing: %s\n", emsg);
229       err = 1;
230       GNUNET_FS_stop (fs);
231       return;
232     }  
233   GNUNET_CRYPTO_hash_to_enc (&nsid,
234                              &enc);
235   GNUNET_snprintf (sbuf,
236                    sizeof (sbuf),
237                    "gnunet://fs/sks/%s/this",
238                    &enc);
239   sks_uri = GNUNET_FS_uri_parse (sbuf, &msg);
240   if (msg != NULL)
241     {
242       fprintf (stderr, "failed to parse URI `%s': %s\n",
243                sbuf,
244                msg);
245       err = 1;
246       GNUNET_FS_stop (fs);
247       GNUNET_free (msg);
248       return;
249     }
250   ksk_search = GNUNET_FS_search_start (fs, ksk_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "ksk_search");
251   sks_search = GNUNET_FS_search_start (fs, sks_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "sks_search");
252   GNUNET_FS_uri_destroy (sks_uri);
253 }
254
255
256 static void
257 sks_cont (void *cls,
258           const struct GNUNET_FS_Uri *uri,
259           const char *emsg)
260 {
261   struct GNUNET_CONTAINER_MetaData *meta;
262   struct GNUNET_TIME_Absolute expiration;
263   struct GNUNET_FS_Uri *ksk_uri;
264   char * msg;
265
266   expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
267   meta = GNUNET_CONTAINER_meta_data_create ();
268   msg = NULL;
269   ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/ns-search", &msg);
270   GNUNET_assert (NULL == msg);
271   ksk_expect_uri = GNUNET_FS_uri_dup (uri);
272   GNUNET_FS_publish_ksk (fs,
273                          ksk_uri,
274                          meta,
275                          uri,
276                          expiration,
277                          1, 1,
278                          GNUNET_FS_PUBLISH_OPTION_NONE,
279                          &publish_cont,
280                          NULL);
281   GNUNET_FS_uri_destroy (ksk_uri);
282   GNUNET_CONTAINER_meta_data_destroy (meta);
283 }
284
285
286 static void
287 adv_cont (void *cls,
288           const struct GNUNET_FS_Uri *uri,
289           const char *emsg)
290 {
291   struct GNUNET_CONTAINER_MetaData *meta;
292   struct GNUNET_FS_Namespace *ns;
293   struct GNUNET_TIME_Absolute expiration;
294
295   if (NULL != emsg)
296     {
297       fprintf (stderr, "Error publishing: %s\n", emsg);
298       err = 1;
299       GNUNET_FS_stop (fs);
300       return;
301     }
302   expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
303   ns = GNUNET_FS_namespace_create (fs,
304                                    "testNamespace");
305   GNUNET_assert (NULL != ns);
306   meta = GNUNET_CONTAINER_meta_data_create ();
307   GNUNET_assert (NULL == emsg);
308   sks_expect_uri = GNUNET_FS_uri_dup (uri);
309   GNUNET_FS_publish_sks (fs,
310                          ns,
311                          "this",
312                          "next",
313                          meta,
314                          uri, /* FIXME: this is non-sense (use CHK URI!?) */
315                          expiration,
316                          1, 1,
317                          GNUNET_FS_PUBLISH_OPTION_NONE,
318                          &sks_cont,
319                          NULL);
320   GNUNET_CONTAINER_meta_data_destroy (meta);
321   GNUNET_FS_namespace_delete (ns, GNUNET_NO);
322 }
323
324
325 static void
326 ns_iterator (void *cls,
327              const char *name,
328              const GNUNET_HashCode *id)
329 {
330   int *ok = cls;
331
332   if (0 != strcmp (name,
333                    "testNamespace"))
334     return;
335   *ok = GNUNET_YES;
336   nsid = *id;
337 }
338
339
340 static void
341 testNamespace ()
342 {
343   struct GNUNET_FS_Namespace *ns;
344   struct GNUNET_TIME_Absolute expiration;
345   struct GNUNET_CONTAINER_MetaData *meta;
346   struct GNUNET_FS_Uri *ksk_uri;
347   int ok;
348
349   ns = GNUNET_FS_namespace_create (fs,
350                                    "testNamespace");
351   GNUNET_assert (NULL != ns);
352   ok = GNUNET_NO;
353   GNUNET_FS_namespace_list (fs, &ns_iterator, &ok);
354   if (GNUNET_NO == ok)
355     {
356       fprintf (stderr, "namespace_list failed to find namespace!\n");
357       GNUNET_FS_namespace_delete (ns, GNUNET_YES);
358       GNUNET_FS_stop (fs);
359       err = 1;
360       return;
361     }
362   expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
363   meta = GNUNET_CONTAINER_meta_data_create ();
364   ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/testnsa", NULL);
365   GNUNET_FS_namespace_advertise (fs,
366                                  ksk_uri,
367                                  ns,
368                                  meta,
369                                  1, 1,
370                                  expiration,                                       
371                                  "root",
372                                  &adv_cont, NULL);
373   GNUNET_FS_uri_destroy (ksk_uri);
374   GNUNET_FS_namespace_delete (ns, GNUNET_NO);
375   GNUNET_CONTAINER_meta_data_destroy (meta);
376 }
377
378
379 static void
380 run (void *cls,
381      char *const *args,
382      const char *cfgfile,
383      const struct GNUNET_CONFIGURATION_Handle *cfg)
384 {
385   setup_peer (&p1, "test_fs_namespace_data.conf");
386   fs = GNUNET_FS_start (cfg,
387                         "test-fs-namespace",
388                         &progress_cb,
389                         NULL,
390                         GNUNET_FS_FLAGS_NONE,
391                         GNUNET_FS_OPTIONS_END);
392   testNamespace ();
393 }
394
395
396 int
397 main (int argc, char *argv[])
398 {
399   char *const argvx[] = { 
400     "test-fs-namespace",
401     "-c",
402     "test_fs_namespace_data.conf",
403 #if VERBOSE
404     "-L", "DEBUG",
405 #endif
406     NULL
407   };
408   struct GNUNET_GETOPT_CommandLineOption options[] = {
409     GNUNET_GETOPT_OPTION_END
410   };
411
412   GNUNET_log_setup ("test_fs_namespace", 
413 #if VERBOSE
414                     "DEBUG",
415 #else
416                     "WARNING",
417 #endif
418                     NULL);
419   GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1,
420                       argvx, "test-fs-namespace",
421                       "nohelp", options, &run, NULL);
422   stop_arm (&p1);
423   if (GNUNET_YES != update_started)
424     {
425       fprintf (stderr,
426                "Update search never started!\n");
427       err = 1;
428     }
429   GNUNET_DISK_directory_remove ("/tmp/gnunet-test-fs-namespace/");
430   return err;
431 }
432
433
434 /* end of test_fs_namespace.c */