-add adv port
[oweals/gnunet.git] / src / testbed / testbed_api_test.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/testbed_api_test.c
23  * @brief high-level test function
24  * @author Christian Grothoff
25  * @author Sree Harsha Totakura
26  */
27 #include "platform.h"
28 #include "gnunet_testbed_service.h"
29
30
31 /**
32  * Context information for test run
33  */
34 struct TestRunContext
35 {
36   /**
37    * Test master callback
38    */
39   GNUNET_TESTBED_TestMaster test_master;
40
41   /**
42    * Closure for test master
43    */
44   void *test_master_cls;
45
46   /**
47    * The controller event callback
48    */
49   GNUNET_TESTBED_ControllerCallback cc;
50
51   /**
52    * Closure for the above callback
53    */
54   void *cc_cls;
55   
56   /**
57    * event mask for the controller callback
58    */
59   uint64_t event_mask;
60
61   /**
62    * Number of peers to start
63    */
64   unsigned int num_peers;
65
66   /**
67    * counter for loading peers
68    */
69   unsigned int peer_cnt;
70
71   /**
72    * Followed by peers list
73    */
74   struct GNUNET_TESTBED_Peer *peers[0];
75 };
76
77
78 /**
79  * Controller event callback
80  *
81  * @param cls NULL
82  * @param event the controller event
83  */
84 static void
85 controller_event_cb (void *cls,
86                      const struct GNUNET_TESTBED_EventInformation *event)
87 {
88   struct TestRunContext *rc = cls;
89
90   if ((NULL != rc->cc) && (0 != (rc->event_mask & (1LL << event->type))))
91     rc->cc (rc->cc_cls, event);
92   if (rc->peer_cnt == rc->num_peers)
93     return;
94   GNUNET_assert (GNUNET_TESTBED_ET_PEER_START == event->type);
95   GNUNET_assert (NULL == rc->peers[rc->peer_cnt]);
96   GNUNET_assert (NULL != event->details.peer_start.peer);
97   rc->peers[rc->peer_cnt++] = event->details.peer_start.peer;
98 }
99
100
101 /**
102  * Task to be executed when peers are ready
103  *
104  * @param cls NULL
105  * @param tc the task context
106  */
107 static void
108 master_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
109 {
110   struct TestRunContext *rc = cls;
111
112   GNUNET_assert (rc->peer_cnt == rc->num_peers);
113   rc->test_master (rc->test_master_cls, rc->num_peers, rc->peers);
114 }
115
116
117 /**
118  * Main run function.
119  *
120  * @param cls NULL
121  * @param args arguments passed to GNUNET_PROGRAM_run
122  * @param cfgfile the path to configuration file
123  * @param config the configuration file handle
124  */
125 static void
126 run (void *cls, char *const *args, const char *cfgfile,
127      const struct GNUNET_CONFIGURATION_Handle *config)
128 {
129   struct TestRunContext *rc = cls;
130   uint64_t event_mask;
131   
132   event_mask = rc->event_mask;
133   event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
134   GNUNET_TESTBED_run (NULL, config, rc->num_peers, event_mask,
135                       &controller_event_cb, rc, &master_task, rc);
136 }
137
138
139 /**
140  * Convenience method for running a "simple" test on the local system
141  * with a single call from 'main'.  Underlay and overlay topology are
142  * configured using the "UNDERLAY" and "OVERLAY" options in the
143  * "[testbed]" section of the configuration (with possible options
144  * given in "UNDERLAY_XXX" and/or "OVERLAY_XXX").
145  *
146  * The test is to be terminated using a call to
147  * "GNUNET_SCHEDULER_shutdown".  If starting the test fails,
148  * the program is stopped without 'master' ever being run.
149  *
150  * NOTE: this function should be called from 'main', NOT from
151  * within a GNUNET_SCHEDULER-loop.  This function will initialze
152  * the scheduler loop, the testbed and then pass control to
153  * 'master'.
154  *
155  * @param testname name of the testcase (to configure logging, etc.)
156  * @param cfg_filename configuration filename to use
157  *              (for testbed, controller and peers)
158  * @param num_peers number of peers to start
159  * @param event_mask bit mask with set of events to call 'cc' for;
160  *                   or-ed values of "1LL" shifted by the
161  *                   respective 'enum GNUNET_TESTBED_EventType'
162  *                   (i.e.  "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...")
163  * @param cc controller callback to invoke on events; This callback is called
164  *        for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't
165  *        set in the event_mask as this is the only way get access to the
166  *        handle of each peer
167  * @param cc_cls closure for cc
168  * @param test_master task to run once the test is ready
169  * @param test_master_cls closure for 'task'.
170  */
171 void
172 GNUNET_TESTBED_test_run (const char *testname, const char *cfg_filename,
173                          unsigned int num_peers,
174                          uint64_t event_mask,
175                          GNUNET_TESTBED_ControllerCallback cc,
176                          void *cc_cls,
177                          GNUNET_TESTBED_TestMaster test_master,
178                          void *test_master_cls)
179 {
180   char *argv2[] = {
181     NULL,
182     "-c",
183     NULL,
184     NULL
185   };
186   struct GNUNET_GETOPT_CommandLineOption options[] = {
187     GNUNET_GETOPT_OPTION_END
188   };
189   struct TestRunContext *rc;
190
191   argv2[0] = GNUNET_strdup (testname);
192   argv2[2] = GNUNET_strdup (cfg_filename);
193   GNUNET_assert (NULL != test_master);
194   GNUNET_assert (num_peers > 0);
195   rc = GNUNET_malloc (sizeof (struct TestRunContext) +
196                       (num_peers * sizeof (struct GNUNET_TESTBED_Peer *)));
197   rc->test_master = test_master;
198   rc->test_master_cls = test_master_cls;
199   rc->num_peers = num_peers;
200   rc->event_mask = event_mask;
201   rc->cc = cc;
202   rc->cc_cls = cc_cls;
203   (void) GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
204                              testname, "nohelp", options, &run, rc);
205   GNUNET_free (rc);
206   GNUNET_free (argv2[0]);
207   GNUNET_free (argv2[2]);
208 }
209
210 /* end of testbed_api_test.c */