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