clean handling of slave
[oweals/gnunet.git] / src / testbed / test_testbed_api_3peers_3controllers.c.new
1 /*
2       This file is part of GNUnet
3       (C) 2008--2012 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 /**
22  * @file testbed/test_testbed_api_3peers_3controllers.c
23  * @brief testcases for the testbed api: 3 peers are configured, started and
24  *          connected together. Each peer resides on its own controller.
25  * @author Sree Harsha Totakura
26  */
27
28
29 /**
30  * The testing architecture is:
31  *                  C1
32  *                 /  \
33  *                /    \
34  *               C2 == C3
35  * C1 is the master controller and C2, C3 are slave controllers. C2 links to C3
36  * laterally
37  */
38
39 #include "platform.h"
40 #include "gnunet_util_lib.h"
41 #include "gnunet_testing_lib-new.h"
42 #include "gnunet_testbed_service.h"
43
44
45 /**
46  * Generic logging shortcut
47  */
48 #define LOG(kind,...)                           \
49   GNUNET_log (kind, __VA_ARGS__)
50
51 /**
52  * Relative time seconds shorthand
53  */
54 #define TIME_REL_SECS(sec) \
55   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
56
57
58 /**
59  * Peer context
60  */
61 struct PeerContext
62 {
63   /**
64    * The peer handle
65    */
66   struct GNUNET_TESTBED_Peer *peer;
67
68   /**
69    * Operations involving this peer
70    */
71   struct GNUNET_TESTBED_Operation *operation;
72
73   /**
74    * set to GNUNET_YES when peer is started
75    */
76   int is_running;
77 };
78
79 /**
80  * Our localhost
81  */
82 static struct GNUNET_TESTBED_Host *host;
83
84 /**
85  * The controller process of one controller
86  */
87 static struct GNUNET_TESTBED_ControllerProc *cp1;
88
89 /**
90  * A neighbouring host
91  */
92 static struct GNUNET_TESTBED_Host *neighbour1;
93
94 /**
95  * Another neighbouring host
96  */
97 static struct GNUNET_TESTBED_Host *neighbour2;
98
99 /**
100  * Handle for neighbour registration
101  */
102 static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
103
104 /**
105  * The controller handle of one controller
106  */
107 static struct GNUNET_TESTBED_Controller *controller1;
108
109 /**
110  * peer 1
111  */
112 static struct PeerContext peer1;
113
114 /**
115  * peer2
116  */
117 static struct PeerContext peer2;
118
119 /**
120  * peer3
121  */
122 static struct PeerContext peer3;
123
124 /**
125  * Handle to starting configuration
126  */
127 static struct GNUNET_CONFIGURATION_Handle *cfg;
128
129 /**
130  * Handle to controller2 configuration, used to establish lateral link from
131  * controller 1
132  */
133 static struct GNUNET_CONFIGURATION_Handle *cfg2;
134
135 /**
136  * Handle to operations involving both peers
137  */
138 static struct GNUNET_TESTBED_Operation *common_operation;
139
140 /**
141  * Abort task identifier
142  */
143 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
144
145 /**
146  * Delayed connect job identifier
147  */
148 static GNUNET_SCHEDULER_TaskIdentifier delayed_connect_task;
149
150 /**
151  * Different stages in testing
152  */
153 enum Stage
154 {
155
156   /**
157    * Initial stage
158    */
159   INIT,
160
161   /**
162    * Controller 1 has started
163    */
164   CONTROLLER1_UP,
165
166   /**
167    * peer1 is created
168    */
169   PEER1_CREATED,
170
171   /**
172    * peer1 is started
173    */
174   PEER1_STARTED,
175
176   /**
177    * Controller 2 has started
178    */
179   CONTROLLER2_UP,
180
181   /**
182    * peer2 is created
183    */
184   PEER2_CREATED,
185
186   /**
187    * peer2 is started
188    */
189   PEER2_STARTED,
190
191   /**
192    * Controller 3 has started
193    */
194   CONTROLLER3_UP,
195
196   /**
197    * Peer3 is created
198    */
199   PEER3_CREATED,
200
201   /**
202    * Peer3 started
203    */
204   PEER3_STARTED,
205
206   /**
207    * peer1 and peer2 are connected
208    */
209   PEERS_1_2_CONNECTED,
210
211   /**
212    * Linking controller B to C
213    */
214   CONTROLLERS_LINKED,
215
216   /**
217    * peer2 and peer3 are connected
218    */
219   PEERS_2_3_CONNECTED,
220
221   /**
222    * Peers are connected once again (this should not fail as they are already connected)
223    */
224   PEERS_CONNECTED_2,
225
226   /**
227    * peers are stopped
228    */
229   PEERS_STOPPED,
230
231   /**
232    * Final success stage
233    */
234   SUCCESS
235 };
236
237 /**
238  * The testing result
239  */
240 static enum Stage result;
241
242 /**
243  * Shutdown nicely
244  *
245  * @param cls NULL
246  * @param tc the task context
247  */
248 static void
249 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
250 {
251   if (GNUNET_SCHEDULER_NO_TASK != abort_task)
252     GNUNET_SCHEDULER_cancel (abort_task);
253   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == delayed_connect_task);
254   if (NULL != reg_handle)
255     GNUNET_TESTBED_cancel_registration (reg_handle);
256   if (NULL != controller1)
257     GNUNET_TESTBED_controller_disconnect (controller1);
258   if (NULL != controller2)
259     GNUNET_TESTBED_controller_disconnect (controller2);
260   GNUNET_CONFIGURATION_destroy (cfg);
261   if (NULL != cfg2)
262     GNUNET_CONFIGURATION_destroy (cfg2);
263   if (NULL != cp1)
264     GNUNET_TESTBED_controller_stop (cp1);
265   if (NULL != host)
266     GNUNET_TESTBED_host_destroy (host);
267   if (NULL != neighbour1)
268     GNUNET_TESTBED_host_destroy (neighbour1);
269   if (NULL != neighbour2)
270     GNUNET_TESTBED_host_destroy (neighbour2);
271 }
272
273
274 /**
275  * abort task to run on test timed out
276  *
277  * @param cls NULL
278  * @param tc the task context
279  */
280 static void
281 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
282 {
283   LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
284   abort_task = GNUNET_SCHEDULER_NO_TASK;
285   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == delayed_connect_task);
286   do_shutdown (cls, tc);
287 }
288
289
290 /**
291  * Callback to be called when an operation is completed
292  *
293  * @param cls the callback closure from functions generating an operation
294  * @param op the operation that has been finished
295  * @param emsg error message in case the operation has failed; will be NULL if
296  *          operation has executed successfully.
297  */
298 static void 
299 op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg);
300
301
302 /**
303  * task for delaying a connect
304  *
305  * @param cls NULL
306  * @param tc the task context
307  */
308 static void
309 do_delayed_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
310 {
311   delayed_connect_task = GNUNET_SCHEDULER_NO_TASK;
312   GNUNET_assert (NULL == common_operation);
313   common_operation = GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, 
314                                                      peer1.peer, peer2.peer);
315 }
316
317
318 /**
319  * Callback to be called when an operation is completed
320  *
321  * @param cls the callback closure from functions generating an operation
322  * @param op the operation that has been finished
323  * @param emsg error message in case the operation has failed; will be NULL if
324  *          operation has executed successfully.
325  */
326 static void 
327 op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
328 {
329   GNUNET_assert (common_operation == op);
330   switch(result)
331   {
332   case PEER3_STARTED:
333     GNUNET_assert (NULL == peer1.operation);
334     GNUNET_assert (NULL == peer2.operation);
335     GNUNET_assert (NULL != common_operation);
336     GNUNET_TESTBED_operation_done (common_operation);
337     common_operation = NULL;
338     result = PEERS_1_2_CONNECTED;
339     LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n");
340     /* delayed_connect_task = */
341     /*     GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (3), */
342     /*                                &do_delayed_connect, NULL); */
343     common_operation = GNUNET_TESTBED_controller_link (controller, 
344     break;
345   case PEERS_CONNECTED:
346     GNUNET_assert (NULL == peer1.operation);
347     GNUNET_assert (NULL == peer2.operation);
348     GNUNET_assert (NULL != common_operation);
349     GNUNET_TESTBED_operation_done (common_operation);
350     common_operation = NULL;
351     result = PEERS_CONNECTED_2;
352     LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected again\n");
353     peer1.operation = GNUNET_TESTBED_peer_stop (peer1.peer, NULL, NULL);
354     peer2.operation = GNUNET_TESTBED_peer_stop (peer2.peer, NULL, NULL);
355     peer3.operation = GNUNET_TESTBED_peer_stop (peer3.peer, NULL, NULL);
356     break;
357   default:
358     GNUNET_assert (0);
359   }
360 }
361
362
363 /**
364  * Functions of this signature are called when a peer has been successfully
365  * created
366  *
367  * @param cls NULL
368  * @param peer the handle for the created peer; NULL on any error during
369  *          creation
370  * @param emsg NULL if peer is not NULL; else MAY contain the error description
371  */
372 static void
373 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
374 {
375   switch (result)
376   {
377   case CONTROLLER1_UP:
378     GNUNET_assert (NULL != peer1.operation);
379     GNUNET_assert (NULL != peer);
380     GNUNET_assert (NULL == peer1.peer);
381     peer1.peer = peer;
382     GNUNET_TESTBED_operation_done (peer1.operation);
383     result = PEER1_CREATED;
384     peer1.operation = GNUNET_TESTBED_peer_start (peer, NULL, NULL);
385     break;
386   case CONTROLLER2_UP:
387     GNUNET_assert (NULL != peer2.operation);
388     GNUNET_assert (NULL != peer);
389     GNUNET_assert (NULL == peer2.peer);
390     peer2.peer = peer;
391     GNUNET_TESTBED_operation_done (peer2.operation);
392     result = PEER2_CREATED;
393     peer2.operation = GNUNET_TESTBED_peer_start (peer, NULL, NULL);
394     break;
395   case CONTROLLER3_UP:
396     GNUNET_assert (NULL != peer3.operation);
397     GNUNET_assert (NULL != peer);
398     GNUNET_assert (NULL == peer3.peer);
399     peer3.peer = peer;
400     GNUNET_TESTBED_operation_done (peer3.operation);
401     result = PEER3_CREATED;
402     peer3.operation = GNUNET_TESTBED_peer_start (peer, NULL, NULL);
403     break;
404   default:
405     GNUNET_assert (0);
406   }  
407 }
408
409
410 /**
411  * Callback to signal successfull startup of the controller process
412  *
413  * @param cls the closure from GNUNET_TESTBED_controller_start()
414  * @param cfg the configuration with which the controller has been started;
415  *          NULL if status is not GNUNET_OK
416  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
417  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
418  */
419 static void
420 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, int status);
421
422
423 /**
424  * Signature of the event handler function called by the
425  * respective event controller.
426  *
427  * @param cls closure
428  * @param event information about the event
429  */
430 static void
431 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
432 {
433   switch (event->type)
434   {
435   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
436     GNUNET_assert (NULL == event->details.operation_finished.op_cls);
437     GNUNET_assert (NULL == event->details.operation_finished.emsg);
438     GNUNET_assert (NULL == event->details.operation_finished.generic);
439     switch (result)
440     {
441     case PEERS_STOPPED:
442       if (event->details.operation_finished.operation == peer1.operation)
443       {
444         GNUNET_TESTBED_operation_done (peer1.operation);
445         peer1.operation = NULL;
446         peer1.peer = NULL;
447       }
448       else if (event->details.operation_finished.operation == peer2.operation)
449       {
450         GNUNET_TESTBED_operation_done (peer2.operation);
451         peer2.operation = NULL;
452         peer2.peer = NULL;
453       }
454       else if (event->details.operation_finished.operation == peer3.operation)
455       {
456         GNUNET_TESTBED_operation_done (peer3.operation);
457         peer3.operation = NULL;
458         peer3.peer = NULL;
459       }
460       else
461         GNUNET_assert (0);
462       if ((NULL == peer1.peer) && (NULL == peer2.peer) && (NULL == peer3.peer))
463       {
464         result = SUCCESS;
465         GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
466       }
467       break;
468     case PEER1_STARTED:
469       GNUNET_assert (NULL != common_operation);
470       GNUNET_TESTBED_operation_done (common_operation);
471       common_operation = NULL;
472       result = CONTROLLER2_UP;
473       peer2.operation =
474           GNUNET_TESTBED_peer_create (controller1, neighbour1, cfg,
475                                       &peer_create_cb, NULL);
476       GNUNET_assert (NULL != peer2.operation);
477       break;
478     case PEER2_STARTED:
479       GNUNET_assert (NULL != common_operation);
480       GNUNET_TESTBED_operation_done (common_operation);
481       common_operation = NULL;
482       result = CONTROLLER3_UP;
483       peer3.operation =
484           GNUNET_TESTBED_peer_create (controller1, neighbour2, cfg,
485                                       &peer_create_cb, NULL);
486       GNUNET_assert (NULL != peer3.operation);
487       break;
488     default:
489       GNUNET_assert (0);
490     }
491     break;
492   case GNUNET_TESTBED_ET_PEER_START:    
493     switch (result)
494     {
495     case PEER1_CREATED:
496       GNUNET_assert (event->details.peer_start.host == host);
497       peer1.is_running = GNUNET_YES;
498       GNUNET_TESTBED_operation_done (peer1.operation);
499       peer1.operation = NULL;
500       result = PEER1_STARTED;
501       common_operation =
502           GNUNET_TESTBED_controller_link (controller1, neighbour1, NULL, cfg,
503                                           GNUNET_YES); 
504       break;
505     case PEER2_CREATED:
506       GNUNET_assert (event->details.peer_start.host == neighbour1);
507       peer2.is_running = GNUNET_YES;
508       GNUNET_TESTBED_operation_done (peer2.operation);
509       peer2.operation = NULL;
510       result = PEER2_STARTED;
511       GNUNET_assert (NULL == common_operation);              
512       common_operation =
513           GNUNET_TESTBED_controller_link (controller1, neighbour2, NULL, cfg,
514                                           GNUNET_YES);
515       GNUNET_assert (NULL != common_operation);
516       break;
517     case PEER3_CREATED:
518       GNUNET_assert (event->details.peer_start.host == neighbour2);
519       peer3.is_running = GNUNET_YES;
520       GNUNET_TESTBED_operation_done (peer3.operation);
521       peer3.operation = NULL;
522       result = PEER3_STARTED;
523       common_operation =
524           GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer,
525                                           peer2.peer);
526       break;
527     default:
528       GNUNET_assert (0);
529     }    
530     break;
531   case GNUNET_TESTBED_ET_PEER_STOP:
532     GNUNET_assert (PEERS_CONNECTED_2 == result);
533     if (event->details.peer_stop.peer == peer1.peer)
534     {
535       peer1.is_running = GNUNET_NO;
536       GNUNET_TESTBED_operation_done (peer1.operation);
537     }
538     else if (event->details.peer_stop.peer == peer2.peer)
539     {
540       peer2.is_running = GNUNET_NO;
541       GNUNET_TESTBED_operation_done (peer2.operation);
542     }
543     else if (event->details.peer_stop.peer == peer3.peer)
544     {
545       peer3.is_running = GNUNET_NO;
546       GNUNET_TESTBED_operation_done (peer3.operation);
547     }
548     else
549       GNUNET_assert (0);
550     if ((GNUNET_NO == peer1.is_running) &&
551         (GNUNET_NO == peer2.is_running) &&
552         (GNUNET_NO == peer3.is_running))
553     {
554       result = PEERS_STOPPED;
555       peer1.operation = GNUNET_TESTBED_peer_destroy (peer1.peer);
556       peer2.operation = GNUNET_TESTBED_peer_destroy (peer2.peer);
557       peer3.operation = GNUNET_TESTBED_peer_destroy (peer3.peer);
558     }
559     break;
560   case GNUNET_TESTBED_ET_CONNECT:
561     GNUNET_assert (NULL == peer1.operation);
562     GNUNET_assert (NULL == peer2.operation);
563     GNUNET_assert (NULL == peer3.operation);
564     switch (result)
565     {
566     case PEER3_STARTED:
567       GNUNET_assert (NULL != common_operation);
568       GNUNET_assert ((event->details.peer_connect.peer1 == peer1.peer) &&
569                      (event->details.peer_connect.peer2 == peer2.peer));
570       break;
571     case PEERS_CONNECTED:
572       GNUNET_assert (NULL != common_operation);
573       GNUNET_assert ((event->details.peer_connect.peer1 == peer2.peer) &&
574                      (event->details.peer_connect.peer2 == peer3.peer));
575       break;
576     default:
577       GNUNET_assert (0);
578     }
579     break;
580   default:
581     GNUNET_assert (0);
582   };
583 }
584
585
586 /**
587  * Callback which will be called to after a host registration succeeded or failed
588  *
589  * @param cls the host which has been registered
590  * @param emsg the error message; NULL if host registration is successful
591  */
592 static void
593 registration_comp (void *cls, const char *emsg)
594 {
595   reg_handle = NULL;
596   if (cls == neighbour1)
597   {
598     neighbour2 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, 0);
599     GNUNET_assert (NULL != neighbour2);
600     reg_handle =
601         GNUNET_TESTBED_register_host (controller1, neighbour2, &registration_comp,
602                                       neighbour2);
603     GNUNET_assert (NULL != reg_handle);
604     return;
605   }
606   GNUNET_assert (cls == neighbour2);
607   peer1.operation =
608       GNUNET_TESTBED_peer_create (controller1, host, cfg, &peer_create_cb,
609                                   &peer1);
610   GNUNET_assert (NULL != peer1.operation);  
611 }
612
613
614 /**
615  * Callback to signal successfull startup of the controller process
616  *
617  * @param cls the closure from GNUNET_TESTBED_controller_start()
618  * @param cfg the configuration with which the controller has been started;
619  *          NULL if status is not GNUNET_OK
620  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
621  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
622  */
623 static void
624 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, int status)
625 {
626   uint64_t event_mask;
627   
628   GNUNET_assert (GNUNET_OK == status);
629   event_mask = 0;
630   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
631   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
632   event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
633   event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
634   switch (result)
635   {
636   case INIT:
637     controller1 =
638         GNUNET_TESTBED_controller_connect (config, host, event_mask, &controller_cb,
639                                            NULL);
640     GNUNET_assert (NULL != controller1);
641     result = CONTROLLER1_UP;
642     neighbour1 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, 0);
643     GNUNET_assert (NULL != neighbour1);
644     reg_handle =
645         GNUNET_TESTBED_register_host (controller1, neighbour1, &registration_comp,
646                                       neighbour1);
647     GNUNET_assert (NULL != reg_handle);
648     break;
649   default:
650     GNUNET_assert (0);
651   }
652   
653 }
654
655
656 /**
657  * Main run function.
658  *
659  * @param cls NULL
660  * @param args arguments passed to GNUNET_PROGRAM_run
661  * @param cfgfile the path to configuration file
662  * @param cfg the configuration file handle
663  */
664 static void
665 run (void *cls, char *const *args, const char *cfgfile,
666      const struct GNUNET_CONFIGURATION_Handle *config)
667 {
668   host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
669   GNUNET_assert (NULL != host);
670   cfg = GNUNET_CONFIGURATION_dup (config);
671   cp1 = GNUNET_TESTBED_controller_start ("127.0.0.1", host, cfg, status_cb,
672                                         NULL);
673   abort_task =
674       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
675                                     (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort,
676                                     NULL);
677 }
678
679
680 /**
681  * Function to check if password-less SSH logins to given ip work
682  *
683  * @param host_str numeric representation of the host's ip
684  * @return GNUNET_YES if password-less SSH login to the given host works;
685  *           GNUNET_NO if not
686  */
687 static int
688 check_ssh (char *host_str)
689 {
690   char *const remote_args[] = {
691     "ssh", "-o", "BatchMode=yes", "-o", "CheckHostIP=no", "-q",
692     host_str, "echo", "SSH", "works", NULL
693   };
694   struct GNUNET_OS_Process *auxp;
695   enum GNUNET_OS_ProcessStatusType type;
696   unsigned long code;
697   int ret;
698
699   auxp =
700       GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
701                                    NULL, "ssh", remote_args);
702   GNUNET_assert (NULL != auxp);
703   do
704   {
705     ret = GNUNET_OS_process_status (auxp, &type, &code);
706     GNUNET_assert (GNUNET_SYSERR != ret);
707     (void) usleep (300);
708   }
709   while (GNUNET_NO == ret);
710   (void) GNUNET_OS_process_wait (auxp);
711   GNUNET_OS_process_destroy (auxp);
712   return (0 != code) ? GNUNET_NO : GNUNET_YES;
713 }
714
715
716 /**
717  * Main function
718  */
719 int
720 main (int argc, char **argv)
721 {
722   char *const argv2[] = { "test_testbed_api_3peers_3controllers",
723     "-c", "test_testbed_api.conf",
724     NULL
725   };
726   struct GNUNET_GETOPT_CommandLineOption options[] = {
727     GNUNET_GETOPT_OPTION_END
728   };
729   int ret;
730
731   if (GNUNET_YES != check_ssh ("127.0.0.1"))
732     goto error_exit;
733   result = INIT;
734   ret =
735       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
736                           "test_testbed_api_3peers_3controllers", "nohelp",
737                           options, &run, NULL);
738   if ((GNUNET_OK != ret) || (SUCCESS != result))
739     return 1;
740   return 0;
741
742  error_exit:
743   (void) PRINTF ("%s",
744                  "Unable to run the test as this system is not configured "
745                  "to use password less SSH logins to localhost.\n"
746                  "Marking test as successful\n");
747   return 0;
748 }
749
750 /* end of test_testbed_api_3peers_3controllers.c */