2 This file is part of GNUnet
3 (C) 2008, 2009 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file testing/testing_group.c
23 * @brief convenience API for writing testcases for GNUnet
24 * @author Christian Grothoff
27 #include "gnunet_arm_service.h"
28 #include "gnunet_testing_lib.h"
31 * Lowest port used for GNUnet testing. Should be high enough to not
32 * conflict with other applications running on the hosts but be low
33 * enough to not conflict with client-ports (typically starting around
36 #define LOW_PORT 10000
39 * Highest port used for GNUnet testing. Should be low enough to not
40 * conflict with the port range for "local" ports (client apps; see
41 * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
43 #define HIGH_PORT 32000
46 * Data we keep per peer.
51 * (Initial) configuration of the host.
52 * (initial because clients could change
53 * it and we would not know about those
56 struct GNUNET_CONFIGURATION_Handle *cfg;
59 * Handle for controlling the daemon.
61 struct GNUNET_TESTING_Daemon *daemon;
66 * Data we keep per host.
76 * Lowest port that we have not yet used
84 * Handle to a group of GNUnet peers.
86 struct GNUNET_TESTING_PeerGroup
91 struct GNUNET_SCHEDULER_Handle *sched;
94 * Configuration template.
96 const struct GNUNET_CONFIGURATION_Handle *cfg;
99 * Function to call on each started daemon.
101 GNUNET_TESTING_NotifyDaemonRunning cb;
109 * NULL-terminated array of information about
112 struct HostData *hosts;
115 * Array of "total" peers.
117 struct PeerData *peers;
120 * Number of peers in this group.
129 struct GNUNET_CONFIGURATION_Handle *ret;
134 * Function to iterate over options. Copies
135 * the options to the target configuration,
136 * updating PORT values as needed.
139 * @param section name of the section
140 * @param option name of the option
141 * @param value value of the option
144 update_config(void *cls,
149 struct UpdateContext *ctx = cls;
153 if ( (0 == strcmp (option, "PORT")) &&
154 (1 == sscanf (value, "%u", &ival)) )
156 GNUNET_snprintf (cval,
162 GNUNET_CONFIGURATION_set_value_string (ctx->ret,
170 * Create a new configuration using the given configuration
171 * as a template; however, each PORT in the existing cfg
172 * must be renumbered by incrementing "*port". If we run
173 * out of "*port" numbers, return NULL.
175 * @param cfg template configuration
176 * @param port port numbers to use, update to reflect
177 * port numbers that were used
178 * @return new configuration, NULL on error
180 static struct GNUNET_CONFIGURATION_Handle*
181 make_config (const struct GNUNET_CONFIGURATION_Handle*cfg,
184 struct UpdateContext uc;
189 uc.ret = GNUNET_CONFIGURATION_create ();
190 GNUNET_CONFIGURATION_iterate (cfg,
193 if (uc.nport >= HIGH_PORT)
196 GNUNET_CONFIGURATION_destroy (uc.ret);
199 *port = (uint16_t) uc.nport;
205 * Start count gnunetd processes with the same set of transports and
206 * applications. The port numbers (any option called "PORT") will be
207 * adjusted to ensure that no two peers running on the same system
208 * have the same port(s) in their respective configurations.
210 * @param sched scheduler to use
211 * @param cfg configuration template to use
212 * @param total number of daemons to start
213 * @param cb function to call on each daemon that was started
214 * @param cb_cls closure for cb
215 * @param hostnames space-separated list of hostnames to use; can be NULL (to run
216 * everything on localhost).
217 * @return NULL on error, otherwise handle to control peer group
219 struct GNUNET_TESTING_PeerGroup *
220 GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
221 const struct GNUNET_CONFIGURATION_Handle *cfg,
223 GNUNET_TESTING_NotifyDaemonRunning cb,
225 const char *hostnames)
227 struct GNUNET_TESTING_PeerGroup *pg;
231 const char *hostname;
232 struct GNUNET_CONFIGURATION_Handle *pcfg;
234 unsigned int hostcnt;
242 pg = GNUNET_malloc (sizeof(struct GNUNET_TESTING_PeerGroup));
248 pg->peers = GNUNET_malloc (total * sizeof(struct PeerData));
249 if (NULL != hostnames)
252 /* skip leading spaces */
253 while ( (0 != *hostnames) &&
254 (isspace(*hostnames)))
257 while ('\0' != *rpos)
263 pg->hosts = GNUNET_malloc (off * sizeof (struct HostData));
265 start = GNUNET_strdup (hostnames);
272 if (strlen(start) > 0)
274 pg->hosts[off].minport = LOW_PORT;
275 pg->hosts[off++].hostname = start;
281 if (strlen(start) > 0)
283 pg->hosts[off].minport = LOW_PORT;
284 pg->hosts[off++].hostname = start;
289 GNUNET_free (pg->hosts);
293 minport = 0; /* make gcc happy */
300 for (off = 0; off < total; off++)
304 hostname = pg->hosts[off % hostcnt].hostname;
305 pcfg = make_config (cfg, &pg->hosts[off % hostcnt].minport);
310 pcfg = make_config (cfg, &minport);
314 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
315 _("Could not create configuration for peer number %u on `%s'!\n"),
317 hostname == NULL ? "localhost" : hostname);
320 pg->peers[off].cfg = pcfg;
321 pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched,
326 if (NULL == pg->peers[off].daemon)
327 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
328 _("Could not start peer number %u!\n"),
336 * Shutdown all peers started in the given group.
338 * @param pg handle to the peer group
341 GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg)
345 for (off = 0; off < pg->total; off++)
347 /* FIXME: should we wait for our
348 continuations to be called here? This
349 would require us to take a continuation
351 if (NULL != pg->peers[off].daemon)
352 GNUNET_TESTING_daemon_stop (pg->peers[off].daemon,
354 if (NULL != pg->peers[off].cfg)
355 GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg);
357 GNUNET_free (pg->peers);
358 if (NULL != pg->hosts)
360 GNUNET_free (pg->hosts[0].hostname);
361 GNUNET_free (pg->hosts);
367 /* end of testing_group.c */