5343e7c5c7da203e3db00c40ba1525a488636a49
[oweals/gnunet.git] / src / include / gnunet_testing_lib.h
1 /*
2       This file is part of GNUnet
3       (C) 2008, 2009 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 2, 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 include/gnunet_testing_lib.h
23  * @brief convenience API for writing testcases for GNUnet
24  *        Many testcases need to start and stop gnunetd,
25  *        and this library is supposed to make that easier
26  *        for TESTCASES.  Normal programs should always
27  *        use functions from gnunet_{util,arm}_lib.h.  This API is
28  *        ONLY for writing testcases!
29  * @author Christian Grothoff
30  */
31
32 #ifndef GNUNET_TESTING_LIB_H
33 #define GNUNET_TESTING_LIB_H
34
35 #include "gnunet_util_lib.h"
36
37 #ifdef __cplusplus
38 extern "C"
39 {
40 #if 0                           /* keep Emacsens' auto-indent happy */
41 }
42 #endif
43 #endif
44
45 /**
46  * Handle for a GNUnet daemon (technically a set of
47  * daemons; the handle is really for the master ARM
48  * daemon) started by the testing library.
49  */
50 struct GNUNET_TESTING_Daemon;
51
52 /**
53  * Prototype of a function that will be called whenever
54  * a daemon was started by the testing library.
55  *
56  * @param cls closure
57  * @param id identifier for the daemon, NULL on error
58  * @param d handle for the daemon
59  * @param emsg error message (NULL on success)
60  */
61 typedef void (*GNUNET_TESTING_NotifyHostkeyCreated)(void *cls,
62                                                     const struct GNUNET_PeerIdentity *id,
63                                                     struct GNUNET_TESTING_Daemon *d,
64                                                     const char *emsg);
65
66 /**
67  * Prototype of a function that will be called whenever
68  * a daemon was started by the testing library.
69  *
70  * @param cls closure
71  * @param id identifier for the daemon, NULL on error
72  * @param cfg configuration used by this daemon
73  * @param d handle for the daemon
74  * @param emsg error message (NULL on success)
75  */
76 typedef void (*GNUNET_TESTING_NotifyDaemonRunning)(void *cls,
77                                                    const struct GNUNET_PeerIdentity *id,
78                                                    const struct GNUNET_CONFIGURATION_Handle *cfg,
79                                                    struct GNUNET_TESTING_Daemon *d,
80                                                    const char *emsg);
81
82
83 /**
84  * Handle to an entire testbed of GNUnet peers.
85  */
86 struct GNUNET_TESTING_Testbed;
87
88 /**
89  * Phases of starting GNUnet on a system.
90  */
91 enum GNUNET_TESTING_StartPhase
92 {
93   /**
94    * Copy the configuration file to the target system.
95    */
96   SP_COPYING,
97
98   /**
99    * Configuration file has been copied, generate hostkey.
100    */
101   SP_COPIED,
102
103   /**
104    * Create the hostkey for the peer.
105    */
106   SP_HOSTKEY_CREATE,
107
108   /**
109    * Hostkey generated, wait for topology to be finished.
110    */
111   SP_HOSTKEY_CREATED,
112
113   /**
114    * Topology has been created, now start ARM.
115    */
116   SP_TOPOLOGY_SETUP,
117
118   /**
119    * ARM has been started, check that it has properly daemonized and
120    * then try to connect to the CORE service (which should be
121    * auto-started by ARM).
122    */
123   SP_START_ARMING,
124
125   /**
126    * We're waiting for CORE to start.
127    */
128   SP_START_CORE,
129
130   /**
131    * Core has notified us that we've established a connection to the service.
132    * The main FSM halts here and waits to be moved to UPDATE or CLEANUP.
133    */
134   SP_START_DONE,
135
136   /**
137    * We've been asked to terminate the instance and are now waiting for
138    * the remote command to stop the gnunet-arm process and delete temporary
139    * files.
140    */
141   SP_SHUTDOWN_START,
142
143   /**
144    * We've received a configuration update and are currently waiting for
145    * the copy process for the update to complete.  Once it is, we will
146    * return to "SP_START_DONE" (and rely on ARM to restart all affected
147    * services).
148    */
149   SP_CONFIG_UPDATE
150 };
151
152 /**
153  * Prototype of a function that will be called when a
154  * particular operation was completed the testing library.
155  *
156  * @param cls closure
157  * @param emsg NULL on success
158  */
159 typedef void (*GNUNET_TESTING_NotifyCompletion)(void *cls,
160                                                 const char *emsg);
161
162 /**
163  * Prototype of a function that will be called with the
164  * number of connections created for a particular topology.
165  *
166  * @param cls closure
167  * @param num_connections the number of connections created
168  */
169 typedef void (*GNUNET_TESTING_NotifyConnections)(void *cls,
170                                                 unsigned int num_connections);
171
172 /**
173  * Handle for a GNUnet daemon (technically a set of
174  * daemons; the handle is really for the master ARM
175  * daemon) started by the testing library.
176  */
177 struct GNUNET_TESTING_Daemon
178 {
179   /**
180    * Our scheduler.
181    */
182   struct GNUNET_SCHEDULER_Handle *sched;
183
184   /**
185    * Our configuration.
186    */
187   struct GNUNET_CONFIGURATION_Handle *cfg;
188
189   /**
190    * Host to run GNUnet on.
191    */
192   char *hostname;
193
194   /**
195    * Result of GNUNET_i2s of this peer,
196    * for printing
197    */
198   char *shortname;
199
200   /**
201    * Username we are using.
202    */
203   char *username;
204
205   /**
206    * Name of the configuration file
207    */
208   char *cfgfile;
209
210   /**
211    * Callback to inform initiator that the peer's
212    * hostkey has been created.
213    */
214   GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback;
215
216   /**
217    * Closure for hostkey creation callback.
218    */
219   void *hostkey_cls;
220
221   /**
222    * Function to call when the peer is running.
223    */
224   GNUNET_TESTING_NotifyDaemonRunning cb;
225
226   /**
227    * Closure for cb.
228    */
229   void *cb_cls;
230
231   /**
232    * Arguments from "daemon_stop" call.
233    */
234   GNUNET_TESTING_NotifyCompletion dead_cb;
235
236   /**
237    * Closure for 'dead_cb'.
238    */
239   void *dead_cb_cls;
240
241   /**
242    * Arguments from "daemon_stop" call.
243    */
244   GNUNET_TESTING_NotifyCompletion update_cb;
245
246   /**
247    * Closure for 'update_cb'.
248    */
249   void *update_cb_cls;
250
251   /**
252    * Identity of this peer (once started).
253    */
254   struct GNUNET_PeerIdentity id;
255
256   /**
257    * Flag to indicate that we've already been asked
258    * to terminate (but could not because some action
259    * was still pending).
260    */
261   int dead;
262
263   /**
264    * PID of the process that we started last.
265    */
266   pid_t pid;
267
268   /**
269    * How many iterations have we been waiting for
270    * the started process to complete?
271    */
272   unsigned int wait_runs;
273
274   /**
275    * In which phase are we during the start of
276    * this process?
277    */
278   enum GNUNET_TESTING_StartPhase phase;
279
280   /**
281    * ID of the current task.
282    */
283   GNUNET_SCHEDULER_TaskIdentifier task;
284
285   /**
286    * Handle to the server.
287    */
288   struct GNUNET_CORE_Handle *server;
289
290   /**
291    * Handle to the transport service of this peer
292    */
293   struct GNUNET_TRANSPORT_Handle *th;
294
295   /**
296    * HELLO message for this peer
297    */
298   struct GNUNET_HELLO_Message *hello;
299
300   /**
301    * Handle to a pipe for reading the hostkey.
302    */
303   struct GNUNET_DISK_PipeHandle *pipe_stdout;
304
305   /**
306    * Set to GNUNET_YES once the peer is up.
307    */
308   int running;
309 };
310
311
312 /**
313  * Handle to a group of GNUnet peers.
314  */
315 struct GNUNET_TESTING_PeerGroup;
316
317
318 /**
319  * Prototype of a function that will be called whenever
320  * two daemons are connected by the testing library.
321  *
322  * @param cls closure
323  * @param first peer id for first daemon
324  * @param second peer id for the second daemon
325  * @param first_cfg config for the first daemon
326  * @param second_cfg config for the second daemon
327  * @param first_daemon handle for the first daemon
328  * @param second_daemon handle for the second daemon
329  * @param emsg error message (NULL on success)
330  */
331 typedef void (*GNUNET_TESTING_NotifyConnection)(void *cls,
332                                                    const struct GNUNET_PeerIdentity *first,
333                                                    const struct GNUNET_PeerIdentity *second,
334                                                    const struct GNUNET_CONFIGURATION_Handle *first_cfg,
335                                                    const struct GNUNET_CONFIGURATION_Handle *second_cfg,
336                                                    struct GNUNET_TESTING_Daemon *first_daemon,
337                                                    struct GNUNET_TESTING_Daemon *second_daemon,
338                                                    const char *emsg);
339
340 /**
341  * Starts a GNUnet daemon.  GNUnet must be installed on the target
342  * system and available in the PATH.  The machine must furthermore be
343  * reachable via "ssh" (unless the hostname is "NULL") without the
344  * need to enter a password.
345  *
346  * @param sched scheduler to use
347  * @param cfg configuration to use
348  * @param hostname name of the machine where to run GNUnet
349  *        (use NULL for localhost).
350  * @param hostkey_callback function to call once the hostkey has been
351  *        generated for this peer, but it hasn't yet been started
352  *        (NULL to start immediately, otherwise waits on GNUNET_TESTING_daemon_continue_start)
353  * @param hostkey_cls closure for hostkey callback
354  * @param cb function to call with the result
355  * @param cb_cls closure for cb
356  * @return handle to the daemon (actual start will be completed asynchronously)
357  */
358 struct GNUNET_TESTING_Daemon *
359 GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
360                              const struct GNUNET_CONFIGURATION_Handle *cfg,
361                              const char *hostname,
362                              GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback,
363                              void *hostkey_cls,
364                              GNUNET_TESTING_NotifyDaemonRunning cb,
365                              void *cb_cls);
366
367 /**
368  * Continues GNUnet daemon startup when user wanted to be notified
369  * once a hostkey was generated (for creating friends files, blacklists,
370  * etc.).
371  *
372  * @param daemon the daemon to finish starting
373  */
374 void
375 GNUNET_TESTING_daemon_continue_startup(struct GNUNET_TESTING_Daemon *daemon);
376
377 /**
378  * Restart (stop and start) a GNUnet daemon.
379  *
380  * @param d the daemon that should be restarted
381  * @param cb function called once the daemon is (re)started
382  * @param cb_cls closure for cb
383  */
384 void
385 GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d,
386                                GNUNET_TESTING_NotifyDaemonRunning cb, void *cb_cls);
387
388 /**
389  * Get a certain testing daemon handle.
390  *
391  * @param pg handle to the set of running peers
392  * @param position the number of the peer to return
393  */
394 struct GNUNET_TESTING_Daemon *
395 GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, unsigned int position);
396
397
398 /**
399  * Stops a GNUnet daemon.
400  *
401  * @param d the daemon that should be stopped
402  * @param cb function called once the daemon was stopped
403  * @param cb_cls closure for cb
404  * @param delete_files GNUNET_YES to remove files, GNUNET_NO
405  *        to leave them (i.e., for a restart)
406  */
407 void GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
408                                  GNUNET_TESTING_NotifyCompletion cb,
409                                  void * cb_cls, int delete_files);
410
411
412 /**
413  * Changes the configuration of a GNUnet daemon.
414  *
415  * @param d the daemon that should be modified
416  * @param cfg the new configuration for the daemon
417  * @param cb function called once the configuration was changed
418  * @param cb_cls closure for cb
419  */
420 void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d,
421                                         struct GNUNET_CONFIGURATION_Handle *cfg,
422                                         GNUNET_TESTING_NotifyCompletion cb,
423                                         void * cb_cls);
424
425
426 /**
427  * Establish a connection between two GNUnet daemons.
428  *
429  * @param d1 handle for the first daemon
430  * @param d2 handle for the second daemon
431  * @param timeout how long is the connection attempt
432  *        allowed to take?
433  * @param max_connect_attempts how many times should we try to reconnect
434  *        (within timeout)
435  * @param cb function to call at the end
436  * @param cb_cls closure for cb
437  */
438 void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
439                                      struct GNUNET_TESTING_Daemon *d2,
440                                      struct GNUNET_TIME_Relative timeout,
441                                      unsigned int max_connect_attempts,
442                                      GNUNET_TESTING_NotifyConnection cb,
443                                      void *cb_cls);
444
445
446
447
448 /**
449  * Start count gnunetd processes with the same set of transports and
450  * applications.  The port numbers (any option called "PORT") will be
451  * adjusted to ensure that no two peers running on the same system
452  * have the same port(s) in their respective configurations.
453  *
454  * @param sched scheduler to use
455  * @param cfg configuration template to use
456  * @param total number of daemons to start
457  * @param hostkey_callback function to call on each peers hostkey generation
458  *        if NULL, peers will be started by this call, if non-null,
459  *        GNUNET_TESTING_daemons_continue_startup must be called after
460  *        successful hostkey generation
461  * @param hostkey_cls closure for hostkey callback
462  * @param cb function to call on each daemon that was started
463  * @param cb_cls closure for cb
464  * @param connect_callback function to call each time two hosts are connected
465  * @param connect_callback_cls closure for connect_callback
466  * @param hostnames space-separated list of hostnames to use; can be NULL (to run
467  *        everything on localhost).
468  * @return NULL on error, otherwise handle to control peer group
469  */
470 struct GNUNET_TESTING_PeerGroup *
471 GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
472                               const struct GNUNET_CONFIGURATION_Handle *cfg,
473                               unsigned int total,
474                               GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback,
475                               void *hostkey_cls,
476                               GNUNET_TESTING_NotifyDaemonRunning cb,
477                               void *cb_cls,
478                               GNUNET_TESTING_NotifyConnection
479                               connect_callback, void *connect_callback_cls,
480                               const char *hostnames);
481
482 /**
483  * Function which continues a peer group starting up
484  * after successfully generating hostkeys for each peer.
485  *
486  * @param pg the peer group to continue starting
487  *
488  */
489 void
490 GNUNET_TESTING_daemons_continue_startup(struct GNUNET_TESTING_PeerGroup *pg);
491
492 /**
493  * Restart all peers in the given group.
494  *
495  * @param pg the handle to the peer group
496  * @param timeout how long to wait on failure
497  * @param callback function to call on completion (or failure)
498  * @param callback_cls closure for the callback function
499  */
500 void
501 GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg,
502                                 GNUNET_TESTING_NotifyCompletion callback,
503                                 void *callback_cls);
504
505
506 /**
507  * Shutdown all peers started in the given group.
508  *
509  * @param pg handle to the peer group
510  */
511 void
512 GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg);
513
514
515 /**
516  * Topologies supported for testbeds.
517  */
518 enum GNUNET_TESTING_Topology
519 {
520   /**
521    * A clique (everyone connected to everyone else).
522    */
523   GNUNET_TESTING_TOPOLOGY_CLIQUE,
524
525   /**
526    * Small-world network (2d torus plus random links).
527    */
528   GNUNET_TESTING_TOPOLOGY_SMALL_WORLD,
529
530   /**
531    * Small-world network (ring plus random links).
532    */
533   GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING,
534
535   /**
536    * Ring topology.
537    */
538   GNUNET_TESTING_TOPOLOGY_RING,
539
540   /**
541    * 2-d torus.
542    */
543   GNUNET_TESTING_TOPOLOGY_2D_TORUS,
544
545   /**
546    * Random graph.
547    */
548   GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI,
549
550   /**
551    * Certain percentage of peers are unable to communicate directly
552    * replicating NAT conditions
553    */
554   GNUNET_TESTING_TOPOLOGY_INTERNAT,
555
556   /**
557    * Scale free topology.
558    */
559   GNUNET_TESTING_TOPOLOGY_SCALE_FREE,
560
561   /**
562    * All peers are disconnected.
563    */
564   GNUNET_TESTING_TOPOLOGY_NONE
565 };
566
567 /**
568  * Options for connecting a topology.
569  */
570 enum GNUNET_TESTING_TopologyOption
571 {
572   /**
573    * Try to connect all peers specified in the topology.
574    */
575   GNUNET_TESTING_TOPOLOGY_OPTION_ALL,
576
577   /**
578    * Choose a random subset of connections to create.
579    */
580   GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM,
581
582   /**
583    * Create at least X connections for each peer.
584    */
585   GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM,
586
587   /**
588    * Using a depth first search, create one connection
589    * per peer.  If any are missed (graph disconnected)
590    * start over at those peers until all have at least one
591    * connection.
592    */
593   GNUNET_TESTING_TOPOLOGY_OPTION_DFS,
594
595   /**
596    * No options specified.
597    */
598   GNUNET_TESTING_TOPOLOGY_OPTION_NONE
599 };
600
601 /*
602  * Takes a peer group and creates a topology based on the
603  * one specified.  Creates a topology means generates friend
604  * files for the peers so they can only connect to those allowed
605  * by the topology.  This will only have an effect once peers
606  * are started if the FRIENDS_ONLY option is set in the base
607  * config.  Also takes an optional restrict topology which
608  * disallows direct TCP connections UNLESS they are specified in
609  * the restricted topology.
610  *
611  * @param pg the peer group struct representing the running peers
612  * @param topology which topology to connect the peers in
613  * @param restrict_topology allow only direct TCP connections in this topology
614  *
615  * @return the maximum number of connections were all allowed peers
616  *         connected to each other
617  */
618 int
619 GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg,
620                                 enum GNUNET_TESTING_Topology topology,
621                                 enum GNUNET_TESTING_Topology restrict_topology);
622
623 /*
624  * @param pg the peer group struct representing the running peers
625  * @param topology which topology to connect the peers in
626  * @param options options for connecting the topology
627  * @param option_modifier modifier for options that take a parameter
628  */
629 int
630 GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
631                                  enum GNUNET_TESTING_Topology topology,
632                                  enum GNUNET_TESTING_TopologyOption options,
633                                  double option_modifier);
634
635 /**
636  * Start "count" GNUnet daemons with a particular topology.
637  *
638  * @param sched scheduler to use
639  * @param cfg configuration template to use
640  * @param count number of peers the testbed should have
641  * @param topology desired topology (enforced via F2F)
642  * @param cb function to call on each daemon that was started
643  * @param cb_cls closure for cb
644  * @param hostname where to run the peers; can be NULL (to run
645  *        everything on localhost). Additional
646  *        hosts can be specified using a NULL-terminated list of
647  *        varargs, hosts will then be used round-robin from that
648  *        list.
649  * @return handle to control the testbed
650  */
651 struct GNUNET_TESTING_Testbed *
652 GNUNET_TESTING_testbed_start (struct GNUNET_SCHEDULER_Handle *sched,
653                               const struct GNUNET_CONFIGURATION_Handle *cfg,
654                               unsigned int count,
655                               enum GNUNET_TESTING_Topology topology,
656                               GNUNET_TESTING_NotifyDaemonRunning cb,
657                               void *cb_cls,
658                               const char *hostname,
659                               ...);
660
661
662 /**
663  * Stop all of the daemons started with the start function.
664  *
665  * @param tb handle for the testbed
666  * @param cb function to call when done
667  * @param cb_cls closure for cb
668  */
669 void
670 GNUNET_TESTING_testbed_stop (struct GNUNET_TESTING_Testbed *tb,
671                              GNUNET_TESTING_NotifyCompletion cb,
672                              void *cb_cls );
673
674
675 /**
676  * Simulate churn in the testbed by stopping some peers (and possibly
677  * re-starting others if churn is called multiple times).  This
678  * function can only be used to create leave-join churn (peers "never"
679  * leave for good).  First "voff" random peers that are currently
680  * online will be taken offline; then "von" random peers that are then
681  * offline will be put back online.  No notifications will be
682  * generated for any of these operations except for the callback upon
683  * completion.  Note that the implementation is at liberty to keep
684  * the ARM service itself (but none of the other services or daemons)
685  * running even though the "peer" is being varied offline.
686  *
687  * @param tb handle for the testbed
688  * @param voff number of peers that should go offline
689  * @param von number of peers that should come back online;
690  *            must be zero on first call (since "testbed_start"
691  *            always starts all of the peers)
692  * @param cb function to call at the end
693  * @param cb_cls closure for cb
694  */
695 void
696 GNUNET_TESTING_testbed_churn (struct GNUNET_TESTING_Testbed *tb,
697                               unsigned int voff,
698                               unsigned int von,
699                               GNUNET_TESTING_NotifyCompletion cb,
700                               void *cb_cls);
701
702
703 #if 0                           /* keep Emacsens' auto-indent happy */
704 {
705 #endif
706 #ifdef __cplusplus
707 }
708 #endif
709
710 #endif