moving ats test from transport dir to separate dir
[oweals/gnunet.git] / src / ats-test / test_transport_ats_multiple_peers.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_multiple_peers.c
22  * @brief testcase for ats functionality by starting multiple peers
23  */
24
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27
28 #include "gnunet_testing_lib.h"
29 #include "gnunet_transport_service.h"
30 #include "gauger.h"
31 #include "gnunet-service-transport_ats.h"
32
33 #define VERBOSE GNUNET_NO
34
35 #define NUM_PEERS 11
36 #define MEASUREMENTS 5
37
38 #define DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
39 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
40 #define SEND_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
41
42 static int ok;
43
44 static int peers_left;
45
46 static int failed_peers;
47
48 static int measurement_started = GNUNET_NO;
49 static char *config_file;
50
51 static struct GNUNET_TESTING_PeerGroup *pg;
52
53 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
54 static GNUNET_SCHEDULER_TaskIdentifier stats_task;
55 static GNUNET_SCHEDULER_TaskIdentifier send_task;
56 struct GNUNET_TESTING_Daemon *master_deamon;
57 struct GNUNET_TESTING_Daemon *ping_deamon;
58
59 struct GNUNET_STATISTICS_Handle *stats;
60
61 struct TEST_result
62 {
63   uint64_t timestamp;
64   uint64_t duration;
65   uint64_t mechs;
66   uint64_t peers;
67   uint64_t solution;
68   uint64_t state;
69 };
70
71 struct TestMessage
72 {
73   struct GNUNET_MessageHeader header;
74   uint32_t num;
75 };
76
77
78 static int count;
79 static int c_new;
80 static int c_unmodified;
81 static int c_modified;
82 static int connected;
83 static int peers;
84
85 static int force_q_updates;
86 static int force_rebuild;
87 static int send_msg;
88 static int machine_parsable;
89
90 static struct TEST_result results_new[MEASUREMENTS + 1];
91 static struct TEST_result results_modified[MEASUREMENTS + 1];
92 static struct TEST_result results_unmodified[MEASUREMENTS + 1];
93 static struct TEST_result current;
94
95 static struct GNUNET_STATISTICS_GetHandle *s_solution;
96 static struct GNUNET_STATISTICS_GetHandle *s_time;
97 static struct GNUNET_STATISTICS_GetHandle *s_peers;
98 static struct GNUNET_STATISTICS_GetHandle *s_mechs;
99 static struct GNUNET_STATISTICS_GetHandle *s_duration;
100 static struct GNUNET_STATISTICS_GetHandle *s_invalid;
101 static struct GNUNET_STATISTICS_GetHandle *s_state;
102
103 struct GNUNET_TRANSPORT_TransmitHandle *t;
104 struct GNUNET_TRANSPORT_Handle *th;
105
106 /**
107  * Check whether peers successfully shut down.
108  */
109 static void
110 shutdown_callback (void *cls, const char *emsg)
111 {
112   if (emsg != NULL)
113   {
114 #if VERBOSE
115     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
116 #endif
117     if (ok == 0)
118       ok = 666;
119   }
120   else
121   {
122 #if VERBOSE
123     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
124     if (stats != NULL)
125       GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
126     stats = NULL;
127 #endif
128   }
129 }
130
131 static void
132 shutdown_peers ()
133 {
134   if (shutdown_task != GNUNET_SCHEDULER_NO_TASK)
135   {
136     GNUNET_SCHEDULER_cancel (shutdown_task);
137     shutdown_task = GNUNET_SCHEDULER_NO_TASK;
138   }
139   if (stats_task != GNUNET_SCHEDULER_NO_TASK)
140   {
141     GNUNET_SCHEDULER_cancel (stats_task);
142     stats_task = GNUNET_SCHEDULER_NO_TASK;
143   }
144   if (send_task != GNUNET_SCHEDULER_NO_TASK)
145   {
146     GNUNET_SCHEDULER_cancel (send_task);
147     send_task = GNUNET_SCHEDULER_NO_TASK;
148   }
149
150   if (t != NULL)
151   {
152     GNUNET_TRANSPORT_notify_transmit_ready_cancel (t);
153     t = NULL;
154   }
155   GNUNET_TRANSPORT_disconnect (th);
156   if (s_time != NULL)
157   {
158     GNUNET_STATISTICS_get_cancel (s_time);
159     s_time = NULL;
160   }
161   if (s_peers != NULL)
162   {
163     GNUNET_STATISTICS_get_cancel (s_peers);
164     s_peers = NULL;
165   }
166   if (s_mechs != NULL)
167   {
168     GNUNET_STATISTICS_get_cancel (s_mechs);
169     s_mechs = NULL;
170   }
171   if (s_solution != NULL)
172   {
173     GNUNET_STATISTICS_get_cancel (s_solution);
174     s_solution = NULL;
175   }
176   if (s_duration != NULL)
177   {
178     GNUNET_STATISTICS_get_cancel (s_duration);
179     s_duration = NULL;
180   }
181   if (s_invalid != NULL)
182   {
183     GNUNET_STATISTICS_get_cancel (s_invalid);
184     s_invalid = NULL;
185   }
186   if (s_state != NULL)
187   {
188     GNUNET_STATISTICS_get_cancel (s_state);
189     s_state = NULL;
190   }
191   GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
192 }
193
194 static void
195 evaluate_measurements ()
196 {
197   int c;
198
199   //int mechs = 0;
200   double average[3];
201   double stddev[3];
202
203   //char * output;
204   c = 1;
205
206   //GNUNET_asprintf(&output, "p,%i,m,%i,",peers, MEASUREMENTS, results_modified[0].mechs,
207
208   average[0] = 0.0;
209   for (c = 0; c < c_new; c++)
210   {
211     average[0] += (double) results_new[c].duration;
212   }
213   average[0] /= c_new;
214
215   stddev[0] = 0.0;
216   for (c = 0; c < c_new; c++)
217   {
218     stddev[0] +=
219         (results_new[c].duration - average[0]) * (results_new[c].duration -
220                                                   average[0]);
221   }
222   stddev[0] /= c_new;
223   stddev[0] = sqrt (stddev[0]);
224   if (!machine_parsable)
225     fprintf (stderr, "new, %i measurements, average: %f stddev: %f\n", c_new,
226              average[0], stddev[0]);
227
228   average[1] = 0.0;
229   for (c = 0; c < c_modified; c++)
230   {
231     average[1] += (double) results_modified[c].duration;
232   }
233   average[1] /= c_modified;
234
235   stddev[1] = 0.0;
236   for (c = 0; c < c_modified; c++)
237   {
238     stddev[1] +=
239         (results_modified[c].duration -
240          average[1]) * (results_modified[c].duration - average[1]);
241   }
242   stddev[1] /= c_modified;
243   stddev[1] = sqrt (stddev[1]);
244   if (!machine_parsable)
245     fprintf (stderr, "modified, %i measurements, average: %f stddev: %f\n",
246              c_modified, average[1], stddev[1]);
247
248   average[2] = 0.0;
249   for (c = 0; c < c_unmodified; c++)
250   {
251     average[2] += (double) results_unmodified[c].duration;
252   }
253   average[2] /= c_unmodified;
254   stddev[2] = 0.0;
255   for (c = 0; c < c_unmodified; c++)
256   {
257     stddev[2] +=
258         (results_unmodified[c].duration -
259          average[2]) * (results_unmodified[c].duration - average[2]);
260   }
261   stddev[2] /= c_unmodified;
262   stddev[2] = sqrt (stddev[2]);
263
264   if (!machine_parsable)
265     fprintf (stderr, "unmodified, %i measurements, average: %f stddev: %f\n",
266              c_unmodified, average[2], stddev[2]);
267
268   if (machine_parsable)
269     fprintf (stderr,
270              "peers,%i,mechs,%llu," "new,%i,%f,%f," "mod,%i,%f,%f,"
271              "unmod,%i,%f,%f\n", peers - 1,
272              (unsigned long long) results_unmodified[0].mechs, c_new,
273              average[0], stddev[0], c_modified, average[1], stddev[1],
274              c_unmodified, average[2], stddev[2]);
275   shutdown_peers ();
276 }
277
278
279 static int
280 stats_cb (void *cls, const char *subsystem, const char *name, uint64_t value,
281           int is_persistent)
282 {
283   static int printed = GNUNET_NO;
284
285 #if VERBOSE_ATS
286   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s = %llu\n", name, value);
287 #endif
288   if (0 == strcmp (name, "ATS invalid solutions"))
289   {
290     if (stats_task != GNUNET_SCHEDULER_NO_TASK)
291     {
292       GNUNET_SCHEDULER_cancel (stats_task);
293       stats_task = GNUNET_SCHEDULER_NO_TASK;
294     }
295     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
296                 "MLP produced invalid %llu result(s)!\n", value);
297     shutdown_peers ();
298     return GNUNET_SYSERR;
299   }
300
301   if (0 == strcmp (name, "ATS solution"))
302   {
303     s_solution = NULL;
304   }
305
306   if (0 == strcmp (name, "ATS peers"))
307   {
308     s_peers = NULL;
309   }
310
311   if (0 == strcmp (name, "ATS mechanisms"))
312   {
313     s_mechs = NULL;
314   }
315
316   if (0 == strcmp (name, "ATS duration"))
317   {
318     s_duration = NULL;
319   }
320   if (0 == strcmp (name, "ATS timestamp"))
321   {
322     s_time = NULL;
323   }
324   if (0 == strcmp (name, "ATS state"))
325   {
326     s_state = NULL;
327   }
328
329   if ((measurement_started == GNUNET_NO) && (0 == strcmp (name, "ATS peers")) &&
330       (value == peers - 1))
331   {
332     measurement_started = GNUNET_YES;
333     count = 1;
334     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All %llu peers connected\n", value);
335 #if !VERBOSE
336     if (!machine_parsable)
337       fprintf (stderr, "%i", count);
338 #endif
339   }
340
341   if (measurement_started == GNUNET_YES)
342   {
343     // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s == %llu\n", name ,value);
344     if (0 == strcmp (name, "ATS timestamp"))
345     {
346       if (current.timestamp == 0)
347       {
348         printed = GNUNET_NO;
349         current.timestamp = value;
350       }
351       if (current.timestamp == value)
352       {
353         printed = GNUNET_YES;
354       }
355       if (current.timestamp != value)
356       {
357         if (current.state == ATS_NEW)
358         {
359           if (c_new < MEASUREMENTS)
360           {
361             results_new[c_new] = current;
362             c_new++;
363           }
364           else
365           {
366             force_rebuild = GNUNET_NO;
367             force_q_updates = GNUNET_NO;
368             send_msg = GNUNET_NO;
369           }
370         }
371         if (current.state == ATS_UNMODIFIED)
372         {
373           if (c_unmodified < MEASUREMENTS)
374           {
375             results_unmodified[c_unmodified] = current;
376             c_unmodified++;
377           }
378
379         }
380         if (current.state == ATS_QUALITY_UPDATED)
381         {
382           if (c_modified < MEASUREMENTS)
383           {
384             results_modified[c_modified] = current;
385             c_modified++;
386           }
387           else
388           {
389             force_q_updates = GNUNET_NO;
390             force_rebuild = GNUNET_YES;
391           }
392         }
393         count++;
394 #if VERBOSE
395         fprintf (stderr, "(new: %i / modified: %i / unmodified: %i) of %i \n",
396                  c_new, c_modified, c_unmodified, MEASUREMENTS);
397 #endif
398         if ((c_modified >= MEASUREMENTS) && (c_new >= MEASUREMENTS) &&
399             (c_unmodified >= MEASUREMENTS))
400         {
401 #if !VERBOSE
402           if (!machine_parsable)
403             fprintf (stdout, "\n");
404 #endif
405           if (stats_task != GNUNET_SCHEDULER_NO_TASK)
406           {
407             GNUNET_SCHEDULER_cancel (stats_task);
408             stats_task = GNUNET_SCHEDULER_NO_TASK;
409           }
410           evaluate_measurements ();
411           return GNUNET_SYSERR;
412         }
413
414         printed = GNUNET_NO;
415         current.timestamp = value;
416 #if !VERBOSE
417         if (!machine_parsable)
418           fprintf (stderr, "..%i", count);
419 #endif
420         return GNUNET_OK;
421       }
422     }
423
424     if (0 == strcmp (name, "ATS solution"))
425     {
426       current.solution = value;
427       if (printed == GNUNET_NO)
428         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] %s: %llu \n", count, name,
429                     value);
430     }
431
432     if (0 == strcmp (name, "ATS peers"))
433     {
434       current.peers = value;
435       if (printed == GNUNET_NO)
436         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] %s: %llu \n", count, name,
437                     value);
438     }
439
440     if (0 == strcmp (name, "ATS mechanisms"))
441     {
442       current.mechs = value;
443       if (printed == GNUNET_NO)
444         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] %s: %llu \n", count, name,
445                     value);
446     }
447
448     if (0 == strcmp (name, "ATS duration"))
449     {
450       current.duration = value;
451       if (printed == GNUNET_NO)
452         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] %s: %llu \n", count, name,
453                     value);
454     }
455     if (0 == strcmp (name, "ATS state"))
456     {
457       current.state = value;
458       const char *cont;
459
460       switch (value)
461       {
462       case ATS_NEW:
463         cont = "NEW";
464         break;
465       case ATS_COST_UPDATED:
466         cont = "C_UPDATED";
467         break;
468       case ATS_QUALITY_UPDATED:
469         cont = "Q_UPDATED";
470         break;
471       case ATS_QUALITY_COST_UPDATED:
472         cont = "QC_UPDATED";
473         break;
474       case ATS_UNMODIFIED:
475         cont = "UNMODIFIED";
476         break;
477       default:
478         GNUNET_break (0);
479         cont = "<undefined>";
480         break;
481       }
482       if (printed == GNUNET_NO)
483         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] ATS state: %s\n", count,
484                     cont);
485     }
486   }
487   return GNUNET_OK;
488 }
489
490
491 static void
492 stats_get_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
493 {
494   stats_task = GNUNET_SCHEDULER_NO_TASK;
495   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
496     return;
497
498   s_time =
499       GNUNET_STATISTICS_get (stats, "transport", "ATS timestamp", TIMEOUT, NULL,
500                              &stats_cb, NULL);
501   s_solution =
502       GNUNET_STATISTICS_get (stats, "transport", "ATS solution", TIMEOUT, NULL,
503                              &stats_cb, NULL);
504   s_duration =
505       GNUNET_STATISTICS_get (stats, "transport", "ATS duration", TIMEOUT, NULL,
506                              &stats_cb, NULL);
507   s_peers =
508       GNUNET_STATISTICS_get (stats, "transport", "ATS peers", TIMEOUT, NULL,
509                              &stats_cb, NULL);
510   s_mechs =
511       GNUNET_STATISTICS_get (stats, "transport", "ATS mechanisms", TIMEOUT,
512                              NULL, &stats_cb, NULL);
513   s_invalid =
514       GNUNET_STATISTICS_get (stats, "transport", "ATS invalid solutions",
515                              TIMEOUT, NULL, &stats_cb, NULL);
516   s_state =
517       GNUNET_STATISTICS_get (stats, "transport", "ATS state", TIMEOUT, NULL,
518                              &stats_cb, NULL);
519
520   stats_task =
521       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
522                                     (GNUNET_TIME_UNIT_MILLISECONDS, 100),
523                                     &stats_get_task, NULL);
524 }
525
526
527 static void
528 delay (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
529 {
530   shutdown_task = GNUNET_SCHEDULER_NO_TASK;
531   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
532     return;
533 #if VERBOSE
534   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Delay over\n");
535 #endif
536   shutdown_peers ();
537 }
538
539 static void
540 connect_peers ()
541 {
542   shutdown_task = GNUNET_SCHEDULER_add_delayed (DELAY, &delay, NULL);
543 }
544
545
546 /* To make compiler happy */
547 void
548 dummy (void)
549 {
550   struct ATS_quality_metric *q = qm;
551
552   q = NULL;
553   q++;
554   struct ATS_ressource *r = ressources;
555
556   r = NULL;
557   r++;
558 }
559
560 static size_t
561 send_dummy_data_task (void *cls, size_t size, void *buf)
562 {
563   int s = sizeof (struct TestMessage);
564   struct TestMessage hdr;
565
566   hdr.header.size = htons (s);
567   hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ATS);
568   if (force_rebuild)
569     hdr.num = htonl (1);
570   else if (force_q_updates)
571     hdr.num = htonl (2);
572   else
573     hdr.num = htonl (0);
574   memcpy (buf, &hdr, s);
575   // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sent bytes: %i of %i\n", s, s);
576   t = NULL;
577   return s;
578 }
579
580
581 static void
582 send_task_f (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
583 {
584   send_task = GNUNET_SCHEDULER_NO_TASK;
585   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
586     return;
587
588   if (t != NULL)
589   {
590     GNUNET_TRANSPORT_notify_transmit_ready_cancel (t);
591     t = NULL;
592   }
593
594   if (send_msg == GNUNET_YES)
595     t = GNUNET_TRANSPORT_notify_transmit_ready (th, &master_deamon->id,
596                                                 sizeof (struct TestMessage), 0,
597                                                 SEND_TIMEOUT,
598                                                 &send_dummy_data_task, NULL);
599   send_task =
600       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
601                                     (GNUNET_TIME_UNIT_MILLISECONDS, 1000),
602                                     &send_task_f, NULL);
603
604 }
605
606 static void
607 notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
608                 const struct GNUNET_TRANSPORT_ATS_Information *ats,
609                 uint32_t ats_count)
610 {
611   send_task = GNUNET_SCHEDULER_add_now (&send_task_f, NULL);
612 }
613
614 static void
615 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
616 {
617   if (GNUNET_SCHEDULER_NO_TASK != send_task)
618   {
619     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
620                 "Disconnect event before transmission request could be scheduled!\n");
621     GNUNET_SCHEDULER_cancel (send_task);
622     send_task = GNUNET_SCHEDULER_NO_TASK;
623   }
624   if (NULL != t)
625   {
626     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
627                 "Disconnect event before transmission request could be completed!\n");
628     GNUNET_TRANSPORT_notify_transmit_ready_cancel (t);
629     t = NULL;
630   }
631 }
632
633 static void
634 daemon_connect_cb (void *cls, const struct GNUNET_PeerIdentity *first,
635                    const struct GNUNET_PeerIdentity *second, uint32_t distance,
636                    const struct GNUNET_CONFIGURATION_Handle *first_cfg,
637                    const struct GNUNET_CONFIGURATION_Handle *second_cfg,
638                    struct GNUNET_TESTING_Daemon *first_daemon,
639                    struct GNUNET_TESTING_Daemon *second_daemon,
640                    const char *emsg)
641 {
642   char *firstc = strdup (GNUNET_i2s (first));
643   char *secondc = strdup (GNUNET_i2s (second));
644
645   connected++;
646   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peers `%s'<->`%s' (%i/%i)\n",
647               firstc, secondc, connected, peers - 1);
648   GNUNET_free (firstc);
649   GNUNET_free (secondc);
650
651   if (((first_daemon == ping_deamon) || (second_daemon == ping_deamon)) &&
652       (master_deamon != NULL) && (ping_deamon != NULL))
653   {
654     th = GNUNET_TRANSPORT_connect (ping_deamon->cfg, &ping_deamon->id, NULL,
655                                    NULL, &notify_connect, &notify_disconnect);
656     force_q_updates = GNUNET_YES;
657     send_msg = GNUNET_YES;
658   }
659 }
660
661
662
663 static void
664 daemon_start_cb (void *cls, const struct GNUNET_PeerIdentity *id,
665                  const struct GNUNET_CONFIGURATION_Handle *cfg,
666                  struct GNUNET_TESTING_Daemon *d, const char *emsg)
667 {
668   if (id == NULL)
669   {
670     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671                 "Start callback called with error (too long starting peers), aborting test!\n");
672     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n");
673     failed_peers++;
674     if (failed_peers == peers_left)
675     {
676       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
677                   "Too many peers failed, ending test!\n");
678       ok = 1;
679       shutdown_peers ();
680     }
681     return;
682   }
683   peers_left--;
684
685   if (master_deamon == NULL)
686   {
687     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Master peer `%s' '%s'\n",
688                 GNUNET_i2s (id), d->cfgfile);
689     master_deamon = d;
690     stats = GNUNET_STATISTICS_create ("transport", master_deamon->cfg);
691     GNUNET_assert (stats != NULL);
692     stats_task = GNUNET_SCHEDULER_add_now (&stats_get_task, NULL);
693   }
694   else
695   {
696     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer `%s'\n",
697                 GNUNET_i2s (id), GNUNET_i2s (&master_deamon->id));
698     GNUNET_TESTING_daemons_connect (d, master_deamon, TIMEOUT, 0, GNUNET_YES,
699                                     &daemon_connect_cb, NULL);
700   }
701
702   if (peers_left == 0)
703   {
704     if (ping_deamon == NULL)
705     {
706       ping_deamon = d;
707       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ping peer `%s' '%s'\n",
708                   GNUNET_i2s (id), d->cfgfile);
709     }
710
711     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers started successfully!\n");
712     connect_peers ();
713     ok = 0;
714   }
715   else if (failed_peers == peers_left)
716   {
717     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718                 "Too many peers failed, ending test!\n");
719     shutdown_peers ();
720     ok = 1;
721   }
722 }
723
724
725 static void
726 run (void *cls, char *const *args, const char *cfgfile,
727      const struct GNUNET_CONFIGURATION_Handle *cfg)
728 {
729   ok = 1;
730   measurement_started = GNUNET_NO;
731 #if VERBOSE
732   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting %i peers.\n", peers);
733 #endif
734   peers_left = peers;
735   pg = GNUNET_TESTING_daemons_start (cfg, peers_left,   /* Total number of peers */
736                                      peers_left,        /* Number of outstanding connections */
737                                      peers_left,        /* Number of parallel ssh connections, or peers being started at once */
738                                      TIMEOUT, NULL, NULL, &daemon_start_cb,
739                                      NULL, NULL, NULL, NULL);
740   GNUNET_assert (pg != NULL);
741 }
742
743
744 static int
745 check ()
746 {
747   char *const argv[] = { "test-testing",
748     "-c",
749     config_file,
750 #if VERBOSE
751     "-L", "DEBUG",
752 #endif
753     NULL
754   };
755   struct GNUNET_GETOPT_CommandLineOption options[] = {
756     GNUNET_GETOPT_OPTION_END
757   };
758   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
759                       "test_transport_ats_multiple_peers", "nohelp", options,
760                       &run, &ok);
761   return ok;
762 }
763
764 int
765 main (int argc, char *argv[])
766 {
767   int ret = 0;
768
769   GNUNET_log_setup ("test-transport-ats-multiple-peers",
770 #if VERBOSE
771                     "DEBUG",
772 #else
773                     "INFO",
774 #endif
775                     NULL);
776
777   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
778   machine_parsable = GNUNET_NO;
779   peers = NUM_PEERS;
780   config_file = "test_transport_ats_4addr.conf";
781
782   int c = 0;
783
784   if (argc >= 2)
785   {
786     for (c = 0; c < argc; c++)
787     {
788       /* set peers */
789       if ((strcmp (argv[c], "-p") == 0) && c < (argc - 1))
790       {
791         peers = atoi (argv[c + 1]);
792         peers++;
793       }
794       /* set machine parsable */
795       if (strcmp (argv[c], "-m") == 0)
796       {
797         machine_parsable = GNUNET_YES;
798       }
799       /* set config file */
800       if ((strcmp (argv[c], "-c") == 0) && c < (argc - 1))
801       {
802         config_file = argv[c + 1];
803       }
804     }
805   }
806
807   ret = check ();
808   /**
809    * Still need to remove the base testing directory here,
810    * because group starts will create subdirectories under this
811    * main dir.  However, we no longer need to sleep, as the
812    * shutdown sequence won't return until everything is cleaned
813    * up.
814    */
815   GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
816   return ret;
817 }
818
819 /* end of test_transport_ats_multiple_peers.c*/