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