aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_group.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing_group.c')
-rw-r--r--src/testing/testing_group.c354
1 files changed, 259 insertions, 95 deletions
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c
index b87507364..424dada34 100644
--- a/src/testing/testing_group.c
+++ b/src/testing/testing_group.c
@@ -27,6 +27,8 @@
27#include "gnunet_arm_service.h" 27#include "gnunet_arm_service.h"
28#include "gnunet_testing_lib.h" 28#include "gnunet_testing_lib.h"
29 29
30#define VERBOSE_TESTING GNUNET_YES
31
30/** 32/**
31 * Lowest port used for GNUnet testing. Should be high enough to not 33 * Lowest port used for GNUnet testing. Should be high enough to not
32 * conflict with other applications running on the hosts but be low 34 * conflict with other applications running on the hosts but be low
@@ -42,6 +44,8 @@
42 */ 44 */
43#define HIGH_PORT 32000 45#define HIGH_PORT 32000
44 46
47#define CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
48
45/** 49/**
46 * Data we keep per peer. 50 * Data we keep per peer.
47 */ 51 */
@@ -54,7 +58,7 @@ struct PeerData
54 * updates). 58 * updates).
55 */ 59 */
56 struct GNUNET_CONFIGURATION_Handle *cfg; 60 struct GNUNET_CONFIGURATION_Handle *cfg;
57 61
58 /** 62 /**
59 * Handle for controlling the daemon. 63 * Handle for controlling the daemon.
60 */ 64 */
@@ -71,7 +75,7 @@ struct HostData
71 * Name of the host. 75 * Name of the host.
72 */ 76 */
73 char *hostname; 77 char *hostname;
74 78
75 /** 79 /**
76 * Lowest port that we have not yet used 80 * Lowest port that we have not yet used
77 * for GNUnet. 81 * for GNUnet.
@@ -87,7 +91,7 @@ struct GNUNET_TESTING_PeerGroup
87{ 91{
88 /** 92 /**
89 * Our scheduler. 93 * Our scheduler.
90 */ 94 */
91 struct GNUNET_SCHEDULER_Handle *sched; 95 struct GNUNET_SCHEDULER_Handle *sched;
92 96
93 /** 97 /**
@@ -97,7 +101,7 @@ struct GNUNET_TESTING_PeerGroup
97 101
98 /** 102 /**
99 * Function to call on each started daemon. 103 * Function to call on each started daemon.
100 */ 104 */
101 GNUNET_TESTING_NotifyDaemonRunning cb; 105 GNUNET_TESTING_NotifyDaemonRunning cb;
102 106
103 /** 107 /**
@@ -105,6 +109,16 @@ struct GNUNET_TESTING_PeerGroup
105 */ 109 */
106 void *cb_cls; 110 void *cb_cls;
107 111
112 /*
113 * Function to call on each topology connection created
114 */
115 GNUNET_TESTING_NotifyConnection notify_connection;
116
117 /*
118 * Callback for notify_connection
119 */
120 void *notify_connection_cls;
121
108 /** 122 /**
109 * NULL-terminated array of information about 123 * NULL-terminated array of information about
110 * hosts. 124 * hosts.
@@ -118,13 +132,13 @@ struct GNUNET_TESTING_PeerGroup
118 132
119 /** 133 /**
120 * Number of peers in this group. 134 * Number of peers in this group.
121 */ 135 */
122 unsigned int total; 136 unsigned int total;
123 137
124}; 138};
125 139
126 140
127struct UpdateContext 141struct UpdateContext
128{ 142{
129 struct GNUNET_CONFIGURATION_Handle *ret; 143 struct GNUNET_CONFIGURATION_Handle *ret;
130 unsigned int nport; 144 unsigned int nport;
@@ -140,29 +154,20 @@ struct UpdateContext
140 * @param option name of the option 154 * @param option name of the option
141 * @param value value of the option 155 * @param value value of the option
142 */ 156 */
143static void 157static void
144update_config(void *cls, 158update_config (void *cls,
145 const char *section, 159 const char *section, const char *option, const char *value)
146 const char *option,
147 const char *value)
148{ 160{
149 struct UpdateContext *ctx = cls; 161 struct UpdateContext *ctx = cls;
150 unsigned int ival; 162 unsigned int ival;
151 char cval[12]; 163 char cval[12];
152 164
153 if ( (0 == strcmp (option, "PORT")) && 165 if ((0 == strcmp (option, "PORT")) && (1 == sscanf (value, "%u", &ival)))
154 (1 == sscanf (value, "%u", &ival)) )
155 { 166 {
156 GNUNET_snprintf (cval, 167 GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++);
157 sizeof(cval),
158 "%u",
159 ctx->nport++);
160 value = cval; 168 value = cval;
161 } 169 }
162 GNUNET_CONFIGURATION_set_value_string (ctx->ret, 170 GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, option, value);
163 section,
164 option,
165 value);
166} 171}
167 172
168 173
@@ -177,9 +182,8 @@ update_config(void *cls,
177 * port numbers that were used 182 * port numbers that were used
178 * @return new configuration, NULL on error 183 * @return new configuration, NULL on error
179 */ 184 */
180static struct GNUNET_CONFIGURATION_Handle* 185static struct GNUNET_CONFIGURATION_Handle *
181make_config (const struct GNUNET_CONFIGURATION_Handle*cfg, 186make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t * port)
182 uint16_t *port)
183{ 187{
184 struct UpdateContext uc; 188 struct UpdateContext uc;
185 uint16_t orig; 189 uint16_t orig;
@@ -187,9 +191,7 @@ make_config (const struct GNUNET_CONFIGURATION_Handle*cfg,
187 orig = *port; 191 orig = *port;
188 uc.nport = *port; 192 uc.nport = *port;
189 uc.ret = GNUNET_CONFIGURATION_create (); 193 uc.ret = GNUNET_CONFIGURATION_create ();
190 GNUNET_CONFIGURATION_iterate (cfg, 194 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
191 &update_config,
192 &uc);
193 if (uc.nport >= HIGH_PORT) 195 if (uc.nport >= HIGH_PORT)
194 { 196 {
195 *port = orig; 197 *port = orig;
@@ -200,6 +202,143 @@ make_config (const struct GNUNET_CONFIGURATION_Handle*cfg,
200 return uc.ret; 202 return uc.ret;
201} 203}
202 204
205static int
206create_clique (struct GNUNET_TESTING_PeerGroup *pg)
207{
208 unsigned int outer_count;
209 unsigned int inner_count;
210 int connect_attempts;
211
212 connect_attempts = 0;
213
214 for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
215 {
216 for (inner_count = outer_count + 1; inner_count < pg->total;
217 inner_count++)
218 {
219#if VERBOSE_TESTING
220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
221 "Connecting peer %d to peer %d\n",
222 outer_count, inner_count);
223#endif
224 GNUNET_TESTING_daemons_connect (pg->peers[outer_count].daemon,
225 pg->peers[inner_count].daemon,
226 CONNECT_TIMEOUT,
227 pg->notify_connection,
228 pg->notify_connection_cls);
229 connect_attempts++;
230 }
231 }
232
233 return connect_attempts;
234}
235
236
237/*
238 * Takes a peer group and attempts to create a topology based on the
239 * one specified in the configuration file. Returns the number of connections
240 * that will attempt to be created, but this will happen asynchronously(?) so
241 * the caller will have to keep track (via the callback) of whether or not
242 * the connection actually happened.
243 *
244 * @param pg the peer group struct representing the running peers
245 *
246 */
247int
248GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg)
249{
250 /* Put stuff at home in here... */
251 unsigned long long topology_num;
252 int ret;
253
254 GNUNET_assert (pg->notify_connection != NULL);
255 ret = 0;
256 if (GNUNET_YES ==
257 GNUNET_CONFIGURATION_get_value_number (pg->cfg, "testing", "topology",
258 &topology_num))
259 {
260 switch (topology_num)
261 {
262 case GNUNET_TESTING_TOPOLOGY_CLIQUE:
263#if VERBOSE_TESTING
264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
265 _("Creating clique topology (may take a bit!)\n"));
266 ret = create_clique (pg);
267 break;
268 case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
269 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
270 _("Creating small world topology (may take a bit!)\n"));
271#endif
272 ret = GNUNET_SYSERR;
273/* ret =
274 GNUNET_REMOTE_connect_small_world_ring (&totalConnections,
275 number_of_daemons,
276 list_as_array, dotOutFile,
277 percentage, logNModifier);
278 */
279 break;
280 case GNUNET_TESTING_TOPOLOGY_RING:
281#if VERBOSE_TESTING
282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
283 _("Creating ring topology (may take a bit!)\n"));
284#endif
285 /*
286 ret = GNUNET_REMOTE_connect_ring (&totalConnections, head, dotOutFile);
287 */
288 ret = GNUNET_SYSERR;
289 break;
290 case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
291#if VERBOSE_TESTING
292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
293 _("Creating 2d torus topology (may take a bit!)\n"));
294#endif
295 /*
296 ret =
297 GNUNET_REMOTE_connect_2d_torus (&totalConnections, number_of_daemons,
298 list_as_array, dotOutFile);
299 */
300 ret = GNUNET_SYSERR;
301 break;
302 case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
303#if VERBOSE_TESTING
304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
305 _("Creating Erdos-Renyi topology (may take a bit!)\n"));
306#endif
307 /* ret =
308 GNUNET_REMOTE_connect_erdos_renyi (&totalConnections, percentage,
309 head, dotOutFile);
310 */
311 ret = GNUNET_SYSERR;
312 break;
313 case GNUNET_TESTING_TOPOLOGY_INTERNAT:
314#if VERBOSE_TESTING
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 _("Creating InterNAT topology (may take a bit!)\n"));
317#endif
318 /*
319 ret =
320 GNUNET_REMOTE_connect_nated_internet (&totalConnections, percentage,
321 number_of_daemons, head,
322 dotOutFile);
323 */
324 ret = GNUNET_SYSERR;
325 break;
326 case GNUNET_TESTING_TOPOLOGY_NONE:
327 ret = 0;
328 break;
329 default:
330 ret = GNUNET_SYSERR;
331 break;
332 }
333 }
334 else
335 {
336 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
337 _("No topology specified, was one intended?\n"));
338 }
339
340 return ret;
341}
203 342
204/** 343/**
205 * Start count gnunetd processes with the same set of transports and 344 * Start count gnunetd processes with the same set of transports and
@@ -212,85 +351,93 @@ make_config (const struct GNUNET_CONFIGURATION_Handle*cfg,
212 * @param total number of daemons to start 351 * @param total number of daemons to start
213 * @param cb function to call on each daemon that was started 352 * @param cb function to call on each daemon that was started
214 * @param cb_cls closure for cb 353 * @param cb_cls closure for cb
354 * @param connect_callback function to call each time two hosts are connected
355 * @param connect_callback_cls closure for connect_callback
215 * @param hostnames space-separated list of hostnames to use; can be NULL (to run 356 * @param hostnames space-separated list of hostnames to use; can be NULL (to run
216 * everything on localhost). 357 * everything on localhost).
217 * @return NULL on error, otherwise handle to control peer group 358 * @return NULL on error, otherwise handle to control peer group
218 */ 359 */
219struct GNUNET_TESTING_PeerGroup * 360struct GNUNET_TESTING_PeerGroup *
220GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, 361GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
221 const struct GNUNET_CONFIGURATION_Handle *cfg, 362 const struct GNUNET_CONFIGURATION_Handle *cfg,
222 unsigned int total, 363 unsigned int total,
223 GNUNET_TESTING_NotifyDaemonRunning cb, 364 GNUNET_TESTING_NotifyDaemonRunning cb,
224 void *cb_cls, 365 void *cb_cls,
225 const char *hostnames) 366 GNUNET_TESTING_NotifyConnection
367 connect_callback, void *connect_callback_cls,
368 const char *hostnames)
226{ 369{
227 struct GNUNET_TESTING_PeerGroup *pg; 370 struct GNUNET_TESTING_PeerGroup *pg;
228 const char *rpos; 371 const char *rpos;
229 char *pos; 372 char *pos;
230 char *start; 373 char *start;
231 const char *hostname; 374 const char *hostname;
375 char *baseservicehome;
376 char *newservicehome;
232 struct GNUNET_CONFIGURATION_Handle *pcfg; 377 struct GNUNET_CONFIGURATION_Handle *pcfg;
233 unsigned int off; 378 unsigned int off;
234 unsigned int hostcnt; 379 unsigned int hostcnt;
235 uint16_t minport; 380 uint16_t minport;
381 int tempsize;
236 382
237 if (0 == total) 383 if (0 == total)
238 { 384 {
239 GNUNET_break (0); 385 GNUNET_break (0);
240 return NULL; 386 return NULL;
241 } 387 }
242 pg = GNUNET_malloc (sizeof(struct GNUNET_TESTING_PeerGroup)); 388 pg = GNUNET_malloc (sizeof (struct GNUNET_TESTING_PeerGroup));
243 pg->sched = sched; 389 pg->sched = sched;
244 pg->cfg = cfg; 390 pg->cfg = cfg;
245 pg->cb = cb; 391 pg->cb = cb;
246 pg->cb_cls = cb_cls; 392 pg->cb_cls = cb_cls;
393 pg->notify_connection = connect_callback;
394 pg->notify_connection_cls = connect_callback_cls;
247 pg->total = total; 395 pg->total = total;
248 pg->peers = GNUNET_malloc (total * sizeof(struct PeerData)); 396 pg->peers = GNUNET_malloc (total * sizeof (struct PeerData));
249 if (NULL != hostnames) 397 if (NULL != hostnames)
250 { 398 {
251 off = 2; 399 off = 2;
252 /* skip leading spaces */ 400 /* skip leading spaces */
253 while ( (0 != *hostnames) && 401 while ((0 != *hostnames) && (isspace (*hostnames)))
254 (isspace(*hostnames))) 402 hostnames++;
255 hostnames++;
256 rpos = hostnames; 403 rpos = hostnames;
257 while ('\0' != *rpos) 404 while ('\0' != *rpos)
258 { 405 {
259 if (isspace (*rpos)) 406 if (isspace (*rpos))
260 off++; 407 off++;
261 rpos++; 408 rpos++;
262 } 409 }
263 pg->hosts = GNUNET_malloc (off * sizeof (struct HostData)); 410 pg->hosts = GNUNET_malloc (off * sizeof (struct HostData));
264 off = 0; 411 off = 0;
265 start = GNUNET_strdup (hostnames); 412 start = GNUNET_strdup (hostnames);
266 pos = start; 413 pos = start;
267 while ('\0' != *pos) 414 while ('\0' != *pos)
268 { 415 {
269 if (isspace (*pos)) 416 if (isspace (*pos))
270 { 417 {
271 *pos = '\0'; 418 *pos = '\0';
272 if (strlen(start) > 0) 419 if (strlen (start) > 0)
273 { 420 {
274 pg->hosts[off].minport = LOW_PORT; 421 pg->hosts[off].minport = LOW_PORT;
275 pg->hosts[off++].hostname = start; 422 pg->hosts[off++].hostname = start;
276 } 423 }
277 start = pos+1; 424 start = pos + 1;
278 } 425 }
279 pos++; 426 pos++;
280 } 427 }
281 if (strlen(start) > 0) 428 if (strlen (start) > 0)
282 { 429 {
283 pg->hosts[off].minport = LOW_PORT; 430 pg->hosts[off].minport = LOW_PORT;
284 pg->hosts[off++].hostname = start; 431 pg->hosts[off++].hostname = start;
285 } 432 }
286 if (off == 0) 433 if (off == 0)
287 { 434 {
288 GNUNET_free (start); 435 GNUNET_free (start);
289 GNUNET_free (pg->hosts); 436 GNUNET_free (pg->hosts);
290 pg->hosts = NULL; 437 pg->hosts = NULL;
291 } 438 }
292 hostcnt = off; 439 hostcnt = off;
293 minport = 0; /* make gcc happy */ 440 minport = 0; /* make gcc happy */
294 } 441 }
295 else 442 else
296 { 443 {
@@ -300,33 +447,51 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
300 for (off = 0; off < total; off++) 447 for (off = 0; off < total; off++)
301 { 448 {
302 if (hostcnt > 0) 449 if (hostcnt > 0)
303 { 450 {
304 hostname = pg->hosts[off % hostcnt].hostname; 451 hostname = pg->hosts[off % hostcnt].hostname;
305 pcfg = make_config (cfg, &pg->hosts[off % hostcnt].minport); 452 pcfg = make_config (cfg, &pg->hosts[off % hostcnt].minport);
306 } 453 }
307 else 454 else
308 { 455 {
309 hostname = NULL; 456 hostname = NULL;
310 pcfg = make_config (cfg, &minport); 457 pcfg = make_config (cfg, &minport);
311 } 458 }
312 if (NULL == pcfg) 459 if (NULL == pcfg)
313 { 460 {
314 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 461 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
315 _("Could not create configuration for peer number %u on `%s'!\n"), 462 _
316 off, 463 ("Could not create configuration for peer number %u on `%s'!\n"),
317 hostname == NULL ? "localhost" : hostname); 464 off, hostname == NULL ? "localhost" : hostname);
318 continue; 465 continue;
319 } 466 }
467
468 if (GNUNET_YES ==
469 GNUNET_CONFIGURATION_get_value_string (pcfg, "PATHS", "SERVICEHOME",
470 &baseservicehome))
471 {
472 tempsize = snprintf (NULL, 0, "%s/%d/", baseservicehome, off) + 1;
473 newservicehome = GNUNET_malloc (tempsize);
474 snprintf (newservicehome, tempsize, "%s/%d/", baseservicehome, off);
475 }
476 else
477 {
478 tempsize = snprintf (NULL, 0, "%s/%d/", "/tmp/gnunet-testing-test-test", off) + 1; /* FIXME: set a default path, or read the TMPDIR variable or something */
479 newservicehome = GNUNET_malloc (tempsize);
480 snprintf (newservicehome, tempsize, "%s/%d/",
481 "/tmp/gnunet-testing-test-test", off);
482 }
483 GNUNET_CONFIGURATION_set_value_string (pcfg,
484 "PATHS",
485 "SERVICEHOME", newservicehome);
486
320 pg->peers[off].cfg = pcfg; 487 pg->peers[off].cfg = pcfg;
321 pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched, 488 pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched,
322 pcfg, 489 pcfg,
323 hostname, 490 hostname,
324 cb, 491 cb, cb_cls);
325 cb_cls);
326 if (NULL == pg->peers[off].daemon) 492 if (NULL == pg->peers[off].daemon)
327 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 493 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
328 _("Could not start peer number %u!\n"), 494 _("Could not start peer number %u!\n"), off);
329 off);
330 } 495 }
331 return pg; 496 return pg;
332} 497}
@@ -345,14 +510,13 @@ GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg)
345 for (off = 0; off < pg->total; off++) 510 for (off = 0; off < pg->total; off++)
346 { 511 {
347 /* FIXME: should we wait for our 512 /* FIXME: should we wait for our
348 continuations to be called here? This 513 continuations to be called here? This
349 would require us to take a continuation 514 would require us to take a continuation
350 as well... */ 515 as well... */
351 if (NULL != pg->peers[off].daemon) 516 if (NULL != pg->peers[off].daemon)
352 GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, 517 GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL);
353 NULL, NULL);
354 if (NULL != pg->peers[off].cfg) 518 if (NULL != pg->peers[off].cfg)
355 GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg); 519 GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg);
356 } 520 }
357 GNUNET_free (pg->peers); 521 GNUNET_free (pg->peers);
358 if (NULL != pg->hosts) 522 if (NULL != pg->hosts)