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 #include "../arm/do_start_process.c"
39 #define LOG(kind,...) \
40 GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
44 * We need pipe control only on WINDOWS
47 #define PIPE_CONTROL GNUNET_YES
49 #define PIPE_CONTROL GNUNET_NO
54 * Lowest port used for GNUnet testing. Should be high enough to not
55 * conflict with other applications running on the hosts but be low
56 * enough to not conflict with client-ports (typically starting around
59 #define LOW_PORT 12000
62 * Highest port used for GNUnet testing. Should be low enough to not
63 * conflict with the port range for "local" ports (client apps; see
64 * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
66 #define HIGH_PORT 56000
69 struct SharedServiceInstance
71 struct SharedService *ss;
75 struct GNUNET_OS_Process *proc;
88 struct SharedServiceInstance **instances;
90 struct GNUNET_CONFIGURATION_Handle *cfg;
96 unsigned int n_instances;
101 * Handle for a system on which GNUnet peers are executed;
102 * a system is used for reserving unique paths and ports.
104 struct GNUNET_TESTING_System
107 * Prefix (i.e. "/tmp/gnunet-testing/") we prepend to each
113 * The trusted ip. Can either be a single ip address or a network address in
124 * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes.
129 * memory map for 'hostkeys_data'.
131 struct GNUNET_DISK_MapHandle *map;
133 struct SharedService **shared_services;
135 unsigned int n_shared_services;
138 * Bitmap where each port that has already been reserved for some GNUnet peer
139 * is recorded. Note that we make no distinction between TCP and UDP ports
140 * and test if a port is already in use before assigning it to a peer/service.
141 * If we detect that a port is already in use, we also mark it in this bitmap.
142 * So all the bits that are zero merely indicate ports that MIGHT be available
145 uint32_t reserved_ports[65536 / 32];
148 * Counter we use to make service home paths unique on this system;
149 * the full path consists of the tmppath and this number. Each
150 * UNIXPATH for a peer is also modified to include the respective
151 * path counter to ensure uniqueness. This field is incremented
152 * by one for each configured peer. Even if peers are destroyed,
153 * we never re-use path counters.
155 uint32_t path_counter;
158 * The number of hostkeys
160 uint32_t total_hostkeys;
163 * Lowest port we are allowed to use.
168 * Highest port we are allowed to use.
175 * Handle for a GNUnet peer controlled by testing.
177 struct GNUNET_TESTING_Peer
180 * The TESTING system associated with this peer
182 struct GNUNET_TESTING_System *system;
185 * Path to the configuration file for this peer.
190 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
191 * Typically 'gnunet-service-arm' (but can be set to a
192 * specific service by 'GNUNET_TESTING_service_run' if
199 * Handle to the running binary of the service, NULL if the
200 * peer/service is currently not running.
202 struct GNUNET_OS_Process *main_process;
205 * The handle to the peer's ARM service
207 struct GNUNET_ARM_Handle *ah;
210 * Handle to ARM monitoring
212 struct GNUNET_ARM_MonitorHandle *mh;
215 * The config of the peer
217 struct GNUNET_CONFIGURATION_Handle *cfg;
220 * The callback to call asynchronously when a peer is stopped
222 GNUNET_TESTING_PeerStopCallback cb;
225 * The closure for the above callback
230 * The cached identity of this peer. Will be populated on call to
231 * GNUNET_TESTING_peer_get_identity()
233 struct GNUNET_PeerIdentity *id;
235 struct SharedServiceInstance **ss_instances;
238 * Array of ports currently allocated to this peer. These ports will be
239 * released upon peer destroy and can be used by other peers which are
245 * The number of ports in the above array
250 * The keynumber of this peer's hostkey
257 * Testing includes a number of pre-created hostkeys for faster peer
258 * startup. This function loads such keys into memory from a file.
260 * @param system the testing system handle
261 * @return GNUNET_OK on success; GNUNET_SYSERR on error
264 hostkeys_load (struct GNUNET_TESTING_System *system)
269 struct GNUNET_DISK_FileHandle *fd;
271 GNUNET_assert (NULL == system->hostkeys_data);
272 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
273 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
274 GNUNET_free (data_dir);
276 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
278 LOG (GNUNET_ERROR_TYPE_ERROR,
279 _("Hostkeys file not found: %s\n"), filename);
280 GNUNET_free (filename);
281 return GNUNET_SYSERR;
283 /* Check hostkey file size, read entire thing into memory */
285 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
289 GNUNET_free (filename);
290 return GNUNET_SYSERR; /* File is empty */
292 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
294 LOG (GNUNET_ERROR_TYPE_ERROR,
295 _("Incorrect hostkey file format: %s\n"), filename);
296 GNUNET_free (filename);
297 return GNUNET_SYSERR;
299 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
300 GNUNET_DISK_PERM_NONE);
303 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
304 GNUNET_free (filename);
305 return GNUNET_SYSERR;
307 GNUNET_free (filename);
308 system->hostkeys_data = GNUNET_DISK_file_map (fd,
310 GNUNET_DISK_MAP_TYPE_READ,
312 GNUNET_DISK_file_close (fd);
313 if (NULL == system->hostkeys_data)
314 return GNUNET_SYSERR;
315 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
321 * Function to remove the loaded hostkeys
323 * @param system the testing system handle
326 hostkeys_unload (struct GNUNET_TESTING_System *system)
328 GNUNET_break (NULL != system->hostkeys_data);
329 system->hostkeys_data = NULL;
330 GNUNET_DISK_file_unmap (system->map);
332 system->hostkeys_data = NULL;
333 system->total_hostkeys = 0;
338 * Function to iterate over options.
341 * @param section name of the section
342 * @param option name of the option
343 * @param value value of the option
346 cfg_copy_iterator (void *cls, const char *section,
347 const char *option, const char *value)
349 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
351 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
356 * Create a system handle. There must only be one system
357 * handle per operating system.
359 * @param testdir only the directory name without any path. This is used for
360 * all service homes; the directory will be created in a temporary
361 * location depending on the underlying OS. This variable will be
362 * overridden with the value of the environmental variable
363 * GNUNET_TESTING_PREFIX, if it exists.
364 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
365 * service configurations generated to allow control connections from
366 * this ip. This can either be a single ip address or a network address
368 * @param hostname the hostname of the system we are using for testing; NULL for
370 * @param shared_services NULL terminated array describing services that are to
371 * be shared among peers
372 * @param lowport lowest port number this system is allowed to allocate (inclusive)
373 * @param highport highest port number this system is allowed to allocate (exclusive)
374 * @return handle to this system, NULL on error
376 struct GNUNET_TESTING_System *
377 GNUNET_TESTING_system_create_with_portrange (const char *testdir,
378 const char *trusted_ip,
379 const char *hostname,
381 GNUNET_TESTING_SharedService *
386 struct GNUNET_TESTING_System *system;
387 struct GNUNET_TESTING_SharedService tss;
388 struct SharedService *ss;
391 GNUNET_assert (NULL != testdir);
392 system = GNUNET_malloc (sizeof (struct GNUNET_TESTING_System));
393 if (NULL == (system->tmppath = getenv (GNUNET_TESTING_PREFIX)))
394 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
396 system->tmppath = GNUNET_strdup (system->tmppath);
397 system->lowport = lowport;
398 system->highport = highport;
399 if (NULL == system->tmppath)
401 GNUNET_free (system);
404 if (NULL != trusted_ip)
405 system->trusted_ip = GNUNET_strdup (trusted_ip);
406 if (NULL != hostname)
407 system->hostname = GNUNET_strdup (hostname);
408 if (GNUNET_OK != hostkeys_load (system))
410 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
413 if (NULL == shared_services)
415 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
417 tss = shared_services[cnt];
418 ss = GNUNET_malloc (sizeof (struct SharedService));
419 ss->sname = GNUNET_strdup (tss.service);
420 ss->cfg = GNUNET_CONFIGURATION_create ();
421 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, ss->sname,
422 &cfg_copy_iterator, ss->cfg);
423 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "TESTING",
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,
469 cleanup_shared_service_instance (struct SharedServiceInstance *i)
471 if (NULL != i->cfg_fn)
473 (void) unlink (i->cfg_fn);
474 GNUNET_free (i->cfg_fn);
476 GNUNET_free_non_null (i->unix_sock);
477 GNUNET_free_non_null (i->port_str);
478 GNUNET_break (NULL == i->proc);
479 GNUNET_break (0 == i->n_refs);
484 start_shared_service_instance (struct SharedServiceInstance *i)
487 char *libexec_binary;
489 GNUNET_assert (NULL == i->proc);
490 GNUNET_assert (NULL != i->cfg_fn);
491 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
492 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
493 GNUNET_free (binary);
494 i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
495 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
502 GNUNET_free (libexec_binary);
504 return GNUNET_SYSERR;
510 stop_shared_service_instance (struct SharedServiceInstance *i)
512 GNUNET_break (0 == i->n_refs);
513 if (0 != GNUNET_OS_process_kill (i->proc, GNUNET_TERM_SIG))
514 LOG (GNUNET_ERROR_TYPE_WARNING,
515 "Killing shared service instance (%s) failed\n", i->ss->sname);
516 (void) GNUNET_OS_process_wait (i->proc);
517 GNUNET_OS_process_destroy (i->proc);
523 * Free system resources.
525 * @param system system to be freed
526 * @param remove_paths should the 'testdir' and all subdirectories
527 * be removed (clean up on shutdown)?
530 GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
533 struct SharedService *ss;
534 struct SharedServiceInstance *i;
538 if (NULL != system->hostkeys_data)
539 hostkeys_unload (system);
540 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
542 ss = system->shared_services[ss_cnt];
543 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
545 i = ss->instances[i_cnt];
547 stop_shared_service_instance (i);
548 cleanup_shared_service_instance (i);
550 GNUNET_free_non_null (ss->instances);
551 GNUNET_CONFIGURATION_destroy (ss->cfg);
552 GNUNET_free (ss->sname);
555 GNUNET_free_non_null (system->shared_services);
556 if (GNUNET_YES == remove_paths)
557 GNUNET_DISK_directory_remove (system->tmppath);
558 GNUNET_free (system->tmppath);
559 GNUNET_free_non_null (system->trusted_ip);
560 GNUNET_free_non_null (system->hostname);
561 GNUNET_free (system);
566 * Reserve a TCP or UDP port for a peer.
568 * @param system system to use for reservation tracking
569 * @return 0 if no free port was available
572 GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
574 struct GNUNET_NETWORK_Handle *socket;
575 struct addrinfo hint;
576 struct addrinfo *ret;
578 uint32_t *port_buckets;
587 FIXME: Instead of using getaddrinfo we should try to determine the port
588 status by the following heurestics.
590 On systems which support both IPv4 and IPv6, only ports open on both
591 address families are considered open.
592 On system with either IPv4 or IPv6. A port is considered open if it's
593 open in the respective address family
595 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
596 hint.ai_socktype = 0;
597 hint.ai_protocol = 0;
600 hint.ai_canonname = NULL;
602 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
603 port_buckets = system->reserved_ports;
604 for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++)
606 xor_image = (UINT32_MAX ^ port_buckets[index]);
607 if (0 == xor_image) /* Ports in the bucket are full */
609 pos = system->lowport % 32;
612 if (0 == ((xor_image >> pos) & 1U))
617 open_port = (index * 32) + pos;
618 if (open_port >= system->highport)
620 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
622 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
623 GNUNET_free (open_port_str);
624 bind_status = GNUNET_NO;
625 for (ai = ret; NULL != ai; ai = ai->ai_next)
627 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
630 bind_status = GNUNET_NETWORK_socket_bind (socket,
633 GNUNET_NETWORK_socket_close (socket);
634 if (GNUNET_OK != bind_status)
636 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0);
639 bind_status = GNUNET_NETWORK_socket_bind (socket,
642 GNUNET_NETWORK_socket_close (socket);
643 if (GNUNET_OK != bind_status)
646 port_buckets[index] |= (1U << pos); /* Set the port bit */
648 if (GNUNET_OK == bind_status)
650 LOG (GNUNET_ERROR_TYPE_DEBUG,
651 "Found a free port %u\n", (unsigned int) open_port);
662 * Release reservation of a TCP or UDP port for a peer
663 * (used during GNUNET_TESTING_peer_destroy).
665 * @param system system to use for reservation tracking
666 * @param port reserved port to release
669 GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
672 uint32_t *port_buckets;
676 port_buckets = system->reserved_ports;
679 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
680 if (0 == (port_buckets[bucket] & (1U << pos)))
682 GNUNET_break(0); /* Port was not reserved by us using reserve_port() */
685 port_buckets[bucket] &= ~(1U << pos);
690 * Testing includes a number of pre-created hostkeys for
691 * faster peer startup. This function can be used to
692 * access the n-th key of those pre-created hostkeys; note
693 * that these keys are ONLY useful for testing and not
694 * secure as the private keys are part of the public
695 * GNUnet source code.
697 * This is primarily a helper function used internally
698 * by #GNUNET_TESTING_peer_configure.
700 * @param system the testing system handle
701 * @param key_number desired pre-created hostkey to obtain
702 * @param id set to the peer's identity (hash of the public
703 * key; if NULL, GNUNET_SYSERR is returned immediately
704 * @return NULL on error (not enough keys)
706 struct GNUNET_CRYPTO_EddsaPrivateKey *
707 GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
709 struct GNUNET_PeerIdentity *id)
711 struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
713 if ((NULL == id) || (NULL == system->hostkeys_data))
715 if (key_number >= system->total_hostkeys)
717 LOG (GNUNET_ERROR_TYPE_ERROR,
718 _("Key number %u does not exist\n"), key_number);
721 private_key = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
723 system->hostkeys_data +
724 (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
725 GNUNET_TESTING_HOSTKEYFILESIZE);
726 GNUNET_CRYPTO_eddsa_key_get_public (private_key,
733 * Structure for holding data to build new configurations from a configuration
739 * The system for which we are building configurations
741 struct GNUNET_TESTING_System *system;
744 * The configuration we are building
746 struct GNUNET_CONFIGURATION_Handle *cfg;
749 * The customized service home path for this peer
754 * Array of ports currently allocated to this peer. These ports will be
755 * released upon peer destroy and can be used by other peers which are
761 * The number of ports in the above array
766 * build status - to signal error while building a configuration
773 * Function to iterate over options. Copies
774 * the options to the target configuration,
775 * updating PORT values as needed.
777 * @param cls the UpdateContext
778 * @param section name of the section
779 * @param option name of the option
780 * @param value value of the option
783 update_config (void *cls, const char *section, const char *option,
786 struct UpdateContext *uc = cls;
790 char *single_variable;
791 char *per_host_variable;
792 unsigned long long num_per_host;
795 if (GNUNET_OK != uc->status)
797 if (! ((0 == strcmp (option, "PORT"))
798 || (0 == strcmp (option, "UNIXPATH"))
799 || (0 == strcmp (option, "HOSTNAME"))))
801 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
802 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
803 if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
807 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
810 new_port = GNUNET_TESTING_reserve_port (uc->system);
813 uc->status = GNUNET_SYSERR;
814 GNUNET_free (single_variable);
815 GNUNET_free (per_host_variable);
818 GNUNET_snprintf (cval, sizeof (cval), "%u", new_port);
820 GNUNET_array_append (uc->ports, uc->nports, new_port);
822 else if ((ival != 0) &&
824 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
826 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
830 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
831 /* ival + ctx->fdnum % num_per_host); */
833 GNUNET_break (0); /* FIXME */
836 if (0 == strcmp (option, "UNIXPATH"))
839 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
842 GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock",
843 uc->gnunet_home, section);
846 else if ((GNUNET_YES ==
847 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
852 GNUNET_break(0); /* FIXME */
855 if (0 == strcmp (option, "HOSTNAME"))
857 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
859 GNUNET_free (single_variable);
860 GNUNET_free (per_host_variable);
861 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
866 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
867 * 'trusted_hosts' in all sections
869 * @param cls the UpdateContext
870 * @param section name of the section
873 update_config_sections (void *cls,
876 struct UpdateContext *uc = cls;
880 char *orig_allowed_hosts;
882 char *ACCEPT_FROM_key;
888 /* Ignore certain options from sections. See
889 https://gnunet.org/bugs/view.php?id=2476 */
890 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
891 "TESTING_IGNORE_KEYS"))
895 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section,
896 "TESTING_IGNORE_KEYS", &val));
898 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
904 ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt);
906 for (key = 0; key < ikeys_cnt; key++)
909 ptr = strstr (ptr, ";");
917 for (key = 0; key < ikeys_cnt; key++)
919 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
922 if ((key == ikeys_cnt) &&
923 (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
927 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr))
929 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section,
930 "ADVERTISED_PORT", ptr);
934 for (key = 0; key < ikeys_cnt; key++)
936 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
945 GNUNET_free_non_null (val);
946 ACCEPT_FROM_key = "ACCEPT_FROM";
947 if ((NULL != uc->system->trusted_ip) &&
948 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
949 ACCEPT_FROM_key = "ACCEPT_FROM6";
951 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key,
952 &orig_allowed_hosts))
954 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
956 if (NULL == uc->system->trusted_ip)
957 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
959 GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts,
960 uc->system->trusted_ip);
961 GNUNET_free (orig_allowed_hosts);
962 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key,
964 GNUNET_free (allowed_hosts);
967 static struct SharedServiceInstance *
968 associate_shared_service (struct GNUNET_TESTING_System *system,
969 struct SharedService *ss,
970 struct GNUNET_CONFIGURATION_Handle *cfg)
972 struct SharedServiceInstance *i;
973 struct GNUNET_CONFIGURATION_Handle *temp;
978 if ( ((0 == ss->share) && (NULL == ss->instances))
981 && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) )
983 i = GNUNET_new (struct SharedServiceInstance);
985 (void) GNUNET_asprintf (&gnunet_home, "%s/shared/%s/%u",
986 system->tmppath, ss->sname, ss->n_instances);
987 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", gnunet_home);
988 port = GNUNET_TESTING_reserve_port (system);
991 GNUNET_free (gnunet_home);
992 cleanup_shared_service_instance (i);
995 GNUNET_array_append (ss->instances, ss->n_instances, i);
996 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
997 (void) GNUNET_asprintf (&i->port_str, "%u", port);
998 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", gnunet_home);
999 GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "GNUNET_HOME",
1001 GNUNET_free (gnunet_home);
1002 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH",
1004 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT",
1006 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1008 GNUNET_CONFIGURATION_destroy (temp);
1009 cleanup_shared_service_instance (i);
1012 GNUNET_CONFIGURATION_destroy (temp);
1016 GNUNET_assert (NULL != ss->instances);
1017 GNUNET_assert (0 < ss->n_instances);
1018 i = ss->instances[ss->n_instances - 1];
1020 GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname,
1021 &cfg_copy_iterator, cfg);
1022 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH",
1024 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1030 * Create a new configuration using the given configuration as a template;
1031 * ports and paths will be modified to select available ports on the local
1032 * system. The default configuration will be available in PATHS section under
1033 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1034 * section to the temporary directory specific to this configuration. If we run
1035 * out of "*port" numbers, return #GNUNET_SYSERR.
1037 * This is primarily a helper function used internally
1038 * by 'GNUNET_TESTING_peer_configure'.
1040 * @param system system to use to coordinate resource usage
1041 * @param cfg template configuration to update
1042 * @param ports array with port numbers used in the created configuration.
1043 * Will be updated upon successful return. Can be NULL
1044 * @param nports the size of the `ports' array. Will be updated.
1045 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1046 * be incomplete and should not be used there upon
1049 GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1050 struct GNUNET_CONFIGURATION_Handle *cfg,
1052 unsigned int *nports)
1054 struct UpdateContext uc;
1055 char *default_config;
1059 uc.status = GNUNET_OK;
1062 GNUNET_asprintf (&uc.gnunet_home, "%s/%u", system->tmppath,
1063 system->path_counter++);
1064 GNUNET_asprintf (&default_config, "%s/config", uc.gnunet_home);
1065 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
1067 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
1069 GNUNET_free (default_config);
1070 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "GNUNET_HOME",
1072 /* make PORTs and UNIXPATHs unique */
1073 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1074 /* allow connections to services from system trusted_ip host */
1075 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1076 /* enable loopback-based connections between peers */
1077 GNUNET_CONFIGURATION_set_value_string (cfg,
1079 "USE_LOCALADDR", "YES");
1080 GNUNET_free (uc.gnunet_home);
1081 if ((NULL != ports) && (NULL != nports))
1084 *nports = uc.nports;
1087 GNUNET_free_non_null (uc.ports);
1093 * Create a new configuration using the given configuration as a template;
1094 * ports and paths will be modified to select available ports on the local
1095 * system. The default configuration will be available in PATHS section under
1096 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1097 * section to the temporary directory specific to this configuration. If we run
1098 * out of "*port" numbers, return SYSERR.
1100 * This is primarily a helper function used internally
1101 * by 'GNUNET_TESTING_peer_configure'.
1103 * @param system system to use to coordinate resource usage
1104 * @param cfg template configuration to update
1105 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1106 * be incomplete and should not be used there upon
1109 GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1110 struct GNUNET_CONFIGURATION_Handle *cfg)
1112 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1117 * Configure a GNUnet peer. GNUnet must be installed on the local
1118 * system and available in the PATH.
1120 * @param system system to use to coordinate resource usage
1121 * @param cfg configuration to use; will be UPDATED (to reflect needed
1122 * changes in port numbers and paths)
1123 * @param key_number number of the hostkey to use for the peer
1124 * @param id identifier for the daemon, will be set, can be NULL
1125 * @param emsg set to freshly allocated error message (set to NULL on success),
1127 * @return handle to the peer, NULL on error
1129 struct GNUNET_TESTING_Peer *
1130 GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1131 struct GNUNET_CONFIGURATION_Handle *cfg,
1132 uint32_t key_number,
1133 struct GNUNET_PeerIdentity *id,
1136 struct GNUNET_TESTING_Peer *peer;
1137 struct GNUNET_DISK_FileHandle *fd;
1138 char *hostkey_filename;
1139 char *config_filename;
1140 char *libexec_binary;
1142 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
1144 struct SharedService *ss;
1145 struct SharedServiceInstance **ss_instances;
1147 unsigned int nports;
1151 ss_instances = NULL;
1154 if (key_number >= system->total_hostkeys)
1156 GNUNET_asprintf (&emsg_,
1157 _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1158 (unsigned int) system->total_hostkeys);
1163 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1165 GNUNET_asprintf (&emsg_,
1166 _("Failed to initialize hostkey for peer %u\n"),
1167 (unsigned int) key_number);
1173 GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1175 GNUNET_asprintf (&emsg_,
1176 _("PRIVATE_KEY option in PEER section missing in configuration\n"));
1179 /* Remove sections for shared services */
1180 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1182 ss = system->shared_services[cnt];
1183 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1185 if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg,
1188 GNUNET_asprintf (&emsg_,
1189 _("Failed to create configuration for peer "
1190 "(not enough free ports?)\n"));
1193 GNUNET_assert (GNUNET_OK ==
1194 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER",
1196 &hostkey_filename));
1197 fd = GNUNET_DISK_file_open (hostkey_filename,
1198 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1199 GNUNET_DISK_PERM_USER_READ
1200 | GNUNET_DISK_PERM_USER_WRITE);
1203 GNUNET_asprintf (&emsg_, _("Cannot open hostkey file `%s': %s\n"),
1204 hostkey_filename, STRERROR (errno));
1205 GNUNET_free (hostkey_filename);
1208 GNUNET_free (hostkey_filename);
1209 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1210 GNUNET_DISK_file_write (fd, system->hostkeys_data
1211 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1212 GNUNET_TESTING_HOSTKEYFILESIZE))
1214 GNUNET_asprintf (&emsg_,
1215 _("Failed to write hostkey file for peer %u: %s\n"),
1216 (unsigned int) key_number,
1218 GNUNET_DISK_file_close (fd);
1221 GNUNET_DISK_file_close (fd);
1222 ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *)
1223 * system->n_shared_services);
1224 for (cnt=0; cnt < system->n_shared_services; cnt++)
1226 ss = system->shared_services[cnt];
1227 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1228 if (NULL == ss_instances[cnt])
1231 GNUNET_assert (GNUNET_OK ==
1232 GNUNET_CONFIGURATION_get_value_filename
1233 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1234 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1236 GNUNET_asprintf (&emsg_,
1237 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1239 (unsigned int) key_number,
1241 GNUNET_free (config_filename);
1244 peer = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Peer));
1245 peer->ss_instances = ss_instances;
1246 peer->cfgfile = config_filename; /* Free in peer_destroy */
1247 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1248 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1249 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1252 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1253 peer->args = strdup ("");
1257 peer->main_binary = GNUNET_CONFIGURATION_expand_dollar (peer->cfg, peer->main_binary);
1258 peer->args = strdup (libexec_binary);
1260 peer->system = system;
1261 peer->key_number = key_number;
1262 GNUNET_free (libexec_binary);
1263 peer->ports = ports; /* Free in peer_destroy */
1264 peer->nports = nports;
1268 GNUNET_free_non_null (ss_instances);
1269 GNUNET_free_non_null (ports);
1270 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1274 GNUNET_free (emsg_);
1280 * Obtain the peer identity from a peer handle.
1282 * @param peer peer handle for which we want the peer's identity
1283 * @param id identifier for the daemon, will be set
1286 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1287 struct GNUNET_PeerIdentity *id)
1289 if (NULL != peer->id)
1291 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1294 peer->id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1295 GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system,
1298 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1305 * @param peer peer to start
1306 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1309 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1311 struct SharedServiceInstance *i;
1314 if (NULL != peer->main_process)
1317 return GNUNET_SYSERR;
1319 GNUNET_assert (NULL != peer->cfgfile);
1320 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1322 i = peer->ss_instances[cnt];
1323 if ((0 == i->n_refs)
1324 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1325 return GNUNET_SYSERR;
1328 peer->main_process = do_start_process (PIPE_CONTROL,
1329 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1336 if (NULL == peer->main_process)
1338 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1339 _("Failed to start `%s': %s\n"),
1342 return GNUNET_SYSERR;
1349 * Start a service at a peer using its ARM service
1351 * @param peer the peer whose service has to be started
1352 * @param service_name name of the service to start
1353 * @param timeout how long should the ARM API try to send the request to start
1355 * @param cont the callback to call with result and status from ARM API
1356 * @param cont_cls the closure for the above callback
1357 * @return GNUNET_OK upon successfully queuing the service start request;
1358 * GNUNET_SYSERR upon error
1361 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1362 const char *service_name,
1363 struct GNUNET_TIME_Relative timeout,
1364 GNUNET_ARM_ResultCallback cont,
1367 if (NULL == peer->ah)
1368 return GNUNET_SYSERR;
1369 GNUNET_ARM_request_service_start (peer->ah,
1371 GNUNET_OS_INHERIT_STD_ALL,
1379 * Stop a service at a peer using its ARM service
1381 * @param peer the peer whose service has to be stopped
1382 * @param service_name name of the service to stop
1383 * @param timeout how long should the ARM API try to send the request to stop
1385 * @param cont the callback to call with result and status from ARM API
1386 * @param cont_cls the closure for the above callback
1387 * @return GNUNET_OK upon successfully queuing the service stop request;
1388 * GNUNET_SYSERR upon error
1391 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1392 const char *service_name,
1393 struct GNUNET_TIME_Relative timeout,
1394 GNUNET_ARM_ResultCallback cont,
1397 if (NULL == peer->ah)
1398 return GNUNET_SYSERR;
1399 GNUNET_ARM_request_service_stop (peer->ah,
1408 * Sends SIGTERM to the peer's main process
1410 * @param peer the handle to the peer
1411 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1412 * or upon any error while sending SIGTERM
1415 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1417 struct SharedServiceInstance *i;
1420 if (NULL == peer->main_process)
1423 return GNUNET_SYSERR;
1425 if (0 != GNUNET_OS_process_kill (peer->main_process, GNUNET_TERM_SIG))
1426 return GNUNET_SYSERR;
1427 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1429 i = peer->ss_instances[cnt];
1430 GNUNET_assert (0 != i->n_refs);
1433 stop_shared_service_instance (i);
1440 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1442 * @param peer the handle to the peer
1443 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1444 * or upon any error while waiting
1447 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1451 if (NULL == peer->main_process)
1454 return GNUNET_SYSERR;
1456 ret = GNUNET_OS_process_wait (peer->main_process);
1457 GNUNET_OS_process_destroy (peer->main_process);
1458 peer->main_process = NULL;
1466 * @param peer peer to stop
1467 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1470 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1472 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1473 return GNUNET_SYSERR;
1474 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1475 return GNUNET_SYSERR;
1481 * Function called whenever we connect to or disconnect from ARM.
1483 * @param cls closure
1484 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1485 * GNUNET_SYSERR on error.
1488 disconn_status (void *cls,
1491 struct GNUNET_TESTING_Peer *peer = cls;
1493 if (GNUNET_SYSERR == connected)
1495 peer->cb (peer->cb_cls, peer, connected);
1498 if (GNUNET_YES == connected)
1500 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1503 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1504 GNUNET_ARM_disconnect_and_free (peer->ah);
1506 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1511 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1512 * through the GNUNET_TESTING_PeerStopCallback().
1514 * @param peer the peer to stop
1515 * @param cb the callback to signal peer shutdown
1516 * @param cb_cls closure for the above callback
1517 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1518 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1522 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1523 GNUNET_TESTING_PeerStopCallback cb,
1526 if (NULL == peer->main_process)
1527 return GNUNET_SYSERR;
1528 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1529 if (NULL == peer->ah)
1530 return GNUNET_SYSERR;
1532 peer->cb_cls = cb_cls;
1538 * Cancel a previous asynchronous peer stop request.
1539 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1540 * peer. It is an error to call this function if the peer stop callback was
1543 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1547 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1549 GNUNET_assert (NULL != peer->ah);
1550 GNUNET_ARM_disconnect_and_free (peer->ah);
1556 * Destroy the peer. Releases resources locked during peer configuration.
1557 * If the peer is still running, it will be stopped AND a warning will be
1558 * printed (users of the API should stop the peer explicitly first).
1560 * @param peer peer to destroy
1563 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1567 if (NULL != peer->main_process)
1568 GNUNET_TESTING_peer_stop (peer);
1569 if (NULL != peer->ah)
1570 GNUNET_ARM_disconnect_and_free (peer->ah);
1571 if (NULL != peer->mh)
1572 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1573 GNUNET_free (peer->cfgfile);
1574 if (NULL != peer->cfg)
1575 GNUNET_CONFIGURATION_destroy (peer->cfg);
1576 GNUNET_free (peer->main_binary);
1577 GNUNET_free (peer->args);
1578 GNUNET_free_non_null (peer->id);
1579 GNUNET_free_non_null (peer->ss_instances);
1580 if (NULL != peer->ports)
1582 for (cnt = 0; cnt < peer->nports; cnt++)
1583 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1584 GNUNET_free (peer->ports);
1591 * Start a single peer and run a test using the testing library.
1592 * Starts a peer using the given configuration and then invokes the
1593 * given callback. This function ALSO initializes the scheduler loop
1594 * and should thus be called directly from "main". The testcase
1595 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1597 * @param testdir only the directory name without any path. This is used for
1598 * all service homes; the directory will be created in a temporary
1599 * location depending on the underlying OS
1600 * @param cfgfilename name of the configuration file to use;
1601 * use NULL to only run with defaults
1602 * @param tm main function of the testcase
1603 * @param tm_cls closure for 'tm'
1604 * @return 0 on success, 1 on error
1607 GNUNET_TESTING_peer_run (const char *testdir,
1608 const char *cfgfilename,
1609 GNUNET_TESTING_TestMain tm,
1612 return GNUNET_TESTING_service_run (testdir, "arm",
1613 cfgfilename, tm, tm_cls);
1618 * Structure for holding service data
1620 struct ServiceContext
1623 * The configuration of the peer in which the service is run
1625 const struct GNUNET_CONFIGURATION_Handle *cfg;
1628 * Callback to signal service startup
1630 GNUNET_TESTING_TestMain tm;
1633 * The peer in which the service is run.
1635 struct GNUNET_TESTING_Peer *peer;
1638 * Closure for the above callback
1645 * Callback to be called when SCHEDULER has been started
1647 * @param cls the ServiceContext
1648 * @param tc the TaskContext
1651 service_run_main (void *cls,
1652 const struct GNUNET_SCHEDULER_TaskContext *tc)
1654 struct ServiceContext *sc = cls;
1656 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1661 * Start a single service (no ARM, except of course if the given
1662 * service name is 'arm') and run a test using the testing library.
1663 * Starts a service using the given configuration and then invokes the
1664 * given callback. This function ALSO initializes the scheduler loop
1665 * and should thus be called directly from "main". The testcase
1666 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1668 * This function is useful if the testcase is for a single service
1669 * and if that service doesn't itself depend on other services.
1671 * @param testdir only the directory name without any path. This is used for
1672 * all service homes; the directory will be created in a temporary
1673 * location depending on the underlying OS
1674 * @param service_name name of the service to run
1675 * @param cfgfilename name of the configuration file to use;
1676 * use NULL to only run with defaults
1677 * @param tm main function of the testcase
1678 * @param tm_cls closure for 'tm'
1679 * @return 0 on success, 1 on error
1682 GNUNET_TESTING_service_run (const char *testdir,
1683 const char *service_name,
1684 const char *cfgfilename,
1685 GNUNET_TESTING_TestMain tm,
1688 struct ServiceContext sc;
1689 struct GNUNET_TESTING_System *system;
1690 struct GNUNET_TESTING_Peer *peer;
1691 struct GNUNET_CONFIGURATION_Handle *cfg;
1693 char *libexec_binary;
1695 GNUNET_log_setup (testdir, "WARNING", NULL);
1696 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1699 cfg = GNUNET_CONFIGURATION_create ();
1700 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1702 LOG (GNUNET_ERROR_TYPE_ERROR,
1703 _("Failed to load configuration from %s\n"), cfgfilename);
1704 GNUNET_CONFIGURATION_destroy (cfg);
1705 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1708 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1711 GNUNET_CONFIGURATION_destroy (cfg);
1712 hostkeys_unload (system);
1713 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1716 GNUNET_free (peer->main_binary);
1717 GNUNET_free (peer->args);
1718 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1719 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1720 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1723 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1724 peer->args = strdup ("");
1727 peer->args = strdup (libexec_binary);
1729 GNUNET_free (libexec_binary);
1730 GNUNET_free (binary);
1731 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1733 GNUNET_TESTING_peer_destroy (peer);
1734 GNUNET_CONFIGURATION_destroy (cfg);
1735 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1742 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1743 if ((NULL != peer->main_process) &&
1744 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1746 GNUNET_TESTING_peer_destroy (peer);
1747 GNUNET_CONFIGURATION_destroy (cfg);
1748 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1751 GNUNET_TESTING_peer_destroy (peer);
1752 GNUNET_CONFIGURATION_destroy (cfg);
1753 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1759 * Sometimes we use the binary name to determine which specific
1760 * test to run. In those cases, the string after the last "_"
1761 * in 'argv[0]' specifies a string that determines the configuration
1762 * file or plugin to use.
1764 * This function returns the respective substring, taking care
1765 * of issues such as binaries ending in '.exe' on W32.
1767 * @param argv0 the name of the binary
1768 * @return string between the last '_' and the '.exe' (or the end of the string),
1769 * NULL if argv0 has no '_'
1772 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1774 size_t slen = strlen (argv0) + 1;
1779 memcpy (sbuf, argv0, slen);
1780 ret = strrchr (sbuf, '_');
1783 ret++; /* skip underscore */
1784 dot = strchr (ret, '.');
1787 return GNUNET_strdup (ret);
1791 /* end of testing.c */