-Merge branch 'master' of ssh://gnunet.org/gnunet into gsoc2018/rest_api
[oweals/gnunet.git] / src / testbed / test_testbed_api_2peers_1controller.c
1 /*
2       This file is part of GNUnet
3       Copyright (C) 2008--2013 GNUnet e.V.
4
5       GNUnet is free software: you can redistribute it and/or modify it
6       under the terms of the GNU Affero General Public License as published
7       by the Free Software Foundation, either version 3 of the License,
8       or (at your 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       Affero General Public License for more details.
14      
15       You should have received a copy of the GNU Affero General Public License
16       along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 /**
20  * @file testbed/test_testbed_api_2peers_1controller.c
21  * @brief testcases for the testbed api: 2 peers are configured, started and
22  *          connected together. The 2 peer reside on a single controller.
23  * @author Sree Harsha Totakura
24  */
25
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_testing_lib.h"
29 #include "gnunet_testbed_service.h"
30
31
32 /**
33  * Generic logging shortcut
34  */
35 #define LOG(kind,...)                           \
36   GNUNET_log (kind, __VA_ARGS__)
37
38 /**
39  * Relative time seconds shorthand
40  */
41 #define TIME_REL_SECS(sec) \
42   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
43
44 /**
45  * Peer context
46  */
47 struct PeerContext
48 {
49   /**
50    * The peer handle
51    */
52   struct GNUNET_TESTBED_Peer *peer;
53
54   /**
55    * Operations involving this peer
56    */
57   struct GNUNET_TESTBED_Operation *operation;
58
59   /**
60    * set to GNUNET_YES when peer is started
61    */
62   int is_running;
63 };
64
65 /**
66  * Our localhost
67  */
68 static struct GNUNET_TESTBED_Host *host;
69
70 /**
71  * The controller process
72  */
73 static struct GNUNET_TESTBED_ControllerProc *cp;
74
75 /**
76  * The controller handle
77  */
78 static struct GNUNET_TESTBED_Controller *controller;
79
80 /**
81  * A neighbouring host
82  */
83 static struct GNUNET_TESTBED_Host *neighbour;
84
85 /**
86  * Handle for neighbour registration
87  */
88 static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
89
90 /**
91  * peer 1
92  */
93 static struct PeerContext peer1;
94
95 /**
96  * peer2
97  */
98 static struct PeerContext peer2;
99
100 /**
101  * Handle to configuration
102  */
103 static struct GNUNET_CONFIGURATION_Handle *cfg;
104
105 /**
106  * Handle to operations involving both peers
107  */
108 static struct GNUNET_TESTBED_Operation *common_operation;
109
110 /**
111  * Abort task identifier
112  */
113 static struct GNUNET_SCHEDULER_Task * abort_task;
114
115 /**
116  * Delayed connect job identifier
117  */
118 static struct GNUNET_SCHEDULER_Task * delayed_connect_task;
119
120 /**
121  * Different stages in testing
122  */
123 enum Stage
124 {
125
126   /**
127    * Initial stage
128    */
129   INIT,
130
131   /**
132    * peers are created
133    */
134   PEERS_CREATED,
135
136   /**
137    * peers are started
138    */
139   PEERS_STARTED,
140
141   /**
142    * peers are connected
143    */
144   PEERS_CONNECTED,
145
146   /**
147    * Peers are connected once again (this should not fail as they are already connected)
148    */
149   PEERS_CONNECTED_2,
150
151   /**
152    * peers are stopped
153    */
154   PEERS_STOPPED,
155
156   /**
157    * Final success stage
158    */
159   SUCCESS
160 };
161
162 /**
163  * The testing result
164  */
165 static enum Stage result;
166
167
168 /**
169  * shortcut to exit during failure
170  */
171 #define FAIL_TEST(cond) do {                                    \
172     if (!(cond)) {                                              \
173       GNUNET_break(0);                                          \
174       if (NULL != abort_task)               \
175         GNUNET_SCHEDULER_cancel (abort_task);                   \
176       abort_task = NULL;                    \
177       GNUNET_SCHEDULER_add_now (do_shutdown, NULL);             \
178       return;                                                   \
179     }                                                          \
180   } while (0)
181
182
183 /**
184  * Shutdown nicely
185  *
186  * @param cls NULL
187  */
188 static void
189 do_shutdown (void *cls)
190 {
191   if (NULL != abort_task)
192     GNUNET_SCHEDULER_cancel (abort_task);
193   if (NULL != delayed_connect_task)
194     GNUNET_SCHEDULER_cancel (delayed_connect_task);
195   if (NULL != reg_handle)
196     GNUNET_TESTBED_cancel_registration (reg_handle);
197   GNUNET_TESTBED_controller_disconnect (controller);
198   GNUNET_CONFIGURATION_destroy (cfg);
199   if (NULL != cp)
200     GNUNET_TESTBED_controller_stop (cp);
201   GNUNET_TESTBED_host_destroy (neighbour);
202   GNUNET_TESTBED_host_destroy (host);
203 }
204
205
206 /**
207  * abort task to run on test timed out
208  *
209  * @param cls NULL
210  */
211 static void
212 do_abort (void *cls)
213 {
214   LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
215   abort_task = NULL;
216   do_shutdown (cls);
217 }
218
219
220 /**
221  * Callback to be called when an operation is completed
222  *
223  * @param cls the callback closure from functions generating an operation
224  * @param op the operation that has been finished
225  * @param emsg error message in case the operation has failed; will be NULL if
226  *          operation has executed successfully.
227  */
228 static void
229 op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg);
230
231
232 /**
233  * task for delaying a connect
234  *
235  * @param cls NULL
236  */
237 static void
238 do_delayed_connect (void *cls)
239 {
240   delayed_connect_task = NULL;
241   FAIL_TEST (NULL == common_operation);
242   common_operation =
243       GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer,
244                                       peer2.peer);
245 }
246
247
248 /**
249  * Callback to be called when an operation is completed
250  *
251  * @param cls the callback closure from functions generating an operation
252  * @param op the operation that has been finished
253  * @param emsg error message in case the operation has failed; will be NULL if
254  *          operation has executed successfully.
255  */
256 static void
257 op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
258 {
259   FAIL_TEST (common_operation == op);
260   switch (result)
261   {
262   case PEERS_STARTED:
263     FAIL_TEST (NULL == peer1.operation);
264     FAIL_TEST (NULL == peer2.operation);
265     FAIL_TEST (NULL != common_operation);
266     break;
267   case PEERS_CONNECTED:
268     FAIL_TEST (NULL == peer1.operation);
269     FAIL_TEST (NULL == peer2.operation);
270     FAIL_TEST (NULL != common_operation);
271     break;
272   default:
273     FAIL_TEST (0);
274   }
275 }
276
277
278 /**
279  * Signature of the event handler function called by the
280  * respective event controller.
281  *
282  * @param cls closure
283  * @param event information about the event
284  */
285 static void
286 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
287 {
288   switch (event->type)
289   {
290   case GNUNET_TESTBED_ET_OPERATION_FINISHED:   /* Will be reached when we destroy peers */
291     FAIL_TEST (PEERS_STOPPED == result);
292     FAIL_TEST (NULL == event->op_cls);
293     FAIL_TEST (NULL == event->details.operation_finished.emsg);
294     FAIL_TEST (NULL == event->details.operation_finished.generic);
295     if (event->op == peer1.operation)
296     {
297       GNUNET_TESTBED_operation_done (peer1.operation);
298       peer1.operation = NULL;
299       peer1.peer = NULL;
300     }
301     else if (event->op == peer2.operation)
302     {
303       GNUNET_TESTBED_operation_done (peer2.operation);
304       peer2.operation = NULL;
305       peer2.peer = NULL;
306     }
307     else
308       FAIL_TEST (0);
309     if ((NULL == peer1.peer) && (NULL == peer2.peer))
310     {
311       result = SUCCESS;
312       GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
313     }
314     break;
315   case GNUNET_TESTBED_ET_PEER_START:
316     FAIL_TEST (INIT == result);
317     FAIL_TEST (event->details.peer_start.host == host);
318     if (event->details.peer_start.peer == peer1.peer)
319     {
320       peer1.is_running = GNUNET_YES;
321       GNUNET_TESTBED_operation_done (peer1.operation);
322       peer1.operation = NULL;
323     }
324     else if (event->details.peer_start.peer == peer2.peer)
325     {
326       peer2.is_running = GNUNET_YES;
327       GNUNET_TESTBED_operation_done (peer2.operation);
328       peer2.operation = NULL;
329     }
330     else
331       FAIL_TEST (0);
332     if ((GNUNET_YES == peer1.is_running) && (GNUNET_YES == peer2.is_running))
333     {
334       result = PEERS_STARTED;
335       common_operation =
336           GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer,
337                                           peer2.peer);
338     }
339     break;
340   case GNUNET_TESTBED_ET_PEER_STOP:
341     FAIL_TEST (PEERS_CONNECTED_2 == result);
342     if (event->details.peer_stop.peer == peer1.peer)
343     {
344       peer1.is_running = GNUNET_NO;
345       GNUNET_TESTBED_operation_done (peer1.operation);
346       peer1.operation = GNUNET_TESTBED_peer_destroy (peer1.peer);
347     }
348     else if (event->details.peer_stop.peer == peer2.peer)
349     {
350       peer2.is_running = GNUNET_NO;
351       GNUNET_TESTBED_operation_done (peer2.operation);
352       peer2.operation = GNUNET_TESTBED_peer_destroy (peer2.peer);
353     }
354     else
355       FAIL_TEST (0);
356     if ((GNUNET_NO == peer1.is_running) && (GNUNET_NO == peer2.is_running))
357       result = PEERS_STOPPED;
358     break;
359   case GNUNET_TESTBED_ET_CONNECT:
360     switch (result)
361     {
362     case PEERS_STARTED:
363       FAIL_TEST (NULL == peer1.operation);
364       FAIL_TEST (NULL == peer2.operation);
365       FAIL_TEST (NULL != common_operation);
366       FAIL_TEST ((event->details.peer_connect.peer1 == peer1.peer) &&
367                  (event->details.peer_connect.peer2 == peer2.peer));
368       GNUNET_TESTBED_operation_done (common_operation);
369       common_operation = NULL;
370       result = PEERS_CONNECTED;
371       LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n");
372       delayed_connect_task =
373           GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (3), &do_delayed_connect,
374                                         NULL);
375       break;
376     case PEERS_CONNECTED:
377       FAIL_TEST (NULL == peer1.operation);
378       FAIL_TEST (NULL == peer2.operation);
379       FAIL_TEST (NULL != common_operation);
380       GNUNET_TESTBED_operation_done (common_operation);
381       common_operation = NULL;
382       result = PEERS_CONNECTED_2;
383       LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected again\n");
384       peer1.operation = GNUNET_TESTBED_peer_stop (NULL, peer1.peer, NULL, NULL);
385       peer2.operation = GNUNET_TESTBED_peer_stop (NULL, peer2.peer, NULL, NULL);
386       break;
387     default:
388       FAIL_TEST (0);
389     }
390     break;
391   default:
392     FAIL_TEST (0);
393   };
394 }
395
396
397 /**
398  * Functions of this signature are called when a peer has been successfully
399  * created
400  *
401  * @param cls the closure from GNUNET_TESTBED_peer_create()
402  * @param peer the handle for the created peer; NULL on any error during
403  *          creation
404  * @param emsg NULL if peer is not NULL; else MAY contain the error description
405  */
406 static void
407 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
408 {
409   struct PeerContext *pc = cls;
410
411   FAIL_TEST (NULL != pc->operation);
412   FAIL_TEST (NULL != peer);
413   FAIL_TEST (NULL == pc->peer);
414   pc->peer = peer;
415   GNUNET_TESTBED_operation_done (pc->operation);
416   pc->operation = GNUNET_TESTBED_peer_start (NULL, pc->peer, NULL, NULL);
417 }
418
419
420 /**
421  * Callback which will be called to after a host registration succeeded or failed
422  *
423  * @param cls the host which has been registered
424  * @param emsg the error message; NULL if host registration is successful
425  */
426 static void
427 registration_comp (void *cls, const char *emsg)
428 {
429   FAIL_TEST (cls == neighbour);
430   reg_handle = NULL;
431   peer1.operation =
432       GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb,
433                                   &peer1);
434   peer2.operation =
435       GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb,
436                                   &peer2);
437   FAIL_TEST (NULL != peer1.operation);
438   FAIL_TEST (NULL != peer2.operation);
439 }
440
441
442 /**
443  * Callback to signal successfull startup of the controller process
444  *
445  * @param cls the closure from GNUNET_TESTBED_controller_start()
446  * @param cfg the configuration with which the controller has been started;
447  *          NULL if status is not GNUNET_OK
448  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
449  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
450  */
451 static void
452 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, int status)
453 {
454   uint64_t event_mask;
455
456   if (GNUNET_OK != status)
457   {
458     cp = NULL;
459     FAIL_TEST (0);
460   }
461   event_mask = 0;
462   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
463   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
464   event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
465   event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
466   controller =
467       GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb,
468                                          NULL);
469   FAIL_TEST (NULL != controller);
470   neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0);
471   FAIL_TEST (NULL != neighbour);
472   reg_handle =
473       GNUNET_TESTBED_register_host (controller, neighbour, &registration_comp,
474                                     neighbour);
475   FAIL_TEST (NULL != reg_handle);
476 }
477
478
479
480 /**
481  * Main run function.
482  *
483  * @param cls NULL
484  * @param args arguments passed to GNUNET_PROGRAM_run
485  * @param cfgfile the path to configuration file
486  * @param cfg the configuration file handle
487  */
488 static void
489 run (void *cls, char *const *args, const char *cfgfile,
490      const struct GNUNET_CONFIGURATION_Handle *config)
491 {
492   cfg = GNUNET_CONFIGURATION_dup (config);
493   host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
494   FAIL_TEST (NULL != host);
495   cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb,
496                                         NULL);
497   abort_task =
498       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
499                                     (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort,
500                                     NULL);
501 }
502
503
504 /**
505  * Main function
506  */
507 int
508 main (int argc, char **argv)
509 {
510   int ret;
511
512   char *const argv2[] = { "test_testbed_api_2peers_1controller",
513     "-c", "test_testbed_api.conf",
514     NULL
515   };
516   struct GNUNET_GETOPT_CommandLineOption options[] = {
517     GNUNET_GETOPT_OPTION_END
518   };
519   result = INIT;
520   ret =
521       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
522                           "test_testbed_api_2peers_1controller", "nohelp",
523                           options, &run, NULL);
524   if ((GNUNET_OK != ret) || (SUCCESS != result))
525     return 1;
526   return 0;
527 }
528
529 /* end of test_testbed_api_2peers_1controller.c */