creating a correct testcase
[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 2, 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_transport_service.h"
29
30 #define VERBOSE GNUNET_YES
31
32 #define START_ARM GNUNET_YES
33
34
35 /**
36  * How long until we give up on transmitting the message?
37  */
38 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
39
40 static int failure;
41
42 static struct GNUNET_SCHEDULER_Handle *sched;
43
44 static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
45     
46 struct PeerContext
47 {
48   struct GNUNET_CONFIGURATION_Handle *cfg;
49   struct GNUNET_TRANSPORT_Handle *th;
50   struct GNUNET_MessageHeader *hello;
51   struct GNUNET_ARM_Handle *arm;
52 #if START_ARM
53   pid_t arm_pid;
54 #endif
55 };
56
57 static struct PeerContext adv_peer;
58
59 static struct PeerContext learn_peer;
60
61 static void
62 clean_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
63 {
64   if (adv_peer.th != NULL)
65     {
66       GNUNET_TRANSPORT_disconnect (adv_peer.th);
67       adv_peer.th = NULL;
68     }
69   if (learn_peer.th != NULL)
70     {
71       GNUNET_TRANSPORT_disconnect (learn_peer.th);
72       learn_peer.th = NULL;
73     }
74   GNUNET_SCHEDULER_shutdown (sched);
75 }
76
77 /**
78  * Timeout, give up.
79  */
80 static void
81 timeout_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
82 {
83   timeout_task = GNUNET_SCHEDULER_NO_TASK;
84   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
85               "Timeout while executing testcase, test failed.\n");
86   failure = GNUNET_YES;
87   clean_up (NULL, tc);
88 }
89
90 static void
91 setup_learn_peer (struct PeerContext *p, const char *cfgname)
92 {
93   p->cfg = GNUNET_CONFIGURATION_create ();
94 #if START_ARM
95   p->arm_pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
96                                         "gnunet-service-arm",
97 #if VERBOSE
98                                         "-L", "DEBUG",
99 #endif
100                                         "-c", cfgname, NULL);
101 #endif
102   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
103   GNUNET_ARM_start_services (p->cfg, sched, "core", NULL);
104   p->th = GNUNET_TRANSPORT_connect (sched, p->cfg, p, NULL,
105                                     NULL, NULL);
106   GNUNET_assert (p->th != NULL);
107 }
108
109
110 static void
111 setup_adv_peer (struct PeerContext *p, const char *cfgname)
112 {
113   p->cfg = GNUNET_CONFIGURATION_create ();
114 #if START_ARM
115   p->arm_pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
116                                         "gnunet-service-arm",
117 #if VERBOSE
118                                         "-L", "DEBUG",
119 #endif
120                                         "-c", cfgname, NULL);
121 #endif
122   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
123   GNUNET_ARM_start_services (p->cfg, sched, "core", NULL);
124   p->th = GNUNET_TRANSPORT_connect (sched, p->cfg, p, NULL, 
125                                     NULL, NULL);
126   GNUNET_assert (p->th != NULL);
127 }
128
129
130
131 static void
132 waitpid_task (void *cls, 
133               const struct GNUNET_SCHEDULER_TaskContext *tc)
134 {
135   struct PeerContext *p = cls;
136
137 #if START_ARM 
138   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
139               "Killing ARM process.\n");
140   if (0 != PLIBC_KILL (p->arm_pid, SIGTERM))
141     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
142   if (GNUNET_OS_process_wait(p->arm_pid) != GNUNET_OK)
143     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
144   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
145               "ARM process %u stopped\n", p->arm_pid);
146 #endif
147   GNUNET_CONFIGURATION_destroy (p->cfg);
148 }
149
150
151 static void
152 stop_cb (void *cls, 
153          int success)
154 {
155   struct PeerContext *p = cls;
156
157   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
158               success
159               ? "ARM stopped core service\n"
160               : "ARM failed to stop core service\n");
161   GNUNET_ARM_disconnect (p->arm);
162   p->arm = NULL;
163   /* make sure this runs after all other tasks are done */
164   GNUNET_SCHEDULER_add_delayed (sched,
165                                 GNUNET_TIME_UNIT_SECONDS,
166                                 &waitpid_task, p);
167 }
168
169
170 static void
171 stop_arm (struct PeerContext *p)
172 {
173   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
174               "Asking ARM to stop core service\n");
175   p->arm = GNUNET_ARM_connect (p->cfg, sched, NULL);
176   GNUNET_ARM_stop_service (p->arm, "core", GNUNET_TIME_UNIT_SECONDS,
177                            &stop_cb, p);
178 }
179
180
181 /**
182  * Try again to connect to transport service.
183  */
184 static void
185 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
186 {
187   stop_arm (&adv_peer);
188   stop_arm (&learn_peer);
189 }
190
191
192 static void
193 run (void *cls,
194      struct GNUNET_SCHEDULER_Handle *s,
195      char *const *args,
196      const char *cfgfile, 
197      const struct GNUNET_CONFIGURATION_Handle *cfg)
198 {
199   failure = GNUNET_NO;
200   sched = s;
201   timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
202                                                TIMEOUT,
203                                                &timeout_error,
204                                                NULL);
205   GNUNET_SCHEDULER_add_delayed (sched,
206                                 GNUNET_TIME_UNIT_FOREVER_REL,
207                                 &shutdown_task,
208                                 NULL);
209   setup_adv_peer (&adv_peer, "test_learning_adv_peer.conf");
210   setup_learn_peer (&learn_peer, "test_learning_learn_peer.conf");
211 }
212
213
214 static int
215 check ()
216 {
217   char *const argv[] = { "test-gnunet-daemon-hostlist",
218     "-c", "learning_data.conf",
219 #if VERBOSE
220     "-L", "DEBUG",
221 #endif
222     NULL
223   };
224   struct GNUNET_GETOPT_CommandLineOption options[] = {
225     GNUNET_GETOPT_OPTION_END
226   };
227   failure = GNUNET_NO;
228   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
229                       argv, "test-gnunet-daemon-hostlist",
230                       "nohelp", options, &run, NULL);
231   return failure;
232 }
233
234 int
235 main (int argc, char *argv[])
236 {
237   
238   int ret;
239
240   GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-hostlist-peer-1");
241   GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-hostlist-peer-2");
242   GNUNET_log_setup ("test-gnunet-daemon-hostlist",
243 #if VERBOSE
244                     "DEBUG",
245 #else
246                     "WARNING",
247 #endif
248                     NULL);
249   ret = check ();
250   GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-hostlist-peer-1");
251   GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-hostlist-peer-2");
252   return ret; 
253 }
254
255 /* end of test_gnunet_daemon_hostlist.c */