-add adv port
[oweals/gnunet.git] / src / testbed / test_testbed_api_controllerlink.c
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_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-new.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    * Link from slave 1 to slave 2 has been successfully created.
100    */
101   SLAVE2_LINK_SUCCESS,
102
103   /**
104    * Peer create on slave 1 successful
105    */
106   SLAVE1_PEER_CREATE_SUCCESS,
107
108   /**
109    * Peer create on slave 2 successful
110    */
111   SLAVE2_PEER_CREATE_SUCCESS,
112
113   /**
114    * Peer startup on slave 1 successful
115    */
116   SLAVE1_PEER_START_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    * Peer on slave 2 successfully stopped
135    */
136   SLAVE2_PEER_STOP_SUCCESS,
137
138   /**
139    * Peer destroy on slave 1 successful
140    */
141   SLAVE1_PEER_DESTROY_SUCCESS,
142
143   /**
144    * Peer destory on slave 2 successful
145    */
146   SLAVE2_PEER_DESTROY_SUCCESS,
147
148   /**
149    * Slave 3 has successfully registered
150    */
151   SLAVE3_REGISTERED,
152
153   /**
154    * Slave 3 has successfully started
155    */
156   SLAVE3_STARTED,
157
158   /**
159    * The configuration of slave 3 is acquired
160    */
161   SLAVE3_GET_CONFIG_SUCCESS,
162
163   /**
164    * Slave 1 has linked to slave 3;
165    */
166   SLAVE3_LINK_SUCCESS
167
168 };
169
170 /**
171  * Host for running master controller
172  */
173 static struct GNUNET_TESTBED_Host *host;
174
175 /**
176  * The master controller process
177  */
178 static struct GNUNET_TESTBED_ControllerProc *cp;
179
180 /**
181  * Handle to master controller
182  */
183 static struct GNUNET_TESTBED_Controller *mc;
184
185 /**
186  * Slave host for running slave controller
187  */
188 static struct GNUNET_TESTBED_Host *slave;
189
190 /**
191  * Another slave host for running another slave controller
192  */
193 static struct GNUNET_TESTBED_Host *slave2;
194
195 /**
196  * Host for slave 3
197  */
198 static struct GNUNET_TESTBED_Host *slave3;
199
200 /**
201  * Slave host registration handle
202  */
203 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
204
205 /**
206  * Handle to global configuration
207  */
208 static struct GNUNET_CONFIGURATION_Handle *cfg;
209
210 /**
211  * Configuration of slave 3 controller
212  */
213 static struct GNUNET_CONFIGURATION_Handle *cfg3;
214
215 /**
216  * Abort task
217  */
218 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
219
220 /**
221  * Operation handle for linking controllers
222  */
223 static struct GNUNET_TESTBED_Operation *op;
224
225 /**
226  * Handle to peer started at slave 1
227  */
228 static struct GNUNET_TESTBED_Peer *slave1_peer;
229
230 /**
231  * Handle to peer started at slave 2
232  */
233 static struct GNUNET_TESTBED_Peer *slave2_peer;
234
235 /**
236  * Handle to a peer started at master controller
237  */
238 static struct GNUNET_TESTBED_Peer *master_peer;
239
240 /**
241  * Event mask
242  */
243 uint64_t event_mask;
244
245 /**
246  * Global testing status
247  */
248 static enum Stage result;
249
250
251 /**
252  * Shutdown nicely
253  *
254  * @param cls NULL
255  * @param tc the task context
256  */
257 static void
258 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
259 {
260   if (GNUNET_SCHEDULER_NO_TASK != abort_task)
261     GNUNET_SCHEDULER_cancel (abort_task);
262   if (NULL != slave3)
263     GNUNET_TESTBED_host_destroy (slave3);
264   if (NULL != slave2)
265     GNUNET_TESTBED_host_destroy (slave2);
266   if (NULL != slave)
267     GNUNET_TESTBED_host_destroy (slave);
268   if (NULL != host)
269     GNUNET_TESTBED_host_destroy (host);
270   if (NULL != mc)
271     GNUNET_TESTBED_controller_disconnect (mc);
272   if (NULL != cfg)
273     GNUNET_CONFIGURATION_destroy (cfg);
274   if (NULL != cfg3)
275     GNUNET_CONFIGURATION_destroy (cfg3);
276   if (NULL != cp)
277     GNUNET_TESTBED_controller_stop (cp);
278   if (NULL != rh)
279     GNUNET_TESTBED_cancel_registration (rh);
280 }
281
282
283 /**
284  * abort task to run on test timed out
285  *
286  * @param cls NULL
287  * @param tc the task context
288  */
289 static void
290 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
291 {
292   LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
293   abort_task = GNUNET_SCHEDULER_NO_TASK;
294   do_shutdown (cls, tc);
295 }
296
297
298 /**
299  * Calls abort now
300  *
301  * @param 
302  * @return 
303  */
304 static void
305 do_abort_now (void *cls)
306 {
307   if (GNUNET_SCHEDULER_NO_TASK != abort_task)
308     GNUNET_SCHEDULER_cancel (abort_task);
309   abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
310 }
311
312
313 /**
314  * Task for inserting delay between tests
315  *
316  * @param
317  * @return
318  */
319 static void
320 delay_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
321 {
322   switch (result)
323   {
324   case SLAVE1_PEER_START_SUCCESS:
325     op = GNUNET_TESTBED_peer_stop (slave1_peer, NULL, NULL);
326     GNUNET_assert (NULL != op);
327     break;
328   case MASTER_SLAVE2_PEERS_CONNECTED:
329     op = GNUNET_TESTBED_peer_stop (slave2_peer, NULL, NULL);
330     GNUNET_assert (NULL != op);
331     break;
332   default:
333     GNUNET_assert (0);
334   }
335 }
336
337
338 /**
339  * Functions of this signature are called when a peer has been successfully
340  * created
341  *
342  * @param cls the closure from GNUNET_TESTBED_peer_create()
343  * @param peer the handle for the created peer; NULL on any error during
344  *          creation
345  * @param emsg NULL if peer is not NULL; else MAY contain the error description
346  */
347 static void
348 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
349 {
350   GNUNET_assert (NULL != peer);
351   GNUNET_assert (NULL == emsg);
352   switch (result)
353   {
354   case MASTER_STARTED:
355     result = MASTER_PEER_CREATE_SUCCESS;
356     master_peer = peer;
357     GNUNET_TESTBED_operation_done (op);
358     op = GNUNET_TESTBED_peer_start (NULL, master_peer, NULL, NULL);
359     break;
360   case SLAVE2_LINK_SUCCESS:
361     result = SLAVE1_PEER_CREATE_SUCCESS;
362     slave1_peer = peer;
363     GNUNET_TESTBED_operation_done (op);
364     op = GNUNET_TESTBED_peer_create (mc, slave2, cfg, peer_create_cb, NULL);
365     break;
366   case SLAVE1_PEER_CREATE_SUCCESS:
367     result = SLAVE2_PEER_CREATE_SUCCESS;
368     slave2_peer = peer;
369     GNUNET_TESTBED_operation_done (op);
370     op = GNUNET_TESTBED_peer_start (NULL, slave1_peer, NULL, NULL);
371     break;
372   default:
373     GNUNET_assert (0);
374   }
375   GNUNET_assert (NULL != op);
376 }
377
378
379 /**
380  * Checks the event if it is an operation finished event and if indicates a
381  * successfull completion of operation
382  *
383  * @param event the event information to check
384  */
385 static void
386 check_operation_success (const struct GNUNET_TESTBED_EventInformation *event)
387 {
388   GNUNET_assert (NULL != event);
389   GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
390   GNUNET_assert (event->details.operation_finished.operation == op);
391   GNUNET_assert (NULL == event->details.operation_finished.op_cls);
392   GNUNET_assert (NULL == event->details.operation_finished.emsg);
393   GNUNET_assert (NULL == event->details.operation_finished.generic);
394 }
395
396
397 /**
398  * Callback which will be called to after a host registration succeeded or failed
399  *
400  * @param cls the host which has been registered
401  * @param emsg the error message; NULL if host registration is successful
402  */
403 static void
404 registration_cont (void *cls, const char *emsg);
405
406
407 /**
408  * Signature of the event handler function called by the
409  * respective event controller.
410  *
411  * @param cls closure
412  * @param event information about the event
413  */
414 static void
415 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
416 {
417   switch (result)
418   {
419   case SLAVE2_REGISTERED:
420     check_operation_success (event);
421     GNUNET_TESTBED_operation_done (op);
422     op = NULL;
423     result = SLAVE1_LINK_SUCCESS;
424     GNUNET_assert (NULL != slave2);
425     GNUNET_assert (NULL != slave);
426     op = GNUNET_TESTBED_controller_link (NULL, mc, slave2, slave, cfg, GNUNET_YES);
427     GNUNET_assert (NULL != op);
428     break;
429   case SLAVE1_LINK_SUCCESS:
430     check_operation_success (event);
431     GNUNET_TESTBED_operation_done (op);
432     op = NULL;
433     result = SLAVE2_LINK_SUCCESS;
434     op = GNUNET_TESTBED_peer_create (mc, slave, cfg, peer_create_cb, NULL);
435     GNUNET_assert (NULL != op);
436     break;
437   case MASTER_PEER_CREATE_SUCCESS:
438     GNUNET_assert (GNUNET_TESTBED_ET_PEER_START == event->type);
439     GNUNET_assert (event->details.peer_start.host == host);
440     GNUNET_assert (event->details.peer_start.peer == master_peer);
441     GNUNET_TESTBED_operation_done (op);
442     result = MASTER_PEER_START_SUCCESS;
443     slave = GNUNET_TESTBED_host_create_with_id (1, "127.0.0.1", NULL, 0);
444     GNUNET_assert (NULL != slave);
445     rh = GNUNET_TESTBED_register_host (mc, slave, &registration_cont, NULL);
446     GNUNET_assert (NULL != rh);
447     break;
448   case SLAVE2_PEER_CREATE_SUCCESS:
449     GNUNET_assert (GNUNET_TESTBED_ET_PEER_START == event->type);
450     GNUNET_assert (event->details.peer_start.host == slave);
451     GNUNET_assert (event->details.peer_start.peer == slave1_peer);
452     GNUNET_TESTBED_operation_done (op);
453     result = SLAVE1_PEER_START_SUCCESS;
454     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
455                                   (GNUNET_TIME_UNIT_SECONDS, 1), &delay_task,
456                                   NULL);
457     break;
458   case SLAVE1_PEER_START_SUCCESS:
459     GNUNET_assert (GNUNET_TESTBED_ET_PEER_STOP == event->type);
460     GNUNET_assert (event->details.peer_stop.peer == slave1_peer);
461     GNUNET_TESTBED_operation_done (op);
462     result = SLAVE1_PEER_STOP_SUCCESS;
463     op = GNUNET_TESTBED_peer_start (NULL, slave2_peer, NULL, NULL);
464     GNUNET_assert (NULL != op);
465     break;
466   case SLAVE1_PEER_STOP_SUCCESS:
467     GNUNET_assert (GNUNET_TESTBED_ET_PEER_START == event->type);
468     GNUNET_assert (event->details.peer_start.host == slave2);
469     GNUNET_assert (event->details.peer_start.peer == slave2_peer);
470     GNUNET_TESTBED_operation_done (op);
471     result = SLAVE2_PEER_START_SUCCESS;
472     op = GNUNET_TESTBED_overlay_connect (mc, NULL, NULL, master_peer,
473                                          slave2_peer);
474     break;
475   case SLAVE2_PEER_START_SUCCESS:
476     GNUNET_assert (NULL != event);
477     GNUNET_assert (GNUNET_TESTBED_ET_CONNECT == event->type);
478     GNUNET_assert (event->details.peer_connect.peer1 == master_peer);
479     GNUNET_assert (event->details.peer_connect.peer2 == slave2_peer);
480     result = MASTER_SLAVE2_PEERS_CONNECTED;
481     GNUNET_TESTBED_operation_done (op);
482     op = NULL;
483     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
484                                   (GNUNET_TIME_UNIT_SECONDS, 1), &delay_task,
485                                   NULL);
486     break;
487   case MASTER_SLAVE2_PEERS_CONNECTED:
488     GNUNET_assert (GNUNET_TESTBED_ET_PEER_STOP == event->type);
489     GNUNET_assert (event->details.peer_stop.peer == slave2_peer);
490     GNUNET_TESTBED_operation_done (op);
491     result = SLAVE2_PEER_STOP_SUCCESS;
492     op = GNUNET_TESTBED_peer_destroy (slave1_peer);
493     GNUNET_assert (NULL != op);
494     break;
495   case SLAVE2_PEER_STOP_SUCCESS:
496     check_operation_success (event);
497     GNUNET_TESTBED_operation_done (op);
498     result = SLAVE1_PEER_DESTROY_SUCCESS;
499     op = GNUNET_TESTBED_peer_destroy (slave2_peer);
500     GNUNET_assert (NULL != op);
501     break;
502   case SLAVE1_PEER_DESTROY_SUCCESS:
503     check_operation_success (event);
504     GNUNET_TESTBED_operation_done (op);
505     op = NULL;
506     result = SLAVE2_PEER_DESTROY_SUCCESS;
507     slave3 = GNUNET_TESTBED_host_create_with_id (3, "127.0.0.1", NULL, 0);
508     rh = GNUNET_TESTBED_register_host (mc, slave3, &registration_cont, NULL);
509     break;
510   case SLAVE3_REGISTERED:
511     check_operation_success (event);
512     GNUNET_TESTBED_operation_done (op);
513     op = NULL;
514     result = SLAVE3_STARTED;
515     op = GNUNET_TESTBED_get_slave_config (NULL, mc, slave3);
516     GNUNET_assert (NULL != op);    
517     break;
518   case SLAVE3_STARTED:
519     GNUNET_assert (NULL != event);
520     GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
521     GNUNET_assert (event->details.operation_finished.operation == op);
522     GNUNET_assert (NULL == event->details.operation_finished.op_cls);
523     GNUNET_assert (NULL == event->details.operation_finished.emsg);
524     cfg3 = GNUNET_CONFIGURATION_dup (event->details.operation_finished.generic);
525     GNUNET_TESTBED_operation_done (op);
526     result = SLAVE3_GET_CONFIG_SUCCESS;
527     op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, slave, cfg3, GNUNET_NO);
528     break;
529   case SLAVE3_GET_CONFIG_SUCCESS:
530     result = SLAVE3_LINK_SUCCESS;
531     GNUNET_TESTBED_operation_done (op);
532     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
533                                   (GNUNET_TIME_UNIT_SECONDS, 3),
534                                   &do_shutdown, NULL);
535     break;
536   default:
537     GNUNET_assert (0);
538   }
539 }
540
541
542 /**
543  * Callback which will be called to after a host registration succeeded or failed
544  *
545  * @param cls the host which has been registered
546  * @param emsg the error message; NULL if host registration is successful
547  */
548 static void
549 registration_cont (void *cls, const char *emsg)
550 {
551   rh = NULL;
552   switch (result)
553   {
554   case MASTER_PEER_START_SUCCESS:
555     GNUNET_assert (NULL == emsg);
556     GNUNET_assert (NULL != mc);
557     result = SLAVE1_REGISTERED;
558     slave2 = GNUNET_TESTBED_host_create_with_id (2, "127.0.0.1", NULL, 0);
559     GNUNET_assert (NULL != slave2);
560     rh = GNUNET_TESTBED_register_host (mc, slave2, &registration_cont, NULL);
561     GNUNET_assert (NULL != rh);
562     break;
563   case SLAVE1_REGISTERED:
564     GNUNET_assert (NULL == emsg);
565     GNUNET_assert (NULL != mc);
566     result = SLAVE2_REGISTERED;
567     GNUNET_assert (NULL != cfg);
568     op = GNUNET_TESTBED_controller_link (NULL, mc, slave, NULL, cfg, GNUNET_YES);
569     GNUNET_assert (NULL != op);
570     break;
571   case SLAVE2_PEER_DESTROY_SUCCESS:
572     GNUNET_assert (NULL == emsg);
573     GNUNET_assert (NULL != mc);
574     GNUNET_assert (NULL == op);
575     result = SLAVE3_REGISTERED;
576     op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, NULL, cfg, GNUNET_YES);
577     GNUNET_assert (NULL != op);
578     break;
579   default:
580     GNUNET_break (0);
581     do_abort_now (NULL);
582   }
583 }
584
585 /**
586  * Callback to signal successfull startup of the controller process
587  *
588  * @param cls the closure from GNUNET_TESTBED_controller_start()
589  * @param cfg the configuration with which the controller has been started;
590  *          NULL if status is not GNUNET_OK
591  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
592  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
593  */
594 static void
595 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
596            int status)
597 {
598   switch (result)
599   {
600   case INIT:
601     GNUNET_assert (GNUNET_OK == status);
602     event_mask = 0;
603     event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
604     event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
605     event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
606     event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
607     mc = GNUNET_TESTBED_controller_connect (config, host, event_mask,
608                                             &controller_cb, NULL);
609     GNUNET_assert (NULL != mc);
610     result = MASTER_STARTED;
611     op = GNUNET_TESTBED_peer_create (mc, host, cfg, peer_create_cb, NULL);
612     GNUNET_assert (NULL != op);
613     break;
614   default:    
615     GNUNET_break (0);
616     cp = NULL;
617     do_abort_now (NULL);
618   }
619 }
620
621
622 /**
623  * Main run function.
624  *
625  * @param cls NULL
626  * @param args arguments passed to GNUNET_PROGRAM_run
627  * @param cfgfile the path to configuration file
628  * @param cfg the configuration file handle
629  */
630 static void
631 run (void *cls, char *const *args, const char *cfgfile,
632      const struct GNUNET_CONFIGURATION_Handle *config)
633 {
634   host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
635   GNUNET_assert (NULL != host);
636   if (GNUNET_YES != GNUNET_TESTBED_is_host_habitable (host, config))
637   {
638     GNUNET_TESTBED_host_destroy (host);
639     host = NULL;
640     (void) PRINTF ("%s",
641                    "Unable to run the test as this system is not configured "
642                    "to use password less SSH logins to localhost.\n"
643                    "Marking test as successful\n");
644     result = SLAVE3_LINK_SUCCESS;
645     return;
646   }
647   cfg = GNUNET_CONFIGURATION_dup (config);
648   cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, cfg, status_cb,
649                                         NULL);
650   abort_task =
651       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
652                                     (GNUNET_TIME_UNIT_MINUTES, 5), &do_abort,
653                                     NULL);
654 }
655
656
657 /**
658  * Main function
659  */
660 int
661 main (int argc, char **argv)
662 {
663   char *const argv2[] = { "test_testbed_api_controllerlink",
664     "-c", "test_testbed_api.conf",
665     NULL
666   };
667   struct GNUNET_GETOPT_CommandLineOption options[] = {
668     GNUNET_GETOPT_OPTION_END
669   };
670   int ret;
671
672   result = INIT;
673   ret =
674       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
675                           "test_testbed_api_controllerlink", "nohelp", options,
676                           &run, NULL);
677   if ((GNUNET_OK != ret) || (SLAVE3_LINK_SUCCESS != result))
678     return 1;
679   return 0;
680 }
681
682 /* end of test_testbed_api_controllerlink.c */
683