-fix missing check of return value
[oweals/gnunet.git] / src / mesh / test_mesh_2dtorus.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011 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 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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file mesh/test_mesh_2dtorus.c
22  *
23  * @brief Test for creating a 2dtorus.
24  */
25 #include "platform.h"
26 #include "gnunet_testing_lib.h"
27
28 #define REMOVE_DIR GNUNET_YES
29
30 /**
31  * How long until we give up on connecting the peers?
32  */
33 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
34
35 /**
36  * Time to wait for stuff that should be rather fast
37  */
38 #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
39
40
41 /**
42  * How many events have happened
43  */
44 static int ok;
45
46 /**
47  * Be verbose
48  */
49 static int verbose;
50
51 /**
52  * Total number of peers in the test.
53  */
54 static unsigned long long num_peers;
55
56 /**
57  * Global configuration file
58  */
59 static struct GNUNET_CONFIGURATION_Handle *testing_cfg;
60
61 /**
62  * Total number of currently running peers.
63  */
64 static unsigned long long peers_running;
65
66 /**
67  * Total number of successful connections in the whole network.
68  */
69 static unsigned int total_connections;
70
71 /**
72  * Total number of counted topo connections
73  */
74 static unsigned int topo_connections;
75
76 /**
77  * Total number of failed connections in the whole network.
78  */
79 static unsigned int failed_connections;
80
81 /**
82  * The currently running peer group.
83  */
84 static struct GNUNET_TESTING_PeerGroup *pg;
85
86 /**
87  * Task called to disconnect peers
88  */
89 static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
90
91 /**
92  * Task called to shutdown test.
93  */
94 static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
95
96
97 /**
98  * Check whether peers successfully shut down.
99  */
100 static void
101 shutdown_callback (void *cls, const char *emsg)
102 {
103   if (emsg != NULL)
104   {
105     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
106                 "test: Shutdown of peers failed! (%s)\n", emsg);
107     ok--;
108   }
109   else
110   {
111     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
112                 "test: All peers successfully shut down!\n");
113   }
114   GNUNET_CONFIGURATION_destroy (testing_cfg);
115 }
116
117
118 static void
119 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
120 {
121   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Ending test.\n");
122   GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
123 }
124
125
126 static void
127 disconnect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
128 {
129   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: disconnecting peers\n");
130
131   if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
132   {
133     GNUNET_SCHEDULER_cancel (shutdown_handle);
134     shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
135   }
136 }
137
138
139 /**
140  * Prototype of a callback function indicating that two peers
141  * are currently connected.
142  *
143  * @param cls closure
144  * @param first peer id for first daemon
145  * @param second peer id for the second daemon
146  * @param distance distance between the connected peers
147  * @param emsg error message (NULL on success)
148  */
149 void
150 topo_cb (void *cls, const struct GNUNET_PeerIdentity *first,
151          const struct GNUNET_PeerIdentity *second, const char *emsg)
152 {
153   topo_connections++;
154   if (NULL != emsg)
155   {
156     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: Error by topo %u: %s\n",
157                 topo_connections, emsg);
158   }
159   else
160   {
161     if (first == NULL || second == NULL)
162     {
163       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u NULL\n",
164                   topo_connections);
165       if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
166       {
167         GNUNET_SCHEDULER_cancel (disconnect_task);
168         disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL);
169       }
170       return;
171     }
172     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u ok\n",
173                 topo_connections);
174     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   %s\n", GNUNET_i2s (first));
175     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   %s\n", GNUNET_i2s (second));
176   }
177 }
178
179
180 /**
181  * peergroup_ready: start test when all peers are connected
182  * @param cls closure
183  * @param emsg error message
184  */
185 static void
186 peergroup_ready (void *cls, const char *emsg)
187 {
188   if (emsg != NULL)
189   {
190     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
191                 "test: Peergroup callback called with error, aborting test!\n");
192     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Error from testing: `%s'\n",
193                 emsg);
194     ok--;
195     GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
196     return;
197   }
198   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
199               "test: Peer Group started successfully with %u connections\n",
200               total_connections);
201   peers_running = GNUNET_TESTING_daemons_running (pg);
202   if (0 < failed_connections)
203   {
204     ok = GNUNET_SYSERR;
205     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: %u connections have FAILED!\n",
206                 failed_connections);
207     disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL);
208
209   }
210   else
211   {
212     GNUNET_TESTING_get_topology (pg, &topo_cb, NULL);
213     disconnect_task =
214         GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_peers, NULL);
215     ok = GNUNET_OK;
216   }
217
218 }
219
220
221 /**
222  * Function that will be called whenever two daemons are connected by
223  * the testing library.
224  *
225  * @param cls closure
226  * @param first peer id for first daemon
227  * @param second peer id for the second daemon
228  * @param distance distance between the connected peers
229  * @param first_cfg config for the first daemon
230  * @param second_cfg config for the second daemon
231  * @param first_daemon handle for the first daemon
232  * @param second_daemon handle for the second daemon
233  * @param emsg error message (NULL on success)
234  */
235 static void
236 connect_cb (void *cls, const struct GNUNET_PeerIdentity *first,
237             const struct GNUNET_PeerIdentity *second, uint32_t distance,
238             const struct GNUNET_CONFIGURATION_Handle *first_cfg,
239             const struct GNUNET_CONFIGURATION_Handle *second_cfg,
240             struct GNUNET_TESTING_Daemon *first_daemon,
241             struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg)
242 {
243   if (emsg == NULL)
244   {
245     total_connections++;
246   }
247   else
248   {
249     failed_connections++;
250     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
251                 "test: Problem with new connection (%s)\n", emsg);
252     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   (%s)\n", GNUNET_i2s (first));
253     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   (%s)\n", GNUNET_i2s (second));
254   }
255
256 }
257
258
259 /**
260  * run: load configuration options and schedule test to run (start peergroup)
261  * @param cls closure
262  * @param args argv
263  * @param cfgfile configuration file name (can be NULL)
264  * @param cfg configuration handle
265  */
266 static void
267 run (void *cls, char *const *args, const char *cfgfile,
268      const struct GNUNET_CONFIGURATION_Handle *cfg)
269 {
270   struct GNUNET_TESTING_Host *hosts;
271
272   ok = GNUNET_NO;
273   total_connections = 0;
274   failed_connections = 0;
275   testing_cfg = GNUNET_CONFIGURATION_dup (cfg);
276
277   GNUNET_log_setup ("test_mesh_2dtorus",
278                     "WARNING",
279                     NULL);
280
281
282   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Starting daemons.\n");
283   if (GNUNET_OK !=
284       GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing_old",
285                                              "num_peers", &num_peers))
286   {
287     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
288                 "Option TESTING:NUM_PEERS is required!\n");
289     return;
290   }
291
292   hosts = GNUNET_TESTING_hosts_load (testing_cfg);
293
294   pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT,
295                                        &connect_cb, &peergroup_ready, NULL,
296                                        hosts);
297   GNUNET_assert (pg != NULL);
298   shutdown_handle =
299     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
300                                     &shutdown_task, NULL);
301 }
302
303
304 /**
305  * test_mesh_2dtorus command line options
306  */
307 static struct GNUNET_GETOPT_CommandLineOption options[] = {
308   {'V', "verbose", NULL,
309    gettext_noop ("be verbose (print progress information)"),
310    0, &GNUNET_GETOPT_set_one, &verbose},
311   GNUNET_GETOPT_OPTION_END
312 };
313
314
315 /**
316  * Main: start test
317  */
318 int
319 main (int argc, char *argv[])
320 {
321   char *const argv2[] = {
322     argv[0],
323     "-c",
324     "test_mesh_2dtorus.conf",
325     NULL
326   };
327
328   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Start\n");
329
330
331   GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
332                       "test_mesh_2dtorus", gettext_noop ("Test mesh 2d torus."),
333                       options, &run, NULL);
334 #if REMOVE_DIR
335   GNUNET_DISK_directory_remove ("/tmp/test_mesh_2dtorus");
336 #endif
337   if (GNUNET_OK != ok)
338   {
339     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n");
340     return 1;
341   }
342   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: success\n");
343   return 0;
344 }
345
346 /* end of test_mesh_2dtorus.c */