- distribute peers equally among island nodes on SuperMUC
[oweals/gnunet.git] / src / testbed / test_testbed_api_controllerlink.c
1 /*
2       This file is part of GNUnet
3       (C) 2008--2013 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_controllerlink.c
23  * @brief testcase for testing controller to subcontroller linking
24  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
25  */
26
27
28 /**
29  * The controller architecture we try to achieve in this test case:
30  *
31  *                    Master Controller
32  *                    //             \\
33  *                   //               \\
34  *         Slave Controller 1---------Slave Controller 3
35  *                  ||
36  *                  ||
37  *         Slave Controller 2
38  */
39
40 #include "platform.h"
41 #include "gnunet_util_lib.h"
42 #include "gnunet_testing_lib.h"
43 #include "gnunet_testbed_service.h"
44
45 /**
46  * Generic logging shortcut
47  */
48 #define LOG(kind,...)                           \
49   GNUNET_log (kind, __VA_ARGS__)
50
51 /**
52  * Debug logging shorthand
53  */
54 #define LOG_DEBUG(...)                          \
55   LOG(GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
56
57 /**
58  * Different stages in testing
59  */
60 enum Stage
61 {
62
63   /**
64    * Initial stage
65    */
66   INIT,
67
68   /**
69    * Master controller has started
70    */
71   MASTER_STARTED,
72
73   /**
74    * A peer has been created on master
75    */
76   MASTER_PEER_CREATE_SUCCESS,
77
78   /**
79    * Peer on master controller has been started successfully.
80    */
81   MASTER_PEER_START_SUCCESS,
82
83   /**
84    * The first slave has been registered at master controller
85    */
86   SLAVE1_REGISTERED,
87
88   /**
89    * The second slave has been registered at the master controller
90    */
91   SLAVE2_REGISTERED,
92
93   /**
94    * Link from master to slave 1 has been successfully created
95    */
96   SLAVE1_LINK_SUCCESS,
97
98   /**
99    * Peer create on slave 1 successful
100    */
101   SLAVE1_PEER_CREATE_SUCCESS,
102
103   /**
104    * Peer startup on slave 1 successful
105    */
106   SLAVE1_PEER_START_SUCCESS,
107
108   /**
109    * Link from slave 1 to slave 2 has been successfully created.
110    */
111   SLAVE2_LINK_SUCCESS,
112
113   /**
114    * Peer create on slave 2 successful
115    */
116   SLAVE2_PEER_CREATE_SUCCESS,
117
118   /**
119    * Peer on slave 1 successfully stopped
120    */
121   SLAVE1_PEER_STOP_SUCCESS,
122
123   /**
124    * Peer startup on slave 2 successful
125    */
126   SLAVE2_PEER_START_SUCCESS,
127
128   /**
129    * Try to connect peers on master and slave 2.
130    */
131   MASTER_SLAVE2_PEERS_CONNECTED,
132
133   /**
134    * Slave 3 has successfully registered
135    */
136   SLAVE3_REGISTERED,
137
138   /**
139    * Slave 3 has successfully started
140    */
141   SLAVE3_STARTED,
142
143   /**
144    * Peer created on slave 3
145    */
146   SLAVE3_PEER_CREATE_SUCCESS,
147
148   /**
149    * Peer started at slave 3
150    */
151   SLAVE3_PEER_START_SUCCESS,
152
153   /**
154    * Try to connect peers on slave2 and slave3
155    */
156   SLAVE2_SLAVE3_PEERS_CONNECTED,
157
158   /**
159    * Peer on slave 2 successfully stopped
160    */
161   SLAVE2_PEER_STOP_SUCCESS,
162
163   /**
164    * Peer destroy on slave 1 successful
165    */
166   SLAVE1_PEER_DESTROY_SUCCESS,
167
168   /**
169    * Peer destory on slave 2 successful
170    */
171   SLAVE2_PEER_DESTROY_SUCCESS,
172
173   /**
174    * The configuration of slave 3 is acquired
175    */
176   SLAVE3_GET_CONFIG_SUCCESS,
177
178   /**
179    * Slave 1 has linked to slave 3;
180    */
181   SLAVE3_LINK_SUCCESS,
182
183   /**
184    * Destory master peer and mark test as success
185    */
186   SUCCESS,
187
188   /**
189    * Marks test as skipped
190    */
191   SKIP
192 };
193
194 /**
195  * Host for running master controller
196  */
197 static struct GNUNET_TESTBED_Host *host;
198
199 /**
200  * The master controller process
201  */
202 static struct GNUNET_TESTBED_ControllerProc *cp;
203
204 /**
205  * Handle to master controller
206  */
207 static struct GNUNET_TESTBED_Controller *mc;
208
209 /**
210  * Slave host for running slave controller
211  */
212 static struct GNUNET_TESTBED_Host *slave;
213
214 /**
215  * Another slave host for running another slave controller
216  */
217 static struct GNUNET_TESTBED_Host *slave2;
218
219 /**
220  * Host for slave 3
221  */
222 static struct GNUNET_TESTBED_Host *slave3;
223
224 /**
225  * Slave host registration handle
226  */
227 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
228
229 /**
230  * Handle to global configuration
231  */
232 static struct GNUNET_CONFIGURATION_Handle *cfg;
233
234 /**
235  * Configuration of slave 3 controller
236  */
237 static struct GNUNET_CONFIGURATION_Handle *cfg3;
238
239 /**
240  * Abort task
241  */
242 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
243
244 /**
245  * Operation handle for linking controllers
246  */
247 static struct GNUNET_TESTBED_Operation *op;
248
249 /**
250  * Handle to peer started at slave 1
251  */
252 static struct GNUNET_TESTBED_Peer *slave1_peer;
253
254 /**
255  * Handle to peer started at slave 2
256  */
257 static struct GNUNET_TESTBED_Peer *slave2_peer;
258
259 /**
260  * Handle to peer started at slave 2
261  */
262 static struct GNUNET_TESTBED_Peer *slave3_peer;
263
264 /**
265  * Handle to a peer started at master controller
266  */
267 static struct GNUNET_TESTBED_Peer *master_peer;
268
269 /**
270  * The handle for whether a host is habitable or not
271  */
272 struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle;
273
274 /**
275  * The task handle for the delay task
276  */
277 GNUNET_SCHEDULER_TaskIdentifier delay_task_id;
278
279 /**
280  * Event mask
281  */
282 uint64_t event_mask;
283
284 /**
285  * Global testing status
286  */
287 static enum Stage result;
288
289 /**
290  * shortcut to exit during failure
291  */
292 #define FAIL_TEST(cond) do {                                    \
293     if (!(cond)) {                                              \
294       GNUNET_break(0);                                          \
295       if (GNUNET_SCHEDULER_NO_TASK != abort_task)               \
296         GNUNET_SCHEDULER_cancel (abort_task);                   \
297       abort_task = GNUNET_SCHEDULER_NO_TASK;                    \
298       GNUNET_SCHEDULER_add_now (do_shutdown, NULL);             \
299       return;                                                   \
300     }                                                          \
301   } while (0)
302
303
304 /**
305  * Shutdown nicely
306  *
307  * @param cls NULL
308  * @param tc the task context
309  */
310 static void
311 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
312 {
313   if (GNUNET_SCHEDULER_NO_TASK != abort_task)
314     GNUNET_SCHEDULER_cancel (abort_task);
315   if (GNUNET_SCHEDULER_NO_TASK != delay_task_id)
316   {
317     GNUNET_SCHEDULER_cancel (delay_task_id);
318     delay_task_id = GNUNET_SCHEDULER_NO_TASK;
319   }
320   if (NULL != hc_handle)
321     GNUNET_TESTBED_is_host_habitable_cancel (hc_handle);
322   if (NULL != mc)
323     GNUNET_TESTBED_controller_disconnect (mc);
324   if (NULL != cp)
325     GNUNET_TESTBED_controller_stop (cp);
326   if (NULL != slave3)
327     GNUNET_TESTBED_host_destroy (slave3);
328   if (NULL != slave2)
329     GNUNET_TESTBED_host_destroy (slave2);
330   if (NULL != slave)
331     GNUNET_TESTBED_host_destroy (slave);
332   if (NULL != host)
333     GNUNET_TESTBED_host_destroy (host);
334   if (NULL != cfg)
335     GNUNET_CONFIGURATION_destroy (cfg);
336   if (NULL != cfg3)
337     GNUNET_CONFIGURATION_destroy (cfg3);
338   if (NULL != rh)
339     GNUNET_TESTBED_cancel_registration (rh);
340 }
341
342
343 /**
344  * abort task to run on test timed out
345  *
346  * @param cls NULL
347  * @param tc the task context
348  */
349 static void
350 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
351 {
352   LOG (GNUNET_ERROR_TYPE_WARNING, "Aborting\n");
353   abort_task = GNUNET_SCHEDULER_NO_TASK;
354   do_shutdown (cls, tc);
355 }
356
357
358 /**
359  * Calls abort now
360  *
361  * @param
362  * @return
363  */
364 static void
365 do_abort_now (void *cls)
366 {
367   if (GNUNET_SCHEDULER_NO_TASK != abort_task)
368     GNUNET_SCHEDULER_cancel (abort_task);
369   abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
370 }
371
372
373 /**
374  * Callback which will be called to after a host registration succeeded or failed
375  *
376  * @param cls the host which has been registered
377  * @param emsg the error message; NULL if host registration is successful
378  */
379 static void
380 registration_cont (void *cls, const char *emsg);
381
382
383 /**
384  * Task for inserting delay between tests
385  *
386  * @param
387  * @return
388  */
389 static void
390 delay_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
391 {
392   delay_task_id = GNUNET_SCHEDULER_NO_TASK;
393   switch (result)
394   {
395   case SLAVE2_PEER_CREATE_SUCCESS:
396     op = GNUNET_TESTBED_peer_stop (NULL, slave1_peer, NULL, NULL);
397     FAIL_TEST (NULL != op);
398     break;
399   case MASTER_SLAVE2_PEERS_CONNECTED:
400     slave3 = GNUNET_TESTBED_host_create_with_id (3, "127.0.0.1", NULL, cfg, 0);
401     rh = GNUNET_TESTBED_register_host (mc, slave3, &registration_cont, NULL);
402     break;
403   case SLAVE2_SLAVE3_PEERS_CONNECTED:
404     op = GNUNET_TESTBED_peer_stop (NULL, slave2_peer, NULL, NULL);
405     FAIL_TEST (NULL != op);
406     break;
407   default:
408     FAIL_TEST (0);
409   }
410 }
411
412
413 /**
414  * Functions of this signature are called when a peer has been successfully
415  * created
416  *
417  * @param cls the closure from GNUNET_TESTBED_peer_create()
418  * @param peer the handle for the created peer; NULL on any error during
419  *          creation
420  * @param emsg NULL if peer is not NULL; else MAY contain the error description
421  */
422 static void
423 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
424 {
425   FAIL_TEST (NULL != peer);
426   FAIL_TEST (NULL == emsg);
427   switch (result)
428   {
429   case MASTER_STARTED:
430     result = MASTER_PEER_CREATE_SUCCESS;
431     master_peer = peer;
432     GNUNET_TESTBED_operation_done (op);
433     op = GNUNET_TESTBED_peer_start (NULL, master_peer, NULL, NULL);
434     break;
435   case SLAVE1_LINK_SUCCESS:
436     result = SLAVE1_PEER_CREATE_SUCCESS;
437     slave1_peer = peer;
438     GNUNET_TESTBED_operation_done (op);
439     op = GNUNET_TESTBED_peer_start (NULL, slave1_peer, NULL, NULL);
440     break;
441   case SLAVE2_LINK_SUCCESS:
442     result = SLAVE2_PEER_CREATE_SUCCESS;
443     slave2_peer = peer;
444     GNUNET_TESTBED_operation_done (op);
445     delay_task_id =
446         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
447                                       (GNUNET_TIME_UNIT_SECONDS, 1),
448                                       &delay_task,
449                                       NULL);
450     break;
451   case SLAVE3_STARTED:
452     result = SLAVE3_PEER_CREATE_SUCCESS;
453     slave3_peer = peer;
454     GNUNET_TESTBED_operation_done (op);
455     op = GNUNET_TESTBED_peer_start (NULL, slave3_peer, NULL, NULL);
456     break;
457   default:
458     FAIL_TEST (0);
459   }
460   FAIL_TEST (NULL != op);
461 }
462
463
464 /**
465  * Checks the event if it is an operation finished event and if indicates a
466  * successfull completion of operation
467  *
468  * @param event the event information to check
469  */
470 static void
471 check_operation_success (const struct GNUNET_TESTBED_EventInformation *event)
472 {
473   FAIL_TEST (NULL != event);
474   FAIL_TEST (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
475   FAIL_TEST (event->op == op);
476   FAIL_TEST (NULL == event->op_cls);
477   FAIL_TEST (NULL == event->details.operation_finished.emsg);
478   FAIL_TEST (NULL == event->details.operation_finished.generic);
479 }
480
481
482 /**
483  * Signature of the event handler function called by the
484  * respective event controller.
485  *
486  * @param cls closure
487  * @param event information about the event
488  */
489 static void
490 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
491 {
492   switch (result)
493   {
494   case SLAVE2_REGISTERED:
495     check_operation_success (event);
496     GNUNET_TESTBED_operation_done (op);
497     op = NULL;
498     result = SLAVE1_LINK_SUCCESS;
499     FAIL_TEST (NULL != slave2);
500     FAIL_TEST (NULL != slave);
501     op = GNUNET_TESTBED_peer_create (mc, slave, cfg, peer_create_cb, NULL);
502     FAIL_TEST (NULL != op);
503     break;
504   case SLAVE1_PEER_START_SUCCESS:
505     check_operation_success (event);
506     GNUNET_TESTBED_operation_done (op);
507     result = SLAVE2_LINK_SUCCESS;
508     op = GNUNET_TESTBED_peer_create (mc, slave2, cfg, peer_create_cb, NULL);
509     FAIL_TEST (NULL != op);
510     break;
511   case MASTER_PEER_CREATE_SUCCESS:
512     FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type);
513     FAIL_TEST (event->details.peer_start.host == host);
514     FAIL_TEST (event->details.peer_start.peer == master_peer);
515     GNUNET_TESTBED_operation_done (op);
516     result = MASTER_PEER_START_SUCCESS;
517     slave = GNUNET_TESTBED_host_create_with_id (1, "127.0.0.1", NULL, cfg, 0);
518     FAIL_TEST (NULL != slave);
519     rh = GNUNET_TESTBED_register_host (mc, slave, &registration_cont, NULL);
520     FAIL_TEST (NULL != rh);
521     break;
522   case SLAVE1_PEER_CREATE_SUCCESS:
523     FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type);
524     FAIL_TEST (event->details.peer_start.host == slave);
525     FAIL_TEST (event->details.peer_start.peer == slave1_peer);
526     GNUNET_TESTBED_operation_done (op);
527     result = SLAVE1_PEER_START_SUCCESS;
528     op = GNUNET_TESTBED_controller_link (NULL, mc, slave2, slave, GNUNET_YES);
529     break;
530   case SLAVE2_PEER_CREATE_SUCCESS:
531     FAIL_TEST (GNUNET_TESTBED_ET_PEER_STOP == event->type);
532     FAIL_TEST (event->details.peer_stop.peer == slave1_peer);
533     GNUNET_TESTBED_operation_done (op);
534     result = SLAVE1_PEER_STOP_SUCCESS;
535     op = GNUNET_TESTBED_peer_start (NULL, slave2_peer, NULL, NULL);
536     FAIL_TEST (NULL != op);
537     break;
538   case SLAVE3_PEER_CREATE_SUCCESS:
539     FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type);
540     FAIL_TEST (event->details.peer_start.host == slave3);
541     FAIL_TEST (event->details.peer_start.peer == slave3_peer);
542     GNUNET_TESTBED_operation_done (op);
543     result = SLAVE3_PEER_START_SUCCESS;
544     sleep (1);
545     LOG_DEBUG ("**************************************\n");
546     op = GNUNET_TESTBED_overlay_connect (mc, NULL, NULL, slave2_peer,
547                                          slave3_peer);
548     FAIL_TEST (NULL != op);
549     break;
550   case SLAVE3_PEER_START_SUCCESS:
551     FAIL_TEST (NULL != event);
552     FAIL_TEST (GNUNET_TESTBED_ET_CONNECT == event->type);
553     FAIL_TEST (event->details.peer_connect.peer1 == slave2_peer);
554     FAIL_TEST (event->details.peer_connect.peer2 == slave3_peer);
555     result = SLAVE2_SLAVE3_PEERS_CONNECTED;
556     GNUNET_TESTBED_operation_done (op);
557     op = NULL;
558     delay_task_id =
559         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
560                                       (GNUNET_TIME_UNIT_SECONDS, 1), &delay_task,
561                                       NULL);
562     break;
563   case SLAVE1_PEER_STOP_SUCCESS:
564     FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type);
565     FAIL_TEST (event->details.peer_start.host == slave2);
566     FAIL_TEST (event->details.peer_start.peer == slave2_peer);
567     GNUNET_TESTBED_operation_done (op);
568     result = SLAVE2_PEER_START_SUCCESS;
569     op = GNUNET_TESTBED_overlay_connect (mc, NULL, NULL, master_peer,
570                                          slave2_peer);
571     break;
572   case SLAVE2_PEER_START_SUCCESS:
573     FAIL_TEST (NULL != event);
574     FAIL_TEST (GNUNET_TESTBED_ET_CONNECT == event->type);
575     FAIL_TEST (event->details.peer_connect.peer1 == master_peer);
576     FAIL_TEST (event->details.peer_connect.peer2 == slave2_peer);
577     result = MASTER_SLAVE2_PEERS_CONNECTED;
578     GNUNET_TESTBED_operation_done (op);
579     op = NULL;
580     delay_task_id =
581         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
582                                       (GNUNET_TIME_UNIT_SECONDS, 1), &delay_task,
583                                       NULL);
584     break;
585   case SLAVE2_SLAVE3_PEERS_CONNECTED:
586     FAIL_TEST (GNUNET_TESTBED_ET_PEER_STOP == event->type);
587     FAIL_TEST (event->details.peer_stop.peer == slave2_peer);
588     GNUNET_TESTBED_operation_done (op);
589     result = SLAVE2_PEER_STOP_SUCCESS;
590     op = GNUNET_TESTBED_peer_destroy (slave1_peer);
591     FAIL_TEST (NULL != op);
592     break;
593   case SLAVE2_PEER_STOP_SUCCESS:
594     check_operation_success (event);
595     GNUNET_TESTBED_operation_done (op);
596     result = SLAVE1_PEER_DESTROY_SUCCESS;
597     op = GNUNET_TESTBED_peer_destroy (slave2_peer);
598     FAIL_TEST (NULL != op);
599     break;
600   case SLAVE1_PEER_DESTROY_SUCCESS:
601     check_operation_success (event);
602     GNUNET_TESTBED_operation_done (op);
603     op = NULL;
604     result = SLAVE2_PEER_DESTROY_SUCCESS;
605     op = GNUNET_TESTBED_get_slave_config (NULL, mc, slave3);
606     FAIL_TEST (NULL != op);
607     break;
608   case SLAVE2_PEER_DESTROY_SUCCESS:
609     FAIL_TEST (NULL != event);
610     FAIL_TEST (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
611     FAIL_TEST (event->op == op);
612     FAIL_TEST (NULL == event->op_cls);
613     FAIL_TEST (NULL == event->details.operation_finished.emsg);
614     cfg3 = GNUNET_CONFIGURATION_dup (event->details.operation_finished.generic);
615     GNUNET_TESTBED_operation_done (op);
616     result = SLAVE3_GET_CONFIG_SUCCESS;
617     op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, slave, GNUNET_NO);
618     break;
619   case SLAVE3_REGISTERED:
620     check_operation_success (event);
621     GNUNET_TESTBED_operation_done (op);
622     op = NULL;
623     result = SLAVE3_STARTED;
624     op = GNUNET_TESTBED_peer_create (mc, slave3, cfg, peer_create_cb, NULL);
625     FAIL_TEST (NULL != op);
626     break;
627   case SLAVE3_GET_CONFIG_SUCCESS:
628     result = SLAVE3_LINK_SUCCESS;
629     GNUNET_TESTBED_operation_done (op);
630     op = GNUNET_TESTBED_peer_destroy (master_peer);
631     break;
632   case SLAVE3_LINK_SUCCESS:
633     check_operation_success (event);
634     result = SUCCESS;
635     GNUNET_TESTBED_operation_done (op);
636     op = NULL;
637     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
638                                   (GNUNET_TIME_UNIT_SECONDS, 1), &do_shutdown,
639                                   NULL);
640     break;
641   default:
642     FAIL_TEST (0);
643   }
644 }
645
646
647 /**
648  * Callback which will be called to after a host registration succeeded or failed
649  *
650  * @param cls the host which has been registered
651  * @param emsg the error message; NULL if host registration is successful
652  */
653 static void
654 registration_cont (void *cls, const char *emsg)
655 {
656   rh = NULL;
657   switch (result)
658   {
659   case MASTER_PEER_START_SUCCESS:
660     FAIL_TEST (NULL == emsg);
661     FAIL_TEST (NULL != mc);
662     result = SLAVE1_REGISTERED;
663     slave2 = GNUNET_TESTBED_host_create_with_id (2, "127.0.0.1", NULL, cfg, 0);
664     FAIL_TEST (NULL != slave2);
665     rh = GNUNET_TESTBED_register_host (mc, slave2, &registration_cont, NULL);
666     FAIL_TEST (NULL != rh);
667     break;
668   case SLAVE1_REGISTERED:
669     FAIL_TEST (NULL == emsg);
670     FAIL_TEST (NULL != mc);
671     result = SLAVE2_REGISTERED;
672     FAIL_TEST (NULL != cfg);
673     op = GNUNET_TESTBED_controller_link (NULL, mc, slave, NULL, GNUNET_YES);
674     FAIL_TEST (NULL != op);
675     break;
676   case MASTER_SLAVE2_PEERS_CONNECTED:
677     FAIL_TEST (NULL == emsg);
678     FAIL_TEST (NULL != mc);
679     FAIL_TEST (NULL == op);
680     result = SLAVE3_REGISTERED;
681     op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, NULL, GNUNET_YES);
682     FAIL_TEST (NULL != op);
683     break;
684   default:
685     GNUNET_break (0);
686     do_abort_now (NULL);
687   }
688 }
689
690 /**
691  * Callback to signal successfull startup of the controller process
692  *
693  * @param cls the closure from GNUNET_TESTBED_controller_start()
694  * @param cfg the configuration with which the controller has been started;
695  *          NULL if status is not GNUNET_OK
696  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
697  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
698  */
699 static void
700 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
701            int status)
702 {
703   switch (result)
704   {
705   case INIT:
706     FAIL_TEST (GNUNET_OK == status);
707     event_mask = 0;
708     event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
709     event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
710     event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
711     event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
712     mc = GNUNET_TESTBED_controller_connect (host, event_mask,
713                                             &controller_cb, NULL);
714     FAIL_TEST (NULL != mc);
715     result = MASTER_STARTED;
716     op = GNUNET_TESTBED_peer_create (mc, host, cfg, peer_create_cb, NULL);
717     FAIL_TEST (NULL != op);
718     break;
719   default:
720     GNUNET_break (0);
721     cp = NULL;
722     do_abort_now (NULL);
723   }
724 }
725
726
727 /**
728  * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to
729  * inform whether the given host is habitable or not. The Handle returned by
730  * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called
731  *
732  * @param cls NULL
733  * @param host the host whose status is being reported; will be NULL if the host
734  *          given to GNUNET_TESTBED_is_host_habitable() is NULL
735  * @param status GNUNET_YES if it is habitable; GNUNET_NO if not
736  */
737 static void
738 host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *_host,
739                    int status)
740 {
741   hc_handle = NULL;
742   if (GNUNET_NO == status)
743   {
744     (void) PRINTF ("%s",
745                    "Unable to run the test as this system is not configured "
746                    "to use password less SSH logins to localhost.\n"
747                    "Skipping test\n");
748     GNUNET_SCHEDULER_cancel (abort_task);
749     abort_task = GNUNET_SCHEDULER_NO_TASK;
750     (void) GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
751     result = SKIP;
752     return;
753   }
754   cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb,
755                                         NULL);
756 }
757
758
759 /**
760  * Main run function.
761  *
762  * @param cls NULL
763  * @param args arguments passed to GNUNET_PROGRAM_run
764  * @param cfgfile the path to configuration file
765  * @param cfg the configuration file handle
766  */
767 static void
768 run (void *cls, char *const *args, const char *cfgfile,
769      const struct GNUNET_CONFIGURATION_Handle *config)
770 {
771   cfg = GNUNET_CONFIGURATION_dup (config);
772   host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
773   FAIL_TEST (NULL != host);
774   if (NULL ==
775       (hc_handle =
776        GNUNET_TESTBED_is_host_habitable (host, config, &host_habitable_cb,
777                                          NULL)))
778   {
779     GNUNET_TESTBED_host_destroy (host);
780     GNUNET_CONFIGURATION_destroy (cfg);
781     cfg = NULL;
782     host = NULL;
783     (void) PRINTF ("%s",
784                    "Unable to run the test as this system is not configured "
785                    "to use password less SSH logins to localhost.\n"
786                    "Marking test as successful\n");
787     result = SKIP;
788     return;
789   }
790   abort_task =
791       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
792                                     (GNUNET_TIME_UNIT_MINUTES, 5), &do_abort,
793                                     NULL);
794 }
795
796
797 /**
798  * Main function
799  */
800 int
801 main (int argc, char **argv)
802 {
803   char *const argv2[] = { "test_testbed_api_controllerlink",
804     "-c", "test_testbed_api.conf",
805     NULL
806   };
807   struct GNUNET_GETOPT_CommandLineOption options[] = {
808     GNUNET_GETOPT_OPTION_END
809   };
810   int ret;
811
812   result = INIT;
813   ret =
814       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
815                           "test_testbed_api_controllerlink", "nohelp", options,
816                           &run, NULL);
817   if (GNUNET_OK != ret)
818     return 1;
819   switch (result)
820   {
821   case SUCCESS:
822     return 0;
823   case SKIP:
824     return 77;                  /* Mark test as skipped */
825   default:
826     return 1;
827   }
828 }
829
830 /* end of test_testbed_api_controllerlink.c */