wlan receive implemented
[oweals/gnunet.git] / src / hostlist / test_gnunet_daemon_hostlist_learning.c
1 /*
2      This file is part of GNUnet
3      (C) 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  * @file hostlist/test_gnunet_daemon_hostlist.c
22  * @brief test for gnunet_daemon_hostslist.c
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "gnunet_arm_service.h"
28 #include "gnunet_core_service.h"
29 #include "gnunet_transport_service.h"
30 #include "gnunet_resolver_service.h"
31 #include "gnunet_statistics_service.h"
32
33 #define VERBOSE GNUNET_YES
34
35 #define START_ARM GNUNET_YES
36 #define MAX_URL_LEN 1000
37
38 /**
39  * How long until wait until testcases fails
40  */
41 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 180)
42 #define CHECK_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
43
44 static int timeout;
45 static int adv_sent;
46 static int adv_arrived;
47
48 static int learned_hostlist_saved;
49 static int learned_hostlist_downloaded;
50
51 static char * current_adv_uri;
52
53 static const struct GNUNET_CONFIGURATION_Handle *cfg;
54
55 static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
56 static GNUNET_SCHEDULER_TaskIdentifier check_task;
57     
58 struct PeerContext
59 {
60   struct GNUNET_CONFIGURATION_Handle *cfg;
61   struct GNUNET_TRANSPORT_Handle *th;
62   struct GNUNET_MessageHeader *hello;
63   struct GNUNET_CORE_Handle *core;
64   struct GNUNET_STATISTICS_Handle *stats;
65 #if START_ARM
66   struct GNUNET_OS_Process *arm_proc;
67 #endif
68 };
69
70 static struct PeerContext adv_peer;
71
72 static struct PeerContext learn_peer;
73
74 static struct GNUNET_STATISTICS_GetHandle * download_stats;
75 static struct GNUNET_STATISTICS_GetHandle * urisrecv_stat;
76 static struct GNUNET_STATISTICS_GetHandle * advsent_stat;
77
78 static void shutdown_testcase()
79 {
80   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown testcase....\n");
81   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping Timeout Task.\n");
82   if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
83   {
84     GNUNET_SCHEDULER_cancel (timeout_task);
85     timeout_task = GNUNET_SCHEDULER_NO_TASK;
86   }
87
88   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping Statistics Task.\n");
89 /*
90   if ((NULL != learn_peer.stats) && (NULL != download_stats))
91     GNUNET_STATISTICS_get_cancel (download_stats);
92   if ((NULL != learn_peer.stats) && (NULL != urisrecv_stat))
93     GNUNET_STATISTICS_get_cancel (urisrecv_stat);
94   if ((NULL != adv_peer.stats) && (NULL != advsent_stat))
95     GNUNET_STATISTICS_get_cancel (advsent_stat);
96 */
97   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping Statistics Check Task.\n");
98   if (check_task != GNUNET_SCHEDULER_NO_TASK)
99   {
100     GNUNET_SCHEDULER_cancel (check_task);
101     check_task = GNUNET_SCHEDULER_NO_TASK;
102   }
103
104   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Freeing uri\n");
105   if ( NULL != current_adv_uri ) GNUNET_free (current_adv_uri);
106   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from Transport.\n");
107   if (adv_peer.th != NULL)
108   {
109     GNUNET_TRANSPORT_disconnect (adv_peer.th);
110     adv_peer.th = NULL;
111   }
112   if (learn_peer.th != NULL)
113   {
114     GNUNET_TRANSPORT_disconnect (learn_peer.th);
115     learn_peer.th = NULL;
116   }
117
118   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from Core.\n");
119   if (adv_peer.core != NULL)
120   {
121     GNUNET_CORE_disconnect (adv_peer.core);
122     adv_peer.core = NULL;
123   }
124   if (learn_peer.core != NULL)
125   {
126     GNUNET_CORE_disconnect (learn_peer.core);
127     learn_peer.core = NULL;
128   }
129   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
130               "Asking ARM to stop core services\n");
131
132
133 #if START_ARM
134   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
135               "Killing hostlist server ARM process.\n");
136   if (0 != GNUNET_OS_process_kill (adv_peer.arm_proc, SIGTERM))
137     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
138   if (GNUNET_OS_process_wait(adv_peer.arm_proc) != GNUNET_OK)
139     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
140   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
141               "Hostlist server ARM process %u stopped\n", GNUNET_OS_process_get_pid (adv_peer.arm_proc));
142   GNUNET_OS_process_close (adv_peer.arm_proc);
143   adv_peer.arm_proc = NULL;
144 #endif
145   
146
147 #if START_ARM
148   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
149               "Killing hostlist client ARM process.\n");
150   if (0 != GNUNET_OS_process_kill (learn_peer.arm_proc, SIGTERM))
151     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
152   if (GNUNET_OS_process_wait(learn_peer.arm_proc) != GNUNET_OK)
153     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
154   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
155               "Hostlist client ARM process %u stopped\n", GNUNET_OS_process_get_pid (learn_peer.arm_proc));
156   GNUNET_OS_process_close (learn_peer.arm_proc);
157   learn_peer.arm_proc = NULL;
158 #endif
159
160   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down scheduler\n");
161   GNUNET_SCHEDULER_shutdown ();
162   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown complete....\n");
163
164 }
165
166 /**
167  * Timeout, give up.
168  */
169 static void
170 timeout_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
171 {
172   timeout_task = GNUNET_SCHEDULER_NO_TASK;
173   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
174     return;
175   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
176               "Timeout while executing testcase, test failed.\n");
177   timeout = GNUNET_YES;
178   shutdown_testcase();
179 }
180
181 static int
182 process_downloads (void *cls,
183               const char *subsystem,
184               const char *name,
185               uint64_t value,
186               int is_persistent)
187 {
188   download_stats = NULL;
189   if ( (value == 2) && (learned_hostlist_downloaded == GNUNET_NO) )
190   {
191     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
192                 _("Peer has successfully downloaded advertised URI \n"));
193     learned_hostlist_downloaded = GNUNET_YES;
194     shutdown_testcase();
195   }
196   return GNUNET_OK;
197 }
198
199 static int
200 process_uris_recv (void *cls,
201               const char *subsystem,
202               const char *name,
203               uint64_t value,
204               int is_persistent)
205 {
206   urisrecv_stat = NULL;
207   if ( ((struct PeerContext *) cls == &learn_peer) && (value == 1) && (learned_hostlist_saved == GNUNET_NO))
208   {
209     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
210                 _("Peer has successfully saved advertised URI \n"));
211     learned_hostlist_saved = GNUNET_YES;
212   }
213   return GNUNET_OK;
214 }
215
216 static int
217 process_adv_sent (void *cls,
218               const char *subsystem,
219               const char *name,
220               uint64_t value,
221               int is_persistent)
222 {
223   advsent_stat = NULL;
224   if ( (value >= 1) && (adv_sent == GNUNET_NO))
225   {
226     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
227                 _("Server has successfully sent advertisement\n"));
228     adv_sent = GNUNET_YES;
229   }
230   return GNUNET_OK;
231 }
232
233
234 /**
235  * Check the server statistics regularly
236  */
237 static void
238 check_statistics (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
239 {
240   char *stat;
241
242   check_task = GNUNET_SCHEDULER_NO_TASK;
243     if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
244       return;
245
246   GNUNET_asprintf (&stat,
247                    gettext_noop("# advertised URI `%s' downloaded"),
248                    current_adv_uri);
249   if ( NULL != learn_peer.stats)
250   {
251     download_stats = GNUNET_STATISTICS_get (learn_peer.stats,
252                            "hostlist",
253                            stat,
254                            GNUNET_TIME_UNIT_MINUTES,
255                            NULL,
256                            &process_downloads,
257                            &learn_peer);
258
259     urisrecv_stat = GNUNET_STATISTICS_get (learn_peer.stats,
260                            "hostlist",
261                            gettext_noop("# advertised hostlist URIs"),
262                            GNUNET_TIME_UNIT_MINUTES,
263                            NULL,
264                            &process_uris_recv,
265                            &learn_peer);
266   }
267   GNUNET_free (stat);
268   if ( NULL != adv_peer.stats)
269   {
270     advsent_stat = GNUNET_STATISTICS_get (adv_peer.stats,
271                            "hostlist",
272                            gettext_noop("# hostlist advertisements send"),
273                            GNUNET_TIME_UNIT_MINUTES,
274                            NULL,
275                            &process_adv_sent,
276                            NULL);
277   }
278   check_task = GNUNET_SCHEDULER_add_delayed (CHECK_INTERVALL,
279                                 &check_statistics,
280                                 NULL);
281 }
282
283 /**
284  * Core handler for p2p hostlist advertisements
285  */
286 static int 
287 ad_arrive_handler (void *cls,
288                    const struct GNUNET_PeerIdentity * peer,
289                    const struct GNUNET_MessageHeader * message,
290                    const struct GNUNET_TRANSPORT_ATS_Information *atsi)
291 {
292   char *hostname;
293   char *expected_uri;
294   unsigned long long port;
295   const struct GNUNET_MessageHeader * incoming;
296
297   if (-1 == GNUNET_CONFIGURATION_get_value_number (adv_peer.cfg,
298                                                    "HOSTLIST",
299                                                    "HTTPPORT",
300                                                    &port))
301     {
302       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
303                   "Could not read advertising server's configuration\n" );
304       return GNUNET_SYSERR;
305     }
306
307   if ( GNUNET_SYSERR  == GNUNET_CONFIGURATION_get_value_string (adv_peer.cfg,
308                                                    "HOSTLIST",
309                                                    "EXTERNAL_DNS_NAME",
310                                                    &hostname))
311     hostname = GNUNET_RESOLVER_local_fqdn_get ();
312
313   GNUNET_asprintf (&expected_uri,
314                    "http://%s:%u/",
315                    hostname != NULL ? hostname : "localhost",
316                    (unsigned int) port);   
317   incoming = (const struct GNUNET_MessageHeader *) message;
318   current_adv_uri = strdup ((char*) &incoming[1]);
319   if ( 0 == strcmp( expected_uri, current_adv_uri ) )
320     {
321       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
322                   "Recieved hostlist advertisement with URI `%s' as expected\n", current_adv_uri);
323       adv_arrived = GNUNET_YES;
324       adv_sent = GNUNET_YES;
325     }
326   else
327     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
328                 "Expected URI `%s' and recieved URI `%s' differ\n", expected_uri, current_adv_uri);
329   GNUNET_free (expected_uri);
330   GNUNET_free_non_null (hostname);
331   return GNUNET_OK;
332 }
333
334 /**
335  * List of handlers if we are learning.
336  */
337 static struct GNUNET_CORE_MessageHandler learn_handlers[] = {
338   { &ad_arrive_handler, GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT, 0},
339   { NULL, 0, 0 }
340 };
341
342 static void
343 setup_learn_peer (struct PeerContext *p, const char *cfgname)
344 {
345   char * filename;
346   unsigned int result;
347   p->cfg = GNUNET_CONFIGURATION_create ();
348 #if START_ARM
349   p->arm_proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
350                                         "gnunet-service-arm",
351 #if VERBOSE
352                                         "-L", "DEBUG",
353 #endif
354                                         "-c", cfgname, NULL);
355 #endif
356   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
357   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (p->cfg,
358                                                           "HOSTLIST",
359                                                           "HOSTLISTFILE",
360                                                           &filename))
361   {
362   if ( GNUNET_YES == GNUNET_DISK_file_test (filename) )
363     {
364       result = remove (filename);
365       if (result == 0)
366       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
367             _("Hostlist file `%s' was removed\n"),filename);
368     }
369   }
370   if ( NULL != filename)  GNUNET_free ( filename );
371
372   p->core = GNUNET_CORE_connect (p->cfg,
373                                  1,
374                                  NULL,
375                                  NULL,
376                                  NULL, NULL, NULL,
377                                  NULL, GNUNET_NO,
378                                  NULL, GNUNET_NO,
379                                  learn_handlers );
380   GNUNET_assert ( NULL != p->core );
381   p->stats = GNUNET_STATISTICS_create ("hostlist", p->cfg);
382   GNUNET_assert ( NULL != p->stats );
383 }
384
385
386 static void
387 setup_adv_peer (struct PeerContext *p, const char *cfgname)
388 {
389
390   p->cfg = GNUNET_CONFIGURATION_create ();
391 #if START_ARM
392   p->arm_proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
393                                         "gnunet-service-arm",
394 #if VERBOSE
395                                         "-L", "DEBUG",
396 #endif
397                                         "-c", cfgname, NULL);
398 #endif
399   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
400   p->stats = GNUNET_STATISTICS_create ("hostlist", p->cfg);
401   GNUNET_assert ( NULL != p->stats );
402
403 }
404
405 static void
406 run (void *cls,
407      char *const *args,
408      const char *cfgfile, 
409      const struct GNUNET_CONFIGURATION_Handle *c)
410 {
411   timeout = GNUNET_NO;
412   adv_sent =GNUNET_NO;
413
414   adv_arrived = 0;
415   learned_hostlist_saved = GNUNET_NO;
416   learned_hostlist_downloaded = GNUNET_NO;
417
418   cfg = c;
419
420   setup_adv_peer (&adv_peer, "test_learning_adv_peer.conf");
421   setup_learn_peer (&learn_peer, "test_learning_learn_peer.conf");
422   timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
423                                                &timeout_error,
424                                                NULL);
425
426   check_task = GNUNET_SCHEDULER_add_delayed (CHECK_INTERVALL,
427                                 &check_statistics,
428                                 NULL);
429 }
430
431 static int
432 check ()
433 {
434   unsigned int failed;
435   char *const argv[] = { "test-gnunet-daemon-hostlist-learning",
436     "-c", "learning_data.conf",
437 #if VERBOSE
438     "-L", "DEBUG",
439 #endif
440     NULL
441   };
442   struct GNUNET_GETOPT_CommandLineOption options[] = {
443     GNUNET_GETOPT_OPTION_END
444   };
445
446   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
447                       argv, "test-gnunet-daemon-hostlist-learning",
448                       "nohelp", options, &run, NULL);
449
450   failed = GNUNET_NO;
451
452   if (learned_hostlist_downloaded == GNUNET_YES)
453     return GNUNET_NO;
454
455   if (timeout == GNUNET_YES)
456   {
457     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
458                 "Testcase could not set up two communicating peers, timeout\n");
459     failed = GNUNET_YES;
460   }
461   if (adv_arrived != GNUNET_YES)
462   {
463     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
464                 "Learning peer did not receive advertisement from server\n");
465     failed = GNUNET_YES;
466   }
467   if ( learned_hostlist_saved == GNUNET_NO )
468     {
469       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
470                   "Peer1: Advertised hostlist was not saved in datastore\n");
471       failed = GNUNET_YES;
472     }
473   if (learned_hostlist_downloaded == GNUNET_NO)
474   {
475     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
476                 "Peer1: Advertised hostlist could not be downloaded from server\n");
477     failed = GNUNET_YES;
478   }
479   if (adv_sent == GNUNET_NO)
480   {
481     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
482                 "Advertised was not sent from server to client\n");
483     failed = GNUNET_YES;
484   }
485   if ( GNUNET_YES == failed )
486     return GNUNET_YES;
487   else
488     return GNUNET_NO;
489 }
490
491 int
492 main (int argc, char *argv[])
493 {
494   
495   int ret;
496
497   GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-hostlist-peer-1");
498   GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-hostlist-peer-2");
499   GNUNET_log_setup ("test-gnunet-daemon-hostlist",
500 #if VERBOSE
501                     "DEBUG",
502 #else
503                     "WARNING",
504 #endif
505                     NULL);
506   ret = check ();
507   GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-hostlist-peer-1");
508   GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-hostlist-peer-2");
509   if ( GNUNET_YES == GNUNET_DISK_file_test ("hostlists_learn_peer.file") )
510     {
511       if ( remove ("hostlists_learn_peer.file")  == 0)
512       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
513             _("Hostlist file hostlists_learn_peer.file was removed\n"));
514     }
515   return ret; 
516 }
517
518 /* end of test_gnunet_daemon_hostlist.c */