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