2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, 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
111 * The trusted ip. Can either be a single ip address or a network address in
122 * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes.
127 * memory map for @e hostkeys_data.
129 struct GNUNET_DISK_MapHandle *map;
131 struct SharedService **shared_services;
133 unsigned int n_shared_services;
136 * Bitmap where each port that has already been reserved for some GNUnet peer
137 * is recorded. Note that we make no distinction between TCP and UDP ports
138 * and test if a port is already in use before assigning it to a peer/service.
139 * If we detect that a port is already in use, we also mark it in this bitmap.
140 * So all the bits that are zero merely indicate ports that MIGHT be available
143 uint32_t reserved_ports[65536 / 32];
146 * Counter we use to make service home paths unique on this system;
147 * the full path consists of the tmppath and this number. Each
148 * UNIXPATH for a peer is also modified to include the respective
149 * path counter to ensure uniqueness. This field is incremented
150 * by one for each configured peer. Even if peers are destroyed,
151 * we never re-use path counters.
153 uint32_t path_counter;
156 * The number of hostkeys
158 uint32_t total_hostkeys;
161 * Lowest port we are allowed to use.
166 * Highest port we are allowed to use.
173 * Handle for a GNUnet peer controlled by testing.
175 struct GNUNET_TESTING_Peer
178 * The TESTING system associated with this peer
180 struct GNUNET_TESTING_System *system;
183 * Path to the configuration file for this peer.
188 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
189 * Typically 'gnunet-service-arm' (but can be set to a
190 * specific service by 'GNUNET_TESTING_service_run' if
197 * Handle to the running binary of the service, NULL if the
198 * peer/service is currently not running.
200 struct GNUNET_OS_Process *main_process;
203 * The handle to the peer's ARM service
205 struct GNUNET_ARM_Handle *ah;
208 * Handle to ARM monitoring
210 struct GNUNET_ARM_MonitorHandle *mh;
213 * The config of the peer
215 struct GNUNET_CONFIGURATION_Handle *cfg;
218 * The callback to call asynchronously when a peer is stopped
220 GNUNET_TESTING_PeerStopCallback cb;
223 * The closure for the above callback
228 * The cached identity of this peer. Will be populated on call to
229 * GNUNET_TESTING_peer_get_identity()
231 struct GNUNET_PeerIdentity *id;
233 struct SharedServiceInstance **ss_instances;
236 * Array of ports currently allocated to this peer. These ports will be
237 * released upon peer destroy and can be used by other peers which are
243 * The number of ports in the above array
248 * The keynumber of this peer's hostkey
255 * Testing includes a number of pre-created hostkeys for faster peer
256 * startup. This function loads such keys into memory from a file.
258 * @param system the testing system handle
259 * @return #GNUNET_OK on success; #GNUNET_SYSERR on error
262 hostkeys_load (struct GNUNET_TESTING_System *system)
267 struct GNUNET_DISK_FileHandle *fd;
269 GNUNET_assert (NULL == system->hostkeys_data);
270 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
271 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
272 GNUNET_free (data_dir);
274 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
276 LOG (GNUNET_ERROR_TYPE_ERROR,
277 _("Hostkeys file not found: %s\n"), filename);
278 GNUNET_free (filename);
279 return GNUNET_SYSERR;
281 /* Check hostkey file size, read entire thing into memory */
283 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
287 GNUNET_free (filename);
288 return GNUNET_SYSERR; /* File is empty */
290 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
292 LOG (GNUNET_ERROR_TYPE_ERROR,
293 _("Incorrect hostkey file format: %s\n"), filename);
294 GNUNET_free (filename);
295 return GNUNET_SYSERR;
297 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
298 GNUNET_DISK_PERM_NONE);
301 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
302 GNUNET_free (filename);
303 return GNUNET_SYSERR;
305 GNUNET_free (filename);
306 system->hostkeys_data = GNUNET_DISK_file_map (fd,
308 GNUNET_DISK_MAP_TYPE_READ,
310 GNUNET_DISK_file_close (fd);
311 if (NULL == system->hostkeys_data)
312 return GNUNET_SYSERR;
313 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
319 * Function to remove the loaded hostkeys
321 * @param system the testing system handle
324 hostkeys_unload (struct GNUNET_TESTING_System *system)
326 GNUNET_break (NULL != system->hostkeys_data);
327 system->hostkeys_data = NULL;
328 GNUNET_DISK_file_unmap (system->map);
330 system->hostkeys_data = NULL;
331 system->total_hostkeys = 0;
336 * Function to iterate over options.
339 * @param section name of the section
340 * @param option name of the option
341 * @param value value of the option
344 cfg_copy_iterator (void *cls, const char *section,
345 const char *option, const char *value)
347 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
349 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
354 * Create a system handle. There must only be one system
355 * handle per operating system.
357 * @param testdir only the directory name without any path. This is used for
358 * all service homes; the directory will be created in a temporary
359 * location depending on the underlying OS. This variable will be
360 * overridden with the value of the environmental variable
361 * GNUNET_TESTING_PREFIX, if it exists.
362 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
363 * service configurations generated to allow control connections from
364 * this ip. This can either be a single ip address or a network address
366 * @param hostname the hostname of the system we are using for testing; NULL for
368 * @param shared_services NULL terminated array describing services that are to
369 * be shared among peers
370 * @param lowport lowest port number this system is allowed to allocate (inclusive)
371 * @param highport highest port number this system is allowed to allocate (exclusive)
372 * @return handle to this system, NULL on error
374 struct GNUNET_TESTING_System *
375 GNUNET_TESTING_system_create_with_portrange (const char *testdir,
376 const char *trusted_ip,
377 const char *hostname,
379 GNUNET_TESTING_SharedService *
384 struct GNUNET_TESTING_System *system;
385 struct GNUNET_TESTING_SharedService tss;
386 struct SharedService *ss;
389 GNUNET_assert (NULL != testdir);
390 system = GNUNET_new (struct GNUNET_TESTING_System);
391 if (NULL == (system->tmppath = getenv (GNUNET_TESTING_PREFIX)))
392 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
394 system->tmppath = GNUNET_strdup (system->tmppath);
395 system->lowport = lowport;
396 system->highport = highport;
397 if (NULL == system->tmppath)
399 GNUNET_free (system);
402 if (NULL != trusted_ip)
403 system->trusted_ip = GNUNET_strdup (trusted_ip);
404 if (NULL != hostname)
405 system->hostname = GNUNET_strdup (hostname);
406 if (GNUNET_OK != hostkeys_load (system))
408 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
411 if (NULL == shared_services)
413 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
415 tss = shared_services[cnt];
416 ss = GNUNET_new (struct SharedService);
417 ss->sname = GNUNET_strdup (tss.service);
418 ss->cfg = GNUNET_CONFIGURATION_create ();
419 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, ss->sname,
420 &cfg_copy_iterator, ss->cfg);
421 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "TESTING",
422 &cfg_copy_iterator, ss->cfg);
423 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "PATHS",
424 &cfg_copy_iterator, ss->cfg);
425 ss->share = tss.share;
426 GNUNET_array_append (system->shared_services, system->n_shared_services,
434 * Create a system handle. There must only be one system handle per operating
435 * system. Uses a default range for allowed ports. Ports are still tested for
438 * @param testdir only the directory name without any path. This is used for all
439 * service homes; the directory will be created in a temporary location
440 * depending on the underlying OS. This variable will be
441 * overridden with the value of the environmental variable
442 * GNUNET_TESTING_PREFIX, if it exists.
443 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
444 * service configurations generated to allow control connections from
445 * this ip. This can either be a single ip address or a network address
447 * @param hostname the hostname of the system we are using for testing; NULL for
449 * @param shared_services NULL terminated array describing services that are to
450 * be shared among peers
451 * @return handle to this system, NULL on error
453 struct GNUNET_TESTING_System *
454 GNUNET_TESTING_system_create (const char *testdir,
455 const char *trusted_ip,
456 const char *hostname,
457 const struct GNUNET_TESTING_SharedService *
460 return GNUNET_TESTING_system_create_with_portrange (testdir,
470 cleanup_shared_service_instance (struct SharedServiceInstance *i)
472 if (NULL != i->cfg_fn)
474 (void) unlink (i->cfg_fn);
475 GNUNET_free (i->cfg_fn);
477 GNUNET_free_non_null (i->unix_sock);
478 GNUNET_free_non_null (i->port_str);
479 GNUNET_break (NULL == i->proc);
480 GNUNET_break (0 == i->n_refs);
486 start_shared_service_instance (struct SharedServiceInstance *i)
489 char *libexec_binary;
491 GNUNET_assert (NULL == i->proc);
492 GNUNET_assert (NULL != i->cfg_fn);
493 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
494 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
495 GNUNET_free (binary);
496 i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
497 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
504 GNUNET_free (libexec_binary);
506 return GNUNET_SYSERR;
512 stop_shared_service_instance (struct SharedServiceInstance *i)
514 GNUNET_break (0 == i->n_refs);
515 if (0 != GNUNET_OS_process_kill (i->proc, GNUNET_TERM_SIG))
516 LOG (GNUNET_ERROR_TYPE_WARNING,
517 "Killing shared service instance (%s) failed\n", i->ss->sname);
518 (void) GNUNET_OS_process_wait (i->proc);
519 GNUNET_OS_process_destroy (i->proc);
525 * Free system resources.
527 * @param system system to be freed
528 * @param remove_paths should the 'testdir' and all subdirectories
529 * be removed (clean up on shutdown)?
532 GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
535 struct SharedService *ss;
536 struct SharedServiceInstance *i;
540 if (NULL != system->hostkeys_data)
541 hostkeys_unload (system);
542 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
544 ss = system->shared_services[ss_cnt];
545 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
547 i = ss->instances[i_cnt];
549 stop_shared_service_instance (i);
550 cleanup_shared_service_instance (i);
552 GNUNET_free_non_null (ss->instances);
553 GNUNET_CONFIGURATION_destroy (ss->cfg);
554 GNUNET_free (ss->sname);
557 GNUNET_free_non_null (system->shared_services);
558 if (GNUNET_YES == remove_paths)
559 GNUNET_DISK_directory_remove (system->tmppath);
560 GNUNET_free (system->tmppath);
561 GNUNET_free_non_null (system->trusted_ip);
562 GNUNET_free_non_null (system->hostname);
563 GNUNET_free (system);
568 * Reserve a TCP or UDP port for a peer.
570 * @param system system to use for reservation tracking
571 * @return 0 if no free port was available
574 GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
576 struct GNUNET_NETWORK_Handle *socket;
577 struct addrinfo hint;
578 struct addrinfo *ret;
580 uint32_t *port_buckets;
589 FIXME: Instead of using getaddrinfo we should try to determine the port
590 status by the following heurestics.
592 On systems which support both IPv4 and IPv6, only ports open on both
593 address families are considered open.
594 On system with either IPv4 or IPv6. A port is considered open if it's
595 open in the respective address family
597 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
598 hint.ai_socktype = 0;
599 hint.ai_protocol = 0;
602 hint.ai_canonname = NULL;
604 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
605 port_buckets = system->reserved_ports;
606 for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++)
608 xor_image = (UINT32_MAX ^ port_buckets[index]);
609 if (0 == xor_image) /* Ports in the bucket are full */
611 pos = system->lowport % 32;
614 if (0 == ((xor_image >> pos) & 1U))
619 open_port = (index * 32) + pos;
620 if (open_port >= system->highport)
622 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
624 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
625 GNUNET_free (open_port_str);
626 bind_status = GNUNET_NO;
627 for (ai = ret; NULL != ai; ai = ai->ai_next)
629 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
632 bind_status = GNUNET_NETWORK_socket_bind (socket,
635 GNUNET_NETWORK_socket_close (socket);
636 if (GNUNET_OK != bind_status)
638 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0);
641 bind_status = GNUNET_NETWORK_socket_bind (socket,
644 GNUNET_NETWORK_socket_close (socket);
645 if (GNUNET_OK != bind_status)
648 port_buckets[index] |= (1U << pos); /* Set the port bit */
650 if (GNUNET_OK == bind_status)
652 LOG (GNUNET_ERROR_TYPE_DEBUG,
653 "Found a free port %u\n", (unsigned int) open_port);
664 * Release reservation of a TCP or UDP port for a peer
665 * (used during #GNUNET_TESTING_peer_destroy()).
667 * @param system system to use for reservation tracking
668 * @param port reserved port to release
671 GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
674 uint32_t *port_buckets;
678 port_buckets = system->reserved_ports;
681 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
682 if (0 == (port_buckets[bucket] & (1U << pos)))
684 GNUNET_break(0); /* Port was not reserved by us using reserve_port() */
687 port_buckets[bucket] &= ~(1U << pos);
692 * Testing includes a number of pre-created hostkeys for
693 * faster peer startup. This function can be used to
694 * access the n-th key of those pre-created hostkeys; note
695 * that these keys are ONLY useful for testing and not
696 * secure as the private keys are part of the public
697 * GNUnet source code.
699 * This is primarily a helper function used internally
700 * by #GNUNET_TESTING_peer_configure.
702 * @param system the testing system handle
703 * @param key_number desired pre-created hostkey to obtain
704 * @param id set to the peer's identity (hash of the public
705 * key; if NULL, NULL is returned immediately
706 * @return NULL on error (not enough keys)
708 struct GNUNET_CRYPTO_EddsaPrivateKey *
709 GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
711 struct GNUNET_PeerIdentity *id)
713 struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
715 if ((NULL == id) || (NULL == system->hostkeys_data))
717 if (key_number >= system->total_hostkeys)
719 LOG (GNUNET_ERROR_TYPE_ERROR,
720 _("Key number %u does not exist\n"),
724 private_key = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
726 system->hostkeys_data +
727 (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
728 GNUNET_TESTING_HOSTKEYFILESIZE);
729 GNUNET_CRYPTO_eddsa_key_get_public (private_key,
736 * Structure for holding data to build new configurations from a configuration
742 * The system for which we are building configurations
744 struct GNUNET_TESTING_System *system;
747 * The configuration we are building
749 struct GNUNET_CONFIGURATION_Handle *cfg;
752 * The customized service home path for this peer
757 * Array of ports currently allocated to this peer. These ports will be
758 * released upon peer destroy and can be used by other peers which are
764 * The number of ports in the above array
769 * build status - to signal error while building a configuration
776 * Function to iterate over options. Copies
777 * the options to the target configuration,
778 * updating PORT values as needed.
780 * @param cls the UpdateContext
781 * @param section name of the section
782 * @param option name of the option
783 * @param value value of the option
786 update_config (void *cls,
791 struct UpdateContext *uc = cls;
795 char *single_variable;
796 char *per_host_variable;
797 unsigned long long num_per_host;
800 if (GNUNET_OK != uc->status)
802 if (! ((0 == strcmp (option, "PORT"))
803 || (0 == strcmp (option, "UNIXPATH"))
804 || (0 == strcmp (option, "HOSTNAME"))))
806 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
807 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
808 if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
812 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
815 new_port = GNUNET_TESTING_reserve_port (uc->system);
818 uc->status = GNUNET_SYSERR;
819 GNUNET_free (single_variable);
820 GNUNET_free (per_host_variable);
823 GNUNET_snprintf (cval, sizeof (cval), "%u", new_port);
825 GNUNET_array_append (uc->ports, uc->nports, new_port);
827 else if ((ival != 0) &&
829 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
831 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
835 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
836 /* ival + ctx->fdnum % num_per_host); */
838 GNUNET_break (0); /* FIXME */
841 if (0 == strcmp (option, "UNIXPATH"))
844 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
847 GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock",
848 uc->gnunet_home, section);
851 else if ((GNUNET_YES ==
852 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
857 GNUNET_break(0); /* FIXME */
860 if (0 == strcmp (option, "HOSTNAME"))
862 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
864 GNUNET_free (single_variable);
865 GNUNET_free (per_host_variable);
866 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
871 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
872 * 'trusted_hosts' in all sections
874 * @param cls the UpdateContext
875 * @param section name of the section
878 update_config_sections (void *cls,
881 struct UpdateContext *uc = cls;
885 char *orig_allowed_hosts;
887 char *ACCEPT_FROM_key;
893 /* Ignore certain options from sections. See
894 https://gnunet.org/bugs/view.php?id=2476 */
895 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
896 "TESTING_IGNORE_KEYS"))
900 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section,
901 "TESTING_IGNORE_KEYS", &val));
903 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
909 ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt);
911 for (key = 0; key < ikeys_cnt; key++)
914 ptr = strstr (ptr, ";");
922 for (key = 0; key < ikeys_cnt; key++)
924 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
927 if ((key == ikeys_cnt) &&
928 (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
932 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr))
934 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section,
935 "ADVERTISED_PORT", ptr);
939 for (key = 0; key < ikeys_cnt; key++)
941 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
950 GNUNET_free_non_null (val);
951 ACCEPT_FROM_key = "ACCEPT_FROM";
952 if ((NULL != uc->system->trusted_ip) &&
953 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
954 ACCEPT_FROM_key = "ACCEPT_FROM6";
956 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key,
957 &orig_allowed_hosts))
959 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
961 if (NULL == uc->system->trusted_ip)
962 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
964 GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts,
965 uc->system->trusted_ip);
966 GNUNET_free (orig_allowed_hosts);
967 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key,
969 GNUNET_free (allowed_hosts);
973 static struct SharedServiceInstance *
974 associate_shared_service (struct GNUNET_TESTING_System *system,
975 struct SharedService *ss,
976 struct GNUNET_CONFIGURATION_Handle *cfg)
978 struct SharedServiceInstance *i;
979 struct GNUNET_CONFIGURATION_Handle *temp;
984 if ( ((0 == ss->share) && (NULL == ss->instances))
987 && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) )
989 i = GNUNET_new (struct SharedServiceInstance);
991 (void) GNUNET_asprintf (&gnunet_home, "%s/shared/%s/%u",
992 system->tmppath, ss->sname, ss->n_instances);
993 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", gnunet_home);
994 port = GNUNET_TESTING_reserve_port (system);
997 GNUNET_free (gnunet_home);
998 cleanup_shared_service_instance (i);
1001 GNUNET_array_append (ss->instances, ss->n_instances, i);
1002 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
1003 (void) GNUNET_asprintf (&i->port_str, "%u", port);
1004 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", gnunet_home);
1005 GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "GNUNET_HOME",
1007 GNUNET_free (gnunet_home);
1008 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH",
1010 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT",
1012 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1014 GNUNET_CONFIGURATION_destroy (temp);
1015 cleanup_shared_service_instance (i);
1018 GNUNET_CONFIGURATION_destroy (temp);
1022 GNUNET_assert (NULL != ss->instances);
1023 GNUNET_assert (0 < ss->n_instances);
1024 i = ss->instances[ss->n_instances - 1];
1026 GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname,
1027 &cfg_copy_iterator, cfg);
1028 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH",
1030 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1036 * Create a new configuration using the given configuration as a template;
1037 * ports and paths will be modified to select available ports on the local
1038 * system. The default configuration will be available in PATHS section under
1039 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1040 * section to the temporary directory specific to this configuration. If we run
1041 * out of "*port" numbers, return #GNUNET_SYSERR.
1043 * This is primarily a helper function used internally
1044 * by 'GNUNET_TESTING_peer_configure'.
1046 * @param system system to use to coordinate resource usage
1047 * @param cfg template configuration to update
1048 * @param ports array with port numbers used in the created configuration.
1049 * Will be updated upon successful return. Can be NULL
1050 * @param nports the size of the `ports' array. Will be updated.
1051 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1052 * be incomplete and should not be used there upon
1055 GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1056 struct GNUNET_CONFIGURATION_Handle *cfg,
1058 unsigned int *nports)
1060 struct UpdateContext uc;
1061 char *default_config;
1065 uc.status = GNUNET_OK;
1068 GNUNET_asprintf (&uc.gnunet_home, "%s/%u", system->tmppath,
1069 system->path_counter++);
1070 GNUNET_asprintf (&default_config, "%s/config", uc.gnunet_home);
1071 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
1073 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
1075 GNUNET_free (default_config);
1076 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "GNUNET_HOME",
1078 /* make PORTs and UNIXPATHs unique */
1079 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1080 /* allow connections to services from system trusted_ip host */
1081 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1082 /* enable loopback-based connections between peers */
1083 GNUNET_CONFIGURATION_set_value_string (cfg,
1085 "USE_LOCALADDR", "YES");
1086 GNUNET_free (uc.gnunet_home);
1087 if ((NULL != ports) && (NULL != nports))
1090 *nports = uc.nports;
1093 GNUNET_free_non_null (uc.ports);
1099 * Create a new configuration using the given configuration as a template;
1100 * ports and paths will be modified to select available ports on the local
1101 * system. The default configuration will be available in PATHS section under
1102 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1103 * section to the temporary directory specific to this configuration. If we run
1104 * out of "*port" numbers, return #GNUNET_SYSERR.
1106 * This is primarily a helper function used internally
1107 * by #GNUNET_TESTING_peer_configure().
1109 * @param system system to use to coordinate resource usage
1110 * @param cfg template configuration to update
1111 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1112 * be incomplete and should not be used there upon
1115 GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1116 struct GNUNET_CONFIGURATION_Handle *cfg)
1118 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1123 * Configure a GNUnet peer. GNUnet must be installed on the local
1124 * system and available in the PATH.
1126 * @param system system to use to coordinate resource usage
1127 * @param cfg configuration to use; will be UPDATED (to reflect needed
1128 * changes in port numbers and paths)
1129 * @param key_number number of the hostkey to use for the peer
1130 * @param id identifier for the daemon, will be set, can be NULL
1131 * @param emsg set to freshly allocated error message (set to NULL on success),
1133 * @return handle to the peer, NULL on error
1135 struct GNUNET_TESTING_Peer *
1136 GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1137 struct GNUNET_CONFIGURATION_Handle *cfg,
1138 uint32_t key_number,
1139 struct GNUNET_PeerIdentity *id,
1142 struct GNUNET_TESTING_Peer *peer;
1143 struct GNUNET_DISK_FileHandle *fd;
1144 char *hostkey_filename;
1145 char *config_filename;
1146 char *libexec_binary;
1148 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
1150 struct SharedService *ss;
1151 struct SharedServiceInstance **ss_instances;
1153 unsigned int nports;
1157 ss_instances = NULL;
1160 if (key_number >= system->total_hostkeys)
1162 GNUNET_asprintf (&emsg_,
1163 _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1164 (unsigned int) system->total_hostkeys);
1169 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1171 GNUNET_asprintf (&emsg_,
1172 _("Failed to initialize hostkey for peer %u\n"),
1173 (unsigned int) key_number);
1179 GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1181 GNUNET_asprintf (&emsg_,
1182 _("PRIVATE_KEY option in PEER section missing in configuration\n"));
1185 /* Remove sections for shared services */
1186 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1188 ss = system->shared_services[cnt];
1189 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1191 if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg,
1194 GNUNET_asprintf (&emsg_,
1195 _("Failed to create configuration for peer "
1196 "(not enough free ports?)\n"));
1199 GNUNET_assert (GNUNET_OK ==
1200 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER",
1202 &hostkey_filename));
1203 fd = GNUNET_DISK_file_open (hostkey_filename,
1204 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1205 GNUNET_DISK_PERM_USER_READ
1206 | GNUNET_DISK_PERM_USER_WRITE);
1209 GNUNET_asprintf (&emsg_, _("Cannot open hostkey file `%s': %s\n"),
1210 hostkey_filename, STRERROR (errno));
1211 GNUNET_free (hostkey_filename);
1214 GNUNET_free (hostkey_filename);
1215 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1216 GNUNET_DISK_file_write (fd, system->hostkeys_data
1217 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1218 GNUNET_TESTING_HOSTKEYFILESIZE))
1220 GNUNET_asprintf (&emsg_,
1221 _("Failed to write hostkey file for peer %u: %s\n"),
1222 (unsigned int) key_number,
1224 GNUNET_DISK_file_close (fd);
1227 GNUNET_DISK_file_close (fd);
1228 ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *)
1229 * system->n_shared_services);
1230 for (cnt=0; cnt < system->n_shared_services; cnt++)
1232 ss = system->shared_services[cnt];
1233 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1234 if (NULL == ss_instances[cnt])
1236 emsg_ = GNUNET_strdup ("FIXME");
1240 GNUNET_assert (GNUNET_OK ==
1241 GNUNET_CONFIGURATION_get_value_filename
1242 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1243 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1245 GNUNET_asprintf (&emsg_,
1246 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1248 (unsigned int) key_number,
1250 GNUNET_free (config_filename);
1253 peer = GNUNET_new (struct GNUNET_TESTING_Peer);
1254 peer->ss_instances = ss_instances;
1255 peer->cfgfile = config_filename; /* Free in peer_destroy */
1256 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1257 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1258 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1261 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1262 peer->args = GNUNET_strdup ("");
1266 peer->args = GNUNET_strdup (libexec_binary);
1268 peer->system = system;
1269 peer->key_number = key_number;
1270 GNUNET_free (libexec_binary);
1271 peer->ports = ports; /* Free in peer_destroy */
1272 peer->nports = nports;
1276 GNUNET_free_non_null (ss_instances);
1277 GNUNET_free_non_null (ports);
1278 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1282 GNUNET_free (emsg_);
1288 * Obtain the peer identity from a peer handle.
1290 * @param peer peer handle for which we want the peer's identity
1291 * @param id identifier for the daemon, will be set
1294 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1295 struct GNUNET_PeerIdentity *id)
1297 if (NULL != peer->id)
1299 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1302 peer->id = GNUNET_new (struct GNUNET_PeerIdentity);
1303 GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system,
1306 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1313 * @param peer peer to start
1314 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (i.e. peer already running)
1317 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1319 struct SharedServiceInstance *i;
1322 if (NULL != peer->main_process)
1325 return GNUNET_SYSERR;
1327 GNUNET_assert (NULL != peer->cfgfile);
1328 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1330 i = peer->ss_instances[cnt];
1331 if ((0 == i->n_refs)
1332 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1333 return GNUNET_SYSERR;
1336 peer->main_binary = GNUNET_CONFIGURATION_expand_dollar (peer->cfg, peer->main_binary);
1337 peer->main_process = GNUNET_OS_start_process_s (PIPE_CONTROL,
1338 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1345 if (NULL == peer->main_process)
1347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1348 _("Failed to start `%s': %s\n"),
1351 return GNUNET_SYSERR;
1358 * Start a service at a peer using its ARM service
1360 * @param peer the peer whose service has to be started
1361 * @param service_name name of the service to start
1362 * @param timeout how long should the ARM API try to send the request to start
1364 * @param cont the callback to call with result and status from ARM API
1365 * @param cont_cls the closure for the above callback
1366 * @return #GNUNET_OK upon successfully queuing the service start request;
1367 * #GNUNET_SYSERR upon error
1370 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1371 const char *service_name,
1372 struct GNUNET_TIME_Relative timeout,
1373 GNUNET_ARM_ResultCallback cont,
1376 if (NULL == peer->ah)
1377 return GNUNET_SYSERR;
1378 GNUNET_ARM_request_service_start (peer->ah,
1380 GNUNET_OS_INHERIT_STD_ALL,
1388 * Stop a service at a peer using its ARM service
1390 * @param peer the peer whose service has to be stopped
1391 * @param service_name name of the service to stop
1392 * @param timeout how long should the ARM API try to send the request to stop
1394 * @param cont the callback to call with result and status from ARM API
1395 * @param cont_cls the closure for the above callback
1396 * @return #GNUNET_OK upon successfully queuing the service stop request;
1397 * #GNUNET_SYSERR upon error
1400 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1401 const char *service_name,
1402 struct GNUNET_TIME_Relative timeout,
1403 GNUNET_ARM_ResultCallback cont,
1406 if (NULL == peer->ah)
1407 return GNUNET_SYSERR;
1408 GNUNET_ARM_request_service_stop (peer->ah,
1417 * Sends SIGTERM to the peer's main process
1419 * @param peer the handle to the peer
1420 * @return #GNUNET_OK if successful; #GNUNET_SYSERR if the main process is NULL
1421 * or upon any error while sending SIGTERM
1424 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1426 struct SharedServiceInstance *i;
1429 if (NULL == peer->main_process)
1432 return GNUNET_SYSERR;
1434 if (0 != GNUNET_OS_process_kill (peer->main_process, GNUNET_TERM_SIG))
1435 return GNUNET_SYSERR;
1436 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1438 i = peer->ss_instances[cnt];
1439 GNUNET_assert (0 != i->n_refs);
1442 stop_shared_service_instance (i);
1449 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1451 * @param peer the handle to the peer
1452 * @return #GNUNET_OK if successful; #GNUNET_SYSERR if the main process is NULL
1453 * or upon any error while waiting
1456 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1460 if (NULL == peer->main_process)
1463 return GNUNET_SYSERR;
1465 ret = GNUNET_OS_process_wait (peer->main_process);
1466 GNUNET_OS_process_destroy (peer->main_process);
1467 peer->main_process = NULL;
1475 * @param peer peer to stop
1476 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1479 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1481 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1482 return GNUNET_SYSERR;
1483 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1484 return GNUNET_SYSERR;
1490 * Function called whenever we connect to or disconnect from ARM.
1492 * @param cls closure
1493 * @param connected #GNUNET_YES if connected, #GNUNET_NO if disconnected,
1494 * #GNUNET_SYSERR on error.
1497 disconn_status (void *cls,
1500 struct GNUNET_TESTING_Peer *peer = cls;
1502 if (GNUNET_SYSERR == connected)
1504 peer->cb (peer->cb_cls, peer, connected);
1507 if (GNUNET_YES == connected)
1509 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1512 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1513 GNUNET_ARM_disconnect_and_free (peer->ah);
1515 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1520 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1521 * through the GNUNET_TESTING_PeerStopCallback().
1523 * @param peer the peer to stop
1524 * @param cb the callback to signal peer shutdown
1525 * @param cb_cls closure for the above callback
1526 * @return #GNUNET_OK upon successfully giving the request to the ARM API (this
1527 * does not mean that the peer is successfully stopped); #GNUNET_SYSERR
1531 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1532 GNUNET_TESTING_PeerStopCallback cb,
1535 if (NULL == peer->main_process)
1536 return GNUNET_SYSERR;
1537 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1538 if (NULL == peer->ah)
1539 return GNUNET_SYSERR;
1541 peer->cb_cls = cb_cls;
1547 * Cancel a previous asynchronous peer stop request.
1548 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1549 * peer. It is an error to call this function if the peer stop callback was
1552 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1556 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1558 GNUNET_assert (NULL != peer->ah);
1559 GNUNET_ARM_disconnect_and_free (peer->ah);
1565 * Destroy the peer. Releases resources locked during peer configuration.
1566 * If the peer is still running, it will be stopped AND a warning will be
1567 * printed (users of the API should stop the peer explicitly first).
1569 * @param peer peer to destroy
1572 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1576 if (NULL != peer->main_process)
1577 GNUNET_TESTING_peer_stop (peer);
1578 if (NULL != peer->ah)
1579 GNUNET_ARM_disconnect_and_free (peer->ah);
1580 if (NULL != peer->mh)
1581 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1582 GNUNET_free (peer->cfgfile);
1583 if (NULL != peer->cfg)
1584 GNUNET_CONFIGURATION_destroy (peer->cfg);
1585 GNUNET_free (peer->main_binary);
1586 GNUNET_free (peer->args);
1587 GNUNET_free_non_null (peer->id);
1588 GNUNET_free_non_null (peer->ss_instances);
1589 if (NULL != peer->ports)
1591 for (cnt = 0; cnt < peer->nports; cnt++)
1592 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1593 GNUNET_free (peer->ports);
1600 * Start a single peer and run a test using the testing library.
1601 * Starts a peer using the given configuration and then invokes the
1602 * given callback. This function ALSO initializes the scheduler loop
1603 * and should thus be called directly from "main". The testcase
1604 * should self-terminate by invoking #GNUNET_SCHEDULER_shutdown().
1606 * @param testdir only the directory name without any path. This is used for
1607 * all service homes; the directory will be created in a temporary
1608 * location depending on the underlying OS
1609 * @param cfgfilename name of the configuration file to use;
1610 * use NULL to only run with defaults
1611 * @param tm main function of the testcase
1612 * @param tm_cls closure for @a tm
1613 * @return 0 on success, 1 on error
1616 GNUNET_TESTING_peer_run (const char *testdir,
1617 const char *cfgfilename,
1618 GNUNET_TESTING_TestMain tm,
1621 return GNUNET_TESTING_service_run (testdir, "arm",
1622 cfgfilename, tm, tm_cls);
1627 * Structure for holding service data
1629 struct ServiceContext
1632 * The configuration of the peer in which the service is run
1634 const struct GNUNET_CONFIGURATION_Handle *cfg;
1637 * Callback to signal service startup
1639 GNUNET_TESTING_TestMain tm;
1642 * The peer in which the service is run.
1644 struct GNUNET_TESTING_Peer *peer;
1647 * Closure for the above callback
1654 * Callback to be called when SCHEDULER has been started
1656 * @param cls the ServiceContext
1659 service_run_main (void *cls)
1661 struct ServiceContext *sc = cls;
1663 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1668 * Start a single service (no ARM, except of course if the given
1669 * service name is 'arm') and run a test using the testing library.
1670 * Starts a service using the given configuration and then invokes the
1671 * given callback. This function ALSO initializes the scheduler loop
1672 * and should thus be called directly from "main". The testcase
1673 * should self-terminate by invoking #GNUNET_SCHEDULER_shutdown().
1675 * This function is useful if the testcase is for a single service
1676 * and if that service doesn't itself depend on other services.
1678 * @param testdir only the directory name without any path. This is used for
1679 * all service homes; the directory will be created in a temporary
1680 * location depending on the underlying OS
1681 * @param service_name name of the service to run
1682 * @param cfgfilename name of the configuration file to use;
1683 * use NULL to only run with defaults
1684 * @param tm main function of the testcase
1685 * @param tm_cls closure for @a tm
1686 * @return 0 on success, 1 on error
1689 GNUNET_TESTING_service_run (const char *testdir,
1690 const char *service_name,
1691 const char *cfgfilename,
1692 GNUNET_TESTING_TestMain tm,
1695 struct ServiceContext sc;
1696 struct GNUNET_TESTING_System *system;
1697 struct GNUNET_TESTING_Peer *peer;
1698 struct GNUNET_CONFIGURATION_Handle *cfg;
1700 char *libexec_binary;
1702 GNUNET_log_setup (testdir, "WARNING", NULL);
1703 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1706 cfg = GNUNET_CONFIGURATION_create ();
1707 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1709 LOG (GNUNET_ERROR_TYPE_ERROR,
1710 _("Failed to load configuration from %s\n"), cfgfilename);
1711 GNUNET_CONFIGURATION_destroy (cfg);
1712 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1715 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1718 GNUNET_CONFIGURATION_destroy (cfg);
1719 hostkeys_unload (system);
1720 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1723 GNUNET_free (peer->main_binary);
1724 GNUNET_free (peer->args);
1725 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1726 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1727 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1730 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1731 peer->args = GNUNET_strdup ("");
1734 peer->args = GNUNET_strdup (libexec_binary);
1736 GNUNET_free (libexec_binary);
1737 GNUNET_free (binary);
1738 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1740 GNUNET_TESTING_peer_destroy (peer);
1741 GNUNET_CONFIGURATION_destroy (cfg);
1742 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1749 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1750 if ((NULL != peer->main_process) &&
1751 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1753 GNUNET_TESTING_peer_destroy (peer);
1754 GNUNET_CONFIGURATION_destroy (cfg);
1755 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1758 GNUNET_TESTING_peer_destroy (peer);
1759 GNUNET_CONFIGURATION_destroy (cfg);
1760 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1766 * Sometimes we use the binary name to determine which specific
1767 * test to run. In those cases, the string after the last "_"
1768 * in 'argv[0]' specifies a string that determines the configuration
1769 * file or plugin to use.
1771 * This function returns the respective substring, taking care
1772 * of issues such as binaries ending in '.exe' on W32.
1774 * @param argv0 the name of the binary
1775 * @return string between the last '_' and the '.exe' (or the end of the string),
1776 * NULL if argv0 has no '_'
1779 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1781 size_t slen = strlen (argv0) + 1;
1786 memcpy (sbuf, argv0, slen);
1787 ret = strrchr (sbuf, '_');
1790 ret++; /* skip underscore */
1791 dot = strchr (ret, '.');
1794 return GNUNET_strdup (ret);
1798 /* end of testing.c */