2 This file is part of GNUnet
3 (C) 2008--2012 Christian Grothoff (and other contributing authors)
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.
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.
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.
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>
29 * The controller architecture we try to achieve in this test case:
34 * Slave Controller 1---------Slave Controller 3
41 #include "gnunet_util_lib.h"
42 #include "gnunet_testing_lib-new.h"
43 #include "gnunet_testbed_service.h"
46 * Generic logging shortcut
48 #define LOG(kind,...) \
49 GNUNET_log (kind, __VA_ARGS__)
52 * Debug logging shorthand
54 #define LOG_DEBUG(...) \
55 LOG(GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
58 * Different stages in testing
69 * Master controller has started
74 * A peer has been created on master
76 MASTER_PEER_CREATE_SUCCESS,
79 * Peer on master controller has been started successfully.
81 MASTER_PEER_START_SUCCESS,
84 * The first slave has been registered at master controller
89 * The second slave has been registered at the master controller
94 * Link from master to slave 1 has been successfully created
99 * Link from slave 1 to slave 2 has been successfully created.
104 * Peer create on slave 1 successful
106 SLAVE1_PEER_CREATE_SUCCESS,
109 * Peer create on slave 2 successful
111 SLAVE2_PEER_CREATE_SUCCESS,
114 * Peer startup on slave 1 successful
116 SLAVE1_PEER_START_SUCCESS,
119 * Peer on slave 1 successfully stopped
121 SLAVE1_PEER_STOP_SUCCESS,
124 * Peer startup on slave 2 successful
126 SLAVE2_PEER_START_SUCCESS,
129 * Try to connect peers on master and slave 2.
131 MASTER_SLAVE2_PEERS_CONNECTED,
134 * Peer on slave 2 successfully stopped
136 SLAVE2_PEER_STOP_SUCCESS,
139 * Peer destroy on slave 1 successful
141 SLAVE1_PEER_DESTROY_SUCCESS,
144 * Peer destory on slave 2 successful
146 SLAVE2_PEER_DESTROY_SUCCESS,
149 * Slave 3 has successfully registered
154 * Slave 3 has successfully started
159 * The configuration of slave 3 is acquired
161 SLAVE3_GET_CONFIG_SUCCESS,
164 * Slave 1 has linked to slave 3;
171 * Host for running master controller
173 static struct GNUNET_TESTBED_Host *host;
176 * The master controller process
178 static struct GNUNET_TESTBED_ControllerProc *cp;
181 * Handle to master controller
183 static struct GNUNET_TESTBED_Controller *mc;
186 * Slave host for running slave controller
188 static struct GNUNET_TESTBED_Host *slave;
191 * Another slave host for running another slave controller
193 static struct GNUNET_TESTBED_Host *slave2;
198 static struct GNUNET_TESTBED_Host *slave3;
201 * Slave host registration handle
203 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
206 * Handle to global configuration
208 static struct GNUNET_CONFIGURATION_Handle *cfg;
211 * Configuration of slave 3 controller
213 static struct GNUNET_CONFIGURATION_Handle *cfg3;
218 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
221 * Operation handle for linking controllers
223 static struct GNUNET_TESTBED_Operation *op;
226 * Handle to peer started at slave 1
228 static struct GNUNET_TESTBED_Peer *slave1_peer;
231 * Handle to peer started at slave 2
233 static struct GNUNET_TESTBED_Peer *slave2_peer;
236 * Handle to a peer started at master controller
238 static struct GNUNET_TESTBED_Peer *master_peer;
246 * Global testing status
248 static enum Stage result;
255 * @param tc the task context
258 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
260 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
261 GNUNET_SCHEDULER_cancel (abort_task);
263 GNUNET_TESTBED_host_destroy (slave3);
265 GNUNET_TESTBED_host_destroy (slave2);
267 GNUNET_TESTBED_host_destroy (slave);
269 GNUNET_TESTBED_host_destroy (host);
271 GNUNET_TESTBED_controller_disconnect (mc);
273 GNUNET_CONFIGURATION_destroy (cfg);
275 GNUNET_CONFIGURATION_destroy (cfg3);
277 GNUNET_TESTBED_controller_stop (cp);
279 GNUNET_TESTBED_cancel_registration (rh);
284 * abort task to run on test timed out
287 * @param tc the task context
290 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
292 LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
293 abort_task = GNUNET_SCHEDULER_NO_TASK;
294 do_shutdown (cls, tc);
305 do_abort_now (void *cls)
307 if (GNUNET_SCHEDULER_NO_TASK != abort_task)
308 GNUNET_SCHEDULER_cancel (abort_task);
309 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);
314 * Task for inserting delay between tests
320 delay_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
324 case SLAVE1_PEER_START_SUCCESS:
325 op = GNUNET_TESTBED_peer_stop (slave1_peer, NULL, NULL);
326 GNUNET_assert (NULL != op);
328 case MASTER_SLAVE2_PEERS_CONNECTED:
329 op = GNUNET_TESTBED_peer_stop (slave2_peer, NULL, NULL);
330 GNUNET_assert (NULL != op);
339 * Functions of this signature are called when a peer has been successfully
342 * @param cls the closure from GNUNET_TESTBED_peer_create()
343 * @param peer the handle for the created peer; NULL on any error during
345 * @param emsg NULL if peer is not NULL; else MAY contain the error description
348 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
350 GNUNET_assert (NULL != peer);
351 GNUNET_assert (NULL == emsg);
355 result = MASTER_PEER_CREATE_SUCCESS;
357 GNUNET_TESTBED_operation_done (op);
358 op = GNUNET_TESTBED_peer_start (NULL, master_peer, NULL, NULL);
360 case SLAVE2_LINK_SUCCESS:
361 result = SLAVE1_PEER_CREATE_SUCCESS;
363 GNUNET_TESTBED_operation_done (op);
364 op = GNUNET_TESTBED_peer_create (mc, slave2, cfg, peer_create_cb, NULL);
366 case SLAVE1_PEER_CREATE_SUCCESS:
367 result = SLAVE2_PEER_CREATE_SUCCESS;
369 GNUNET_TESTBED_operation_done (op);
370 op = GNUNET_TESTBED_peer_start (NULL, slave1_peer, NULL, NULL);
375 GNUNET_assert (NULL != op);
380 * Checks the event if it is an operation finished event and if indicates a
381 * successfull completion of operation
383 * @param event the event information to check
386 check_operation_success (const struct GNUNET_TESTBED_EventInformation *event)
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);
398 * Callback which will be called to after a host registration succeeded or failed
400 * @param cls the host which has been registered
401 * @param emsg the error message; NULL if host registration is successful
404 registration_cont (void *cls, const char *emsg);
408 * Signature of the event handler function called by the
409 * respective event controller.
412 * @param event information about the event
415 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
419 case SLAVE2_REGISTERED:
420 check_operation_success (event);
421 GNUNET_TESTBED_operation_done (op);
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);
429 case SLAVE1_LINK_SUCCESS:
430 check_operation_success (event);
431 GNUNET_TESTBED_operation_done (op);
433 result = SLAVE2_LINK_SUCCESS;
434 op = GNUNET_TESTBED_peer_create (mc, slave, cfg, peer_create_cb, NULL);
435 GNUNET_assert (NULL != op);
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, ®istration_cont, NULL);
446 GNUNET_assert (NULL != rh);
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,
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);
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,
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);
483 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
484 (GNUNET_TIME_UNIT_SECONDS, 1), &delay_task,
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);
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);
502 case SLAVE1_PEER_DESTROY_SUCCESS:
503 check_operation_success (event);
504 GNUNET_TESTBED_operation_done (op);
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, ®istration_cont, NULL);
510 case SLAVE3_REGISTERED:
511 check_operation_success (event);
512 GNUNET_TESTBED_operation_done (op);
514 result = SLAVE3_STARTED;
515 op = GNUNET_TESTBED_get_slave_config (NULL, mc, slave3);
516 GNUNET_assert (NULL != op);
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);
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),
543 * Callback which will be called to after a host registration succeeded or failed
545 * @param cls the host which has been registered
546 * @param emsg the error message; NULL if host registration is successful
549 registration_cont (void *cls, const char *emsg)
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, ®istration_cont, NULL);
561 GNUNET_assert (NULL != rh);
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);
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);
586 * Callback to signal successfull startup of the controller process
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
595 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
601 GNUNET_assert (GNUNET_OK == status);
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);
626 * @param args arguments passed to GNUNET_PROGRAM_run
627 * @param cfgfile the path to configuration file
628 * @param cfg the configuration file handle
631 run (void *cls, char *const *args, const char *cfgfile,
632 const struct GNUNET_CONFIGURATION_Handle *config)
634 host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
635 GNUNET_assert (NULL != host);
636 cfg = GNUNET_CONFIGURATION_dup (config);
637 cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, cfg, status_cb,
640 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
641 (GNUNET_TIME_UNIT_MINUTES, 5), &do_abort,
647 * Function to check if
648 * 1. Password-less SSH logins to given ip work
649 * 2. gnunet-helper-testbed is found on the PATH on the remote side
651 * @param host_str numeric representation of the host's ip
652 * @return GNUNET_YES if password-less SSH login to the given host works;
656 check_ssh (char *host_str)
658 char *const remote_args[] = {
659 "ssh", "-o", "BatchMode=yes", "-o", "CheckHostIP=no",
660 "-o", "NoHostAuthenticationForLocalhost=yes", "-q",
661 host_str, "which", "gnunet-helper-testbed", NULL
663 struct GNUNET_OS_Process *auxp;
664 enum GNUNET_OS_ProcessStatusType type;
669 GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
670 NULL, "ssh", remote_args);
671 GNUNET_assert (NULL != auxp);
674 ret = GNUNET_OS_process_status (auxp, &type, &code);
675 GNUNET_assert (GNUNET_SYSERR != ret);
678 while (GNUNET_NO == ret);
679 (void) GNUNET_OS_process_wait (auxp);
680 GNUNET_OS_process_destroy (auxp);
681 return (0 != code) ? GNUNET_NO : GNUNET_YES;
689 main (int argc, char **argv)
691 char *const argv2[] = { "test_testbed_api_controllerlink",
692 "-c", "test_testbed_api.conf",
695 struct GNUNET_GETOPT_CommandLineOption options[] = {
696 GNUNET_GETOPT_OPTION_END
700 if (GNUNET_YES != check_ssh ("127.0.0.1"))
704 GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
705 "test_testbed_api_controllerlink", "nohelp", options,
707 if ((GNUNET_OK != ret) || (SLAVE3_LINK_SUCCESS != result))
713 "Unable to run the test as this system is not configured "
714 "to use password less SSH logins to localhost.\n"
715 "Marking test as successful\n");
719 /* end of test_testbed_api_controllerlink.c */