-Merge branch 'master' of ssh://gnunet.org/gnunet into gsoc2018/rest_api
[oweals/gnunet.git] / src / util / test_service.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2013, 2016 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19  * @file util/test_service.c
20  * @brief tests for service.c
21  * @author Christian Grothoff
22  */
23 #include "platform.h"
24 #include "gnunet_util_lib.h"
25
26 /**
27  * Message type we use for testing.
28  */
29 #define MY_TYPE 256
30
31 #define TIMEOUT GNUNET_TIME_UNIT_SECONDS
32
33 static int global_ret = 1;
34
35 static struct GNUNET_MQ_Handle *mq;
36
37 /**
38  * Timeout task.
39  */
40 static struct GNUNET_SCHEDULER_Task *tt;
41
42
43 static void
44 handle_recv (void *cls,
45              const struct GNUNET_MessageHeader *message)
46 {
47   struct GNUNET_SERVICE_Client *client = cls;
48   
49   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
50               "Received client message...\n");
51   GNUNET_SERVICE_client_continue (client);
52   global_ret = 2;
53   if (NULL != mq)
54   {
55     GNUNET_MQ_destroy (mq);
56     mq = NULL;
57   }
58 }
59
60
61 /**
62  * Function called when the client connects to the service.
63  *
64  * @param cls the name of the service
65  * @param c connecting client
66  * @param mq message queue to talk to the client
67  * @return @a c so we have the client handle in the future
68  */
69 static void *
70 connect_cb (void *cls,
71             struct GNUNET_SERVICE_Client *c,
72             struct GNUNET_MQ_Handle *mq)
73 {
74   /* FIXME: in the future, do something with mq
75      to test sending messages to the client! */
76   return c;
77 }
78
79
80 /**
81  * Function called when the client disconnects.
82  *
83  * @param cls our service name
84  * @param c disconnecting client
85  * @param internal_cls must match @a c
86  */ 
87 static void
88 disconnect_cb (void *cls,
89                struct GNUNET_SERVICE_Client *c,
90                void *internal_cls)
91 {
92   GNUNET_assert (c == internal_cls);
93   if (2 == global_ret)
94   {
95     GNUNET_SCHEDULER_shutdown ();
96     global_ret = 0;
97     if (NULL != tt)
98     {
99       GNUNET_SCHEDULER_cancel (tt);
100       tt = NULL;
101     }
102   }
103 }
104
105
106 static void
107 timeout_task (void *cls)
108 {
109   tt = NULL;
110   if (NULL != mq)
111   {
112     GNUNET_MQ_destroy (mq);
113     mq = NULL;
114   }
115   global_ret = 33;
116   GNUNET_SCHEDULER_shutdown ();
117 }
118
119
120 /**
121  * Initialization function of the service.  Starts
122  * a client to connect to the service.
123  *
124  * @param cls the name of the service (const char *)
125  * @param cfg the configuration we use
126  * @param sh handle to the service
127  */
128 static void
129 service_init (void *cls,
130               const struct GNUNET_CONFIGURATION_Handle *cfg,
131               struct GNUNET_SERVICE_Handle *sh)
132 {
133   const char *service_name = cls;
134   struct GNUNET_MQ_Envelope *env;
135   struct GNUNET_MessageHeader *msg;
136
137   GNUNET_assert (NULL == tt);
138   tt = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
139                                      &timeout_task,
140                                      NULL);
141   mq = GNUNET_CLIENT_connect (cfg,
142                               service_name,
143                               NULL,
144                               NULL,
145                               NULL);
146   GNUNET_assert (NULL != mq);
147   env = GNUNET_MQ_msg (msg,
148                        MY_TYPE);
149   GNUNET_MQ_send (mq,
150                   env);
151 }
152
153
154 /**
155  * Main method, starts the service and initiates
156  * the running of the test.
157  *
158  * @param sname name of the service to run
159  */
160 static int
161 check (const char *sname)
162 {
163   struct GNUNET_MQ_MessageHandler myhandlers[] = {
164     GNUNET_MQ_hd_fixed_size (recv,
165                              MY_TYPE,
166                              struct GNUNET_MessageHeader,
167                              NULL),
168     GNUNET_MQ_handler_end ()
169   };
170   char *const argv[] = {
171     (char *) sname,
172     "-c",
173     "test_service_data.conf",
174     NULL
175   };
176   
177   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
178               "Starting `%s' service\n",
179               sname);
180   global_ret = 1;
181   GNUNET_assert (0 ==
182                  GNUNET_SERVICE_run_ (3,
183                                       argv,
184                                       sname,
185                                       GNUNET_SERVICE_OPTION_NONE,
186                                       &service_init,
187                                       &connect_cb,
188                                       &disconnect_cb,
189                                       (void *) sname,
190                                       myhandlers));
191   return global_ret;
192 }
193
194
195 int
196 main (int argc,
197       char *argv[])
198 {
199   int ret = 0;
200   struct GNUNET_NETWORK_Handle *s = NULL;
201
202   GNUNET_log_setup ("test-service",
203                     "WARNING",
204                     NULL);
205   ret += check ("test_service");
206   ret += check ("test_service");
207 #ifndef MINGW
208   s = GNUNET_NETWORK_socket_create (PF_INET6,
209                                     SOCK_STREAM,
210                                     0);
211 #endif
212   if (NULL == s)
213   {
214     if ( (errno == ENOBUFS) ||
215          (errno == ENOMEM) ||
216          (errno == ENFILE) ||
217          (errno == EACCES) )
218     {
219       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
220                            "socket");
221       return 1;
222     }
223     FPRINTF (stderr,
224              "IPv6 support seems to not be available (%s), not testing it!\n",
225              strerror (errno));
226   }
227   else
228   {
229     GNUNET_break (GNUNET_OK ==
230                   GNUNET_NETWORK_socket_close (s));
231     ret += check ("test_service6");
232   }
233   return ret;
234 }
235
236 /* end of test_service.c */