2 This file is part of GNUnet
3 (C) 2008, 2009, 2012 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 3, 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.c
23 * @brief convenience API for writing testcases for GNUnet
24 * Many testcases need to start and stop a peer/service
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 (or internal use of the testbed).
29 * @author Christian Grothoff
33 #include "gnunet_util_lib.h"
34 #include "gnunet_arm_service.h"
35 #include "gnunet_testing_lib.h"
37 #define LOG(kind,...) \
38 GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
42 * We need pipe control only on WINDOWS
45 #define PIPE_CONTROL GNUNET_YES
47 #define PIPE_CONTROL GNUNET_NO
52 * Lowest port used for GNUnet testing. Should be high enough to not
53 * conflict with other applications running on the hosts but be low
54 * enough to not conflict with client-ports (typically starting around
57 #define LOW_PORT 12000
60 * Highest port used for GNUnet testing. Should be low enough to not
61 * conflict with the port range for "local" ports (client apps; see
62 * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
64 #define HIGH_PORT 56000
67 struct SharedServiceInstance
69 struct SharedService *ss;
73 struct GNUNET_OS_Process *proc;
86 struct SharedServiceInstance **instances;
88 struct GNUNET_CONFIGURATION_Handle *cfg;
94 unsigned int n_instances;
99 * Handle for a system on which GNUnet peers are executed;
100 * a system is used for reserving unique paths and ports.
102 struct GNUNET_TESTING_System
105 * Prefix (i.e. "/tmp/gnunet-testing/") we prepend to each
110 * The trusted ip. Can either be a single ip address or a network address in
121 * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes.
126 * memory map for 'hostkeys_data'.
128 struct GNUNET_DISK_MapHandle *map;
130 struct SharedService **shared_services;
132 unsigned int n_shared_services;
135 * Bitmap where each port that has already been reserved for some GNUnet peer
136 * is recorded. Note that we make no distinction between TCP and UDP ports
137 * and test if a port is already in use before assigning it to a peer/service.
138 * If we detect that a port is already in use, we also mark it in this bitmap.
139 * So all the bits that are zero merely indicate ports that MIGHT be available
142 uint32_t reserved_ports[65536 / 32];
145 * Counter we use to make service home paths unique on this system;
146 * the full path consists of the tmppath and this number. Each
147 * UNIXPATH for a peer is also modified to include the respective
148 * path counter to ensure uniqueness. This field is incremented
149 * by one for each configured peer. Even if peers are destroyed,
150 * we never re-use path counters.
152 uint32_t path_counter;
155 * The number of hostkeys
157 uint32_t total_hostkeys;
160 * Lowest port we are allowed to use.
165 * Highest port we are allowed to use.
172 * Handle for a GNUnet peer controlled by testing.
174 struct GNUNET_TESTING_Peer
177 * The TESTING system associated with this peer
179 struct GNUNET_TESTING_System *system;
182 * Path to the configuration file for this peer.
187 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
188 * Typically 'gnunet-service-arm' (but can be set to a
189 * specific service by 'GNUNET_TESTING_service_run' if
196 * Handle to the running binary of the service, NULL if the
197 * peer/service is currently not running.
199 struct GNUNET_OS_Process *main_process;
202 * The handle to the peer's ARM service
204 struct GNUNET_ARM_Handle *ah;
207 * Handle to ARM monitoring
209 struct GNUNET_ARM_MonitorHandle *mh;
212 * The config of the peer
214 struct GNUNET_CONFIGURATION_Handle *cfg;
217 * The callback to call asynchronously when a peer is stopped
219 GNUNET_TESTING_PeerStopCallback cb;
222 * The closure for the above callback
227 * The cached identity of this peer. Will be populated on call to
228 * GNUNET_TESTING_peer_get_identity()
230 struct GNUNET_PeerIdentity *id;
232 struct SharedServiceInstance **ss_instances;
235 * Array of ports currently allocated to this peer. These ports will be
236 * released upon peer destroy and can be used by other peers which are
242 * The number of ports in the above array
247 * The keynumber of this peer's hostkey
254 * Testing includes a number of pre-created hostkeys for faster peer
255 * startup. This function loads such keys into memory from a file.
257 * @param system the testing system handle
258 * @return GNUNET_OK on success; GNUNET_SYSERR on error
261 hostkeys_load (struct GNUNET_TESTING_System *system)
266 struct GNUNET_DISK_FileHandle *fd;
268 GNUNET_assert (NULL == system->hostkeys_data);
269 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
270 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
271 GNUNET_free (data_dir);
273 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
275 LOG (GNUNET_ERROR_TYPE_ERROR,
276 _("Hostkeys file not found: %s\n"), filename);
277 GNUNET_free (filename);
278 return GNUNET_SYSERR;
280 /* Check hostkey file size, read entire thing into memory */
282 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
286 GNUNET_free (filename);
287 return GNUNET_SYSERR; /* File is empty */
289 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
291 LOG (GNUNET_ERROR_TYPE_ERROR,
292 _("Incorrect hostkey file format: %s\n"), filename);
293 GNUNET_free (filename);
294 return GNUNET_SYSERR;
296 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
297 GNUNET_DISK_PERM_NONE);
300 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
301 GNUNET_free (filename);
302 return GNUNET_SYSERR;
304 GNUNET_free (filename);
305 system->hostkeys_data = GNUNET_DISK_file_map (fd,
307 GNUNET_DISK_MAP_TYPE_READ,
309 GNUNET_DISK_file_close (fd);
310 if (NULL == system->hostkeys_data)
311 return GNUNET_SYSERR;
312 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
318 * Function to remove the loaded hostkeys
320 * @param system the testing system handle
323 hostkeys_unload (struct GNUNET_TESTING_System *system)
325 GNUNET_break (NULL != system->hostkeys_data);
326 system->hostkeys_data = NULL;
327 GNUNET_DISK_file_unmap (system->map);
329 system->hostkeys_data = NULL;
330 system->total_hostkeys = 0;
335 * Function to iterate over options.
338 * @param section name of the section
339 * @param option name of the option
340 * @param value value of the option
343 cfg_copy_iterator (void *cls, const char *section,
344 const char *option, const char *value)
346 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
348 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
353 * Create a system handle. There must only be one system
354 * handle per operating system.
356 * @param testdir only the directory name without any path. This is used for
357 * all service homes; the directory will be created in a temporary
358 * location depending on the underlying OS
359 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
360 * service configurations generated to allow control connections from
361 * this ip. This can either be a single ip address or a network address
363 * @param hostname the hostname of the system we are using for testing; NULL for
365 * @param shared_services NULL terminated array describing services that are to
366 * be shared among peers
367 * @param lowport lowest port number this system is allowed to allocate (inclusive)
368 * @param highport highest port number this system is allowed to allocate (exclusive)
369 * @return handle to this system, NULL on error
371 struct GNUNET_TESTING_System *
372 GNUNET_TESTING_system_create_with_portrange (const char *testdir,
373 const char *trusted_ip,
374 const char *hostname,
376 GNUNET_TESTING_SharedService *
381 struct GNUNET_TESTING_System *system;
382 struct GNUNET_TESTING_SharedService tss;
383 struct SharedService *ss;
386 GNUNET_assert (NULL != testdir);
387 system = GNUNET_malloc (sizeof (struct GNUNET_TESTING_System));
388 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
389 system->lowport = lowport;
390 system->highport = highport;
391 if (NULL == system->tmppath)
393 GNUNET_free (system);
396 if (NULL != trusted_ip)
397 system->trusted_ip = GNUNET_strdup (trusted_ip);
398 if (NULL != hostname)
399 system->hostname = GNUNET_strdup (hostname);
400 if (GNUNET_OK != hostkeys_load (system))
402 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
405 if (NULL == shared_services)
407 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
409 tss = shared_services[cnt];
410 ss = GNUNET_malloc (sizeof (struct SharedService));
411 ss->sname = GNUNET_strdup (tss.service);
412 ss->cfg = GNUNET_CONFIGURATION_create ();
413 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, ss->sname,
414 &cfg_copy_iterator, ss->cfg);
415 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "TESTING",
416 &cfg_copy_iterator, ss->cfg);
417 ss->share = tss.share;
418 GNUNET_array_append (system->shared_services, system->n_shared_services,
426 * Create a system handle. There must only be one system handle per operating
427 * system. Uses a default range for allowed ports. Ports are still tested for
430 * @param testdir only the directory name without any path. This is used for all
431 * service homes; the directory will be created in a temporary location
432 * depending on the underlying OS
433 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
434 * service configurations generated to allow control connections from
435 * this ip. This can either be a single ip address or a network address
437 * @param hostname the hostname of the system we are using for testing; NULL for
439 * @param shared_services NULL terminated array describing services that are to
440 * be shared among peers
441 * @return handle to this system, NULL on error
443 struct GNUNET_TESTING_System *
444 GNUNET_TESTING_system_create (const char *testdir,
445 const char *trusted_ip,
446 const char *hostname,
447 const struct GNUNET_TESTING_SharedService *
450 return GNUNET_TESTING_system_create_with_portrange (testdir,
459 cleanup_shared_service_instance (struct SharedServiceInstance *i)
461 if (NULL != i->cfg_fn)
463 (void) unlink (i->cfg_fn);
464 GNUNET_free (i->cfg_fn);
466 GNUNET_free_non_null (i->unix_sock);
467 GNUNET_free_non_null (i->port_str);
468 GNUNET_break (NULL == i->proc);
469 GNUNET_break (0 == i->n_refs);
474 start_shared_service_instance (struct SharedServiceInstance *i)
477 char *libexec_binary;
479 GNUNET_assert (NULL == i->proc);
480 GNUNET_assert (NULL != i->cfg_fn);
481 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
482 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
483 GNUNET_free (binary);
484 i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
485 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
492 GNUNET_free (libexec_binary);
494 return GNUNET_SYSERR;
500 stop_shared_service_instance (struct SharedServiceInstance *i)
502 GNUNET_break (0 == i->n_refs);
503 if (0 != GNUNET_OS_process_kill (i->proc, SIGTERM))
504 LOG (GNUNET_ERROR_TYPE_WARNING,
505 "Killing shared service instance (%s) failed\n", i->ss->sname);
506 (void) GNUNET_OS_process_wait (i->proc);
507 GNUNET_OS_process_destroy (i->proc);
513 * Free system resources.
515 * @param system system to be freed
516 * @param remove_paths should the 'testdir' and all subdirectories
517 * be removed (clean up on shutdown)?
520 GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
523 struct SharedService *ss;
524 struct SharedServiceInstance *i;
528 if (NULL != system->hostkeys_data)
529 hostkeys_unload (system);
530 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
532 ss = system->shared_services[ss_cnt];
533 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
535 i = ss->instances[i_cnt];
537 stop_shared_service_instance (i);
538 cleanup_shared_service_instance (i);
540 GNUNET_free_non_null (ss->instances);
541 GNUNET_CONFIGURATION_destroy (ss->cfg);
542 GNUNET_free (ss->sname);
545 GNUNET_free_non_null (system->shared_services);
546 if (GNUNET_YES == remove_paths)
547 GNUNET_DISK_directory_remove (system->tmppath);
548 GNUNET_free (system->tmppath);
549 GNUNET_free_non_null (system->trusted_ip);
550 GNUNET_free_non_null (system->hostname);
551 GNUNET_free (system);
556 * Reserve a TCP or UDP port for a peer.
558 * @param system system to use for reservation tracking
559 * @return 0 if no free port was available
562 GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
564 struct GNUNET_NETWORK_Handle *socket;
565 struct addrinfo hint;
566 struct addrinfo *ret;
568 uint32_t *port_buckets;
577 FIXME: Instead of using getaddrinfo we should try to determine the port
578 status by the following heurestics.
580 On systems which support both IPv4 and IPv6, only ports open on both
581 address families are considered open.
582 On system with either IPv4 or IPv6. A port is considered open if it's
583 open in the respective address family
585 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
586 hint.ai_socktype = 0;
587 hint.ai_protocol = 0;
590 hint.ai_canonname = NULL;
592 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
593 port_buckets = system->reserved_ports;
594 for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++)
596 xor_image = (UINT32_MAX ^ port_buckets[index]);
597 if (0 == xor_image) /* Ports in the bucket are full */
599 pos = system->lowport % 32;
602 if (0 == ((xor_image >> pos) & 1U))
607 open_port = (index * 32) + pos;
608 if (open_port >= system->highport)
610 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
612 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
613 GNUNET_free (open_port_str);
614 bind_status = GNUNET_NO;
615 for (ai = ret; NULL != ai; ai = ai->ai_next)
617 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
620 bind_status = GNUNET_NETWORK_socket_bind (socket,
624 GNUNET_NETWORK_socket_close (socket);
625 if (GNUNET_OK != bind_status)
627 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0);
630 bind_status = GNUNET_NETWORK_socket_bind (socket,
634 GNUNET_NETWORK_socket_close (socket);
635 if (GNUNET_OK != bind_status)
638 port_buckets[index] |= (1U << pos); /* Set the port bit */
640 if (GNUNET_OK == bind_status)
642 LOG (GNUNET_ERROR_TYPE_DEBUG,
643 "Found a free port %u\n", (unsigned int) open_port);
654 * Release reservation of a TCP or UDP port for a peer
655 * (used during GNUNET_TESTING_peer_destroy).
657 * @param system system to use for reservation tracking
658 * @param port reserved port to release
661 GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
664 uint32_t *port_buckets;
668 port_buckets = system->reserved_ports;
671 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
672 if (0 == (port_buckets[bucket] & (1U << pos)))
674 GNUNET_break(0); /* Port was not reserved by us using reserve_port() */
677 port_buckets[bucket] &= ~(1U << pos);
682 * Testing includes a number of pre-created hostkeys for
683 * faster peer startup. This function can be used to
684 * access the n-th key of those pre-created hostkeys; note
685 * that these keys are ONLY useful for testing and not
686 * secure as the private keys are part of the public
687 * GNUnet source code.
689 * This is primarily a helper function used internally
690 * by #GNUNET_TESTING_peer_configure.
692 * @param system the testing system handle
693 * @param key_number desired pre-created hostkey to obtain
694 * @param id set to the peer's identity (hash of the public
695 * key; if NULL, GNUNET_SYSERR is returned immediately
696 * @return NULL on error (not enough keys)
698 struct GNUNET_CRYPTO_EccPrivateKey *
699 GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
701 struct GNUNET_PeerIdentity *id)
703 struct GNUNET_CRYPTO_EccPrivateKey *private_key;
705 if ((NULL == id) || (NULL == system->hostkeys_data))
707 if (key_number >= system->total_hostkeys)
709 LOG (GNUNET_ERROR_TYPE_ERROR,
710 _("Key number %u does not exist\n"), key_number);
713 private_key = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey);
715 system->hostkeys_data +
716 (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
717 GNUNET_TESTING_HOSTKEYFILESIZE);
718 GNUNET_CRYPTO_ecc_key_get_public_for_signature (private_key,
725 * Structure for holding data to build new configurations from a configuration
731 * The system for which we are building configurations
733 struct GNUNET_TESTING_System *system;
736 * The configuration we are building
738 struct GNUNET_CONFIGURATION_Handle *cfg;
741 * The customized service home path for this peer
746 * Array of ports currently allocated to this peer. These ports will be
747 * released upon peer destroy and can be used by other peers which are
753 * The number of ports in the above array
758 * build status - to signal error while building a configuration
765 * Function to iterate over options. Copies
766 * the options to the target configuration,
767 * updating PORT values as needed.
769 * @param cls the UpdateContext
770 * @param section name of the section
771 * @param option name of the option
772 * @param value value of the option
775 update_config (void *cls, const char *section, const char *option,
778 struct UpdateContext *uc = cls;
782 char *single_variable;
783 char *per_host_variable;
784 unsigned long long num_per_host;
787 if (GNUNET_OK != uc->status)
789 if (! ((0 == strcmp (option, "PORT"))
790 || (0 == strcmp (option, "UNIXPATH"))
791 || (0 == strcmp (option, "HOSTNAME"))))
793 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
794 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
795 if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
799 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
802 new_port = GNUNET_TESTING_reserve_port (uc->system);
805 uc->status = GNUNET_SYSERR;
806 GNUNET_free (single_variable);
807 GNUNET_free (per_host_variable);
810 GNUNET_snprintf (cval, sizeof (cval), "%u", new_port);
812 GNUNET_array_append (uc->ports, uc->nports, new_port);
814 else if ((ival != 0) &&
816 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
818 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
822 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
823 /* ival + ctx->fdnum % num_per_host); */
825 GNUNET_break (0); /* FIXME */
828 if (0 == strcmp (option, "UNIXPATH"))
831 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
834 GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock",
835 uc->service_home, section);
838 else if ((GNUNET_YES ==
839 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
844 GNUNET_break(0); /* FIXME */
847 if (0 == strcmp (option, "HOSTNAME"))
849 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
851 GNUNET_free (single_variable);
852 GNUNET_free (per_host_variable);
853 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
858 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
859 * 'trusted_hosts' in all sections
861 * @param cls the UpdateContext
862 * @param section name of the section
865 update_config_sections (void *cls,
868 struct UpdateContext *uc = cls;
872 char *orig_allowed_hosts;
874 char *ACCEPT_FROM_key;
880 /* Ignore certain options from sections. See
881 https://gnunet.org/bugs/view.php?id=2476 */
882 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
883 "TESTING_IGNORE_KEYS"))
887 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section,
888 "TESTING_IGNORE_KEYS", &val));
890 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
896 ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt);
898 for (key = 0; key < ikeys_cnt; key++)
901 ptr = strstr (ptr, ";");
909 for (key = 0; key < ikeys_cnt; key++)
911 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
914 if ((key == ikeys_cnt) &&
915 (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
919 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr))
921 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section,
922 "ADVERTISED_PORT", ptr);
926 for (key = 0; key < ikeys_cnt; key++)
928 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
937 GNUNET_free_non_null (val);
938 ACCEPT_FROM_key = "ACCEPT_FROM";
939 if ((NULL != uc->system->trusted_ip) &&
940 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
941 ACCEPT_FROM_key = "ACCEPT_FROM6";
943 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key,
944 &orig_allowed_hosts))
946 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
948 if (NULL == uc->system->trusted_ip)
949 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
951 GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts,
952 uc->system->trusted_ip);
953 GNUNET_free (orig_allowed_hosts);
954 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key,
956 GNUNET_free (allowed_hosts);
959 static struct SharedServiceInstance *
960 associate_shared_service (struct GNUNET_TESTING_System *system,
961 struct SharedService *ss,
962 struct GNUNET_CONFIGURATION_Handle *cfg)
964 struct SharedServiceInstance *i;
965 struct GNUNET_CONFIGURATION_Handle *temp;
970 if ( ((0 == ss->share) && (NULL == ss->instances))
973 && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) )
975 i = GNUNET_malloc (sizeof (struct SharedServiceInstance));
977 (void) GNUNET_asprintf (&service_home, "%s/shared/%s/%u",
978 system->tmppath, ss->sname, ss->n_instances);
979 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", service_home);
980 port = GNUNET_TESTING_reserve_port (system);
983 GNUNET_free (service_home);
984 cleanup_shared_service_instance (i);
987 GNUNET_array_append (ss->instances, ss->n_instances, i);
988 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
989 (void) GNUNET_asprintf (&i->port_str, "%u", port);
990 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", service_home);
991 GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "SERVICEHOME",
993 GNUNET_free (service_home);
994 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH",
996 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT",
998 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1000 GNUNET_CONFIGURATION_destroy (temp);
1001 cleanup_shared_service_instance (i);
1004 GNUNET_CONFIGURATION_destroy (temp);
1008 GNUNET_assert (NULL != ss->instances);
1009 GNUNET_assert (0 < ss->n_instances);
1010 i = ss->instances[ss->n_instances - 1];
1012 GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname,
1013 &cfg_copy_iterator, cfg);
1014 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH",
1016 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1022 * Create a new configuration using the given configuration as a template;
1023 * ports and paths will be modified to select available ports on the local
1024 * system. The default configuration will be available in PATHS section under
1025 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1026 * section to the temporary directory specific to this configuration. If we run
1027 * out of "*port" numbers, return SYSERR.
1029 * This is primarily a helper function used internally
1030 * by 'GNUNET_TESTING_peer_configure'.
1032 * @param system system to use to coordinate resource usage
1033 * @param cfg template configuration to update
1034 * @param ports array with port numbers used in the created configuration.
1035 * Will be updated upon successful return. Can be NULL
1036 * @param nports the size of the `ports' array. Will be updated.
1037 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1038 * be incomplete and should not be used there upon
1041 GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1042 struct GNUNET_CONFIGURATION_Handle *cfg,
1044 unsigned int *nports)
1046 struct UpdateContext uc;
1047 char *default_config;
1051 uc.status = GNUNET_OK;
1054 GNUNET_asprintf (&uc.service_home, "%s/%u", system->tmppath,
1055 system->path_counter++);
1056 GNUNET_asprintf (&default_config, "%s/config", uc.service_home);
1057 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
1059 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
1061 GNUNET_free (default_config);
1062 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "SERVICEHOME",
1064 /* make PORTs and UNIXPATHs unique */
1065 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1066 /* allow connections to services from system trusted_ip host */
1067 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1068 /* enable loopback-based connections between peers */
1069 GNUNET_CONFIGURATION_set_value_string (cfg,
1071 "USE_LOCALADDR", "YES");
1072 GNUNET_free (uc.service_home);
1073 if ((NULL != ports) && (NULL != nports))
1076 *nports = uc.nports;
1079 GNUNET_free_non_null (uc.ports);
1085 * Create a new configuration using the given configuration as a template;
1086 * ports and paths will be modified to select available ports on the local
1087 * system. The default configuration will be available in PATHS section under
1088 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1089 * section to the temporary directory specific to this configuration. If we run
1090 * out of "*port" numbers, return SYSERR.
1092 * This is primarily a helper function used internally
1093 * by 'GNUNET_TESTING_peer_configure'.
1095 * @param system system to use to coordinate resource usage
1096 * @param cfg template configuration to update
1097 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1098 * be incomplete and should not be used there upon
1101 GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1102 struct GNUNET_CONFIGURATION_Handle *cfg)
1104 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1109 * Configure a GNUnet peer. GNUnet must be installed on the local
1110 * system and available in the PATH.
1112 * @param system system to use to coordinate resource usage
1113 * @param cfg configuration to use; will be UPDATED (to reflect needed
1114 * changes in port numbers and paths)
1115 * @param key_number number of the hostkey to use for the peer
1116 * @param id identifier for the daemon, will be set, can be NULL
1117 * @param emsg set to freshly allocated error message (set to NULL on success),
1119 * @return handle to the peer, NULL on error
1121 struct GNUNET_TESTING_Peer *
1122 GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1123 struct GNUNET_CONFIGURATION_Handle *cfg,
1124 uint32_t key_number,
1125 struct GNUNET_PeerIdentity *id,
1128 struct GNUNET_TESTING_Peer *peer;
1129 struct GNUNET_DISK_FileHandle *fd;
1130 char *hostkey_filename;
1131 char *config_filename;
1132 char *libexec_binary;
1134 struct GNUNET_CRYPTO_EccPrivateKey *pk;
1136 struct SharedService *ss;
1137 struct SharedServiceInstance **ss_instances;
1139 unsigned int nports;
1143 ss_instances = NULL;
1146 if (key_number >= system->total_hostkeys)
1148 GNUNET_asprintf (&emsg_,
1149 _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1150 (unsigned int) system->total_hostkeys);
1155 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1157 GNUNET_asprintf (&emsg_,
1158 _("Failed to initialize hostkey for peer %u\n"),
1159 (unsigned int) key_number);
1165 GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1167 GNUNET_asprintf (&emsg_,
1168 _("PRIVATE_KEY option in PEER section missing in configuration\n"));
1171 /* Remove sections for shared services */
1172 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1174 ss = system->shared_services[cnt];
1175 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1177 if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg,
1180 GNUNET_asprintf (&emsg_,
1181 _("Failed to create configuration for peer "
1182 "(not enough free ports?)\n"));
1185 GNUNET_assert (GNUNET_OK ==
1186 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER",
1188 &hostkey_filename));
1189 fd = GNUNET_DISK_file_open (hostkey_filename,
1190 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1191 GNUNET_DISK_PERM_USER_READ
1192 | GNUNET_DISK_PERM_USER_WRITE);
1195 GNUNET_asprintf (&emsg_, _("Cannot open hostkey file `%s': %s\n"),
1196 hostkey_filename, STRERROR (errno));
1197 GNUNET_free (hostkey_filename);
1200 GNUNET_free (hostkey_filename);
1201 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1202 GNUNET_DISK_file_write (fd, system->hostkeys_data
1203 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1204 GNUNET_TESTING_HOSTKEYFILESIZE))
1206 GNUNET_asprintf (&emsg_,
1207 _("Failed to write hostkey file for peer %u: %s\n"),
1208 (unsigned int) key_number,
1210 GNUNET_DISK_file_close (fd);
1213 GNUNET_DISK_file_close (fd);
1214 ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *)
1215 * system->n_shared_services);
1216 for (cnt=0; cnt < system->n_shared_services; cnt++)
1218 ss = system->shared_services[cnt];
1219 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1220 if (NULL == ss_instances[cnt])
1223 GNUNET_assert (GNUNET_OK ==
1224 GNUNET_CONFIGURATION_get_value_string
1225 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1226 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1228 GNUNET_asprintf (&emsg_,
1229 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1231 (unsigned int) key_number,
1233 GNUNET_free (config_filename);
1236 peer = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Peer));
1237 peer->ss_instances = ss_instances;
1238 peer->cfgfile = config_filename; /* Free in peer_destroy */
1239 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1240 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1241 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1244 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1245 peer->args = strdup ("");
1248 peer->args = strdup (libexec_binary);
1249 peer->system = system;
1250 peer->key_number = key_number;
1251 GNUNET_free (libexec_binary);
1252 peer->ports = ports; /* Free in peer_destroy */
1253 peer->nports = nports;
1257 GNUNET_free_non_null (ss_instances);
1258 GNUNET_free_non_null (ports);
1259 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1263 GNUNET_free (emsg_);
1269 * Obtain the peer identity from a peer handle.
1271 * @param peer peer handle for which we want the peer's identity
1272 * @param id identifier for the daemon, will be set
1275 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1276 struct GNUNET_PeerIdentity *id)
1278 if (NULL != peer->id)
1280 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1283 peer->id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1284 GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system,
1287 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1294 * @param peer peer to start
1295 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1298 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1300 struct SharedServiceInstance *i;
1303 if (NULL != peer->main_process)
1306 return GNUNET_SYSERR;
1308 GNUNET_assert (NULL != peer->cfgfile);
1309 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1311 i = peer->ss_instances[cnt];
1312 if ((0 == i->n_refs)
1313 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1314 return GNUNET_SYSERR;
1317 peer->main_process = GNUNET_OS_start_process (PIPE_CONTROL,
1318 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1326 if (NULL == peer->main_process)
1328 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1329 _("Failed to start `%s': %s\n"),
1332 return GNUNET_SYSERR;
1339 * Start a service at a peer using its ARM service
1341 * @param peer the peer whose service has to be started
1342 * @param service_name name of the service to start
1343 * @param timeout how long should the ARM API try to send the request to start
1345 * @param cont the callback to call with result and status from ARM API
1346 * @param cont_cls the closure for the above callback
1347 * @return GNUNET_OK upon successfully queuing the service start request;
1348 * GNUNET_SYSERR upon error
1351 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1352 const char *service_name,
1353 struct GNUNET_TIME_Relative timeout,
1354 GNUNET_ARM_ResultCallback cont,
1357 if (NULL == peer->ah)
1358 return GNUNET_SYSERR;
1359 GNUNET_ARM_request_service_start (peer->ah,
1361 GNUNET_OS_INHERIT_STD_ALL,
1369 * Stop a service at a peer using its ARM service
1371 * @param peer the peer whose service has to be stopped
1372 * @param service_name name of the service to stop
1373 * @param timeout how long should the ARM API try to send the request to stop
1375 * @param cont the callback to call with result and status from ARM API
1376 * @param cont_cls the closure for the above callback
1377 * @return GNUNET_OK upon successfully queuing the service stop request;
1378 * GNUNET_SYSERR upon error
1381 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1382 const char *service_name,
1383 struct GNUNET_TIME_Relative timeout,
1384 GNUNET_ARM_ResultCallback cont,
1387 if (NULL == peer->ah)
1388 return GNUNET_SYSERR;
1389 GNUNET_ARM_request_service_stop (peer->ah,
1398 * Sends SIGTERM to the peer's main process
1400 * @param peer the handle to the peer
1401 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1402 * or upon any error while sending SIGTERM
1405 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1407 struct SharedServiceInstance *i;
1410 if (NULL == peer->main_process)
1413 return GNUNET_SYSERR;
1415 if (0 != GNUNET_OS_process_kill (peer->main_process, SIGTERM))
1416 return GNUNET_SYSERR;
1417 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1419 i = peer->ss_instances[cnt];
1420 GNUNET_assert (0 != i->n_refs);
1423 stop_shared_service_instance (i);
1430 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1432 * @param peer the handle to the peer
1433 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1434 * or upon any error while waiting
1437 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1441 if (NULL == peer->main_process)
1444 return GNUNET_SYSERR;
1446 ret = GNUNET_OS_process_wait (peer->main_process);
1447 GNUNET_OS_process_destroy (peer->main_process);
1448 peer->main_process = NULL;
1456 * @param peer peer to stop
1457 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1460 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1462 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1463 return GNUNET_SYSERR;
1464 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1465 return GNUNET_SYSERR;
1471 * Function called whenever we connect to or disconnect from ARM.
1473 * @param cls closure
1474 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1475 * GNUNET_SYSERR on error.
1478 disconn_status (void *cls,
1481 struct GNUNET_TESTING_Peer *peer = cls;
1483 if (GNUNET_SYSERR == connected)
1485 peer->cb (peer->cb_cls, peer, connected);
1488 if (GNUNET_YES == connected)
1490 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1493 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1494 GNUNET_ARM_disconnect_and_free (peer->ah);
1496 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1501 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1502 * through the GNUNET_TESTING_PeerStopCallback().
1504 * @param peer the peer to stop
1505 * @param cb the callback to signal peer shutdown
1506 * @param cb_cls closure for the above callback
1507 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1508 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1512 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1513 GNUNET_TESTING_PeerStopCallback cb,
1516 if (NULL == peer->main_process)
1517 return GNUNET_SYSERR;
1518 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1519 if (NULL == peer->ah)
1520 return GNUNET_SYSERR;
1522 peer->cb_cls = cb_cls;
1528 * Cancel a previous asynchronous peer stop request.
1529 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1530 * peer. It is an error to call this function if the peer stop callback was
1533 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1537 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1539 GNUNET_assert (NULL != peer->ah);
1540 GNUNET_ARM_disconnect_and_free (peer->ah);
1546 * Destroy the peer. Releases resources locked during peer configuration.
1547 * If the peer is still running, it will be stopped AND a warning will be
1548 * printed (users of the API should stop the peer explicitly first).
1550 * @param peer peer to destroy
1553 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1557 if (NULL != peer->main_process)
1558 GNUNET_TESTING_peer_stop (peer);
1559 if (NULL != peer->ah)
1560 GNUNET_ARM_disconnect_and_free (peer->ah);
1561 if (NULL != peer->mh)
1562 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1563 GNUNET_free (peer->cfgfile);
1564 if (NULL != peer->cfg)
1565 GNUNET_CONFIGURATION_destroy (peer->cfg);
1566 GNUNET_free (peer->main_binary);
1567 GNUNET_free (peer->args);
1568 GNUNET_free_non_null (peer->id);
1569 GNUNET_free_non_null (peer->ss_instances);
1570 if (NULL != peer->ports)
1572 for (cnt = 0; cnt < peer->nports; cnt++)
1573 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1574 GNUNET_free (peer->ports);
1581 * Start a single peer and run a test using the testing library.
1582 * Starts a peer using the given configuration and then invokes the
1583 * given callback. This function ALSO initializes the scheduler loop
1584 * and should thus be called directly from "main". The testcase
1585 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1587 * @param testdir only the directory name without any path. This is used for
1588 * all service homes; the directory will be created in a temporary
1589 * location depending on the underlying OS
1590 * @param cfgfilename name of the configuration file to use;
1591 * use NULL to only run with defaults
1592 * @param tm main function of the testcase
1593 * @param tm_cls closure for 'tm'
1594 * @return 0 on success, 1 on error
1597 GNUNET_TESTING_peer_run (const char *testdir,
1598 const char *cfgfilename,
1599 GNUNET_TESTING_TestMain tm,
1602 return GNUNET_TESTING_service_run (testdir, "arm",
1603 cfgfilename, tm, tm_cls);
1608 * Structure for holding service data
1610 struct ServiceContext
1613 * The configuration of the peer in which the service is run
1615 const struct GNUNET_CONFIGURATION_Handle *cfg;
1618 * Callback to signal service startup
1620 GNUNET_TESTING_TestMain tm;
1623 * The peer in which the service is run.
1625 struct GNUNET_TESTING_Peer *peer;
1628 * Closure for the above callback
1635 * Callback to be called when SCHEDULER has been started
1637 * @param cls the ServiceContext
1638 * @param tc the TaskContext
1641 service_run_main (void *cls,
1642 const struct GNUNET_SCHEDULER_TaskContext *tc)
1644 struct ServiceContext *sc = cls;
1646 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1651 * Start a single service (no ARM, except of course if the given
1652 * service name is 'arm') and run a test using the testing library.
1653 * Starts a service using the given configuration and then invokes the
1654 * given callback. This function ALSO initializes the scheduler loop
1655 * and should thus be called directly from "main". The testcase
1656 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1658 * This function is useful if the testcase is for a single service
1659 * and if that service doesn't itself depend on other services.
1661 * @param testdir only the directory name without any path. This is used for
1662 * all service homes; the directory will be created in a temporary
1663 * location depending on the underlying OS
1664 * @param service_name name of the service to run
1665 * @param cfgfilename name of the configuration file to use;
1666 * use NULL to only run with defaults
1667 * @param tm main function of the testcase
1668 * @param tm_cls closure for 'tm'
1669 * @return 0 on success, 1 on error
1672 GNUNET_TESTING_service_run (const char *testdir,
1673 const char *service_name,
1674 const char *cfgfilename,
1675 GNUNET_TESTING_TestMain tm,
1678 struct ServiceContext sc;
1679 struct GNUNET_TESTING_System *system;
1680 struct GNUNET_TESTING_Peer *peer;
1681 struct GNUNET_CONFIGURATION_Handle *cfg;
1683 char *libexec_binary;
1685 GNUNET_log_setup (testdir, "WARNING", NULL);
1686 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1689 cfg = GNUNET_CONFIGURATION_create ();
1690 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1692 LOG (GNUNET_ERROR_TYPE_ERROR,
1693 _("Failed to load configuration from %s\n"), cfgfilename);
1694 GNUNET_CONFIGURATION_destroy (cfg);
1695 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1698 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1701 GNUNET_CONFIGURATION_destroy (cfg);
1702 hostkeys_unload (system);
1703 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1706 GNUNET_free (peer->main_binary);
1707 GNUNET_free (peer->args);
1708 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1709 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1710 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1713 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1714 peer->args = strdup ("");
1717 peer->args = strdup (libexec_binary);
1719 GNUNET_free (libexec_binary);
1720 GNUNET_free (binary);
1721 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1723 GNUNET_TESTING_peer_destroy (peer);
1724 GNUNET_CONFIGURATION_destroy (cfg);
1725 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1732 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1733 if ((NULL != peer->main_process) &&
1734 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1736 GNUNET_TESTING_peer_destroy (peer);
1737 GNUNET_CONFIGURATION_destroy (cfg);
1738 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1741 GNUNET_TESTING_peer_destroy (peer);
1742 GNUNET_CONFIGURATION_destroy (cfg);
1743 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1749 * Sometimes we use the binary name to determine which specific
1750 * test to run. In those cases, the string after the last "_"
1751 * in 'argv[0]' specifies a string that determines the configuration
1752 * file or plugin to use.
1754 * This function returns the respective substring, taking care
1755 * of issues such as binaries ending in '.exe' on W32.
1757 * @param argv0 the name of the binary
1758 * @return string between the last '_' and the '.exe' (or the end of the string),
1759 * NULL if argv0 has no '_'
1762 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1764 size_t slen = strlen (argv0) + 1;
1769 memcpy (sbuf, argv0, slen);
1770 ret = strrchr (sbuf, '_');
1773 ret++; /* skip underscore */
1774 dot = strchr (ret, '.');
1777 return GNUNET_strdup (ret);
1781 /* end of testing.c */