missing conf
[oweals/gnunet.git] / src / transport / test_transport_ats.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 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 testing/test_transport_ats.c
22  * @brief testcase for ats functionality
23  */
24 #include "platform.h"
25 #include "gnunet_testing_lib.h"
26 #include "gnunet_scheduler_lib.h"
27
28 #define VERBOSE GNUNET_NO
29
30 #define NUM_PEERS 11
31 #define MEASUREMENTS 5
32
33 #define DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
34 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
35
36
37 static int ok;
38
39 static int peers_left;
40
41 static int failed_peers;
42
43 static int measurement_started;
44
45 static struct GNUNET_TESTING_PeerGroup *pg;
46
47 static  GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
48 static  GNUNET_SCHEDULER_TaskIdentifier stats_task;
49
50 struct GNUNET_TESTING_Daemon * master_deamon;
51
52 struct GNUNET_STATISTICS_Handle * stats;
53
54 struct TEST_result
55 {
56         uint64_t timestamp;
57         uint64_t duration;
58         uint64_t mechs;
59         uint64_t peers;
60         uint64_t solution;
61 };
62
63 static int r_index;
64 //static int measurements;
65 static int peers;
66 static struct TEST_result results[MEASUREMENTS];
67
68
69 /**
70  * Check whether peers successfully shut down.
71  */
72 void
73 shutdown_callback (void *cls, const char *emsg)
74 {
75   if (emsg != NULL)
76     {
77 #if VERBOSE
78       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
79 #endif
80       if (ok == 0)
81         ok = 666;
82     }
83   else
84     {
85 #if VERBOSE
86       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
87                   "All peers successfully shut down!\n");
88 #endif
89     }
90 }
91
92 static void shutdown_peers()
93 {
94         if (shutdown_task != GNUNET_SCHEDULER_NO_TASK)
95                 GNUNET_SCHEDULER_cancel(shutdown_task);
96         if (stats_task != GNUNET_SCHEDULER_NO_TASK)
97                 GNUNET_SCHEDULER_cancel(stats_task);
98
99     GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
100 }
101
102 static void evaluate_measurements()
103 {
104         int c;
105         char * output = NULL;
106         char * temp;
107         for (c=0; c<MEASUREMENTS;c++)
108         {
109                 GNUNET_asprintf(&temp, "%s ,%i,%llu,%llu,%llu,%llu,", (output==NULL) ? "" : output, c, results[c].peers, results[c].mechs, results[c].duration, results[c].solution);
110                 GNUNET_free_non_null (output);
111                 output = temp;
112         }
113         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,"%s\n",output);
114         shutdown_peers();
115 }
116
117 int stats_cb (void *cls,
118                            const char *subsystem,
119                            const char *name,
120                            uint64_t value,
121                            int is_persistent)
122 {
123     if ((measurement_started == GNUNET_NO) && (0 == strcmp (name, "ATS peers")) && (value == peers-1))
124     {
125                 measurement_started = GNUNET_YES;
126                 r_index = 0;
127                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All %llu peers connected\n", value);
128     }
129     if (measurement_started == GNUNET_YES)
130     {
131                 // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s == %llu\n", name ,value);
132                 if (0 == strcmp (name,"ATS timestamp"))
133                 {
134                         if (results[r_index].timestamp == 0)
135                                 results[r_index].timestamp = value;
136                         if (results[r_index].timestamp != value)
137                         {
138                                 r_index++;
139                                 if (r_index >= MEASUREMENTS)
140                                 {
141                                         evaluate_measurements();
142                                         return GNUNET_NO;
143                                 }
144                                 results[r_index].timestamp = value;
145                         }
146
147                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148                                                 "[%i] ATS solution: %s %llu \n", r_index, name, value);
149                 }
150
151                 if (0 == strcmp (name,"ATS solution"))
152                 {
153                         results[r_index].solution = value;
154                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
155                                                 "[%i] ATS solution: %s %llu \n", r_index, name, value);
156                 }
157
158                 if (0 == strcmp (name,"ATS peers"))
159                 {
160                         results[r_index].peers = value;
161                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
162                                                 "[%i] ATS peers: %s %llu \n", r_index, name, value);
163                 }
164
165                 if (0 == strcmp (name,"ATS mechanisms"))
166                 {
167                         results[r_index].mechs = value;
168                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] ATS mechanisms: %s %llu \n", r_index, name, value);
169                 }
170
171                 if (0 == strcmp (name,"ATS duration"))
172                 {
173                         results[r_index].duration = value;
174                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] ATS duration: %s %llu \n", r_index, name, value);
175                 }
176     }
177     return GNUNET_OK;
178 }
179
180
181 void
182 stats_get_task (void *cls,
183                           const struct GNUNET_SCHEDULER_TaskContext *tc)
184 {
185         stats_task = GNUNET_SCHEDULER_NO_TASK;
186         if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
187             return;
188
189         GNUNET_STATISTICS_get (stats, "transport", "ATS timestamp", TIMEOUT, NULL, &stats_cb, NULL);
190         GNUNET_STATISTICS_get (stats, "transport", "ATS solution", TIMEOUT, NULL, &stats_cb, NULL);
191         GNUNET_assert (NULL != GNUNET_STATISTICS_get (stats, "transport","ATS duration", TIMEOUT, NULL, &stats_cb, NULL));
192         GNUNET_STATISTICS_get (stats, "transport", "ATS peers", TIMEOUT, NULL, &stats_cb, NULL);
193         GNUNET_STATISTICS_get (stats, "transport", "ATS mechanisms", TIMEOUT, NULL, &stats_cb, NULL);
194
195         stats_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250), &stats_get_task, NULL);
196 }
197
198 void
199 delay (void *cls,
200                           const struct GNUNET_SCHEDULER_TaskContext *tc)
201 {
202         shutdown_task = GNUNET_SCHEDULER_NO_TASK;
203         if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
204             return;
205
206 #if VERBOSE
207         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Delay over\n");
208 #endif
209         GNUNET_STATISTICS_destroy(stats, GNUNET_NO);
210         shutdown_peers ();
211 }
212
213 static void connect_peers()
214 {
215     shutdown_task = GNUNET_SCHEDULER_add_delayed(DELAY, &delay, NULL);
216
217 }
218
219 void daemon_connect_cb(void *cls,
220                                                 const struct GNUNET_PeerIdentity *first,
221                                                 const struct GNUNET_PeerIdentity *second,
222                                                 uint32_t distance,
223                                                 const struct GNUNET_CONFIGURATION_Handle *first_cfg,
224                                                 const struct GNUNET_CONFIGURATION_Handle *second_cfg,
225                                                 struct GNUNET_TESTING_Daemon *first_daemon,
226                                                 struct GNUNET_TESTING_Daemon *second_daemon,
227                                                 const char *emsg)
228 {
229           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peers `%s'<->`%s': `%s' \n", GNUNET_i2s(first), GNUNET_i2s(second), (emsg==NULL) ? "OK" : emsg);
230 }
231
232 void cont_cb (void *cls, int success)
233 {
234     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
235                 "STATS cont_cb: %i\n", success);
236 }
237
238 static void
239 daemon_start_cb (void *cls,
240        const struct GNUNET_PeerIdentity *id,
241        const struct GNUNET_CONFIGURATION_Handle *cfg,
242        struct GNUNET_TESTING_Daemon *d, const char *emsg)
243 {
244   if (id == NULL)
245     {
246       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
247                   "Start callback called with error (too long starting peers), aborting test!\n");
248       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n");
249       failed_peers++;
250       if (failed_peers == peers_left)
251         {
252           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253                       "Too many peers failed, ending test!\n");
254           ok = 1;
255         shutdown_peers ();
256         }
257       return;
258     }
259   peers_left--;
260
261   if (master_deamon == NULL)
262   {
263           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Master peer `%s' '%s'\n", GNUNET_i2s(id), d->cfgfile);
264
265           master_deamon = d;
266           stats = GNUNET_STATISTICS_create("transport", master_deamon->cfg);
267           GNUNET_assert (stats != NULL);
268           stats_task = GNUNET_SCHEDULER_add_now(&stats_get_task, NULL);
269   }
270   else
271   {
272           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer `%s'\n", GNUNET_i2s(id), GNUNET_i2s(&master_deamon->id));
273           GNUNET_TESTING_daemons_connect(d, master_deamon, TIMEOUT, 0, GNUNET_YES,&daemon_connect_cb, NULL);
274   }
275
276   if (peers_left == 0)
277     {
278       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
279                   "All peers started successfully!\n");
280       connect_peers();
281       ok = 0;
282     }
283   else if (failed_peers == peers_left)
284     {
285       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
286                   "Too many peers failed, ending test!\n");
287       GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
288       ok = 1;
289     }
290 }
291
292
293 static void
294 run (void *cls,
295      char *const *args,
296      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
297 {
298   ok = 1;
299   measurement_started = GNUNET_NO;
300 #if VERBOSE
301   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting %i peers.\n", NUM_PEERS);
302 #endif
303   peers_left = peers;
304   pg = GNUNET_TESTING_daemons_start (cfg,
305                                      peers_left, /* Total number of peers */
306                                      peers_left, /* Number of outstanding connections */
307                                      peers_left, /* Number of parallel ssh connections, or peers being started at once */
308                                      TIMEOUT,
309                                      NULL, NULL,
310                                      &daemon_start_cb, NULL, NULL, NULL, NULL);
311   GNUNET_assert (pg != NULL);
312 }
313
314 static int
315 check ()
316 {
317   char *const argv[] = { "test-testing",
318     "-c",
319     "test_transport_ats.conf",
320 #if VERBOSE
321     "-L", "DEBUG",
322 #endif
323     NULL
324   };
325   struct GNUNET_GETOPT_CommandLineOption options[] = {
326     GNUNET_GETOPT_OPTION_END
327   };
328   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
329                       argv, "test-testing-group", "nohelp",
330                       options, &run, &ok);
331   return ok;
332 }
333
334 int
335 main (int argc, char *argv[])
336 {
337   int ret;
338
339   GNUNET_log_setup ("test-transport-ats",
340 #if VERBOSE
341                     "DEBUG",
342 #else
343                     "WARNING",
344 #endif
345                     NULL);
346
347   peers = NUM_PEERS;
348   if (argc >= 2)
349   {
350           peers = atoi(argv[1]);
351           peers++;
352           if(peers <1)
353                   peers = NUM_PEERS;
354   }
355   ret = check ();
356   /**
357    * Still need to remove the base testing directory here,
358    * because group starts will create subdirectories under this
359    * main dir.  However, we no longer need to sleep, as the
360    * shutdown sequence won't return until everything is cleaned
361    * up.
362    */
363   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
364   return ret;
365 }
366
367 /* end of test_transport_ats.c*/