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. This variable will be
359 * overridden with the value of the environmental variable
360 * GNUNET_TESTING_PREFIX, if it exists.
361 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
362 * service configurations generated to allow control connections from
363 * this ip. This can either be a single ip address or a network address
365 * @param hostname the hostname of the system we are using for testing; NULL for
367 * @param shared_services NULL terminated array describing services that are to
368 * be shared among peers
369 * @param lowport lowest port number this system is allowed to allocate (inclusive)
370 * @param highport highest port number this system is allowed to allocate (exclusive)
371 * @return handle to this system, NULL on error
373 struct GNUNET_TESTING_System *
374 GNUNET_TESTING_system_create_with_portrange (const char *testdir,
375 const char *trusted_ip,
376 const char *hostname,
378 GNUNET_TESTING_SharedService *
383 struct GNUNET_TESTING_System *system;
384 struct GNUNET_TESTING_SharedService tss;
385 struct SharedService *ss;
388 GNUNET_assert (NULL != testdir);
389 system = GNUNET_malloc (sizeof (struct GNUNET_TESTING_System));
390 if (NULL != (system->tmppath = getenv ("GNUNET_TESTING_PREFIX")))
391 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
393 system->tmppath = GNUNET_strdup (system->tmppath);
394 system->lowport = lowport;
395 system->highport = highport;
396 if (NULL == system->tmppath)
398 GNUNET_free (system);
401 if (NULL != trusted_ip)
402 system->trusted_ip = GNUNET_strdup (trusted_ip);
403 if (NULL != hostname)
404 system->hostname = GNUNET_strdup (hostname);
405 if (GNUNET_OK != hostkeys_load (system))
407 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
410 if (NULL == shared_services)
412 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
414 tss = shared_services[cnt];
415 ss = GNUNET_malloc (sizeof (struct SharedService));
416 ss->sname = GNUNET_strdup (tss.service);
417 ss->cfg = GNUNET_CONFIGURATION_create ();
418 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, ss->sname,
419 &cfg_copy_iterator, ss->cfg);
420 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "TESTING",
421 &cfg_copy_iterator, ss->cfg);
422 ss->share = tss.share;
423 GNUNET_array_append (system->shared_services, system->n_shared_services,
431 * Create a system handle. There must only be one system handle per operating
432 * system. Uses a default range for allowed ports. Ports are still tested for
435 * @param testdir only the directory name without any path. This is used for all
436 * service homes; the directory will be created in a temporary location
437 * depending on the underlying OS
438 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
439 * service configurations generated to allow control connections from
440 * this ip. This can either be a single ip address or a network address
442 * @param hostname the hostname of the system we are using for testing; NULL for
444 * @param shared_services NULL terminated array describing services that are to
445 * be shared among peers
446 * @return handle to this system, NULL on error
448 struct GNUNET_TESTING_System *
449 GNUNET_TESTING_system_create (const char *testdir,
450 const char *trusted_ip,
451 const char *hostname,
452 const struct GNUNET_TESTING_SharedService *
455 return GNUNET_TESTING_system_create_with_portrange (testdir,
464 cleanup_shared_service_instance (struct SharedServiceInstance *i)
466 if (NULL != i->cfg_fn)
468 (void) unlink (i->cfg_fn);
469 GNUNET_free (i->cfg_fn);
471 GNUNET_free_non_null (i->unix_sock);
472 GNUNET_free_non_null (i->port_str);
473 GNUNET_break (NULL == i->proc);
474 GNUNET_break (0 == i->n_refs);
479 start_shared_service_instance (struct SharedServiceInstance *i)
482 char *libexec_binary;
484 GNUNET_assert (NULL == i->proc);
485 GNUNET_assert (NULL != i->cfg_fn);
486 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
487 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
488 GNUNET_free (binary);
489 i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
490 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
497 GNUNET_free (libexec_binary);
499 return GNUNET_SYSERR;
505 stop_shared_service_instance (struct SharedServiceInstance *i)
507 GNUNET_break (0 == i->n_refs);
508 if (0 != GNUNET_OS_process_kill (i->proc, SIGTERM))
509 LOG (GNUNET_ERROR_TYPE_WARNING,
510 "Killing shared service instance (%s) failed\n", i->ss->sname);
511 (void) GNUNET_OS_process_wait (i->proc);
512 GNUNET_OS_process_destroy (i->proc);
518 * Free system resources.
520 * @param system system to be freed
521 * @param remove_paths should the 'testdir' and all subdirectories
522 * be removed (clean up on shutdown)?
525 GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
528 struct SharedService *ss;
529 struct SharedServiceInstance *i;
533 if (NULL != system->hostkeys_data)
534 hostkeys_unload (system);
535 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
537 ss = system->shared_services[ss_cnt];
538 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
540 i = ss->instances[i_cnt];
542 stop_shared_service_instance (i);
543 cleanup_shared_service_instance (i);
545 GNUNET_free_non_null (ss->instances);
546 GNUNET_CONFIGURATION_destroy (ss->cfg);
547 GNUNET_free (ss->sname);
550 GNUNET_free_non_null (system->shared_services);
551 if (GNUNET_YES == remove_paths)
552 GNUNET_DISK_directory_remove (system->tmppath);
553 GNUNET_free (system->tmppath);
554 GNUNET_free_non_null (system->trusted_ip);
555 GNUNET_free_non_null (system->hostname);
556 GNUNET_free (system);
561 * Reserve a TCP or UDP port for a peer.
563 * @param system system to use for reservation tracking
564 * @return 0 if no free port was available
567 GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
569 struct GNUNET_NETWORK_Handle *socket;
570 struct addrinfo hint;
571 struct addrinfo *ret;
573 uint32_t *port_buckets;
582 FIXME: Instead of using getaddrinfo we should try to determine the port
583 status by the following heurestics.
585 On systems which support both IPv4 and IPv6, only ports open on both
586 address families are considered open.
587 On system with either IPv4 or IPv6. A port is considered open if it's
588 open in the respective address family
590 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
591 hint.ai_socktype = 0;
592 hint.ai_protocol = 0;
595 hint.ai_canonname = NULL;
597 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
598 port_buckets = system->reserved_ports;
599 for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++)
601 xor_image = (UINT32_MAX ^ port_buckets[index]);
602 if (0 == xor_image) /* Ports in the bucket are full */
604 pos = system->lowport % 32;
607 if (0 == ((xor_image >> pos) & 1U))
612 open_port = (index * 32) + pos;
613 if (open_port >= system->highport)
615 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
617 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
618 GNUNET_free (open_port_str);
619 bind_status = GNUNET_NO;
620 for (ai = ret; NULL != ai; ai = ai->ai_next)
622 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
625 bind_status = GNUNET_NETWORK_socket_bind (socket,
629 GNUNET_NETWORK_socket_close (socket);
630 if (GNUNET_OK != bind_status)
632 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0);
635 bind_status = GNUNET_NETWORK_socket_bind (socket,
639 GNUNET_NETWORK_socket_close (socket);
640 if (GNUNET_OK != bind_status)
643 port_buckets[index] |= (1U << pos); /* Set the port bit */
645 if (GNUNET_OK == bind_status)
647 LOG (GNUNET_ERROR_TYPE_DEBUG,
648 "Found a free port %u\n", (unsigned int) open_port);
659 * Release reservation of a TCP or UDP port for a peer
660 * (used during GNUNET_TESTING_peer_destroy).
662 * @param system system to use for reservation tracking
663 * @param port reserved port to release
666 GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
669 uint32_t *port_buckets;
673 port_buckets = system->reserved_ports;
676 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
677 if (0 == (port_buckets[bucket] & (1U << pos)))
679 GNUNET_break(0); /* Port was not reserved by us using reserve_port() */
682 port_buckets[bucket] &= ~(1U << pos);
687 * Testing includes a number of pre-created hostkeys for
688 * faster peer startup. This function can be used to
689 * access the n-th key of those pre-created hostkeys; note
690 * that these keys are ONLY useful for testing and not
691 * secure as the private keys are part of the public
692 * GNUnet source code.
694 * This is primarily a helper function used internally
695 * by #GNUNET_TESTING_peer_configure.
697 * @param system the testing system handle
698 * @param key_number desired pre-created hostkey to obtain
699 * @param id set to the peer's identity (hash of the public
700 * key; if NULL, GNUNET_SYSERR is returned immediately
701 * @return NULL on error (not enough keys)
703 struct GNUNET_CRYPTO_EccPrivateKey *
704 GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
706 struct GNUNET_PeerIdentity *id)
708 struct GNUNET_CRYPTO_EccPrivateKey *private_key;
710 if ((NULL == id) || (NULL == system->hostkeys_data))
712 if (key_number >= system->total_hostkeys)
714 LOG (GNUNET_ERROR_TYPE_ERROR,
715 _("Key number %u does not exist\n"), key_number);
718 private_key = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey);
720 system->hostkeys_data +
721 (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
722 GNUNET_TESTING_HOSTKEYFILESIZE);
723 GNUNET_CRYPTO_ecc_key_get_public_for_signature (private_key,
730 * Structure for holding data to build new configurations from a configuration
736 * The system for which we are building configurations
738 struct GNUNET_TESTING_System *system;
741 * The configuration we are building
743 struct GNUNET_CONFIGURATION_Handle *cfg;
746 * The customized service home path for this peer
751 * Array of ports currently allocated to this peer. These ports will be
752 * released upon peer destroy and can be used by other peers which are
758 * The number of ports in the above array
763 * build status - to signal error while building a configuration
770 * Function to iterate over options. Copies
771 * the options to the target configuration,
772 * updating PORT values as needed.
774 * @param cls the UpdateContext
775 * @param section name of the section
776 * @param option name of the option
777 * @param value value of the option
780 update_config (void *cls, const char *section, const char *option,
783 struct UpdateContext *uc = cls;
787 char *single_variable;
788 char *per_host_variable;
789 unsigned long long num_per_host;
792 if (GNUNET_OK != uc->status)
794 if (! ((0 == strcmp (option, "PORT"))
795 || (0 == strcmp (option, "UNIXPATH"))
796 || (0 == strcmp (option, "HOSTNAME"))))
798 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
799 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
800 if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
804 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
807 new_port = GNUNET_TESTING_reserve_port (uc->system);
810 uc->status = GNUNET_SYSERR;
811 GNUNET_free (single_variable);
812 GNUNET_free (per_host_variable);
815 GNUNET_snprintf (cval, sizeof (cval), "%u", new_port);
817 GNUNET_array_append (uc->ports, uc->nports, new_port);
819 else if ((ival != 0) &&
821 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
823 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
827 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
828 /* ival + ctx->fdnum % num_per_host); */
830 GNUNET_break (0); /* FIXME */
833 if (0 == strcmp (option, "UNIXPATH"))
836 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
839 GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock",
840 uc->service_home, section);
843 else if ((GNUNET_YES ==
844 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
849 GNUNET_break(0); /* FIXME */
852 if (0 == strcmp (option, "HOSTNAME"))
854 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
856 GNUNET_free (single_variable);
857 GNUNET_free (per_host_variable);
858 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
863 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
864 * 'trusted_hosts' in all sections
866 * @param cls the UpdateContext
867 * @param section name of the section
870 update_config_sections (void *cls,
873 struct UpdateContext *uc = cls;
877 char *orig_allowed_hosts;
879 char *ACCEPT_FROM_key;
885 /* Ignore certain options from sections. See
886 https://gnunet.org/bugs/view.php?id=2476 */
887 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
888 "TESTING_IGNORE_KEYS"))
892 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section,
893 "TESTING_IGNORE_KEYS", &val));
895 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
901 ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt);
903 for (key = 0; key < ikeys_cnt; key++)
906 ptr = strstr (ptr, ";");
914 for (key = 0; key < ikeys_cnt; key++)
916 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
919 if ((key == ikeys_cnt) &&
920 (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
924 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr))
926 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section,
927 "ADVERTISED_PORT", ptr);
931 for (key = 0; key < ikeys_cnt; key++)
933 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
942 GNUNET_free_non_null (val);
943 ACCEPT_FROM_key = "ACCEPT_FROM";
944 if ((NULL != uc->system->trusted_ip) &&
945 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
946 ACCEPT_FROM_key = "ACCEPT_FROM6";
948 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key,
949 &orig_allowed_hosts))
951 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
953 if (NULL == uc->system->trusted_ip)
954 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
956 GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts,
957 uc->system->trusted_ip);
958 GNUNET_free (orig_allowed_hosts);
959 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key,
961 GNUNET_free (allowed_hosts);
964 static struct SharedServiceInstance *
965 associate_shared_service (struct GNUNET_TESTING_System *system,
966 struct SharedService *ss,
967 struct GNUNET_CONFIGURATION_Handle *cfg)
969 struct SharedServiceInstance *i;
970 struct GNUNET_CONFIGURATION_Handle *temp;
975 if ( ((0 == ss->share) && (NULL == ss->instances))
978 && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) )
980 i = GNUNET_malloc (sizeof (struct SharedServiceInstance));
982 (void) GNUNET_asprintf (&service_home, "%s/shared/%s/%u",
983 system->tmppath, ss->sname, ss->n_instances);
984 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", service_home);
985 port = GNUNET_TESTING_reserve_port (system);
988 GNUNET_free (service_home);
989 cleanup_shared_service_instance (i);
992 GNUNET_array_append (ss->instances, ss->n_instances, i);
993 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
994 (void) GNUNET_asprintf (&i->port_str, "%u", port);
995 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", service_home);
996 GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "SERVICEHOME",
998 GNUNET_free (service_home);
999 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH",
1001 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT",
1003 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1005 GNUNET_CONFIGURATION_destroy (temp);
1006 cleanup_shared_service_instance (i);
1009 GNUNET_CONFIGURATION_destroy (temp);
1013 GNUNET_assert (NULL != ss->instances);
1014 GNUNET_assert (0 < ss->n_instances);
1015 i = ss->instances[ss->n_instances - 1];
1017 GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname,
1018 &cfg_copy_iterator, cfg);
1019 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH",
1021 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1027 * Create a new configuration using the given configuration as a template;
1028 * ports and paths will be modified to select available ports on the local
1029 * system. The default configuration will be available in PATHS section under
1030 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1031 * section to the temporary directory specific to this configuration. If we run
1032 * out of "*port" numbers, return SYSERR.
1034 * This is primarily a helper function used internally
1035 * by 'GNUNET_TESTING_peer_configure'.
1037 * @param system system to use to coordinate resource usage
1038 * @param cfg template configuration to update
1039 * @param ports array with port numbers used in the created configuration.
1040 * Will be updated upon successful return. Can be NULL
1041 * @param nports the size of the `ports' array. Will be updated.
1042 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1043 * be incomplete and should not be used there upon
1046 GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1047 struct GNUNET_CONFIGURATION_Handle *cfg,
1049 unsigned int *nports)
1051 struct UpdateContext uc;
1052 char *default_config;
1056 uc.status = GNUNET_OK;
1059 GNUNET_asprintf (&uc.service_home, "%s/%u", system->tmppath,
1060 system->path_counter++);
1061 GNUNET_asprintf (&default_config, "%s/config", uc.service_home);
1062 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
1064 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
1066 GNUNET_free (default_config);
1067 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "SERVICEHOME",
1069 /* make PORTs and UNIXPATHs unique */
1070 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1071 /* allow connections to services from system trusted_ip host */
1072 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1073 /* enable loopback-based connections between peers */
1074 GNUNET_CONFIGURATION_set_value_string (cfg,
1076 "USE_LOCALADDR", "YES");
1077 GNUNET_free (uc.service_home);
1078 if ((NULL != ports) && (NULL != nports))
1081 *nports = uc.nports;
1084 GNUNET_free_non_null (uc.ports);
1090 * Create a new configuration using the given configuration as a template;
1091 * ports and paths will be modified to select available ports on the local
1092 * system. The default configuration will be available in PATHS section under
1093 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1094 * section to the temporary directory specific to this configuration. If we run
1095 * out of "*port" numbers, return SYSERR.
1097 * This is primarily a helper function used internally
1098 * by 'GNUNET_TESTING_peer_configure'.
1100 * @param system system to use to coordinate resource usage
1101 * @param cfg template configuration to update
1102 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1103 * be incomplete and should not be used there upon
1106 GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1107 struct GNUNET_CONFIGURATION_Handle *cfg)
1109 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1114 * Configure a GNUnet peer. GNUnet must be installed on the local
1115 * system and available in the PATH.
1117 * @param system system to use to coordinate resource usage
1118 * @param cfg configuration to use; will be UPDATED (to reflect needed
1119 * changes in port numbers and paths)
1120 * @param key_number number of the hostkey to use for the peer
1121 * @param id identifier for the daemon, will be set, can be NULL
1122 * @param emsg set to freshly allocated error message (set to NULL on success),
1124 * @return handle to the peer, NULL on error
1126 struct GNUNET_TESTING_Peer *
1127 GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1128 struct GNUNET_CONFIGURATION_Handle *cfg,
1129 uint32_t key_number,
1130 struct GNUNET_PeerIdentity *id,
1133 struct GNUNET_TESTING_Peer *peer;
1134 struct GNUNET_DISK_FileHandle *fd;
1135 char *hostkey_filename;
1136 char *config_filename;
1137 char *libexec_binary;
1139 struct GNUNET_CRYPTO_EccPrivateKey *pk;
1141 struct SharedService *ss;
1142 struct SharedServiceInstance **ss_instances;
1144 unsigned int nports;
1148 ss_instances = NULL;
1151 if (key_number >= system->total_hostkeys)
1153 GNUNET_asprintf (&emsg_,
1154 _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1155 (unsigned int) system->total_hostkeys);
1160 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1162 GNUNET_asprintf (&emsg_,
1163 _("Failed to initialize hostkey for peer %u\n"),
1164 (unsigned int) key_number);
1170 GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1172 GNUNET_asprintf (&emsg_,
1173 _("PRIVATE_KEY option in PEER section missing in configuration\n"));
1176 /* Remove sections for shared services */
1177 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1179 ss = system->shared_services[cnt];
1180 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1182 if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg,
1185 GNUNET_asprintf (&emsg_,
1186 _("Failed to create configuration for peer "
1187 "(not enough free ports?)\n"));
1190 GNUNET_assert (GNUNET_OK ==
1191 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER",
1193 &hostkey_filename));
1194 fd = GNUNET_DISK_file_open (hostkey_filename,
1195 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1196 GNUNET_DISK_PERM_USER_READ
1197 | GNUNET_DISK_PERM_USER_WRITE);
1200 GNUNET_asprintf (&emsg_, _("Cannot open hostkey file `%s': %s\n"),
1201 hostkey_filename, STRERROR (errno));
1202 GNUNET_free (hostkey_filename);
1205 GNUNET_free (hostkey_filename);
1206 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1207 GNUNET_DISK_file_write (fd, system->hostkeys_data
1208 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1209 GNUNET_TESTING_HOSTKEYFILESIZE))
1211 GNUNET_asprintf (&emsg_,
1212 _("Failed to write hostkey file for peer %u: %s\n"),
1213 (unsigned int) key_number,
1215 GNUNET_DISK_file_close (fd);
1218 GNUNET_DISK_file_close (fd);
1219 ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *)
1220 * system->n_shared_services);
1221 for (cnt=0; cnt < system->n_shared_services; cnt++)
1223 ss = system->shared_services[cnt];
1224 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1225 if (NULL == ss_instances[cnt])
1228 GNUNET_assert (GNUNET_OK ==
1229 GNUNET_CONFIGURATION_get_value_string
1230 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1231 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1233 GNUNET_asprintf (&emsg_,
1234 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1236 (unsigned int) key_number,
1238 GNUNET_free (config_filename);
1241 peer = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Peer));
1242 peer->ss_instances = ss_instances;
1243 peer->cfgfile = config_filename; /* Free in peer_destroy */
1244 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1245 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1246 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1249 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1250 peer->args = strdup ("");
1253 peer->args = strdup (libexec_binary);
1254 peer->system = system;
1255 peer->key_number = key_number;
1256 GNUNET_free (libexec_binary);
1257 peer->ports = ports; /* Free in peer_destroy */
1258 peer->nports = nports;
1262 GNUNET_free_non_null (ss_instances);
1263 GNUNET_free_non_null (ports);
1264 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1268 GNUNET_free (emsg_);
1274 * Obtain the peer identity from a peer handle.
1276 * @param peer peer handle for which we want the peer's identity
1277 * @param id identifier for the daemon, will be set
1280 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1281 struct GNUNET_PeerIdentity *id)
1283 if (NULL != peer->id)
1285 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1288 peer->id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1289 GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system,
1292 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1299 * @param peer peer to start
1300 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1303 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1305 struct SharedServiceInstance *i;
1308 if (NULL != peer->main_process)
1311 return GNUNET_SYSERR;
1313 GNUNET_assert (NULL != peer->cfgfile);
1314 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1316 i = peer->ss_instances[cnt];
1317 if ((0 == i->n_refs)
1318 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1319 return GNUNET_SYSERR;
1322 peer->main_process = GNUNET_OS_start_process (PIPE_CONTROL,
1323 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1331 if (NULL == peer->main_process)
1333 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1334 _("Failed to start `%s': %s\n"),
1337 return GNUNET_SYSERR;
1344 * Start a service at a peer using its ARM service
1346 * @param peer the peer whose service has to be started
1347 * @param service_name name of the service to start
1348 * @param timeout how long should the ARM API try to send the request to start
1350 * @param cont the callback to call with result and status from ARM API
1351 * @param cont_cls the closure for the above callback
1352 * @return GNUNET_OK upon successfully queuing the service start request;
1353 * GNUNET_SYSERR upon error
1356 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1357 const char *service_name,
1358 struct GNUNET_TIME_Relative timeout,
1359 GNUNET_ARM_ResultCallback cont,
1362 if (NULL == peer->ah)
1363 return GNUNET_SYSERR;
1364 GNUNET_ARM_request_service_start (peer->ah,
1366 GNUNET_OS_INHERIT_STD_ALL,
1374 * Stop a service at a peer using its ARM service
1376 * @param peer the peer whose service has to be stopped
1377 * @param service_name name of the service to stop
1378 * @param timeout how long should the ARM API try to send the request to stop
1380 * @param cont the callback to call with result and status from ARM API
1381 * @param cont_cls the closure for the above callback
1382 * @return GNUNET_OK upon successfully queuing the service stop request;
1383 * GNUNET_SYSERR upon error
1386 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1387 const char *service_name,
1388 struct GNUNET_TIME_Relative timeout,
1389 GNUNET_ARM_ResultCallback cont,
1392 if (NULL == peer->ah)
1393 return GNUNET_SYSERR;
1394 GNUNET_ARM_request_service_stop (peer->ah,
1403 * Sends SIGTERM to the peer's main process
1405 * @param peer the handle to the peer
1406 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1407 * or upon any error while sending SIGTERM
1410 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1412 struct SharedServiceInstance *i;
1415 if (NULL == peer->main_process)
1418 return GNUNET_SYSERR;
1420 if (0 != GNUNET_OS_process_kill (peer->main_process, SIGTERM))
1421 return GNUNET_SYSERR;
1422 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1424 i = peer->ss_instances[cnt];
1425 GNUNET_assert (0 != i->n_refs);
1428 stop_shared_service_instance (i);
1435 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1437 * @param peer the handle to the peer
1438 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1439 * or upon any error while waiting
1442 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1446 if (NULL == peer->main_process)
1449 return GNUNET_SYSERR;
1451 ret = GNUNET_OS_process_wait (peer->main_process);
1452 GNUNET_OS_process_destroy (peer->main_process);
1453 peer->main_process = NULL;
1461 * @param peer peer to stop
1462 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1465 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1467 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1468 return GNUNET_SYSERR;
1469 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1470 return GNUNET_SYSERR;
1476 * Function called whenever we connect to or disconnect from ARM.
1478 * @param cls closure
1479 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1480 * GNUNET_SYSERR on error.
1483 disconn_status (void *cls,
1486 struct GNUNET_TESTING_Peer *peer = cls;
1488 if (GNUNET_SYSERR == connected)
1490 peer->cb (peer->cb_cls, peer, connected);
1493 if (GNUNET_YES == connected)
1495 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1498 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1499 GNUNET_ARM_disconnect_and_free (peer->ah);
1501 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1506 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1507 * through the GNUNET_TESTING_PeerStopCallback().
1509 * @param peer the peer to stop
1510 * @param cb the callback to signal peer shutdown
1511 * @param cb_cls closure for the above callback
1512 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1513 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1517 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1518 GNUNET_TESTING_PeerStopCallback cb,
1521 if (NULL == peer->main_process)
1522 return GNUNET_SYSERR;
1523 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1524 if (NULL == peer->ah)
1525 return GNUNET_SYSERR;
1527 peer->cb_cls = cb_cls;
1533 * Cancel a previous asynchronous peer stop request.
1534 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1535 * peer. It is an error to call this function if the peer stop callback was
1538 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1542 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1544 GNUNET_assert (NULL != peer->ah);
1545 GNUNET_ARM_disconnect_and_free (peer->ah);
1551 * Destroy the peer. Releases resources locked during peer configuration.
1552 * If the peer is still running, it will be stopped AND a warning will be
1553 * printed (users of the API should stop the peer explicitly first).
1555 * @param peer peer to destroy
1558 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1562 if (NULL != peer->main_process)
1563 GNUNET_TESTING_peer_stop (peer);
1564 if (NULL != peer->ah)
1565 GNUNET_ARM_disconnect_and_free (peer->ah);
1566 if (NULL != peer->mh)
1567 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1568 GNUNET_free (peer->cfgfile);
1569 if (NULL != peer->cfg)
1570 GNUNET_CONFIGURATION_destroy (peer->cfg);
1571 GNUNET_free (peer->main_binary);
1572 GNUNET_free (peer->args);
1573 GNUNET_free_non_null (peer->id);
1574 GNUNET_free_non_null (peer->ss_instances);
1575 if (NULL != peer->ports)
1577 for (cnt = 0; cnt < peer->nports; cnt++)
1578 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1579 GNUNET_free (peer->ports);
1586 * Start a single peer and run a test using the testing library.
1587 * Starts a peer using the given configuration and then invokes the
1588 * given callback. This function ALSO initializes the scheduler loop
1589 * and should thus be called directly from "main". The testcase
1590 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1592 * @param testdir only the directory name without any path. This is used for
1593 * all service homes; the directory will be created in a temporary
1594 * location depending on the underlying OS
1595 * @param cfgfilename name of the configuration file to use;
1596 * use NULL to only run with defaults
1597 * @param tm main function of the testcase
1598 * @param tm_cls closure for 'tm'
1599 * @return 0 on success, 1 on error
1602 GNUNET_TESTING_peer_run (const char *testdir,
1603 const char *cfgfilename,
1604 GNUNET_TESTING_TestMain tm,
1607 return GNUNET_TESTING_service_run (testdir, "arm",
1608 cfgfilename, tm, tm_cls);
1613 * Structure for holding service data
1615 struct ServiceContext
1618 * The configuration of the peer in which the service is run
1620 const struct GNUNET_CONFIGURATION_Handle *cfg;
1623 * Callback to signal service startup
1625 GNUNET_TESTING_TestMain tm;
1628 * The peer in which the service is run.
1630 struct GNUNET_TESTING_Peer *peer;
1633 * Closure for the above callback
1640 * Callback to be called when SCHEDULER has been started
1642 * @param cls the ServiceContext
1643 * @param tc the TaskContext
1646 service_run_main (void *cls,
1647 const struct GNUNET_SCHEDULER_TaskContext *tc)
1649 struct ServiceContext *sc = cls;
1651 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1656 * Start a single service (no ARM, except of course if the given
1657 * service name is 'arm') and run a test using the testing library.
1658 * Starts a service using the given configuration and then invokes the
1659 * given callback. This function ALSO initializes the scheduler loop
1660 * and should thus be called directly from "main". The testcase
1661 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1663 * This function is useful if the testcase is for a single service
1664 * and if that service doesn't itself depend on other services.
1666 * @param testdir only the directory name without any path. This is used for
1667 * all service homes; the directory will be created in a temporary
1668 * location depending on the underlying OS
1669 * @param service_name name of the service to run
1670 * @param cfgfilename name of the configuration file to use;
1671 * use NULL to only run with defaults
1672 * @param tm main function of the testcase
1673 * @param tm_cls closure for 'tm'
1674 * @return 0 on success, 1 on error
1677 GNUNET_TESTING_service_run (const char *testdir,
1678 const char *service_name,
1679 const char *cfgfilename,
1680 GNUNET_TESTING_TestMain tm,
1683 struct ServiceContext sc;
1684 struct GNUNET_TESTING_System *system;
1685 struct GNUNET_TESTING_Peer *peer;
1686 struct GNUNET_CONFIGURATION_Handle *cfg;
1688 char *libexec_binary;
1690 GNUNET_log_setup (testdir, "WARNING", NULL);
1691 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1694 cfg = GNUNET_CONFIGURATION_create ();
1695 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1697 LOG (GNUNET_ERROR_TYPE_ERROR,
1698 _("Failed to load configuration from %s\n"), cfgfilename);
1699 GNUNET_CONFIGURATION_destroy (cfg);
1700 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1703 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1706 GNUNET_CONFIGURATION_destroy (cfg);
1707 hostkeys_unload (system);
1708 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1711 GNUNET_free (peer->main_binary);
1712 GNUNET_free (peer->args);
1713 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1714 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1715 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1718 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1719 peer->args = strdup ("");
1722 peer->args = strdup (libexec_binary);
1724 GNUNET_free (libexec_binary);
1725 GNUNET_free (binary);
1726 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1728 GNUNET_TESTING_peer_destroy (peer);
1729 GNUNET_CONFIGURATION_destroy (cfg);
1730 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1737 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1738 if ((NULL != peer->main_process) &&
1739 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1741 GNUNET_TESTING_peer_destroy (peer);
1742 GNUNET_CONFIGURATION_destroy (cfg);
1743 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1746 GNUNET_TESTING_peer_destroy (peer);
1747 GNUNET_CONFIGURATION_destroy (cfg);
1748 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1754 * Sometimes we use the binary name to determine which specific
1755 * test to run. In those cases, the string after the last "_"
1756 * in 'argv[0]' specifies a string that determines the configuration
1757 * file or plugin to use.
1759 * This function returns the respective substring, taking care
1760 * of issues such as binaries ending in '.exe' on W32.
1762 * @param argv0 the name of the binary
1763 * @return string between the last '_' and the '.exe' (or the end of the string),
1764 * NULL if argv0 has no '_'
1767 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1769 size_t slen = strlen (argv0) + 1;
1774 memcpy (sbuf, argv0, slen);
1775 ret = strrchr (sbuf, '_');
1778 ret++; /* skip underscore */
1779 dot = strchr (ret, '.');
1782 return GNUNET_strdup (ret);
1786 /* end of testing.c */