b78d11dbe876acb2926abac2b6d513de7279a5e9
[oweals/gnunet.git] / src / transport / transport-testing.h
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2006, 2009, 2015, 2016 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file transport-testing.h
23  * @brief testing lib for transport service
24  * @author Matthias Wachs
25  * @author Christian Grothoff
26  */
27 #ifndef TRANSPORT_TESTING_H
28 #define TRANSPORT_TESTING_H
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_hello_lib.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_testing_lib.h"
34
35
36 /* ************* Basic functions for starting/stopping/connecting *********** */
37
38 /**
39  * Context for a single peer
40  */
41 struct GNUNET_TRANSPORT_TESTING_PeerContext;
42
43 /**
44  * Definition for a transport testing handle
45  */
46 struct GNUNET_TRANSPORT_TESTING_Handle;
47
48
49 /**
50  * Callback when two peers are connected and both have called the connect callback
51  * to notify clients about a new peer
52  *
53  * @param p FIXME: remove ASAP.
54  * @param cls closure
55  */
56 typedef void
57 (*GNUNET_TRANSPORT_TESTING_StartCallback) (struct GNUNET_TRANSPORT_TESTING_PeerContext *p,
58                                            void *cls);
59
60
61
62 /**
63  * Context for a single peer
64  */
65 struct GNUNET_TRANSPORT_TESTING_PeerContext
66 {
67   /**
68    * Next element in the DLL
69    */
70   struct GNUNET_TRANSPORT_TESTING_PeerContext *next;
71
72   /**
73    * Previous element in the DLL
74    */
75   struct GNUNET_TRANSPORT_TESTING_PeerContext *prev;
76
77   /**
78    * Transport testing handle this peer belongs to
79    */
80   struct GNUNET_TRANSPORT_TESTING_Handle *tth;
81
82   /**
83    * Peer's configuration
84    */
85   struct GNUNET_CONFIGURATION_Handle *cfg;
86
87   /**
88    * Peer's transport service handle
89    */
90   struct GNUNET_TRANSPORT_Handle *th;
91
92   /**
93    * Peer's ATS handle.
94    */
95   struct GNUNET_ATS_ConnectivityHandle *ats;
96
97   /**
98    * Peer's transport get hello handle to retrieve peer's HELLO message
99    */
100   struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
101
102   /**
103    * Peer's testing handle
104    */
105   struct GNUNET_TESTING_Peer *peer;
106
107   /**
108    * Peer identity
109    */
110   struct GNUNET_PeerIdentity id;
111
112   /**
113    * Handle for the peer's ARM process
114    */
115   struct GNUNET_OS_Process *arm_proc;
116
117   /**
118    * Receive callback
119    */
120   GNUNET_TRANSPORT_ReceiveCallback rec;
121
122   /**
123    * Notify connect callback
124    */
125   GNUNET_TRANSPORT_NotifyConnect nc;
126
127   /**
128    * Notify disconnect callback
129    */
130   GNUNET_TRANSPORT_NotifyDisconnect nd;
131
132   /**
133    * Startup completed callback
134    */
135   GNUNET_TRANSPORT_TESTING_StartCallback start_cb;
136
137   /**
138    * Peers HELLO Message
139    */
140   struct GNUNET_HELLO_Message *hello;
141
142   /**
143    * Closure for the callbacks
144    */
145   void *cb_cls;
146
147   /**
148    * An unique number to identify the peer
149    */
150   unsigned int no;
151 };
152
153
154 /**
155  * Handle for a request to connect two peers.
156  */
157 struct GNUNET_TRANSPORT_TESTING_ConnectRequest
158 {
159   /**
160    * Kept in a DLL.
161    */
162   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *next;
163
164   /**
165    * Kept in a DLL.
166    */
167   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *prev;
168
169   /**
170    * Peer we want to connect.
171    */
172   struct GNUNET_TRANSPORT_TESTING_PeerContext *p1;
173
174   /**
175    * Peer we want to connect.
176    */
177   struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
178
179   /**
180    * Task by which we accomplish the connection.
181    */
182   struct GNUNET_SCHEDULER_Task *tct;
183
184   /**
185    * Handle by which we ask ATS to faciliate the connection.
186    */
187   struct GNUNET_ATS_ConnectivitySuggestHandle *ats_sh;
188
189   /**
190    * Handle by which we inform the peer about the HELLO of
191    * the other peer.
192    */
193   struct GNUNET_TRANSPORT_OfferHelloHandle *oh;
194
195   /**
196    * Function to call upon completion.
197    */
198   GNUNET_SCHEDULER_TaskCallback cb;
199
200   /**
201    * Closure for @e cb.
202    */
203   void *cb_cls;
204
205   int p1_c; // dead?
206   int p2_c; // dead?
207 };
208
209
210 /**
211  * Handle for a test run.
212  */
213 struct GNUNET_TRANSPORT_TESTING_Handle
214 {
215   /**
216    * Testing library system handle
217    */
218   struct GNUNET_TESTING_System *tl_system;
219
220   /**
221    * head DLL of connect contexts
222    */
223   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_head;
224
225   /**
226    * head DLL of connect contexts
227    */
228   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_tail;
229
230   /**
231    * head DLL of peers
232    */
233   struct GNUNET_TRANSPORT_TESTING_PeerContext *p_head;
234
235   /**
236    * tail DLL of peers
237    */
238   struct GNUNET_TRANSPORT_TESTING_PeerContext *p_tail;
239 };
240
241
242 /**
243  * Initialize the transport testing
244  *
245  * @return transport testing handle
246  */
247 struct GNUNET_TRANSPORT_TESTING_Handle *
248 GNUNET_TRANSPORT_TESTING_init (void);
249
250
251 /**
252  * Clean up the transport testing
253  *
254  * @param tth transport testing handle
255  */
256 void
257 GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth);
258
259
260 /**
261  * Start a peer with the given configuration
262  *
263  * @param tth the testing handle
264  * @param cfgname configuration file
265  * @param peer_id the peer_id
266  * @param rec receive callback
267  * @param nc connect callback
268  * @param nd disconnect callback
269  * @param start_cb start callback
270  * @param cb_cls closure for callback
271  * @return the peer context
272  */
273 struct GNUNET_TRANSPORT_TESTING_PeerContext *
274 GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth,
275                                      const char *cfgname,
276                                      int peer_id,
277                                      GNUNET_TRANSPORT_ReceiveCallback rec,
278                                      GNUNET_TRANSPORT_NotifyConnect nc,
279                                      GNUNET_TRANSPORT_NotifyDisconnect nd,
280                                      GNUNET_TRANSPORT_TESTING_StartCallback start_cb,
281                                      void *cb_cls);
282
283
284 /**
285  * Shutdown the given peer
286  *
287  * @param p the peer
288  */
289 void
290 GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_PeerContext *pc);
291
292
293 /**
294  * Stops and restarts the given peer, sleeping (!) for 5s in between.
295  *
296  * @param p the peer
297  * @param restart_cb restart callback
298  * @param cb_cls callback closure
299  * @return #GNUNET_OK in success otherwise #GNUNET_SYSERR
300  */
301 int
302 GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_PeerContext *p,
303                                        GNUNET_TRANSPORT_TESTING_StartCallback restart_cb,
304                                        void *cb_cls);
305
306
307
308 /**
309  * Connect the given peers and call the callback when both peers
310  * report the inbound connection. Remarks: start_peer's notify_connect
311  * callback can be called before.
312  *
313  * @param p1 peer 1
314  * @param p2 peer 2
315  * @param cb the callback to call when both peers notified that they are connected
316  * @param cls callback cls
317  * @return a connect request handle
318  */
319 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
320 GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_PeerContext *p1,
321                                         struct GNUNET_TRANSPORT_TESTING_PeerContext *p2,
322                                         GNUNET_SCHEDULER_TaskCallback cb,
323                                         void *cls);
324
325
326 /**
327  * Cancel the request to connect two peers.  You MUST cancel the
328  * request if you stop the peers before the peers connected
329  * succesfully.
330  *
331  * @param cc a connect request handle
332  */
333 void
334 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc);
335
336
337 /* ********************** high-level process functions *************** */
338
339
340 /**
341  * Function called once the peers have been launched and
342  * connected by #GNUNET_TRANSPORT_TESTING_connect_check().
343  *
344  * @param cls closure
345  * @param num_peers size of the @a p array
346  * @param p the peers that were launched
347  */
348 typedef void
349 (*GNUNET_TRANSPORT_TESTING_ConnectContinuation)(void *cls,
350                                                 unsigned int num_peers,
351                                                 struct GNUNET_TRANSPORT_TESTING_PeerContext *p[]);
352
353
354 /**
355  * Internal data structure.
356  */
357 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList;
358
359 /**
360  * Internal data structure.
361  */
362 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext;
363
364
365 /**
366  * Function called by the transport for each received message.
367  *
368  * @param cls closure
369  * @param receiver receiver of the message
370  * @param sender sender of the message
371  * @param message the message
372  */
373 typedef void
374 (*GNUNET_TRANSPORT_TESTING_ReceiveCallback) (void *cls,
375                                              struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
376                                              const struct GNUNET_PeerIdentity *sender,
377                                              const struct GNUNET_MessageHeader *message);
378
379
380 /**
381  * Function called to notify transport users that another
382  * peer connected to us.
383  *
384  * @param cls closure
385  * @param me peer experiencing the event
386  * @param other peer that connected to @a me
387  */
388 typedef void
389 (*GNUNET_TRANSPORT_TESTING_NotifyConnect) (void *cls,
390                                            struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
391                                            const struct GNUNET_PeerIdentity *other);
392
393
394 /**
395  * Function called to notify transport users that another
396  * peer disconnected from us.
397  *
398  * @param cls closure
399  * @param me peer experiencing the event
400  * @param other peer that disconnected from @a me
401  */
402 typedef void
403 (*GNUNET_TRANSPORT_TESTING_NotifyDisconnect) (void *cls,
404                                               struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
405                                               const struct GNUNET_PeerIdentity *other);
406
407
408 /**
409  * Closure that must be passed to
410  * #GNUNET_TRANSPORT_TESTING_connect_check.
411  */
412 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext
413 {
414
415   /**
416    * How should we continue after the connect?
417    */
418   GNUNET_SCHEDULER_TaskCallback connect_continuation;
419
420   /**
421    * Closure for @e connect_continuation.
422    */
423   void *connect_continuation_cls;
424
425   /**
426    * Which configuration file should we pass to the
427    * #GNUNET_PROGRAM_run() of the testcase?
428    */
429   const char *config_file;
430
431   /**
432    * Receiver argument to give for peers we start.
433    */
434   GNUNET_TRANSPORT_TESTING_ReceiveCallback rec;
435
436   /**
437    * Notify connect argument to give for peers we start.
438    */
439   GNUNET_TRANSPORT_TESTING_NotifyConnect nc;
440
441   /**
442    * Notify disconnect argument to give for peers we start.
443    */
444   GNUNET_TRANSPORT_TESTING_NotifyDisconnect nd;
445
446   /**
447    * Closure for @e rec, @e nc and @e nd.
448    */
449   void *cls;
450
451   /**
452    * Custom task to run on shutdown.
453    */
454   GNUNET_SCHEDULER_TaskCallback shutdown_task;
455
456   /**
457    * Closure for @e shutdown_task.
458    */
459   void *shutdown_task_cls;
460
461   /**
462    * Custom task to run after peers were started but before we try to
463    * connect them.  If this function is set, we wait ONE second after
464    * running this function until we continue with connecting the
465    * peers.
466    */
467   GNUNET_SCHEDULER_TaskCallback pre_connect_task;
468
469   /**
470    * Closure for @e shutdown_task.
471    */
472   void *pre_connect_task_cls;
473
474   /**
475    * When should the testcase time out?
476    */
477   struct GNUNET_TIME_Relative timeout;
478
479   /**
480    * Should we try to create connections in both directions?
481    */
482   int bi_directional;
483
484   /* ******* fields set by #GNUNET_TRANSPORT_TESTING_connect_check **** */
485
486   /**
487    * Number of peers involved in the test.
488    */
489   unsigned int num_peers;
490
491   /**
492    * Configuration files we have, array with @e num_peers entries.
493    */
494   char **cfg_files;
495
496   /**
497    * Array with @e num_peers entries.
498    */
499   struct GNUNET_TRANSPORT_TESTING_PeerContext **p;
500
501   /**
502    * Name of the plugin.
503    */
504   const char *test_plugin;
505
506   /**
507    * Name of the testcase.
508    */
509   const char *test_name;
510
511   /**
512    * Configuration object for the testcase.
513    */
514   const struct GNUNET_CONFIGURATION_Handle *cfg;
515
516   /**
517    * Main testing handle.
518    */
519   struct GNUNET_TRANSPORT_TESTING_Handle *tth;
520
521   /**
522    * Result from the main function, set to #GNUNET_OK on success.
523    * Clients should set to #GNUNET_SYSERR to indicate test failure.
524    */
525   int global_ret;
526
527   /* ******* internal state, clients should not mess with this **** */
528
529   /**
530    * Task run on timeout.
531    */
532   struct GNUNET_SCHEDULER_Task *timeout_task;
533
534   /**
535    * Task run to connect peers.
536    */
537   struct GNUNET_SCHEDULER_Task *connect_task;
538
539   /**
540    * Number of peers that have been started.
541    */
542   unsigned int started;
543
544   /**
545    * DLL of active connect requests.
546    */
547   struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl_head;
548
549   /**
550    * DLL of active connect requests.
551    */
552   struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl_tail;
553
554   /**
555    * Array with @e num_peers entries.
556    */
557   struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ip;
558
559 };
560
561
562 /**
563  * Find peer by peer ID.
564  *
565  * @param ccc context to search
566  * @param peer peer to look for
567  * @return NULL if @a peer was not found
568  */
569 struct GNUNET_TRANSPORT_TESTING_PeerContext *
570 GNUNET_TRANSPORT_TESTING_find_peer (struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc,
571                                     const struct GNUNET_PeerIdentity *peer);
572
573
574 /**
575  * Common implementation of the #GNUNET_TRANSPORT_TESTING_CheckCallback.
576  * Starts and connects the two peers, then invokes the
577  * `connect_continuation` from @a cls.  Sets up a timeout to
578  * abort the test, and a shutdown handler to clean up properly
579  * on exit.
580  *
581  * @param cls closure of type `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
582  * @param tth_ initialized testing handle
583  * @param test_plugin_ name of the plugin
584  * @param test_name_ name of the test
585  * @param num_peers number of entries in the @a cfg_file array
586  * @param cfg_files array of names of configuration files for the peers
587  * @return #GNUNET_SYSERR on error
588  */
589 int
590 GNUNET_TRANSPORT_TESTING_connect_check (void *cls,
591                                         struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
592                                         const char *test_plugin_,
593                                         const char *test_name_,
594                                         unsigned int num_peers,
595                                         char *cfg_files[]);
596
597
598 /**
599  * Main function of a testcase.  Called with the initial setup data
600  * for the test as derived from the source name and the binary name.
601  *
602  * @param cls closure
603  * @param tth_ initialized testing handle
604  * @param test_plugin_ name of the plugin
605  * @param test_name_ name of the test
606  * @param num_peers number of entries in the @a cfg_file array
607  * @param cfg_files array of names of configuration files for the peers
608  * @return #GNUNET_SYSERR on error
609  */
610 typedef int
611 (*GNUNET_TRANSPORT_TESTING_CheckCallback)(void *cls,
612                                           struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
613                                           const char *test_plugin_,
614                                           const char *test_name_,
615                                           unsigned int num_peers,
616                                           char *cfg_files[]);
617
618
619 /**
620  * Setup testcase.  Calls @a check with the data the test needs.
621  *
622  * @param argv0 binary name (argv[0])
623  * @param filename source file name (__FILE__)
624  * @param num_peers number of peers to start
625  * @param check main function to run
626  * @param check_cls closure for @a check
627  * @return #GNUNET_OK on success
628  */
629 int
630 GNUNET_TRANSPORT_TESTING_main_ (const char *argv0,
631                                 const char *filename,
632                                 unsigned int num_peers,
633                                 GNUNET_TRANSPORT_TESTING_CheckCallback check,
634                                 void *check_cls);
635
636
637 /**
638  * Setup testcase.  Calls @a check with the data the test needs.
639  *
640  * @param num_peers number of peers to start
641  * @param check main function to run
642  * @param check_cls closure for @a check
643  * @return #GNUNET_OK on success
644  */
645 #define GNUNET_TRANSPORT_TESTING_main(num_peers,check,check_cls) \
646   GNUNET_TRANSPORT_TESTING_main_ (argv[0], __FILE__, num_peers, check, check_cls)
647
648
649
650 /* ********************** log-only convenience functions ************* */
651
652
653 /**
654  * Log a connect event.
655  *
656  * @param cls NULL
657  * @param me peer that had the event
658  * @param other peer that connected.
659  */
660 void
661 GNUNET_TRANSPORT_TESTING_log_connect (void *cls,
662                                       struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
663                                       const struct GNUNET_PeerIdentity *other);
664
665
666 /**
667  * Log a disconnect event.
668  *
669  * @param cls NULL
670  * @param me peer that had the event
671  * @param other peer that disconnected.
672  */
673 void
674 GNUNET_TRANSPORT_TESTING_log_disconnect (void *cls,
675                                          struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
676                                          const struct GNUNET_PeerIdentity *other);
677
678
679
680 /* ********************** low-level filename functions *************** */
681
682
683 /**
684  * Extracts the test filename from an absolute file name and removes
685  * the extension.
686  *
687  * @param file absolute file name
688  * @return resulting test name
689  */
690 char *
691 GNUNET_TRANSPORT_TESTING_get_test_name (const char *file);
692
693
694 /**
695  * This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and
696  * if existing ".exe"-prefix and adds the peer-number
697  *
698  * @param file filename of the test, e.g. argv[0]
699  * @param count peer number
700  * @return configuration name to use
701  */
702 char *
703 GNUNET_TRANSPORT_TESTING_get_config_name (const char *file,
704                                           int count);
705
706
707 /**
708  * Extracts the plugin anme from an absolute file name and the test name
709  * @param file absolute file name
710  * @param test test name
711  * @return the plugin name
712  */
713 char *
714 GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *executable,
715                                                const char *testname);
716
717
718 /**
719  * Extracts the filename from an absolute file name and removes the
720  * extenstion
721  *
722  * @param file absolute file name
723  * @return the source name
724  */
725 char *
726 GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file);
727
728 #endif
729 /* end of transport_testing.h */