- add subdirectory gitignore files
[oweals/gnunet.git] / src / hostlist / test_gnunet_daemon_hostlist.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2009, 2016 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, 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 #include "gnunet_transport_core_service.h"
30 #include "gnunet_transport_hello_service.h"
31
32
33 /**
34  * How long until we give up on transmitting the message?
35  */
36 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 150)
37
38 static int ok;
39
40 static struct GNUNET_SCHEDULER_Task *timeout_task;
41
42 struct PeerContext
43 {
44   struct GNUNET_CONFIGURATION_Handle *cfg;
45   struct GNUNET_TRANSPORT_CoreHandle *th;
46   struct GNUNET_MessageHeader *hello;
47   struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
48   struct GNUNET_OS_Process *arm_proc;
49 };
50
51 static struct PeerContext p1;
52
53 static struct PeerContext p2;
54
55
56 static void
57 clean_up (void *cls)
58 {
59   if (NULL != p1.th)
60   {
61     if (NULL != p1.ghh)
62     {
63       GNUNET_TRANSPORT_hello_get_cancel (p1.ghh);
64       p1.ghh = NULL;
65     }
66     GNUNET_TRANSPORT_core_disconnect (p1.th);
67     p1.th = NULL;
68   }
69   if (NULL != p2.th)
70   {
71     if (NULL != p2.ghh)
72     {
73       GNUNET_TRANSPORT_hello_get_cancel (p2.ghh);
74       p2.ghh = NULL;
75     }
76     GNUNET_TRANSPORT_core_disconnect (p2.th);
77     p2.th = NULL;
78   }
79   GNUNET_SCHEDULER_shutdown ();
80 }
81
82
83 /**
84  * Timeout, give up.
85  */
86 static void
87 timeout_error (void *cls)
88 {
89   timeout_task = NULL;
90   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
91               "Timeout trying to connect peers, test failed.\n");
92   clean_up (NULL);
93 }
94
95
96 /**
97  * Function called to notify transport users that another
98  * peer connected to us.
99  *
100  * @param cls closure
101  * @param peer the peer that connected
102  * @param mq message queue to send messages to the peer
103  */
104 static void *
105 notify_connect (void *cls,
106                 const struct GNUNET_PeerIdentity *peer,
107                 struct GNUNET_MQ_Handle *mq)
108 {
109   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
110               "Peers connected, shutting down.\n");
111   ok = 0;
112   if (NULL != timeout_task)
113   {
114     GNUNET_SCHEDULER_cancel (timeout_task);
115     timeout_task = NULL;
116   }
117   GNUNET_SCHEDULER_add_now (&clean_up,
118                             NULL);
119   return NULL;
120 }
121
122
123 static void
124 process_hello (void *cls,
125                const struct GNUNET_MessageHeader *message)
126 {
127   struct PeerContext *p = cls;
128
129   GNUNET_TRANSPORT_hello_get_cancel (p->ghh);
130   p->ghh = NULL;
131   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
132               "Received HELLO, starting hostlist service.\n");
133 }
134
135
136 static void
137 setup_peer (struct PeerContext *p,
138             const char *cfgname)
139 {
140   char *binary;
141
142   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
143   p->cfg = GNUNET_CONFIGURATION_create ();
144   p->arm_proc =
145     GNUNET_OS_start_process (GNUNET_YES,
146                              GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
147                              NULL,
148                              NULL,
149                              NULL,
150                              binary,
151                              "gnunet-service-arm",
152                              "-c",
153                              cfgname,
154                              NULL);
155   GNUNET_assert (GNUNET_OK ==
156                  GNUNET_CONFIGURATION_load (p->cfg,
157                                             cfgname));
158   p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
159                                          NULL,
160                                          NULL,
161                                          p,
162                                          &notify_connect,
163                                          NULL,
164                                          NULL);
165   GNUNET_assert (NULL != p->th);
166   p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg,
167                                        GNUNET_TRANSPORT_AC_ANY,
168                                        &process_hello,
169                                        p);
170   GNUNET_free (binary);
171 }
172
173
174 static void
175 waitpid_task (void *cls)
176 {
177   struct PeerContext *p = cls;
178
179   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
180               "Killing ARM process.\n");
181   if (0 != GNUNET_OS_process_kill (p->arm_proc,
182                                    GNUNET_TERM_SIG))
183     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
184                          "kill");
185   if (GNUNET_OK !=
186       GNUNET_OS_process_wait (p->arm_proc))
187     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
188                          "waitpid");
189   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
190               "ARM process %u stopped\n",
191               GNUNET_OS_process_get_pid (p->arm_proc));
192   GNUNET_OS_process_destroy (p->arm_proc);
193   p->arm_proc = NULL;
194   GNUNET_CONFIGURATION_destroy (p->cfg);
195 }
196
197
198 static void
199 stop_arm (struct PeerContext *p)
200 {
201   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
202               "Asking ARM to stop core service\n");
203   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
204                                 &waitpid_task,
205                                 p);
206 }
207
208
209 /**
210  * Try again to connect to transport service.
211  */
212 static void
213 shutdown_task (void *cls)
214 {
215   stop_arm (&p1);
216   stop_arm (&p2);
217 }
218
219
220 static void
221 run (void *cls,
222      char *const *args,
223      const char *cfgfile,
224      const struct GNUNET_CONFIGURATION_Handle *cfg)
225 {
226   GNUNET_assert (ok == 1);
227   ok++;
228   timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
229                                                &timeout_error,
230                                                NULL);
231   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
232                                  NULL);
233   setup_peer (&p1,
234               "test_gnunet_daemon_hostlist_peer1.conf");
235   setup_peer (&p2,
236               "test_gnunet_daemon_hostlist_peer2.conf");
237 }
238
239
240 static int
241 check ()
242 {
243   char *const argv[] = {
244     "test-gnunet-daemon-hostlist",
245     "-c", "test_gnunet_daemon_hostlist_data.conf",
246     NULL
247   };
248   struct GNUNET_GETOPT_CommandLineOption options[] = {
249     GNUNET_GETOPT_OPTION_END
250   };
251   ok = 1;
252   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
253                       argv,
254                       "test-gnunet-daemon-hostlist",
255                       "nohelp",
256                       options,
257                       &run,
258                       &ok);
259   return ok;
260 }
261
262
263 int
264 main (int argc, char *argv[])
265 {
266   int ret;
267
268   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1");
269   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2");
270   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist");
271   GNUNET_log_setup ("test-gnunet-daemon-hostlist",
272                     "WARNING",
273                     NULL);
274   ret = check ();
275   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1");
276   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2");
277   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist");
278   return ret;
279 }
280
281 /* end of test_gnunet_daemon_hostlist.c */