aboutsummaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing')
-rw-r--r--src/testing/Makefile.am29
-rw-r--r--src/testing/test_testing.c116
-rw-r--r--src/testing/test_testing_data.conf29
-rw-r--r--src/testing/testing.c186
-rw-r--r--src/testing/testing_group.c315
5 files changed, 547 insertions, 128 deletions
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 635570482..9ac831a88 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -15,17 +15,20 @@ libgnunettesting_la_SOURCES = \
15 testing.c \ 15 testing.c \
16 testing_group.c \ 16 testing_group.c \
17 testing_testbed.c 17 testing_testbed.c
18libgnunettesting_la_LIBADD = \ 18libgnunettesting_la_LIBADD = $(XLIB) \
19 $(top_builddir)/src/util/libgnunetutil.la $(XLIB) 19 $(top_builddir)/src/core/libgnunetcore.la \
20 20 $(top_builddir)/src/transport/libgnunettransport.la \
21#check_PROGRAMS = \ 21 $(top_builddir)/src/util/libgnunetutil.la
22# test_testing
23#
24#TESTS = $(check_PROGRAMS)
25#
26#test_testing_SOURCES = \
27# test_testing.c
28#test_testing_LDADD = \
29# $(top_builddir)/src/testing/libgnunettesting.la \
30# $(top_builddir)/src/util/libgnunetutil.la
31 22
23check_PROGRAMS = \
24 test_testing
25
26TESTS = $(check_PROGRAMS)
27
28test_testing_SOURCES = \
29 test_testing.c
30test_testing_LDADD = \
31 $(top_builddir)/src/testing/libgnunettesting.la \
32 $(top_builddir)/src/util/libgnunetutil.la
33
34EXTRA_DIST = test_testing_data.conf
diff --git a/src/testing/test_testing.c b/src/testing/test_testing.c
new file mode 100644
index 000000000..cbedf60fb
--- /dev/null
+++ b/src/testing/test_testing.c
@@ -0,0 +1,116 @@
1/*
2 This file is part of GNUnet.
3 (C) 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 * @file testing/test_testing.c
22 * @brief testcase for testing.c
23 */
24#include "platform.h"
25#include "gnunet_testing_lib.h"
26
27#define VERBOSE GNUNET_YES
28
29static int ok;
30
31static void end_cb(void *cls,
32 const char *emsg)
33{
34 GNUNET_assert (emsg == NULL);
35#if VERBOSE
36 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
37 "Daemon terminated, will now exit.\n");
38#endif
39 ok = 0;
40}
41
42static void my_cb(void *cls,
43 const struct GNUNET_PeerIdentity *id,
44 const struct GNUNET_CONFIGURATION_Handle *cfg,
45 struct GNUNET_TESTING_Daemon *d,
46 const char *emsg)
47{
48 GNUNET_assert (id != NULL);
49#if VERBOSE
50 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
51 "Daemon started, will now stop it.\n");
52#endif
53 GNUNET_TESTING_daemon_stop (d, &end_cb, NULL);
54}
55
56
57static void
58run (void *cls,
59 struct GNUNET_SCHEDULER_Handle *sched,
60 char *const *args,
61 const char *cfgfile,
62 const struct GNUNET_CONFIGURATION_Handle *cfg)
63{
64 struct GNUNET_TESTING_Daemon *d;
65
66 ok = 1;
67#if VERBOSE
68 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
69 "Starting daemon.\n");
70#endif
71 d = GNUNET_TESTING_daemon_start (sched,
72 cfg,
73 NULL,
74 &my_cb,
75 NULL);
76 GNUNET_assert (d != NULL);
77}
78
79static int
80check ()
81{
82 char *const argv[] = { "test-testing",
83 "-c",
84 "test_testing_data.conf",
85#if VERBOSE
86 "-L", "DEBUG",
87#endif
88 NULL
89 };
90 struct GNUNET_GETOPT_CommandLineOption options[] = {
91 GNUNET_GETOPT_OPTION_END
92 };
93 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
94 argv, "test-tesing", "nohelp",
95 options, &run, &ok);
96 return ok;
97}
98
99int
100main (int argc, char *argv[])
101{
102 int ret;
103
104 GNUNET_log_setup ("test-testing",
105#if VERBOSE
106 "DEBUG",
107#else
108 "WARNING",
109#endif
110 NULL);
111 ret = check ();
112
113 return ret;
114}
115
116/* end of test_testing.c */
diff --git a/src/testing/test_testing_data.conf b/src/testing/test_testing_data.conf
new file mode 100644
index 000000000..7c46fdf34
--- /dev/null
+++ b/src/testing/test_testing_data.conf
@@ -0,0 +1,29 @@
1[PATHS]
2SERVICEHOME = /tmp/test-gnunet-testing/
3DEFAULTCONFIG = test_testing_data.conf
4
5[resolver]
6PORT = 2564
7
8[transport]
9PORT = 2565
10PLUGINS = tcp
11
12[arm]
13PORT = 2566
14DEFAULTSERVICES = transport core
15
16[statistics]
17PORT = 2567
18
19[tcp]
20PORT = 2568
21
22[peerinfo]
23PORT = 2569
24
25[core]
26PORT = 2570
27
28[testing]
29WEAKRANDOM = YES
diff --git a/src/testing/testing.c b/src/testing/testing.c
index 3406355c5..5d465e05f 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -85,7 +85,7 @@ struct GNUNET_TESTING_Daemon
85 /** 85 /**
86 * Our configuration. 86 * Our configuration.
87 */ 87 */
88 const struct GNUNET_CONFIGURATION_Handle *cfg; 88 struct GNUNET_CONFIGURATION_Handle *cfg;
89 89
90 /** 90 /**
91 * Host to run GNUnet on. 91 * Host to run GNUnet on.
@@ -202,10 +202,11 @@ testing_init (void *cls,
202 d->cb = NULL; 202 d->cb = NULL;
203 if (server == NULL) 203 if (server == NULL)
204 { 204 {
205 cb (d->cb_cls, NULL, d->cfg, d,
206 _("Failed to connect to core service\n"));
207 if (GNUNET_YES == d->dead) 205 if (GNUNET_YES == d->dead)
208 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); 206 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls);
207 else if (NULL != cb)
208 cb (d->cb_cls, NULL, d->cfg, d,
209 _("Failed to connect to core service\n"));
209 return; 210 return;
210 } 211 }
211#if DEBUG_TESTING 212#if DEBUG_TESTING
@@ -216,7 +217,7 @@ testing_init (void *cls,
216 d->id = *my_identity; 217 d->id = *my_identity;
217 if (GNUNET_YES == d->dead) 218 if (GNUNET_YES == d->dead)
218 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); 219 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls);
219 else 220 else if (NULL != cb)
220 cb (d->cb_cls, my_identity, d->cfg, d, NULL); 221 cb (d->cb_cls, my_identity, d->cfg, d, NULL);
221 d->server = server; 222 d->server = server;
222} 223}
@@ -240,6 +241,11 @@ start_fsm (void *cls,
240 unsigned long code; 241 unsigned long code;
241 char *dst; 242 char *dst;
242 243
244#if DEBUG_TESTING
245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
246 "Peer FSM is in phase %u.\n",
247 d->phase);
248#endif
243 d->task = GNUNET_SCHEDULER_NO_TASK; 249 d->task = GNUNET_SCHEDULER_NO_TASK;
244 switch (d->phase) 250 switch (d->phase)
245 { 251 {
@@ -255,11 +261,12 @@ start_fsm (void *cls,
255 { 261 {
256 cb = d->cb; 262 cb = d->cb;
257 d->cb = NULL; 263 d->cb = NULL;
258 cb (d->cb_cls, 264 if (NULL != cb)
259 NULL, 265 cb (d->cb_cls,
260 d->cfg, 266 NULL,
261 d, 267 d->cfg,
262 _("`scp' does not seem to terminate.\n")); 268 d,
269 _("`scp' does not seem to terminate.\n"));
263 return; 270 return;
264 } 271 }
265 /* wait some more */ 272 /* wait some more */
@@ -278,11 +285,12 @@ start_fsm (void *cls,
278 { 285 {
279 cb = d->cb; 286 cb = d->cb;
280 d->cb = NULL; 287 d->cb = NULL;
281 cb (d->cb_cls, 288 if (NULL != cb)
282 NULL, 289 cb (d->cb_cls,
283 d->cfg, 290 NULL,
284 d, 291 d->cfg,
285 _("`scp' did not complete cleanly.\n")); 292 d,
293 _("`scp' did not complete cleanly.\n"));
286 return; 294 return;
287 } 295 }
288#if DEBUG_TESTING 296#if DEBUG_TESTING
@@ -299,7 +307,11 @@ start_fsm (void *cls,
299 "gnunet-service-arm", 307 "gnunet-service-arm",
300 "-c", 308 "-c",
301 d->cfgfile, 309 d->cfgfile,
310#if DEBUG_TESTING
311 "-L", "DEBUG",
312#else
302 "-d", 313 "-d",
314#endif
303 NULL); 315 NULL);
304 } 316 }
305 else 317 else
@@ -328,16 +340,31 @@ start_fsm (void *cls,
328 (NULL == d->hostname) ? "gnunet-service-arm" : "ssh"); 340 (NULL == d->hostname) ? "gnunet-service-arm" : "ssh");
329 cb = d->cb; 341 cb = d->cb;
330 d->cb = NULL; 342 d->cb = NULL;
331 cb (d->cb_cls, 343 if (NULL != cb)
332 NULL, 344 cb (d->cb_cls,
333 d->cfg, 345 NULL,
334 d, 346 d->cfg,
335 (NULL == d->hostname) 347 d,
336 ? _("Failed to start `gnunet-service-arm' process.\n") 348 (NULL == d->hostname)
337 : _("Failed to start `ssh' process.\n")); 349 ? _("Failed to start `gnunet-service-arm' process.\n")
350 : _("Failed to start `ssh' process.\n"));
338 } 351 }
352#if DEBUG_TESTING
353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
354 "Started `%s', waiting for `%s' to be up.\n",
355 "gnunet-service-arm",
356 "gnunet-service-core");
357#endif
339 d->phase = SP_START_ARMING; 358 d->phase = SP_START_ARMING;
340 d->wait_runs = 0; 359 d->wait_runs = 0;
360 d->task
361 = GNUNET_SCHEDULER_add_delayed (d->sched,
362 GNUNET_NO,
363 GNUNET_SCHEDULER_PRIORITY_KEEP,
364 GNUNET_SCHEDULER_NO_TASK,
365 GNUNET_CONSTANTS_EXEC_WAIT,
366 &start_fsm,
367 d);
341 break; 368 break;
342 case SP_START_ARMING: 369 case SP_START_ARMING:
343 if (GNUNET_OK != 370 if (GNUNET_OK !=
@@ -350,13 +377,14 @@ start_fsm (void *cls,
350 { 377 {
351 cb = d->cb; 378 cb = d->cb;
352 d->cb = NULL; 379 d->cb = NULL;
353 cb (d->cb_cls, 380 if (NULL != cb)
354 NULL, 381 cb (d->cb_cls,
355 d->cfg, 382 NULL,
356 d, 383 d->cfg,
357 (NULL == d->hostname) 384 d,
358 ? _("`gnunet-service-arm' does not seem to terminate.\n") 385 (NULL == d->hostname)
359 : _("`ssh' does not seem to terminate.\n")); 386 ? _("`gnunet-service-arm' does not seem to terminate.\n")
387 : _("`ssh' does not seem to terminate.\n"));
360 return; 388 return;
361 } 389 }
362 /* wait some more */ 390 /* wait some more */
@@ -424,18 +452,24 @@ start_fsm (void *cls,
424 if ( (type != GNUNET_OS_PROCESS_EXITED) || 452 if ( (type != GNUNET_OS_PROCESS_EXITED) ||
425 (code != 0) ) 453 (code != 0) )
426 { 454 {
427 d->dead_cb (d->dead_cb_cls, 455 if (NULL != d->dead_cb)
428 _("`sshp' did not complete cleanly.\n")); 456 d->dead_cb (d->dead_cb_cls,
457 _("`ssh' did not complete cleanly.\n"));
429 GNUNET_free (d->cfgfile); 458 GNUNET_free (d->cfgfile);
430 GNUNET_free_non_null (d->hostname); 459 GNUNET_free_non_null (d->hostname);
431 GNUNET_free_non_null (d->username); 460 GNUNET_free_non_null (d->username);
432 GNUNET_free (d); 461 GNUNET_free (d);
433 return; 462 return;
434 } 463 }
464#if DEBUG_TESTING
465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
466 "Peer shutdown complete.\n");
467#endif
435 GNUNET_free (d->cfgfile); 468 GNUNET_free (d->cfgfile);
436 GNUNET_free_non_null (d->hostname); 469 GNUNET_free_non_null (d->hostname);
437 GNUNET_free_non_null (d->username); 470 GNUNET_free_non_null (d->username);
438 d->dead_cb (d->dead_cb_cls, NULL); 471 if (NULL != d->dead_cb)
472 d->dead_cb (d->dead_cb_cls, NULL);
439 GNUNET_free (d); 473 GNUNET_free (d);
440 break; 474 break;
441 case SP_CONFIG_UPDATE: 475 case SP_CONFIG_UPDATE:
@@ -450,11 +484,12 @@ start_fsm (void *cls,
450 { 484 {
451 cb = d->cb; 485 cb = d->cb;
452 d->cb = NULL; 486 d->cb = NULL;
453 cb (d->cb_cls, 487 if (NULL != cb)
454 NULL, 488 cb (d->cb_cls,
455 d->cfg, 489 NULL,
456 d, 490 d->cfg,
457 _("`scp' does not seem to terminate.\n")); 491 d,
492 _("`scp' does not seem to terminate.\n"));
458 return; 493 return;
459 } 494 }
460 /* wait some more */ 495 /* wait some more */
@@ -471,15 +506,17 @@ start_fsm (void *cls,
471 if ( (type != GNUNET_OS_PROCESS_EXITED) || 506 if ( (type != GNUNET_OS_PROCESS_EXITED) ||
472 (code != 0) ) 507 (code != 0) )
473 { 508 {
474 d->update_cb (d->update_cb_cls, 509 if (NULL != d->update_cb)
475 _("`scp' did not complete cleanly.\n")); 510 d->update_cb (d->update_cb_cls,
511 _("`scp' did not complete cleanly.\n"));
476 return; 512 return;
477 } 513 }
478#if DEBUG_TESTING 514#if DEBUG_TESTING
479 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
480 "Successfully copied configuration file.\n"); 516 "Successfully copied configuration file.\n");
481#endif 517#endif
482 d->update_cb (d->update_cb_cls, NULL); 518 if (NULL != d->update_cb)
519 d->update_cb (d->update_cb_cls, NULL);
483 d->phase = SP_START_DONE; 520 d->phase = SP_START_DONE;
484 break; 521 break;
485 } 522 }
@@ -502,7 +539,7 @@ start_fsm (void *cls,
502 */ 539 */
503struct GNUNET_TESTING_Daemon * 540struct GNUNET_TESTING_Daemon *
504GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, 541GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
505 struct GNUNET_CONFIGURATION_Handle *cfg, 542 const struct GNUNET_CONFIGURATION_Handle *cfg,
506 const char *hostname, 543 const char *hostname,
507 GNUNET_TESTING_NotifyDaemonRunning cb, 544 GNUNET_TESTING_NotifyDaemonRunning cb,
508 void *cb_cls) 545 void *cb_cls)
@@ -513,9 +550,13 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
513 550
514 ret = GNUNET_malloc (sizeof(struct GNUNET_TESTING_Daemon)); 551 ret = GNUNET_malloc (sizeof(struct GNUNET_TESTING_Daemon));
515 ret->sched = sched; 552 ret->sched = sched;
516 ret->cfg = cfg;
517 ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname); 553 ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname);
518 ret->cfgfile = GNUNET_DISK_mktemp ("gnunet-testing-config"); 554 ret->cfgfile = GNUNET_DISK_mktemp ("gnunet-testing-config");
555#if DEBUG_TESTING
556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
557 "Setting up peer with configuration file `%s'.\n",
558 ret->cfgfile);
559#endif
519 if (NULL == ret->cfgfile) 560 if (NULL == ret->cfgfile)
520 { 561 {
521 GNUNET_free_non_null (ret->hostname); 562 GNUNET_free_non_null (ret->hostname);
@@ -524,15 +565,21 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
524 } 565 }
525 ret->cb = cb; 566 ret->cb = cb;
526 ret->cb_cls = cb_cls; 567 ret->cb_cls = cb_cls;
568 ret->cfg = GNUNET_CONFIGURATION_dup (cfg);
569 GNUNET_CONFIGURATION_set_value_string (ret->cfg,
570 "PATHS",
571 "DEFAULTCONFIG",
572 ret->cfgfile);
527 /* 1) write configuration to temporary file */ 573 /* 1) write configuration to temporary file */
528 if (GNUNET_OK != 574 if (GNUNET_OK !=
529 GNUNET_CONFIGURATION_write (cfg, 575 GNUNET_CONFIGURATION_write (ret->cfg,
530 ret->cfgfile)) 576 ret->cfgfile))
531 { 577 {
532 if (0 != UNLINK (ret->cfgfile)) 578 if (0 != UNLINK (ret->cfgfile))
533 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 579 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
534 "unlink", 580 "unlink",
535 ret->cfgfile); 581 ret->cfgfile);
582 GNUNET_CONFIGURATION_destroy (ret->cfg);
536 GNUNET_free_non_null (ret->hostname); 583 GNUNET_free_non_null (ret->hostname);
537 GNUNET_free (ret->cfgfile); 584 GNUNET_free (ret->cfgfile);
538 GNUNET_free (ret); 585 GNUNET_free (ret);
@@ -581,6 +628,7 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
581 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 628 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
582 "unlink", 629 "unlink",
583 ret->cfgfile); 630 ret->cfgfile);
631 GNUNET_CONFIGURATION_destroy (ret->cfg);
584 GNUNET_free_non_null (ret->hostname); 632 GNUNET_free_non_null (ret->hostname);
585 GNUNET_free_non_null (ret->username); 633 GNUNET_free_non_null (ret->username);
586 GNUNET_free (ret->cfgfile); 634 GNUNET_free (ret->cfgfile);
@@ -589,7 +637,7 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
589 } 637 }
590 ret->task 638 ret->task
591 = GNUNET_SCHEDULER_add_delayed (sched, 639 = GNUNET_SCHEDULER_add_delayed (sched,
592 GNUNET_NO, 640 GNUNET_YES,
593 GNUNET_SCHEDULER_PRIORITY_KEEP, 641 GNUNET_SCHEDULER_PRIORITY_KEEP,
594 GNUNET_SCHEDULER_NO_TASK, 642 GNUNET_SCHEDULER_NO_TASK,
595 GNUNET_CONSTANTS_EXEC_WAIT, 643 GNUNET_CONSTANTS_EXEC_WAIT,
@@ -597,6 +645,10 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
597 ret); 645 ret);
598 return ret; 646 return ret;
599 } 647 }
648#if DEBUG_TESTING
649 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
650 "No need to copy configuration file since we are running locally.\n");
651#endif
600 ret->phase = SP_COPIED; 652 ret->phase = SP_COPIED;
601 GNUNET_SCHEDULER_add_continuation (sched, 653 GNUNET_SCHEDULER_add_continuation (sched,
602 GNUNET_NO, 654 GNUNET_NO,
@@ -687,7 +739,7 @@ void GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
687 d->dead_cb_cls = cb_cls; 739 d->dead_cb_cls = cb_cls;
688 d->task 740 d->task
689 = GNUNET_SCHEDULER_add_delayed (d->sched, 741 = GNUNET_SCHEDULER_add_delayed (d->sched,
690 GNUNET_NO, 742 GNUNET_YES,
691 GNUNET_SCHEDULER_PRIORITY_KEEP, 743 GNUNET_SCHEDULER_PRIORITY_KEEP,
692 GNUNET_SCHEDULER_NO_TASK, 744 GNUNET_SCHEDULER_NO_TASK,
693 GNUNET_CONSTANTS_EXEC_WAIT, 745 GNUNET_CONSTANTS_EXEC_WAIT,
@@ -695,11 +747,13 @@ void GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
695 d); 747 d);
696 return; 748 return;
697 } 749 }
750 GNUNET_CONFIGURATION_destroy (d->cfg);
698 GNUNET_free (d->cfgfile); 751 GNUNET_free (d->cfgfile);
699 GNUNET_free_non_null (d->hostname); 752 GNUNET_free_non_null (d->hostname);
700 GNUNET_free_non_null (d->username); 753 GNUNET_free_non_null (d->username);
701 GNUNET_free (d); 754 GNUNET_free (d);
702 cb (cb_cls, NULL); 755 if (NULL != cb)
756 cb (cb_cls, NULL);
703} 757}
704 758
705 759
@@ -720,8 +774,9 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d,
720 774
721 if (d->phase != SP_START_DONE) 775 if (d->phase != SP_START_DONE)
722 { 776 {
723 cb (cb_cls, 777 if (NULL != cb)
724 _("Peer not yet running, can not change configuration at this point.")); 778 cb (cb_cls,
779 _("Peer not yet running, can not change configuration at this point."));
725 return; 780 return;
726 } 781 }
727 782
@@ -730,7 +785,8 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d,
730 GNUNET_CONFIGURATION_write (cfg, 785 GNUNET_CONFIGURATION_write (cfg,
731 d->cfgfile)) 786 d->cfgfile))
732 { 787 {
733 cb (cb_cls, 788 if (NULL != cb)
789 cb (cb_cls,
734 _("Failed to write new configuration to disk.")); 790 _("Failed to write new configuration to disk."));
735 return; 791 return;
736 } 792 }
@@ -739,7 +795,8 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d,
739 if (NULL == d->hostname) 795 if (NULL == d->hostname)
740 { 796 {
741 /* signal success */ 797 /* signal success */
742 cb (cb_cls, NULL); 798 if (NULL != cb)
799 cb (cb_cls, NULL);
743 return; 800 return;
744 } 801 }
745 d->phase = SP_CONFIG_UPDATE; 802 d->phase = SP_CONFIG_UPDATE;
@@ -765,8 +822,9 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d,
765 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 822 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
766 _("Could not start `%s' process to copy configuration file.\n"), 823 _("Could not start `%s' process to copy configuration file.\n"),
767 "scp"); 824 "scp");
768 cb (cb_cls, 825 if (NULL != cb)
769 _("Failed to copy new configuration to remote machine.")); 826 cb (cb_cls,
827 _("Failed to copy new configuration to remote machine."));
770 d->phase = SP_START_DONE; 828 d->phase = SP_START_DONE;
771 return; 829 return;
772 } 830 }
@@ -802,10 +860,14 @@ static size_t
802transmit_ready (void *cls, size_t size, void *buf) 860transmit_ready (void *cls, size_t size, void *buf)
803{ 861{
804 struct ConnectContext *ctx = cls; 862 struct ConnectContext *ctx = cls;
805 if (buf == NULL) 863
806 ctx->cb (ctx->cb_cls, _("Peers failed to connect")); 864 if (NULL != ctx->cb)
807 else 865 {
808 ctx->cb (ctx->cb_cls, NULL); 866 if (buf == NULL)
867 ctx->cb (ctx->cb_cls, _("Peers failed to connect"));
868 else
869 ctx->cb (ctx->cb_cls, NULL);
870 }
809 GNUNET_free (ctx); 871 GNUNET_free (ctx);
810 return 0; 872 return 0;
811} 873}
@@ -831,8 +893,9 @@ process_hello (void *cls,
831 if (peer == NULL) 893 if (peer == NULL)
832 { 894 {
833 /* signal error */ 895 /* signal error */
834 ctx->cb (ctx->cb_cls, 896 if (NULL != ctx->cb)
835 _("Failed to receive `HELLO' from peer\n")); 897 ctx->cb (ctx->cb_cls,
898 _("Failed to receive `HELLO' from peer\n"));
836 GNUNET_TRANSPORT_disconnect (ctx->d1th); 899 GNUNET_TRANSPORT_disconnect (ctx->d1th);
837 GNUNET_TRANSPORT_disconnect (ctx->d2th); 900 GNUNET_TRANSPORT_disconnect (ctx->d2th);
838 GNUNET_free (ctx); 901 GNUNET_free (ctx);
@@ -873,7 +936,8 @@ void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
873 if ( (d1->server == NULL) || 936 if ( (d1->server == NULL) ||
874 (d2->server == NULL) ) 937 (d2->server == NULL) )
875 { 938 {
876 cb (cb_cls, _("Peers are not fully running yet, can not connect!\n")); 939 if (NULL != cb)
940 cb (cb_cls, _("Peers are not fully running yet, can not connect!\n"));
877 return; 941 return;
878 } 942 }
879 ctx = GNUNET_malloc (sizeof(struct ConnectContext)); 943 ctx = GNUNET_malloc (sizeof(struct ConnectContext));
@@ -886,7 +950,8 @@ void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
886 if (ctx->d1th == NULL) 950 if (ctx->d1th == NULL)
887 { 951 {
888 GNUNET_free (ctx); 952 GNUNET_free (ctx);
889 cb (cb_cls, _("Failed to connect to transport service!\n")); 953 if (NULL != cb)
954 cb (cb_cls, _("Failed to connect to transport service!\n"));
890 return; 955 return;
891 } 956 }
892 ctx->d2th = GNUNET_TRANSPORT_connect (d2->sched, d2->cfg, d2, NULL, NULL, NULL); 957 ctx->d2th = GNUNET_TRANSPORT_connect (d2->sched, d2->cfg, d2, NULL, NULL, NULL);
@@ -894,7 +959,8 @@ void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
894 { 959 {
895 GNUNET_TRANSPORT_disconnect (ctx->d1th); 960 GNUNET_TRANSPORT_disconnect (ctx->d1th);
896 GNUNET_free (ctx); 961 GNUNET_free (ctx);
897 cb (cb_cls, _("Failed to connect to transport service!\n")); 962 if (NULL != cb)
963 cb (cb_cls, _("Failed to connect to transport service!\n"));
898 return; 964 return;
899 } 965 }
900 GNUNET_TRANSPORT_get_hello (ctx->d1th, 966 GNUNET_TRANSPORT_get_hello (ctx->d1th,
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c
index 917a524de..b87507364 100644
--- a/src/testing/testing_group.c
+++ b/src/testing/testing_group.c
@@ -27,6 +27,58 @@
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/**
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
34 * 32k).
35 */
36#define LOW_PORT 10000
37
38/**
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).
42 */
43#define HIGH_PORT 32000
44
45/**
46 * Data we keep per peer.
47 */
48struct PeerData
49{
50 /**
51 * (Initial) configuration of the host.
52 * (initial because clients could change
53 * it and we would not know about those
54 * updates).
55 */
56 struct GNUNET_CONFIGURATION_Handle *cfg;
57
58 /**
59 * Handle for controlling the daemon.
60 */
61 struct GNUNET_TESTING_Daemon *daemon;
62};
63
64
65/**
66 * Data we keep per host.
67 */
68struct HostData
69{
70 /**
71 * Name of the host.
72 */
73 char *hostname;
74
75 /**
76 * Lowest port that we have not yet used
77 * for GNUnet.
78 */
79 uint16_t minport;
80};
81
30 82
31/** 83/**
32 * Handle to a group of GNUnet peers. 84 * Handle to a group of GNUnet peers.
@@ -41,7 +93,7 @@ struct GNUNET_TESTING_PeerGroup
41 /** 93 /**
42 * Configuration template. 94 * Configuration template.
43 */ 95 */
44 struct GNUNET_CONFIGURATION_Handle *cfg; 96 const struct GNUNET_CONFIGURATION_Handle *cfg;
45 97
46 /** 98 /**
47 * Function to call on each started daemon. 99 * Function to call on each started daemon.
@@ -54,14 +106,15 @@ struct GNUNET_TESTING_PeerGroup
54 void *cb_cls; 106 void *cb_cls;
55 107
56 /** 108 /**
57 * NULL-terminated array of hostnames. 109 * NULL-terminated array of information about
110 * hosts.
58 */ 111 */
59 char **hostnames; 112 struct HostData *hosts;
60 113
61 /** 114 /**
62 * Array of "total" peers. 115 * Array of "total" peers.
63 */ 116 */
64 struct GNUNET_TESTING_Daemon **peers; 117 struct PeerData *peers;
65 118
66 /** 119 /**
67 * Number of peers in this group. 120 * Number of peers in this group.
@@ -71,79 +124,212 @@ struct GNUNET_TESTING_PeerGroup
71}; 124};
72 125
73 126
127struct UpdateContext
128{
129 struct GNUNET_CONFIGURATION_Handle *ret;
130 unsigned int nport;
131};
132
74/** 133/**
75 * Start count gnunetd processes with the same set of transports and 134 * Function to iterate over options. Copies
76 * applications. The port numbers (any option called "PORT") will be 135 * the options to the target configuration,
77 * adjusted to ensure that no two peers running on the same system 136 * updating PORT values as needed.
78 * have the same port(s) in their respective configurations.
79 * 137 *
80 * @param sched scheduler to use 138 * @param cls closure
81 * @param cfg configuration template to use 139 * @param section name of the section
82 * @param total number of daemons to start 140 * @param option name of the option
83 * @param cb function to call on each daemon that was started 141 * @param value value of the option
84 * @param cb_cls closure for cb
85 * @param hostname where to run the peers; can be NULL (to run
86 * everything on localhost).
87 * @param va Additional hosts can be specified using a NULL-terminated list of
88 * varargs, hosts will then be used round-robin from that
89 * list; va only contains anything if hostname != NULL.
90 * @return NULL on error, otherwise handle to control peer group
91 */ 142 */
92struct GNUNET_TESTING_PeerGroup * 143static void
93GNUNET_TESTING_daemons_start_va (struct GNUNET_SCHEDULER_Handle *sched, 144update_config(void *cls,
94 const struct GNUNET_CONFIGURATION_Handle *cfg, 145 const char *section,
95 unsigned int total, 146 const char *option,
96 GNUNET_TESTING_NotifyDaemonRunning cb, 147 const char *value)
97 void *cb_cls,
98 const char *hostname,
99 va_list va)
100{ 148{
101 struct GNUNET_TESTING_PeerGroup *pg; 149 struct UpdateContext *ctx = cls;
102 150 unsigned int ival;
103 pg = GNUNET_malloc (sizeof(struct GNUNET_TESTING_PeerGroup)); 151 char cval[12];
104 return pg; 152
153 if ( (0 == strcmp (option, "PORT")) &&
154 (1 == sscanf (value, "%u", &ival)) )
155 {
156 GNUNET_snprintf (cval,
157 sizeof(cval),
158 "%u",
159 ctx->nport++);
160 value = cval;
161 }
162 GNUNET_CONFIGURATION_set_value_string (ctx->ret,
163 section,
164 option,
165 value);
105} 166}
106 167
107 168
108/** 169/**
109 * Start count gnunetd processes with the same set of 170 * Create a new configuration using the given configuration
110 * transports and applications. The port numbers will 171 * as a template; however, each PORT in the existing cfg
111 * be computed by adding delta each time (zero 172 * must be renumbered by incrementing "*port". If we run
112 * times for the first peer). 173 * out of "*port" numbers, return NULL.
174 *
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
179 */
180static struct GNUNET_CONFIGURATION_Handle*
181make_config (const struct GNUNET_CONFIGURATION_Handle*cfg,
182 uint16_t *port)
183{
184 struct UpdateContext uc;
185 uint16_t orig;
186
187 orig = *port;
188 uc.nport = *port;
189 uc.ret = GNUNET_CONFIGURATION_create ();
190 GNUNET_CONFIGURATION_iterate (cfg,
191 &update_config,
192 &uc);
193 if (uc.nport >= HIGH_PORT)
194 {
195 *port = orig;
196 GNUNET_CONFIGURATION_destroy (uc.ret);
197 return NULL;
198 }
199 *port = (uint16_t) uc.nport;
200 return uc.ret;
201}
202
203
204/**
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.
113 * 209 *
114 * @param sched scheduler to use 210 * @param sched scheduler to use
115 * @param cfg configuration template to use 211 * @param cfg configuration template to use
116 * @param total number of daemons to start 212 * @param total number of daemons to start
117 * @param timeout how long is this allowed to take?
118 * @param cb function to call on each daemon that was started 213 * @param cb function to call on each daemon that was started
119 * @param cb_cls closure for cb 214 * @param cb_cls closure for cb
120 * @param hostname where to run the peers; can be NULL (to run 215 * @param hostnames space-separated list of hostnames to use; can be NULL (to run
121 * everything on localhost). Additional 216 * everything on localhost).
122 * hosts can be specified using a NULL-terminated list of
123 * varargs, hosts will then be used round-robin from that
124 * list.
125 * @return NULL on error, otherwise handle to control peer group 217 * @return NULL on error, otherwise handle to control peer group
126 */ 218 */
127struct GNUNET_TESTING_PeerGroup * 219struct GNUNET_TESTING_PeerGroup *
128GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, 220GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
129 struct GNUNET_CONFIGURATION_Handle *cfg, 221 const struct GNUNET_CONFIGURATION_Handle *cfg,
130 unsigned int total, 222 unsigned int total,
131 GNUNET_TESTING_NotifyDaemonRunning cb, 223 GNUNET_TESTING_NotifyDaemonRunning cb,
132 void *cb_cls, 224 void *cb_cls,
133 const char *hostname, 225 const char *hostnames)
134 ...)
135{ 226{
136 struct GNUNET_TESTING_PeerGroup * ret; 227 struct GNUNET_TESTING_PeerGroup *pg;
137 va_list va; 228 const char *rpos;
138 229 char *pos;
139 va_start (va, hostname); 230 char *start;
140 ret = GNUNET_TESTING_daemons_start_va (sched, cfg, 231 const char *hostname;
141 total, cb, cb_cls, hostname, 232 struct GNUNET_CONFIGURATION_Handle *pcfg;
142 va); 233 unsigned int off;
143 va_end (va); 234 unsigned int hostcnt;
144 return ret; 235 uint16_t minport;
145}
146 236
237 if (0 == total)
238 {
239 GNUNET_break (0);
240 return NULL;
241 }
242 pg = GNUNET_malloc (sizeof(struct GNUNET_TESTING_PeerGroup));
243 pg->sched = sched;
244 pg->cfg = cfg;
245 pg->cb = cb;
246 pg->cb_cls = cb_cls;
247 pg->total = total;
248 pg->peers = GNUNET_malloc (total * sizeof(struct PeerData));
249 if (NULL != hostnames)
250 {
251 off = 2;
252 /* skip leading spaces */
253 while ( (0 != *hostnames) &&
254 (isspace(*hostnames)))
255 hostnames++;
256 rpos = hostnames;
257 while ('\0' != *rpos)
258 {
259 if (isspace (*rpos))
260 off++;
261 rpos++;
262 }
263 pg->hosts = GNUNET_malloc (off * sizeof (struct HostData));
264 off = 0;
265 start = GNUNET_strdup (hostnames);
266 pos = start;
267 while ('\0' != *pos)
268 {
269 if (isspace (*pos))
270 {
271 *pos = '\0';
272 if (strlen(start) > 0)
273 {
274 pg->hosts[off].minport = LOW_PORT;
275 pg->hosts[off++].hostname = start;
276 }
277 start = pos+1;
278 }
279 pos++;
280 }
281 if (strlen(start) > 0)
282 {
283 pg->hosts[off].minport = LOW_PORT;
284 pg->hosts[off++].hostname = start;
285 }
286 if (off == 0)
287 {
288 GNUNET_free (start);
289 GNUNET_free (pg->hosts);
290 pg->hosts = NULL;
291 }
292 hostcnt = off;
293 minport = 0; /* make gcc happy */
294 }
295 else
296 {
297 hostcnt = 0;
298 minport = LOW_PORT;
299 }
300 for (off = 0; off < total; off++)
301 {
302 if (hostcnt > 0)
303 {
304 hostname = pg->hosts[off % hostcnt].hostname;
305 pcfg = make_config (cfg, &pg->hosts[off % hostcnt].minport);
306 }
307 else
308 {
309 hostname = NULL;
310 pcfg = make_config (cfg, &minport);
311 }
312 if (NULL == pcfg)
313 {
314 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
315 _("Could not create configuration for peer number %u on `%s'!\n"),
316 off,
317 hostname == NULL ? "localhost" : hostname);
318 continue;
319 }
320 pg->peers[off].cfg = pcfg;
321 pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched,
322 pcfg,
323 hostname,
324 cb,
325 cb_cls);
326 if (NULL == pg->peers[off].daemon)
327 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
328 _("Could not start peer number %u!\n"),
329 off);
330 }
331 return pg;
332}
147 333
148 334
149/** 335/**
@@ -154,7 +340,26 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
154void 340void
155GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg) 341GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg)
156{ 342{
157 343 unsigned int off;
344
345 for (off = 0; off < pg->total; off++)
346 {
347 /* FIXME: should we wait for our
348 continuations to be called here? This
349 would require us to take a continuation
350 as well... */
351 if (NULL != pg->peers[off].daemon)
352 GNUNET_TESTING_daemon_stop (pg->peers[off].daemon,
353 NULL, NULL);
354 if (NULL != pg->peers[off].cfg)
355 GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg);
356 }
357 GNUNET_free (pg->peers);
358 if (NULL != pg->hosts)
359 {
360 GNUNET_free (pg->hosts[0].hostname);
361 GNUNET_free (pg->hosts);
362 }
158 GNUNET_free (pg); 363 GNUNET_free (pg);
159} 364}
160 365