70f6fa84603eb4800d36036d3e88b7bc88c21cff
[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     SUCCESS
79
80   };
81
82 /**
83  * Host for running master controller
84  */
85 static struct GNUNET_TESTBED_Host *host;
86
87 /**
88  * The master controller process
89  */
90 static struct GNUNET_TESTBED_ControllerProc *cp;
91
92 /**
93  * Handle to master controller
94  */
95 static struct GNUNET_TESTBED_Controller *mc;
96
97 /**
98  * Slave host for running slave controller
99  */
100 static struct GNUNET_TESTBED_Host *slave;
101
102 /**
103  * Another slave host for running another slave controller
104  */
105 static struct GNUNET_TESTBED_Host *slave2;
106
107 /**
108  * Slave host registration handle
109  */
110 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
111
112 /**
113  * Handle to global configuration
114  */
115 static struct GNUNET_CONFIGURATION_Handle *cfg;
116
117 /**
118  * Abort task
119  */
120 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
121
122 /**
123  * Operation handle for linking controllers
124  */
125 static struct GNUNET_TESTBED_Operation *op;
126
127 /**
128  * Event mask
129  */
130 uint64_t event_mask;
131
132 /**
133  * Global testing status
134  */
135 static enum Stage result;
136
137
138 /**
139  * Shutdown nicely
140  *
141  * @param cls NULL
142  * @param tc the task context
143  */
144 static void
145 do_shutdown (void *cls, const const struct GNUNET_SCHEDULER_TaskContext *tc)
146 {
147   if (GNUNET_SCHEDULER_NO_TASK != abort_task)
148     GNUNET_SCHEDULER_cancel (abort_task);
149   if (NULL != slave2)
150     GNUNET_TESTBED_host_destroy (slave2);
151     if (NULL != slave)
152     GNUNET_TESTBED_host_destroy (slave);
153   if (NULL != host)
154     GNUNET_TESTBED_host_destroy (host);
155   if (NULL != mc)
156     GNUNET_TESTBED_controller_disconnect (mc);
157   if (NULL != cfg)
158     GNUNET_CONFIGURATION_destroy (cfg);
159   if (NULL != cp)
160     GNUNET_TESTBED_controller_stop (cp);
161   if (NULL != rh)
162     GNUNET_TESTBED_cancel_registration (rh);
163   
164 }
165
166
167 /**
168  * abort task to run on test timed out
169  *
170  * @param cls NULL
171  * @param tc the task context
172  */
173 static void
174 do_abort (void *cls, const const struct GNUNET_SCHEDULER_TaskContext *tc)
175 {
176   LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
177   abort_task = GNUNET_SCHEDULER_NO_TASK;
178   do_shutdown (cls, tc);
179 }
180
181
182 /**
183  * Signature of the event handler function called by the
184  * respective event controller.
185  *
186  * @param cls closure
187  * @param event information about the event
188  */
189 static void 
190 controller_cb(void *cls, const struct GNUNET_TESTBED_EventInformation *event)
191 {
192   switch (result)
193   {
194   case SLAVE2_REGISTERED:
195     GNUNET_assert (NULL != event);
196     GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
197     GNUNET_assert (event->details.operation_finished.operation == op);
198     GNUNET_assert (NULL == event->details.operation_finished.op_cls);
199     GNUNET_assert (NULL == event->details.operation_finished.emsg);
200     GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC ==
201                    event->details.operation_finished.pit);
202     GNUNET_assert (NULL == event->details.operation_finished.op_result.generic);
203     GNUNET_TESTBED_operation_done (op);
204     op = NULL;
205     result = SLAVE1_LINK_SUCCESS;
206     GNUNET_assert (NULL != slave2);
207     GNUNET_assert (NULL != slave);
208     op = GNUNET_TESTBED_controller_link (mc, slave2, slave, cfg, GNUNET_YES);
209     GNUNET_assert (NULL != op);
210     break;
211   case SLAVE1_LINK_SUCCESS:
212     GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
213     GNUNET_assert (event->details.operation_finished.operation == op);
214     GNUNET_assert (NULL == event->details.operation_finished.op_cls);
215     GNUNET_assert (NULL == event->details.operation_finished.emsg);
216     GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC ==
217                    event->details.operation_finished.pit);
218     GNUNET_assert (NULL == event->details.operation_finished.op_result.generic);
219     GNUNET_TESTBED_operation_done (op);
220     op = NULL;
221     result = SUCCESS;
222     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
223     break;
224   default:
225     GNUNET_assert (0);
226   }
227 }
228
229
230 /**
231  * Callback which will be called to after a host registration succeeded or failed
232  *
233  * @param cls the host which has been registered
234  * @param emsg the error message; NULL if host registration is successful
235  */
236 static void 
237 registration_cont (void *cls, const char *emsg)
238 {
239   rh = NULL;
240   switch (result)
241   {
242   case MASTER_STARTED:
243     GNUNET_assert (NULL == emsg);
244     GNUNET_assert (NULL != mc);
245     result = SLAVE1_REGISTERED;
246     slave2 = GNUNET_TESTBED_host_create_with_id (2, "127.0.0.1", NULL, 0);
247     GNUNET_assert (NULL != slave2);
248     rh = GNUNET_TESTBED_register_host (mc, slave2, &registration_cont, NULL);
249     GNUNET_assert (NULL != rh);
250     break;
251   case SLAVE1_REGISTERED:
252     GNUNET_assert (NULL == emsg);
253     GNUNET_assert (NULL != mc);
254     result = SLAVE2_REGISTERED;
255     GNUNET_assert (NULL != cfg);
256     op = GNUNET_TESTBED_controller_link (mc, slave, NULL, cfg, GNUNET_YES);
257     GNUNET_assert (NULL != op);
258     break;
259   case INIT:
260   case SUCCESS:
261   case SLAVE2_REGISTERED:
262   case SLAVE1_LINK_SUCCESS:
263     GNUNET_assert (0);
264   }
265 }
266
267 /**
268  * Callback to signal successfull startup of the controller process
269  *
270  * @param cls the closure from GNUNET_TESTBED_controller_start()
271  * @param cfg the configuration with which the controller has been started;
272  *          NULL if status is not GNUNET_OK
273  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
274  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
275  */
276 static void 
277 status_cb (void *cls, 
278            const struct GNUNET_CONFIGURATION_Handle *config, int status)
279 {
280   switch (result)
281   {
282   case INIT:
283     GNUNET_assert (GNUNET_OK == status);
284     event_mask = 0;
285     event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
286     event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
287     event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
288     event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
289     mc = GNUNET_TESTBED_controller_connect (config, host, event_mask,
290                                             &controller_cb, NULL);
291     GNUNET_assert (NULL != mc);
292     result = MASTER_STARTED;
293     slave = GNUNET_TESTBED_host_create_with_id (1, "127.0.0.1", NULL, 0);
294     GNUNET_assert (NULL != slave);
295     rh = GNUNET_TESTBED_register_host (mc, slave, &registration_cont, NULL);
296     GNUNET_assert (NULL != rh);
297     break;
298   default:
299     GNUNET_assert (0);
300   }
301 }
302
303
304 /**
305  * Main run function. 
306  *
307  * @param cls NULL
308  * @param args arguments passed to GNUNET_PROGRAM_run
309  * @param cfgfile the path to configuration file
310  * @param cfg the configuration file handle
311  */
312 static void
313 run (void *cls, char *const *args, const char *cfgfile,
314      const struct GNUNET_CONFIGURATION_Handle *config)
315 {
316   host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
317   GNUNET_assert (NULL != host);
318   cfg = GNUNET_CONFIGURATION_dup (config);
319   cp =
320     GNUNET_TESTBED_controller_start ("127.0.0.1", host, cfg, status_cb, NULL);
321   abort_task = GNUNET_SCHEDULER_add_delayed 
322     (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5), 
323      &do_abort, NULL);
324 }
325
326
327 /**
328  * Main function
329  */
330 int main (int argc, char **argv)
331 {
332   int ret;
333   char *const argv2[] = { "test_testbed_api_controllerlink",
334                           "-c", "test_testbed_api.conf",
335                           NULL
336   };
337   struct GNUNET_GETOPT_CommandLineOption options[] = {
338     GNUNET_GETOPT_OPTION_END
339   };
340   char *const remote_args[] = {
341     "ssh", "-o", "BatchMode=yes", "127.0.0.1", "echo", "Hello", "World", NULL
342   };
343   struct GNUNET_OS_Process *auxp;
344   enum GNUNET_OS_ProcessStatusType type;
345   unsigned long code;
346   
347   auxp = GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL,
348                                       NULL, NULL, "ssh", remote_args);
349   GNUNET_assert (NULL != auxp);
350   do
351   {
352     ret = GNUNET_OS_process_status (auxp, &type, &code);    
353     GNUNET_assert (GNUNET_SYSERR != ret);
354     (void) usleep (300);    
355   } while (GNUNET_NO == ret);
356   if (0 != code)
357   {    
358     (void) printf ("Unable to run the test as this system is not configured "
359                    "to use password less SSH logins to localhost.\n"
360                    "Marking test as successful\n");
361     return 0;    
362   }  
363   result = INIT;
364   ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
365                             "test_testbed_api_controllerlink", "nohelp", options, &run,
366                             NULL);
367   if ((GNUNET_OK != ret) || (SUCCESS != result))
368     return 1;
369   return 0;
370 }