4e67ef152cf7c86ba361b9efe371794528232d27
[oweals/gnunet.git] / src / testbed / test_testbed_api_3peers_3controllers.c
1 /*
2       This file is part of GNUnet
3       Copyright (C) 2008--2013 GNUnet e.V.
4
5       GNUnet is free software: you can redistribute it and/or modify it
6       under the terms of the GNU Affero General Public License as published
7       by the Free Software Foundation, either version 3 of the License,
8       or (at your 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       Affero General Public License for more details.
14      
15       You should have received a copy of the GNU Affero General Public License
16       along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 /**
20  * @file testbed/test_testbed_api_3peers_3controllers.c
21  * @brief testcases for the testbed api: 3 peers are configured, started and
22  *          connected together. Each peer resides on its own controller.
23  * @author Sree Harsha Totakura
24  */
25
26
27 /**
28  * The testing architecture is:
29  *                  A
30  *                 / \
31  *                /   \
32  *               B === C
33  * A is the master controller and B, C are slave controllers. B links to C
34  * laterally.
35  * Peers are mapped to controllers in the following relations:
36  *             Peer         Controller
37  *               1              A
38  *               2              B
39  *               3              C
40  *
41  */
42
43 #include "platform.h"
44 #include "gnunet_util_lib.h"
45 #include "gnunet_testing_lib.h"
46 #include "gnunet_testbed_service.h"
47
48
49 /**
50  * Generic logging shortcut
51  */
52 #define LOG(kind,...)                           \
53   GNUNET_log (kind, __VA_ARGS__)
54
55 /**
56  * Relative time seconds shorthand
57  */
58 #define TIME_REL_SECS(sec) \
59   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
60
61
62 /**
63  * Peer context
64  */
65 struct PeerContext
66 {
67   /**
68    * The peer handle
69    */
70   struct GNUNET_TESTBED_Peer *peer;
71
72   /**
73    * Operations involving this peer
74    */
75   struct GNUNET_TESTBED_Operation *operation;
76
77   /**
78    * set to GNUNET_YES when peer is started
79    */
80   int is_running;
81 };
82
83 /**
84  * Our localhost
85  */
86 static struct GNUNET_TESTBED_Host *host;
87
88 /**
89  * The controller process of one controller
90  */
91 static struct GNUNET_TESTBED_ControllerProc *cp1;
92
93 /**
94  * A neighbouring host
95  */
96 static struct GNUNET_TESTBED_Host *neighbour1;
97
98 /**
99  * Another neighbouring host
100  */
101 static struct GNUNET_TESTBED_Host *neighbour2;
102
103 /**
104  * Handle for neighbour registration
105  */
106 static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
107
108 /**
109  * The controller handle of one controller
110  */
111 static struct GNUNET_TESTBED_Controller *controller1;
112
113 /**
114  * peer 1
115  */
116 static struct PeerContext peer1;
117
118 /**
119  * peer2
120  */
121 static struct PeerContext peer2;
122
123 /**
124  * peer3
125  */
126 static struct PeerContext peer3;
127
128 /**
129  * Handle to starting configuration
130  */
131 static struct GNUNET_CONFIGURATION_Handle *cfg;
132
133 /**
134  * Handle to slave controller C's configuration, used to establish lateral link from
135  * master controller
136  */
137 static struct GNUNET_CONFIGURATION_Handle *cfg2;
138
139 /**
140  * Handle to operations involving both peers
141  */
142 static struct GNUNET_TESTBED_Operation *common_operation;
143
144 /**
145  * The handle for whether a host is habitable or not
146  */
147 struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle;
148
149 /**
150  * Abort task identifier
151  */
152 static struct GNUNET_SCHEDULER_Task * abort_task;
153
154 /**
155  * Delayed connect job identifier
156  */
157 static struct GNUNET_SCHEDULER_Task * delayed_connect_task;
158
159 /**
160  * Different stages in testing
161  */
162 enum Stage
163 {
164
165   /**
166    * Initial stage
167    */
168   INIT,
169
170   /**
171    * Controller 1 has started
172    */
173   CONTROLLER1_UP,
174
175   /**
176    * peer1 is created
177    */
178   PEER1_CREATED,
179
180   /**
181    * peer1 is started
182    */
183   PEER1_STARTED,
184
185   /**
186    * Controller 2 has started
187    */
188   CONTROLLER2_UP,
189
190   /**
191    * peer2 is created
192    */
193   PEER2_CREATED,
194
195   /**
196    * peer2 is started
197    */
198   PEER2_STARTED,
199
200   /**
201    * Controller 3 has started
202    */
203   CONTROLLER3_UP,
204
205   /**
206    * Peer3 is created
207    */
208   PEER3_CREATED,
209
210   /**
211    * Peer3 started
212    */
213   PEER3_STARTED,
214
215   /**
216    * peer1 and peer2 are connected
217    */
218   PEERS_1_2_CONNECTED,
219
220   /**
221    * peer2 and peer3 are connected
222    */
223   PEERS_2_3_CONNECTED,
224
225   /**
226    * Peers are connected once again (this should not fail as they are already connected)
227    */
228   PEERS_CONNECTED_2,
229
230   /**
231    * peers are stopped
232    */
233   PEERS_STOPPED,
234
235   /**
236    * Final success stage
237    */
238   SUCCESS,
239
240   /**
241    * Optional stage for marking test to be skipped
242    */
243   SKIP
244 };
245
246 /**
247  * The testing result
248  */
249 static enum Stage result;
250
251 /**
252  * Shutdown nicely
253  *
254  * @param cls NULL
255  */
256 static void
257 do_shutdown (void *cls)
258 {
259   if (NULL != abort_task)
260     GNUNET_SCHEDULER_cancel (abort_task);
261   if (NULL != hc_handle)
262     GNUNET_TESTBED_is_host_habitable_cancel (hc_handle);
263   GNUNET_assert (NULL == delayed_connect_task);
264   if (NULL != common_operation)
265     GNUNET_TESTBED_operation_done (common_operation);
266   if (NULL != reg_handle)
267     GNUNET_TESTBED_cancel_registration (reg_handle);
268   if (NULL != controller1)
269     GNUNET_TESTBED_controller_disconnect (controller1);
270   GNUNET_CONFIGURATION_destroy (cfg);
271   if (NULL != cfg2)
272     GNUNET_CONFIGURATION_destroy (cfg2);
273   if (NULL != cp1)
274     GNUNET_TESTBED_controller_stop (cp1);
275   if (NULL != host)
276     GNUNET_TESTBED_host_destroy (host);
277   if (NULL != neighbour1)
278     GNUNET_TESTBED_host_destroy (neighbour1);
279   if (NULL != neighbour2)
280     GNUNET_TESTBED_host_destroy (neighbour2);
281 }
282
283
284 /**
285  * abort task to run on test timed out
286  *
287  * @param cls NULL
288  */
289 static void
290 do_abort (void *cls)
291 {
292   LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
293   abort_task = NULL;
294   if (NULL != delayed_connect_task)
295   {
296     GNUNET_SCHEDULER_cancel (delayed_connect_task);
297     delayed_connect_task = NULL;
298   }
299   do_shutdown (cls);
300 }
301
302
303 static void
304 abort_test ()
305 {
306   if (NULL != abort_task)
307     GNUNET_SCHEDULER_cancel (abort_task);
308   abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
309 }
310
311
312 /**
313  * Callback to be called when an operation is completed
314  *
315  * @param cls the callback closure from functions generating an operation
316  * @param op the operation that has been finished
317  * @param emsg error message in case the operation has failed; will be NULL if
318  *          operation has executed successfully.
319  */
320 static void
321 op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg);
322
323
324 /**
325  * task for delaying a connect
326  *
327  * @param cls NULL
328  */
329 static void
330 do_delayed_connect (void *cls)
331 {
332   delayed_connect_task = NULL;
333   if (NULL != common_operation)
334   {
335     GNUNET_break (0);
336     abort_test ();
337     return;
338   }
339   common_operation =
340       GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer,
341                                       peer2.peer);
342 }
343
344
345 /**
346  * Callback to be called when an operation is completed
347  *
348  * @param cls the callback closure from functions generating an operation
349  * @param op the operation that has been finished
350  * @param emsg error message in case the operation has failed; will be NULL if
351  *          operation has executed successfully.
352  */
353 static void
354 op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
355 {
356   if (common_operation != op)
357   {
358     GNUNET_break (0);
359     abort_test ();
360     return;
361   }
362
363   switch (result)
364   {
365   case PEER3_STARTED:
366   case PEERS_2_3_CONNECTED:
367   case PEERS_1_2_CONNECTED:
368     break;
369   default:
370     GNUNET_break (0);
371     abort_test ();
372     return;
373   }
374   if ((NULL != peer1.operation) || (NULL != peer2.operation) ||
375       (NULL != peer3.operation))
376   {
377     GNUNET_break (0);
378     abort_test ();
379     return;
380   }
381 }
382
383
384 /**
385  * Functions of this signature are called when a peer has been successfully
386  * created
387  *
388  * @param cls NULL
389  * @param peer the handle for the created peer; NULL on any error during
390  *          creation
391  * @param emsg NULL if peer is not NULL; else MAY contain the error description
392  */
393 static void
394 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
395 {
396   switch (result)
397   {
398   case CONTROLLER1_UP:
399     if ((NULL == peer1.operation) || (NULL == peer) || (NULL != peer1.peer))
400     {
401       GNUNET_break (0);
402       abort_test ();
403       return;
404     }
405     peer1.peer = peer;
406     GNUNET_TESTBED_operation_done (peer1.operation);
407     result = PEER1_CREATED;
408     peer1.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL);
409     break;
410   case CONTROLLER2_UP:
411     if ((NULL == peer2.operation) || (NULL == peer) || (NULL != peer2.peer))
412     {
413       GNUNET_break (0);
414       abort_test ();
415       return;
416     }
417     peer2.peer = peer;
418     GNUNET_TESTBED_operation_done (peer2.operation);
419     result = PEER2_CREATED;
420     peer2.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL);
421     break;
422   case CONTROLLER3_UP:
423     if ((NULL == peer3.operation) || (NULL == peer) || (NULL != peer3.peer))
424     {
425       GNUNET_break (0);
426       abort_test ();
427       return;
428     }
429     peer3.peer = peer;
430     GNUNET_TESTBED_operation_done (peer3.operation);
431     result = PEER3_CREATED;
432     peer3.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL);
433     break;
434   default:
435     GNUNET_break (0);
436     abort_test ();
437     return;
438   }
439 }
440
441
442 /**
443  * Signature of the event handler function called by the
444  * respective event controller.
445  *
446  * @param cls closure
447  * @param event information about the event
448  */
449 static void
450 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
451 {
452   switch (event->type)
453   {
454   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
455     if ((NULL != event->op_cls) ||
456         (NULL != event->details.operation_finished.emsg))
457     {
458       GNUNET_break (0);
459       abort_test ();
460       return;
461     }
462     switch (result)
463     {
464     case PEERS_STOPPED:
465       if (NULL != event->details.operation_finished.generic)
466       {
467         GNUNET_break (0);
468         abort_test ();
469         return;
470       }
471       if (event->op == peer1.operation)
472       {
473         GNUNET_TESTBED_operation_done (peer1.operation);
474         peer1.operation = NULL;
475         peer1.peer = NULL;
476       }
477       else if (event->op == peer2.operation)
478       {
479         GNUNET_TESTBED_operation_done (peer2.operation);
480         peer2.operation = NULL;
481         peer2.peer = NULL;
482       }
483       else if (event->op == peer3.operation)
484       {
485         GNUNET_TESTBED_operation_done (peer3.operation);
486         peer3.operation = NULL;
487         peer3.peer = NULL;
488       }
489       else
490       {
491         GNUNET_break (0);
492         abort_test ();
493         return;
494       }
495       if ((NULL == peer1.peer) && (NULL == peer2.peer) && (NULL == peer3.peer))
496       {
497         result = SUCCESS;
498         GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
499       }
500       break;
501     case PEER1_STARTED:
502       if ((NULL != event->details.operation_finished.generic) ||
503           (NULL == common_operation))
504       {
505         GNUNET_break (0);
506         abort_test ();
507         return;
508       }
509       GNUNET_TESTBED_operation_done (common_operation);
510       common_operation = NULL;
511       result = CONTROLLER2_UP;
512       peer2.operation =
513           GNUNET_TESTBED_peer_create (controller1, neighbour1, cfg,
514                                       &peer_create_cb, NULL);
515       if (NULL == peer2.operation)
516       {
517         GNUNET_break (0);
518         abort_test ();
519         return;
520       }
521       break;
522     case PEER2_STARTED:
523       if ((NULL != event->details.operation_finished.generic) ||
524           (NULL == common_operation))
525       {
526         GNUNET_break (0);
527         abort_test ();
528         return;
529       }
530       GNUNET_TESTBED_operation_done (common_operation);
531       common_operation = NULL;
532       result = CONTROLLER3_UP;
533       peer3.operation =
534           GNUNET_TESTBED_peer_create (controller1, neighbour2, cfg,
535                                       &peer_create_cb, NULL);
536       if (NULL == peer3.operation)
537       {
538         GNUNET_break (0);
539         abort_test ();
540         return;
541       }
542       break;
543     default:
544       GNUNET_break (0);
545       abort_test ();
546       return;
547     }
548     break;
549   case GNUNET_TESTBED_ET_PEER_START:
550     switch (result)
551     {
552     case PEER1_CREATED:
553       if (event->details.peer_start.host != host)
554       {
555         GNUNET_break (0);
556         abort_test ();
557         return;
558       }
559       peer1.is_running = GNUNET_YES;
560       GNUNET_TESTBED_operation_done (peer1.operation);
561       peer1.operation = NULL;
562       result = PEER1_STARTED;
563       common_operation =
564           GNUNET_TESTBED_controller_link (NULL, controller1, neighbour1, NULL,
565                                           GNUNET_YES);
566       break;
567     case PEER2_CREATED:
568       if (event->details.peer_start.host != neighbour1)
569       {
570         GNUNET_break (0);
571         abort_test ();
572         return;
573       }
574       peer2.is_running = GNUNET_YES;
575       GNUNET_TESTBED_operation_done (peer2.operation);
576       peer2.operation = NULL;
577       result = PEER2_STARTED;
578       if (NULL != common_operation)
579       {
580         GNUNET_break (0);
581         abort_test ();
582         return;
583       }
584       common_operation =
585           GNUNET_TESTBED_controller_link (NULL, controller1, neighbour2, NULL,
586                                           GNUNET_YES);
587       if (NULL == common_operation)
588       {
589         GNUNET_break (0);
590         abort_test ();
591         return;
592       }
593       break;
594     case PEER3_CREATED:
595       if (event->details.peer_start.host != neighbour2)
596       {
597         GNUNET_break (0);
598         abort_test ();
599         return;
600       }
601       peer3.is_running = GNUNET_YES;
602       GNUNET_TESTBED_operation_done (peer3.operation);
603       peer3.operation = NULL;
604       result = PEER3_STARTED;
605       common_operation =
606           GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer2.peer,
607                                           peer1.peer);
608       break;
609     default:
610       GNUNET_break (0);
611       abort_test ();
612       return;
613     }
614     break;
615   case GNUNET_TESTBED_ET_PEER_STOP:
616     if (PEERS_CONNECTED_2 != result)
617     {
618       GNUNET_break (0);
619       abort_test ();
620       return;
621     }
622     if (event->details.peer_stop.peer == peer1.peer)
623     {
624       peer1.is_running = GNUNET_NO;
625       GNUNET_TESTBED_operation_done (peer1.operation);
626     }
627     else if (event->details.peer_stop.peer == peer2.peer)
628     {
629       peer2.is_running = GNUNET_NO;
630       GNUNET_TESTBED_operation_done (peer2.operation);
631     }
632     else if (event->details.peer_stop.peer == peer3.peer)
633     {
634       peer3.is_running = GNUNET_NO;
635       GNUNET_TESTBED_operation_done (peer3.operation);
636     }
637     else
638     {
639       GNUNET_break (0);
640       abort_test ();
641       return;
642     }
643     if ((GNUNET_NO == peer1.is_running) && (GNUNET_NO == peer2.is_running) &&
644         (GNUNET_NO == peer3.is_running))
645     {
646       result = PEERS_STOPPED;
647       peer1.operation = GNUNET_TESTBED_peer_destroy (peer1.peer);
648       peer2.operation = GNUNET_TESTBED_peer_destroy (peer2.peer);
649       peer3.operation = GNUNET_TESTBED_peer_destroy (peer3.peer);
650     }
651     break;
652   case GNUNET_TESTBED_ET_CONNECT:
653     if ((NULL != peer1.operation) || (NULL != peer2.operation) ||
654         (NULL != peer3.operation) || (NULL == common_operation))
655     {
656       GNUNET_break (0);
657       abort_test ();
658       return;
659     }
660     switch (result)
661     {
662     case PEER3_STARTED:
663       if ((event->details.peer_connect.peer1 != peer2.peer) ||
664           (event->details.peer_connect.peer2 != peer1.peer))
665       {
666         GNUNET_break (0);
667         abort_test ();
668         return;
669       }
670       GNUNET_TESTBED_operation_done (common_operation);
671       common_operation = NULL;
672       result = PEERS_1_2_CONNECTED;
673       LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n");
674       common_operation =
675           GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer2.peer,
676                                           peer3.peer);
677       break;
678     case PEERS_1_2_CONNECTED:
679       if ((event->details.peer_connect.peer1 != peer2.peer) ||
680           (event->details.peer_connect.peer2 != peer3.peer))
681       {
682         GNUNET_break (0);
683         abort_test ();
684         return;
685       }
686       GNUNET_TESTBED_operation_done (common_operation);
687       common_operation = NULL;
688       result = PEERS_2_3_CONNECTED;
689       delayed_connect_task =
690           GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (3), &do_delayed_connect,
691                                         NULL);
692       break;
693     case PEERS_2_3_CONNECTED:
694       if ((event->details.peer_connect.peer1 != peer1.peer) ||
695           (event->details.peer_connect.peer2 != peer2.peer))
696       {
697         GNUNET_break (0);
698         abort_test ();
699         return;
700       }
701       GNUNET_TESTBED_operation_done (common_operation);
702       common_operation = NULL;
703       result = PEERS_CONNECTED_2;
704       LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected again\n");
705       peer1.operation = GNUNET_TESTBED_peer_stop (NULL, peer1.peer, NULL, NULL);
706       peer2.operation = GNUNET_TESTBED_peer_stop (NULL, peer2.peer, NULL, NULL);
707       peer3.operation = GNUNET_TESTBED_peer_stop (NULL, peer3.peer, NULL, NULL);
708       break;
709     default:
710       GNUNET_break (0);
711       abort_test ();
712       return;
713     }
714     break;
715   default:
716     GNUNET_break (0);
717     abort_test ();
718     return;
719   }
720 }
721
722
723 /**
724  * Callback which will be called to after a host registration succeeded or failed
725  *
726  * @param cls the host which has been registered
727  * @param emsg the error message; NULL if host registration is successful
728  */
729 static void
730 registration_comp (void *cls, const char *emsg)
731 {
732   reg_handle = NULL;
733   if (cls == neighbour1)
734   {
735     neighbour2 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0);
736     if (NULL == neighbour2)
737     {
738       GNUNET_break (0);
739       abort_test ();
740       return;
741     }
742     reg_handle =
743         GNUNET_TESTBED_register_host (controller1, neighbour2,
744                                       &registration_comp, neighbour2);
745     if (NULL == reg_handle)
746     {
747       GNUNET_break (0);
748       abort_test ();
749       return;
750     }
751     return;
752   }
753   if (cls != neighbour2)
754   {
755     GNUNET_break (0);
756     abort_test ();
757     return;
758   }
759   peer1.operation =
760       GNUNET_TESTBED_peer_create (controller1, host, cfg, &peer_create_cb,
761                                   &peer1);
762   if (NULL == peer1.operation)
763   {
764     GNUNET_break (0);
765     abort_test ();
766     return;
767   }
768 }
769
770
771 /**
772  * Callback to signal successfull startup of the controller process
773  *
774  * @param cls the closure from GNUNET_TESTBED_controller_start()
775  * @param cfg the configuration with which the controller has been started;
776  *          NULL if status is not GNUNET_OK
777  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
778  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
779  */
780 static void
781 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
782            int status)
783 {
784   uint64_t event_mask;
785
786   if (GNUNET_OK != status)
787   {
788     GNUNET_break (0);
789     cp1 = NULL;
790     abort_test ();
791     return;
792   }
793   event_mask = 0;
794   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
795   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
796   event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
797   event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
798   switch (result)
799   {
800   case INIT:
801     controller1 =
802         GNUNET_TESTBED_controller_connect (host, event_mask,
803                                            &controller_cb, NULL);
804     if (NULL == controller1)
805     {
806       GNUNET_break (0);
807       abort_test ();
808       return;
809     }
810     result = CONTROLLER1_UP;
811     neighbour1 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0);
812     if (NULL == neighbour1)
813     {
814       GNUNET_break (0);
815       abort_test ();
816       return;
817     }
818     reg_handle =
819         GNUNET_TESTBED_register_host (controller1, neighbour1,
820                                       &registration_comp, neighbour1);
821     if (NULL == reg_handle)
822     {
823       GNUNET_break (0);
824       abort_test ();
825       return;
826     }
827     break;
828   default:
829     GNUNET_break (0);
830     abort_test ();
831     return;
832   }
833 }
834
835
836 /**
837  * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to
838  * inform whether the given host is habitable or not. The Handle returned by
839  * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called
840  *
841  * @param cls NULL
842  * @param host the host whose status is being reported; will be NULL if the host
843  *          given to GNUNET_TESTBED_is_host_habitable() is NULL
844  * @param status #GNUNET_YES if it is habitable; #GNUNET_NO if not
845  */
846 static void
847 host_habitable_cb (void *cls,
848                    const struct GNUNET_TESTBED_Host *_host,
849                    int status)
850 {
851   hc_handle = NULL;
852   if (GNUNET_NO == status)
853   {
854     (void) PRINTF ("%s",
855                    "Unable to run the test as this system is not configured "
856                    "to use password less SSH logins to localhost.\n"
857                    "Skipping test\n");
858     GNUNET_SCHEDULER_cancel (abort_task);
859     abort_task = NULL;
860     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
861     result = SKIP;
862     return;
863   }
864   cp1 =
865       GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, NULL);
866 }
867
868
869 /**
870  * Main run function.
871  *
872  * @param cls NULL
873  * @param args arguments passed to GNUNET_PROGRAM_run
874  * @param cfgfile the path to configuration file
875  * @param cfg the configuration file handle
876  */
877 static void
878 run (void *cls, char *const *args, const char *cfgfile,
879      const struct GNUNET_CONFIGURATION_Handle *config)
880 {
881   cfg = GNUNET_CONFIGURATION_dup (config);
882   host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
883   if (NULL == host)
884   {
885     GNUNET_break (0);
886     abort_test ();
887     return;
888   }
889   if (NULL ==
890       (hc_handle =
891        GNUNET_TESTBED_is_host_habitable (host, config, &host_habitable_cb,
892                                          NULL)))
893   {
894     GNUNET_TESTBED_host_destroy (host);
895     host = NULL;
896     (void) PRINTF ("%s",
897                    "Unable to run the test as this system is not configured "
898                    "to use password less SSH logins to localhost.\n"
899                    "Skipping test\n");
900     result = SKIP;
901     return;
902   }
903   abort_task =
904       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
905                                     (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort,
906                                     NULL);
907 }
908
909
910 /**
911  * Main function
912  */
913 int
914 main (int argc, char **argv)
915 {
916   char *const argv2[] = { "test_testbed_api_3peers_3controllers",
917     "-c", "test_testbed_api.conf",
918     NULL
919   };
920   struct GNUNET_GETOPT_CommandLineOption options[] = {
921     GNUNET_GETOPT_OPTION_END
922   };
923   int ret;
924
925   result = INIT;
926   ret =
927       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
928                           "test_testbed_api_3peers_3controllers", "nohelp",
929                           options, &run, NULL);
930   if (GNUNET_OK != ret)
931     return 1;
932   switch (result)
933   {
934   case SUCCESS:
935     return 0;
936   case SKIP:
937     return 77;                  /* Mark test as skipped */
938   default:
939     return 1;
940   }
941 }
942
943 /* end of test_testbed_api_3peers_3controllers.c */