5236ada4a19d2795cb24cb63f4d300d82e221bd4
[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 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_testing_lib-new.h"
30 #include "gnunet_testbed_service.h"
31
32 /**
33  * Generic logging shortcut
34  */
35 #define LOG(kind,...)                           \
36   GNUNET_log (kind, __VA_ARGS__)
37
38 /**
39  * Debug logging shorthand
40  */
41 #define LOG_DEBUG(...)                          \
42   LOG(GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
43
44 /**
45  * Different stages in testing
46  */
47 enum Stage
48   {
49
50     /**
51      * Initial stage
52      */
53     INIT,
54
55     /**
56      * Master controller has started
57      */
58     MASTER_STARTED,
59
60     /**
61      * The first slave has been registered at master controller
62      */
63     SLAVE1_REGISTERED,
64
65     /**
66      * The second slave has been registered at the master controller
67      */
68     SLAVE2_REGISTERED,
69     
70     /**
71      * Link from master to slave 1 has been successfully created
72      */
73     SLAVE1_LINK_SUCCESS,
74
75     /**
76      * Link from slave 1 to slave 2 has been successfully created.
77      */
78     SLAVE2_LINK_SUCCESS,
79
80     /**
81      * Peer create on slave 1 successful
82      */
83     SLAVE1_PEER_CREATE_SUCCESS,
84
85     /**
86      * Test is successful
87      */
88     SUCCESS
89   };
90
91 /**
92  * Host for running master controller
93  */
94 static struct GNUNET_TESTBED_Host *host;
95
96 /**
97  * The master controller process
98  */
99 static struct GNUNET_TESTBED_ControllerProc *cp;
100
101 /**
102  * Handle to master controller
103  */
104 static struct GNUNET_TESTBED_Controller *mc;
105
106 /**
107  * Slave host for running slave controller
108  */
109 static struct GNUNET_TESTBED_Host *slave;
110
111 /**
112  * Another slave host for running another slave controller
113  */
114 static struct GNUNET_TESTBED_Host *slave2;
115
116 /**
117  * Slave host registration handle
118  */
119 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
120
121 /**
122  * Handle to global configuration
123  */
124 static struct GNUNET_CONFIGURATION_Handle *cfg;
125
126 /**
127  * Abort task
128  */
129 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
130
131 /**
132  * Operation handle for linking controllers
133  */
134 static struct GNUNET_TESTBED_Operation *op;
135
136 /**
137  * Handle to peer started at slave 1
138  */
139 static struct GNUNET_TESTBED_Peer *slave1_peer;
140
141 /**
142  * Handle to peer started at slave 2
143  */
144 static struct GNUNET_TESTBED_Peer *slave2_peer;
145
146 /**
147  * Event mask
148  */
149 uint64_t event_mask;
150
151 /**
152  * Global testing status
153  */
154 static enum Stage result;
155
156
157 /**
158  * Shutdown nicely
159  *
160  * @param cls NULL
161  * @param tc the task context
162  */
163 static void
164 do_shutdown (void *cls, const const struct GNUNET_SCHEDULER_TaskContext *tc)
165 {
166   if (GNUNET_SCHEDULER_NO_TASK != abort_task)
167     GNUNET_SCHEDULER_cancel (abort_task);
168   if (NULL != slave2)
169     GNUNET_TESTBED_host_destroy (slave2);
170     if (NULL != slave)
171     GNUNET_TESTBED_host_destroy (slave);
172   if (NULL != host)
173     GNUNET_TESTBED_host_destroy (host);
174   if (NULL != mc)
175     GNUNET_TESTBED_controller_disconnect (mc);
176   if (NULL != cfg)
177     GNUNET_CONFIGURATION_destroy (cfg);
178   if (NULL != cp)
179     GNUNET_TESTBED_controller_stop (cp);
180   if (NULL != rh)
181     GNUNET_TESTBED_cancel_registration (rh);
182   
183 }
184
185
186 /**
187  * abort task to run on test timed out
188  *
189  * @param cls NULL
190  * @param tc the task context
191  */
192 static void
193 do_abort (void *cls, const const struct GNUNET_SCHEDULER_TaskContext *tc)
194 {
195   LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
196   abort_task = GNUNET_SCHEDULER_NO_TASK;
197   do_shutdown (cls, tc);
198 }
199
200
201 /**
202  * Functions of this signature are called when a peer has been successfully
203  * created
204  *
205  * @param cls the closure from GNUNET_TESTBED_peer_create()
206  * @param peer the handle for the created peer; NULL on any error during
207  *          creation
208  * @param emsg NULL if peer is not NULL; else MAY contain the error description
209  */
210 static void 
211 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
212 {
213   switch (result)
214   {
215   case SLAVE2_LINK_SUCCESS:
216     GNUNET_assert (NULL != peer);
217     GNUNET_assert (NULL == emsg);
218     result = SLAVE1_PEER_CREATE_SUCCESS;    
219     slave1_peer = peer;
220     GNUNET_TESTBED_operation_done (op);    
221     op = GNUNET_TESTBED_peer_create (mc, slave2, cfg, peer_create_cb, NULL);
222     GNUNET_assert (NULL != op);
223     break;
224   case SLAVE1_PEER_CREATE_SUCCESS:
225     GNUNET_assert (NULL != peer);
226     GNUNET_assert (NULL == emsg);
227     result = SUCCESS;
228     slave2_peer = peer;    
229     GNUNET_TESTBED_operation_done (op);
230     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
231     break;
232   default:
233     GNUNET_assert (0);    
234   }
235 }
236
237
238 /**
239  * Signature of the event handler function called by the
240  * respective event controller.
241  *
242  * @param cls closure
243  * @param event information about the event
244  */
245 static void 
246 controller_cb(void *cls, const struct GNUNET_TESTBED_EventInformation *event)
247 {
248   switch (result)
249   {
250   case SLAVE2_REGISTERED:
251     GNUNET_assert (NULL != event);
252     GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
253     GNUNET_assert (event->details.operation_finished.operation == op);
254     GNUNET_assert (NULL == event->details.operation_finished.op_cls);
255     GNUNET_assert (NULL == event->details.operation_finished.emsg);
256     GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC ==
257                    event->details.operation_finished.pit);
258     GNUNET_assert (NULL == event->details.operation_finished.op_result.generic);
259     GNUNET_TESTBED_operation_done (op);
260     op = NULL;
261     result = SLAVE1_LINK_SUCCESS;
262     GNUNET_assert (NULL != slave2);
263     GNUNET_assert (NULL != slave);
264     op = GNUNET_TESTBED_controller_link (mc, slave2, slave, cfg, GNUNET_YES);
265     GNUNET_assert (NULL != op);
266     break;
267   case SLAVE1_LINK_SUCCESS:
268     GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
269     GNUNET_assert (event->details.operation_finished.operation == op);
270     GNUNET_assert (NULL == event->details.operation_finished.op_cls);
271     GNUNET_assert (NULL == event->details.operation_finished.emsg);
272     GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC ==
273                    event->details.operation_finished.pit);
274     GNUNET_assert (NULL == event->details.operation_finished.op_result.generic);
275     GNUNET_TESTBED_operation_done (op);
276     op = NULL;
277     result = SLAVE2_LINK_SUCCESS;
278     op = GNUNET_TESTBED_peer_create (mc, slave, cfg, peer_create_cb, NULL);
279     GNUNET_assert (NULL != op);
280     break;    
281   default:
282     GNUNET_assert (0);
283   }
284 }
285
286
287 /**
288  * Callback which will be called to after a host registration succeeded or failed
289  *
290  * @param cls the host which has been registered
291  * @param emsg the error message; NULL if host registration is successful
292  */
293 static void 
294 registration_cont (void *cls, const char *emsg)
295 {
296   rh = NULL;
297   switch (result)
298   {
299   case MASTER_STARTED:
300     GNUNET_assert (NULL == emsg);
301     GNUNET_assert (NULL != mc);
302     result = SLAVE1_REGISTERED;
303     slave2 = GNUNET_TESTBED_host_create_with_id (2, "127.0.0.1", NULL, 0);
304     GNUNET_assert (NULL != slave2);
305     rh = GNUNET_TESTBED_register_host (mc, slave2, &registration_cont, NULL);
306     GNUNET_assert (NULL != rh);
307     break;
308   case SLAVE1_REGISTERED:
309     GNUNET_assert (NULL == emsg);
310     GNUNET_assert (NULL != mc);
311     result = SLAVE2_REGISTERED;
312     GNUNET_assert (NULL != cfg);
313     op = GNUNET_TESTBED_controller_link (mc, slave, NULL, cfg, GNUNET_YES);
314     GNUNET_assert (NULL != op);
315     break;
316   default:
317     GNUNET_assert (0);
318   }
319 }
320
321 /**
322  * Callback to signal successfull startup of the controller process
323  *
324  * @param cls the closure from GNUNET_TESTBED_controller_start()
325  * @param cfg the configuration with which the controller has been started;
326  *          NULL if status is not GNUNET_OK
327  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
328  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
329  */
330 static void 
331 status_cb (void *cls, 
332            const struct GNUNET_CONFIGURATION_Handle *config, int status)
333 {
334   switch (result)
335   {
336   case INIT:
337     GNUNET_assert (GNUNET_OK == status);
338     event_mask = 0;
339     event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
340     event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
341     event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
342     event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
343     mc = GNUNET_TESTBED_controller_connect (config, host, event_mask,
344                                             &controller_cb, NULL);
345     GNUNET_assert (NULL != mc);
346     result = MASTER_STARTED;
347     slave = GNUNET_TESTBED_host_create_with_id (1, "127.0.0.1", NULL, 0);
348     GNUNET_assert (NULL != slave);
349     rh = GNUNET_TESTBED_register_host (mc, slave, &registration_cont, NULL);
350     GNUNET_assert (NULL != rh);
351     break;
352   default:
353     GNUNET_assert (0);
354   }
355 }
356
357
358 /**
359  * Main run function. 
360  *
361  * @param cls NULL
362  * @param args arguments passed to GNUNET_PROGRAM_run
363  * @param cfgfile the path to configuration file
364  * @param cfg the configuration file handle
365  */
366 static void
367 run (void *cls, char *const *args, const char *cfgfile,
368      const struct GNUNET_CONFIGURATION_Handle *config)
369 {
370   host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
371   GNUNET_assert (NULL != host);
372   cfg = GNUNET_CONFIGURATION_dup (config);
373   cp =
374     GNUNET_TESTBED_controller_start ("127.0.0.1", host, cfg, status_cb, NULL);
375   abort_task = GNUNET_SCHEDULER_add_delayed 
376     (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5), 
377      &do_abort, NULL);
378 }
379
380
381 /**
382  * Main function
383  */
384 int main (int argc, char **argv)
385 {
386   int ret;
387   char *const argv2[] = { "test_testbed_api_controllerlink",
388                           "-c", "test_testbed_api.conf",
389                           NULL
390   };
391   struct GNUNET_GETOPT_CommandLineOption options[] = {
392     GNUNET_GETOPT_OPTION_END
393   };
394   char *const remote_args[] = {
395     "ssh", "-o", "BatchMode=yes", "127.0.0.1", "echo", "Hello", "World", NULL
396   };
397   struct GNUNET_OS_Process *auxp;
398   enum GNUNET_OS_ProcessStatusType type;
399   unsigned long code;
400   
401   auxp = GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL,
402                                       NULL, NULL, "ssh", remote_args);
403   GNUNET_assert (NULL != auxp);
404   do
405   {
406     ret = GNUNET_OS_process_status (auxp, &type, &code);    
407     GNUNET_assert (GNUNET_SYSERR != ret);
408     (void) usleep (300);    
409   } while (GNUNET_NO == ret);
410   if (0 != code)
411   {    
412     (void) printf ("Unable to run the test as this system is not configured "
413                    "to use password less SSH logins to localhost.\n"
414                    "Marking test as successful\n");
415     return 0;    
416   }  
417   result = INIT;
418   ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
419                             "test_testbed_api_controllerlink", "nohelp", options, &run,
420                             NULL);
421   if ((GNUNET_OK != ret) || (SUCCESS != result))
422     return 1;
423   return 0;
424 }