missing function reference
[oweals/gnunet.git] / src / testing / test_testing_topology_clique.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 testing/test_testing_group.c
22  * @brief testcase for functions to connect two peers in testing.c
23  */
24 #include "platform.h"
25 #include "gnunet_testing_lib.h"
26
27 #define VERBOSE GNUNET_NO
28
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, 60)
34
35 #define DEFAULT_NUM_PEERS 4;
36
37 static int ok;
38
39 static unsigned long long num_peers;
40
41 static int total_connections;
42
43 static int peers_left;
44
45 static struct GNUNET_TESTING_PeerGroup *pg;
46
47 static struct GNUNET_SCHEDULER_Handle *sched;
48
49 const struct GNUNET_CONFIGURATION_Handle *main_cfg;
50
51 GNUNET_SCHEDULER_TaskIdentifier die_task;
52
53
54 static void
55 finish_testing ()
56 {
57   GNUNET_assert (pg != NULL);
58   GNUNET_TESTING_daemons_stop (pg);
59   ok = 0;
60 }
61
62
63 void
64 topology_callback (void *cls,
65                    const struct GNUNET_PeerIdentity *first,
66                    const struct GNUNET_PeerIdentity *second,
67                    const struct GNUNET_CONFIGURATION_Handle *first_cfg,
68                    const struct GNUNET_CONFIGURATION_Handle *second_cfg,
69                    struct GNUNET_TESTING_Daemon *first_daemon,
70                    struct GNUNET_TESTING_Daemon *second_daemon,
71                    const char *emsg)
72 {
73   /* Keep track of connections here if the client needs to know?
74    * Still, we have no real handle to say the i'th peer of the peer group
75    * even though we know that X peers exist in i...  But we may want to
76    * know about the peer for logging purposes here (I'm sure we will actually
77    * so the API may need changed).  Question, should the API expose what
78    * a peer group is, or provide convenience/accessor functions? */
79   if (emsg == NULL)
80     {
81       total_connections++;
82 #if VERBOSE
83       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n",
84                GNUNET_TESTING_daemon_get_shortname (first_daemon),
85                GNUNET_TESTING_daemon_get_shortname (second_daemon));
86 #endif
87     }
88 #if VERBOSE
89   else
90     {
91
92       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect peer %s to peer %s with error %s\n",
93                GNUNET_TESTING_daemon_get_shortname (first_daemon),
94                GNUNET_TESTING_daemon_get_shortname (second_daemon), emsg);
95     }
96 #endif
97
98   if (total_connections * 2 == num_peers * (num_peers - 1))
99     {
100 #if VERBOSE
101       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
102                   "Created %d total connections, which is our target number!  Ending test.\n",
103                   total_connections * 2);
104 #endif
105       GNUNET_SCHEDULER_cancel (sched, die_task);
106       finish_testing ();
107     }
108   else
109     {
110 #if VERBOSE
111       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
112                   "Have %d total connections, Need %d\n",
113                   total_connections * 2, num_peers * (num_peers - 1));
114 #endif
115     }
116 }
117
118
119 static void
120 end_badly ()
121 {
122   GNUNET_SCHEDULER_cancel (sched, die_task);
123   if (pg != NULL)
124     {
125       GNUNET_TESTING_daemons_stop (pg);
126       ok = 7331;                /* Opposite of leet */
127     }
128   else
129     ok = 401;                   /* Never got peers started */
130 }
131
132
133 static void
134 create_topology ()
135 {
136   int expected_connections;     /* Is there any way we can use this to check
137                                    how many connections we are expecting to
138                                    finish the topology?  It would be nice so
139                                    that we could estimate completion time,
140                                    but since GNUNET_TESTING_create_topology
141                                    goes off and starts connecting we may get
142                                    the topology callback before we have
143                                    finished and not know how many!  We could
144                                    just never touch expected_connections,
145                                    and if we get called back when it's still
146                                    0 then we know we can't believe it.  I
147                                    don't like this though, because it may
148                                    technically be possible for all connections
149                                    to have been created and the callback
150                                    called without us setting
151                                    expected_connections!  Other options are
152                                    doing a trial connection setup, or
153                                    calculating the number of connections.
154                                    Problem with calculating is that for random
155                                    topologies this isn't reliable.  Problem
156                                    with counting is we then iterate over them
157                                    twice instead of once.  Probably the best
158                                    option though.  Grr, also doing trial
159                                    connection set up means we need to call
160                                    fake_topology_create and then
161                                    real_topology_create which is also ugly.
162                                    Then we need to maintain state inside pg as
163                                    well, which I was trying to avoid. */
164
165   if ((pg != NULL) && (peers_left == 0))
166     {
167       /* create_topology will read the topology information from
168          the config already contained in the peer group, so should
169          we have create_topology called from start peers?  I think
170          maybe this way is best so that the client can know both
171          when peers are started, and when they are connected.
172        */
173       expected_connections = GNUNET_TESTING_create_topology (pg);
174 #if VERBOSE
175       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
176                   "Have %d expected connections\n", expected_connections);
177 #endif
178     }
179
180   GNUNET_SCHEDULER_cancel (sched, die_task);
181
182   die_task = GNUNET_SCHEDULER_add_delayed (sched,
183                                            GNUNET_TIME_relative_multiply
184                                            (GNUNET_TIME_UNIT_SECONDS, 20),
185                                            &finish_testing, NULL);
186 }
187
188
189 static void
190 my_cb (void *cls,
191        const struct GNUNET_PeerIdentity *id,
192        const struct GNUNET_CONFIGURATION_Handle *cfg,
193        struct GNUNET_TESTING_Daemon *d, const char *emsg)
194 {
195   GNUNET_assert (id != NULL);
196 #if VERBOSE
197   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %d out of %d\n",
198               (num_peers - peers_left) + 1, num_peers);
199 #endif
200   peers_left--;
201   if (peers_left == 0)
202     {
203 #if VERBOSE
204       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
205                   "All %d daemons started, now creating topology!\n",
206                   num_peers);
207 #endif
208       GNUNET_SCHEDULER_cancel (sched, die_task);
209       /* Set up task in case topology creation doesn't finish
210        * within a reasonable amount of time */
211       die_task = GNUNET_SCHEDULER_add_delayed (sched,
212                                                GNUNET_TIME_relative_multiply
213                                                (GNUNET_TIME_UNIT_MINUTES, 5),
214                                                &end_badly, NULL);
215       create_topology ();
216       ok = 0;
217     }
218 }
219
220
221 static void
222 run (void *cls,
223      struct GNUNET_SCHEDULER_Handle *s,
224      char *const *args,
225      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
226 {
227   sched = s;
228   ok = 1;
229 #if VERBOSE
230   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
231               "Starting daemons based on config file %s\n", cfgfile);
232 #endif
233   if (GNUNET_SYSERR ==
234       GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
235                                              &num_peers))
236     num_peers = DEFAULT_NUM_PEERS;
237
238   main_cfg = cfg;
239
240   peers_left = num_peers;
241
242   /* Set up a task to end testing if peer start fails */
243   die_task = GNUNET_SCHEDULER_add_delayed (sched,
244                                            GNUNET_TIME_relative_multiply
245                                            (GNUNET_TIME_UNIT_MINUTES, 5),
246                                            &end_badly, NULL);
247
248   pg = GNUNET_TESTING_daemons_start (sched, cfg,
249                                      peers_left, &my_cb, NULL,
250                                      &topology_callback, NULL, NULL);
251
252   /*
253      if (ret != GNUNET_SYSERR)
254      ret = send_test_messages (pg);
255    */
256
257 }
258
259 static int
260 check ()
261 {
262   char *const argv[] = { "test-testing-topology",
263     "-c",
264     "test_testing_data_topology_clique.conf",
265 #if VERBOSE
266     "-L", "DEBUG",
267 #endif
268     NULL
269   };
270   struct GNUNET_GETOPT_CommandLineOption options[] = {
271     GNUNET_GETOPT_OPTION_END
272   };
273   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
274                       argv, "test-testing-topology", "nohelp",
275                       options, &run, &ok);
276   return ok;
277 }
278
279 int
280 main (int argc, char *argv[])
281 {
282   int ret;
283
284   GNUNET_log_setup ("test-testing-topology_clique",
285 #if VERBOSE
286                     "DEBUG",
287 #else
288                     "WARNING",
289 #endif
290                     NULL);
291   ret = check ();
292   sleep (1);
293   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
294   return ret;
295 }
296
297 /* end of test_testing_group.c */