stuff
[oweals/gnunet.git] / src / util / test_service.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 util/test_service.c
22  * @brief tests for service.c
23  */
24 #include "platform.h"
25 #include "gnunet_common.h"
26 #include "gnunet_client_lib.h"
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_program_lib.h"
29 #include "gnunet_service_lib.h"
30 #include "gnunet_scheduler_lib.h"
31 #include "gnunet_time_lib.h"
32
33
34 #define VERBOSE GNUNET_NO
35
36 #define PORT 12435
37
38 #define MY_TYPE 256
39
40 static struct GNUNET_SCHEDULER_Handle *sched;
41
42 static struct GNUNET_SERVICE_Context *sctx;
43
44 static int ok = 1;
45
46 void
47 end_cont (void *cls,
48           int reason)
49 {
50   if (sctx != NULL)
51     GNUNET_SERVICE_stop (sctx);
52   else
53     GNUNET_SCHEDULER_shutdown (sched);
54   ok = 0;
55 }
56
57 static void
58 end_it (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
59 {
60   struct GNUNET_CLIENT_Connection *client = cls;
61
62   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down service\n");
63   GNUNET_CLIENT_service_shutdown (sched, client, GNUNET_TIME_UNIT_FOREVER_REL, &end_cont, NULL);
64 }
65
66
67 static size_t
68 build_msg (void *cls, size_t size, void *buf)
69 {
70   struct GNUNET_CLIENT_Connection *client = cls;
71   struct GNUNET_MessageHeader *msg = buf;
72
73   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected, transmitting\n");
74   GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
75   msg->type = htons (MY_TYPE);
76   msg->size = htons (sizeof (struct GNUNET_MessageHeader));
77   GNUNET_SCHEDULER_add_continuation (sched,
78                                      &end_it,
79                                      client,
80                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
81   return sizeof (struct GNUNET_MessageHeader);
82 }
83
84
85 static void
86 ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
87 {
88   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
89   struct GNUNET_CLIENT_Connection *client;
90
91   GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE));
92   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service confirmed running\n");
93   sched = tc->sched;
94   client = GNUNET_CLIENT_connect (tc->sched, "test_service", cfg);
95   GNUNET_assert (client != NULL);
96   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
97               "Client connecting, waiting to transmit\n");
98   GNUNET_CLIENT_notify_transmit_ready (client,
99                                        sizeof (struct GNUNET_MessageHeader),
100                                        GNUNET_TIME_UNIT_SECONDS,
101                                        GNUNET_NO, &build_msg, client);
102 }
103
104 static void
105 recv_cb (void *cls,
106          struct GNUNET_SERVER_Client *client,
107          const struct GNUNET_MessageHeader *message)
108 {
109   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving client message...\n");
110   GNUNET_SERVER_receive_done (client, GNUNET_OK);
111 }
112
113 static struct GNUNET_SERVER_MessageHandler myhandlers[] = {
114   {&recv_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)},
115   {NULL, NULL, 0, 0}
116 };
117
118
119
120
121 static void
122 runner (void *cls,
123         struct GNUNET_SCHEDULER_Handle *sched,
124         struct GNUNET_SERVER_Handle *server,
125         const struct GNUNET_CONFIGURATION_Handle *cfg)
126 {
127   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service initializing\n");
128   GNUNET_SERVER_add_handlers (server, myhandlers);
129   GNUNET_CLIENT_service_test (sched,
130                               "test_service",
131                               cfg, GNUNET_TIME_UNIT_SECONDS, &ready,
132                               (void *) cfg);
133 }
134
135
136 /**
137  * Main method, starts scheduler with task1,
138  * checks that "ok" is correct at the end.
139  */
140 static int
141 check ()
142 {
143   ok = 1;
144   char *const argv[] = {
145     "test_service",
146     "-c",
147     "test_service_data.conf",
148     "-L",
149 #if VERBOSE
150     "DEBUG",
151 #else
152     "WARNING",
153 #endif
154     NULL
155   };
156   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting service\n");
157   GNUNET_assert (GNUNET_OK ==
158                  GNUNET_SERVICE_run (5,
159                                      argv,
160                                      "test_service",
161                                      GNUNET_SERVICE_OPTION_NONE,
162                                      &runner, &ok));
163   GNUNET_assert (0 == ok);
164   return ok;
165 }
166
167 static void
168 ready6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
169 {
170   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
171   struct GNUNET_CLIENT_Connection *client;
172
173   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "V6 ready\n");
174   sched = tc->sched;
175   GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE));
176   client = GNUNET_CLIENT_connect (tc->sched, "test_service6", cfg);
177   GNUNET_assert (client != NULL);
178   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "V6 client connected\n");
179   GNUNET_CLIENT_notify_transmit_ready (client,
180                                        sizeof (struct GNUNET_MessageHeader),
181                                        GNUNET_TIME_UNIT_SECONDS,
182                                        GNUNET_NO, &build_msg, client);
183 }
184
185 static void
186 runner6 (void *cls,
187          struct GNUNET_SCHEDULER_Handle *sched,
188          struct GNUNET_SERVER_Handle *server,
189          const struct GNUNET_CONFIGURATION_Handle *cfg)
190 {
191   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initializing v6 service\n");
192   GNUNET_SERVER_add_handlers (server, myhandlers);
193   GNUNET_CLIENT_service_test (sched,
194                               "test_service6",
195                               cfg, GNUNET_TIME_UNIT_SECONDS, &ready6,
196                               (void *) cfg);
197 }
198
199 /**
200  * Main method, starts scheduler with task1,
201  * checks that "ok" is correct at the end.
202  */
203 static int
204 check6 ()
205 {
206   char *const argv[] = {
207     "test_service6",
208     "-c",
209     "test_service_data.conf",
210     "-L",
211 #if VERBOSE
212     "DEBUG",
213 #else
214     "WARNING",
215 #endif
216     NULL
217   };
218   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting v6 service\n");
219   GNUNET_assert (GNUNET_OK ==
220                  GNUNET_SERVICE_run (5,
221                                      argv,
222                                      "test_service6",
223                                      GNUNET_SERVICE_OPTION_NONE,
224                                      &runner6, &ok));
225   GNUNET_assert (0 == ok);
226   return ok;
227 }
228
229
230 /**
231  * Main method, starts scheduler with task1,
232  * checks that "ok" is correct at the end.
233  */
234 static int
235 check6d ()
236 {
237   ok = 1;
238   char *const argv[] = {
239     "test_service6",
240     "-c",
241     "test_service_data.conf",
242     "-L",
243 #if VERBOSE
244     "DEBUG",
245 #else
246     "WARNING",
247 #endif
248     "-d",
249     NULL
250   };
251   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting V6 as daemon\n");
252   GNUNET_assert (GNUNET_OK ==
253                  GNUNET_SERVICE_run (6,
254                                      argv,
255                                      "test_service6",
256                                      GNUNET_SERVICE_OPTION_NONE,
257                                      &runner6, &ok));
258   GNUNET_break (0 == ok);
259   return ok;
260 }
261
262
263 static void
264 start_stop_main (void *cls,
265                  struct GNUNET_SCHEDULER_Handle *sched,
266                  char *const *args,
267                  const char *cfgfile,
268                  const struct GNUNET_CONFIGURATION_Handle *cfg)
269 {
270   int *ret = cls;
271   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
272               "Starting service using start method\n");
273   sctx = GNUNET_SERVICE_start ("test_service", sched, cfg);
274   runner (cls, sched, GNUNET_SERVICE_get_server (sctx), cfg);
275   *ret = 0;
276 }
277
278
279 static int
280 check_start_stop ()
281 {
282   char *const argv[] = {
283     "test-service-program",
284     "-c",
285     "test_service_data.conf",
286     "-L",
287 #if VERBOSE
288     "DEBUG",
289 #else
290     "WARNING",
291 #endif
292     NULL
293   };
294   const struct GNUNET_GETOPT_CommandLineOption options[] = {
295     GNUNET_GETOPT_OPTION_END
296   };
297   int ret = 1;
298   GNUNET_assert (GNUNET_OK ==
299                  GNUNET_PROGRAM_run (5,
300                                      argv,
301                                      "test-service-program",
302                                      "no help",
303                                      options, &start_stop_main, &ret));
304
305   GNUNET_break (0 == ret);
306   return ret;
307 }
308
309
310 int
311 main (int argc, char *argv[])
312 {
313   int ret = 0;
314   struct GNUNET_NETWORK_Handle *s = NULL;
315
316   GNUNET_log_setup ("test-service",
317 #if VERBOSE
318                     "DEBUG",
319 #else
320                     "WARNING",
321 #endif
322                     NULL);
323   ret += check ();
324   ret += check ();
325
326   // FIXME
327 #ifndef MINGW
328   s = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
329 #endif
330   if (NULL == s)
331     {
332       if ((errno == ENOBUFS) ||
333           (errno == ENOMEM) || (errno == ENFILE) || (errno == EACCES))
334         {
335           GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
336           return 1;
337         }
338       fprintf (stderr,
339                "IPv6 support seems to not be available (%s), not testing it!\n",
340                strerror (errno));
341     }
342   else
343     {
344       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
345       ret += check6 ();
346       ret += check6d ();        /* with daemonization */
347     }
348   ret += check_start_stop ();
349
350   return ret;
351 }
352
353 /* end of test_service.c */