2 This file is part of GNUnet
3 (C) 2008, 2009, 2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testing/testing.c
23 * @brief convenience API for writing testcases for GNUnet
24 * Many testcases need to start and stop a peer/service
25 * and this library is supposed to make that easier
26 * for TESTCASES. Normal programs should always
27 * use functions from gnunet_{util,arm}_lib.h. This API is
28 * ONLY for writing testcases (or internal use of the testbed).
29 * @author Christian Grothoff
33 #include "gnunet_util_lib.h"
34 #include "gnunet_arm_service.h"
35 #include "gnunet_testing_lib.h"
37 #define LOG(kind,...) \
38 GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
42 * We need pipe control only on WINDOWS
45 #define PIPE_CONTROL GNUNET_YES
47 #define PIPE_CONTROL GNUNET_NO
52 * Lowest port used for GNUnet testing. Should be high enough to not
53 * conflict with other applications running on the hosts but be low
54 * enough to not conflict with client-ports (typically starting around
57 #define LOW_PORT 12000
60 * Highest port used for GNUnet testing. Should be low enough to not
61 * conflict with the port range for "local" ports (client apps; see
62 * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
64 #define HIGH_PORT 56000
67 struct SharedServiceInstance
69 struct SharedService *ss;
73 struct GNUNET_OS_Process *proc;
86 struct SharedServiceInstance **instances;
88 struct GNUNET_CONFIGURATION_Handle *cfg;
94 unsigned int n_instances;
99 * Handle for a system on which GNUnet peers are executed;
100 * a system is used for reserving unique paths and ports.
102 struct GNUNET_TESTING_System
105 * Prefix (i.e. "/tmp/gnunet-testing/") we prepend to each
110 * The trusted ip. Can either be a single ip address or a network address in
121 * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes.
126 * memory map for 'hostkeys_data'.
128 struct GNUNET_DISK_MapHandle *map;
130 struct SharedService **shared_services;
132 unsigned int n_shared_services;
135 * Bitmap where each port that has already been reserved for some GNUnet peer
136 * is recorded. Note that we make no distinction between TCP and UDP ports
137 * and test if a port is already in use before assigning it to a peer/service.
138 * If we detect that a port is already in use, we also mark it in this bitmap.
139 * So all the bits that are zero merely indicate ports that MIGHT be available
142 uint32_t reserved_ports[65536 / 32];
145 * Counter we use to make service home paths unique on this system;
146 * the full path consists of the tmppath and this number. Each
147 * UNIXPATH for a peer is also modified to include the respective
148 * path counter to ensure uniqueness. This field is incremented
149 * by one for each configured peer. Even if peers are destroyed,
150 * we never re-use path counters.
152 uint32_t path_counter;
155 * The number of hostkeys
157 uint32_t total_hostkeys;
160 * Lowest port we are allowed to use.
165 * Highest port we are allowed to use.
172 * Handle for a GNUnet peer controlled by testing.
174 struct GNUNET_TESTING_Peer
177 * The TESTING system associated with this peer
179 struct GNUNET_TESTING_System *system;
182 * Path to the configuration file for this peer.
187 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
188 * Typically 'gnunet-service-arm' (but can be set to a
189 * specific service by 'GNUNET_TESTING_service_run' if
196 * Handle to the running binary of the service, NULL if the
197 * peer/service is currently not running.
199 struct GNUNET_OS_Process *main_process;
202 * The handle to the peer's ARM service
204 struct GNUNET_ARM_Handle *ah;
207 * Handle to ARM monitoring
209 struct GNUNET_ARM_MonitorHandle *mh;
212 * The config of the peer
214 struct GNUNET_CONFIGURATION_Handle *cfg;
217 * The callback to call asynchronously when a peer is stopped
219 GNUNET_TESTING_PeerStopCallback cb;
222 * The closure for the above callback
227 * The cached identity of this peer. Will be populated on call to
228 * GNUNET_TESTING_peer_get_identity()
230 struct GNUNET_PeerIdentity *id;
232 struct SharedServiceInstance **ss_instances;
235 * Array of ports currently allocated to this peer. These ports will be
236 * released upon peer destroy and can be used by other peers which are
242 * The number of ports in the above array
247 * The keynumber of this peer's hostkey
254 * Testing includes a number of pre-created hostkeys for faster peer
255 * startup. This function loads such keys into memory from a file.
257 * @param system the testing system handle
258 * @return GNUNET_OK on success; GNUNET_SYSERR on error
261 hostkeys_load (struct GNUNET_TESTING_System *system)
266 struct GNUNET_DISK_FileHandle *fd;
268 GNUNET_assert (NULL == system->hostkeys_data);
269 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
270 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
271 GNUNET_free (data_dir);
273 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
275 LOG (GNUNET_ERROR_TYPE_ERROR,
276 _("Hostkeys file not found: %s\n"), filename);
277 GNUNET_free (filename);
278 return GNUNET_SYSERR;
280 /* Check hostkey file size, read entire thing into memory */
282 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
286 GNUNET_free (filename);
287 return GNUNET_SYSERR; /* File is empty */
289 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
291 LOG (GNUNET_ERROR_TYPE_ERROR,
292 _("Incorrect hostkey file format: %s\n"), filename);
293 GNUNET_free (filename);
294 return GNUNET_SYSERR;
296 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
297 GNUNET_DISK_PERM_NONE);
300 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
301 GNUNET_free (filename);
302 return GNUNET_SYSERR;
304 GNUNET_free (filename);
305 system->hostkeys_data = GNUNET_DISK_file_map (fd,
307 GNUNET_DISK_MAP_TYPE_READ,
309 GNUNET_DISK_file_close (fd);
310 if (NULL == system->hostkeys_data)
311 return GNUNET_SYSERR;
312 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
318 * Function to remove the loaded hostkeys
320 * @param system the testing system handle
323 hostkeys_unload (struct GNUNET_TESTING_System *system)
325 GNUNET_break (NULL != system->hostkeys_data);
326 system->hostkeys_data = NULL;
327 GNUNET_DISK_file_unmap (system->map);
329 system->hostkeys_data = NULL;
330 system->total_hostkeys = 0;
335 * Function to iterate over options.
338 * @param section name of the section
339 * @param option name of the option
340 * @param value value of the option
343 cfg_copy_iterator (void *cls, const char *section,
344 const char *option, const char *value)
346 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
348 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
353 * Create a system handle. There must only be one system
354 * handle per operating system.
356 * @param testdir only the directory name without any path. This is used for
357 * all service homes; the directory will be created in a temporary
358 * location depending on the underlying OS
359 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
360 * service configurations generated to allow control connections from
361 * this ip. This can either be a single ip address or a network address
363 * @param hostname the hostname of the system we are using for testing; NULL for
365 * @param shared_services NULL terminated array describing services that are to
366 * be shared among peers
367 * @param lowport lowest port number this system is allowed to allocate (inclusive)
368 * @param highport highest port number this system is allowed to allocate (exclusive)
369 * @return handle to this system, NULL on error
371 struct GNUNET_TESTING_System *
372 GNUNET_TESTING_system_create_with_portrange (const char *testdir,
373 const char *trusted_ip,
374 const char *hostname,
376 GNUNET_TESTING_SharedService *
381 struct GNUNET_TESTING_System *system;
382 struct GNUNET_TESTING_SharedService tss;
383 struct SharedService *ss;
386 GNUNET_assert (NULL != testdir);
387 system = GNUNET_malloc (sizeof (struct GNUNET_TESTING_System));
388 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
389 system->lowport = lowport;
390 system->highport = highport;
391 if (NULL == system->tmppath)
393 GNUNET_free (system);
396 if (NULL != trusted_ip)
397 system->trusted_ip = GNUNET_strdup (trusted_ip);
398 if (NULL != hostname)
399 system->hostname = GNUNET_strdup (hostname);
400 if (GNUNET_OK != hostkeys_load (system))
402 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
405 if (NULL == shared_services)
407 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
409 tss = shared_services[cnt];
410 ss = GNUNET_malloc (sizeof (struct SharedService));
411 ss->sname = GNUNET_strdup (tss.service);
412 ss->cfg = GNUNET_CONFIGURATION_create ();
413 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, ss->sname,
414 &cfg_copy_iterator, ss->cfg);
415 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "TESTING",
416 &cfg_copy_iterator, ss->cfg);
417 ss->share = tss.share;
418 GNUNET_array_append (system->shared_services, system->n_shared_services,
426 * Create a system handle. There must only be one system handle per operating
427 * system. Uses a default range for allowed ports. Ports are still tested for
430 * @param testdir only the directory name without any path. This is used for all
431 * service homes; the directory will be created in a temporary location
432 * depending on the underlying OS
433 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
434 * service configurations generated to allow control connections from
435 * this ip. This can either be a single ip address or a network address
437 * @param hostname the hostname of the system we are using for testing; NULL for
439 * @param shared_services NULL terminated array describing services that are to
440 * be shared among peers
441 * @return handle to this system, NULL on error
443 struct GNUNET_TESTING_System *
444 GNUNET_TESTING_system_create (const char *testdir,
445 const char *trusted_ip,
446 const char *hostname,
447 const struct GNUNET_TESTING_SharedService *
450 return GNUNET_TESTING_system_create_with_portrange (testdir,
459 cleanup_shared_service_instance (struct SharedServiceInstance *i)
461 if (NULL != i->cfg_fn)
463 (void) unlink (i->cfg_fn);
464 GNUNET_free (i->cfg_fn);
466 GNUNET_free_non_null (i->unix_sock);
467 GNUNET_free_non_null (i->port_str);
468 GNUNET_break (NULL == i->proc);
469 GNUNET_break (0 == i->n_refs);
474 start_shared_service_instance (struct SharedServiceInstance *i)
477 char *libexec_binary;
479 GNUNET_assert (NULL == i->proc);
480 GNUNET_assert (NULL != i->cfg_fn);
481 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
482 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
483 GNUNET_free (binary);
484 i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
485 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
492 GNUNET_free (libexec_binary);
494 return GNUNET_SYSERR;
500 stop_shared_service_instance (struct SharedServiceInstance *i)
502 GNUNET_break (0 == i->n_refs);
503 if (0 != GNUNET_OS_process_kill (i->proc, SIGTERM))
504 LOG (GNUNET_ERROR_TYPE_WARNING,
505 "Killing shared service instance (%s) failed\n", i->ss->sname);
506 (void) GNUNET_OS_process_wait (i->proc);
507 GNUNET_OS_process_destroy (i->proc);
513 * Free system resources.
515 * @param system system to be freed
516 * @param remove_paths should the 'testdir' and all subdirectories
517 * be removed (clean up on shutdown)?
520 GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
523 struct SharedService *ss;
524 struct SharedServiceInstance *i;
528 if (NULL != system->hostkeys_data)
529 hostkeys_unload (system);
530 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
532 ss = system->shared_services[ss_cnt];
533 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
535 i = ss->instances[i_cnt];
537 stop_shared_service_instance (i);
538 cleanup_shared_service_instance (i);
540 GNUNET_free_non_null (ss->instances);
541 GNUNET_CONFIGURATION_destroy (ss->cfg);
542 GNUNET_free (ss->sname);
545 GNUNET_free_non_null (system->shared_services);
546 if (GNUNET_YES == remove_paths)
547 GNUNET_DISK_directory_remove (system->tmppath);
548 GNUNET_free (system->tmppath);
549 GNUNET_free_non_null (system->trusted_ip);
550 GNUNET_free_non_null (system->hostname);
551 GNUNET_free (system);
556 * Reserve a TCP or UDP port for a peer.
558 * @param system system to use for reservation tracking
559 * @return 0 if no free port was available
562 GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
564 struct GNUNET_NETWORK_Handle *socket;
565 struct addrinfo hint;
566 struct addrinfo *ret;
568 uint32_t *port_buckets;
577 FIXME: Instead of using getaddrinfo we should try to determine the port
578 status by the following heurestics.
580 On systems which support both IPv4 and IPv6, only ports open on both
581 address families are considered open.
582 On system with either IPv4 or IPv6. A port is considered open if it's
583 open in the respective address family
585 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
586 hint.ai_socktype = 0;
587 hint.ai_protocol = 0;
590 hint.ai_canonname = NULL;
592 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
593 port_buckets = system->reserved_ports;
594 for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++)
596 xor_image = (UINT32_MAX ^ port_buckets[index]);
597 if (0 == xor_image) /* Ports in the bucket are full */
599 pos = system->lowport % 32;
602 if (0 == ((xor_image >> pos) & 1U))
607 open_port = (index * 32) + pos;
608 if (open_port >= system->highport)
610 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
612 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
613 GNUNET_free (open_port_str);
614 bind_status = GNUNET_NO;
615 for (ai = ret; NULL != ai; ai = ai->ai_next)
617 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
620 bind_status = GNUNET_NETWORK_socket_bind (socket,
624 GNUNET_NETWORK_socket_close (socket);
625 if (GNUNET_OK != bind_status)
627 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0);
630 bind_status = GNUNET_NETWORK_socket_bind (socket,
634 GNUNET_NETWORK_socket_close (socket);
635 if (GNUNET_OK != bind_status)
638 port_buckets[index] |= (1U << pos); /* Set the port bit */
640 if (GNUNET_OK == bind_status)
642 LOG (GNUNET_ERROR_TYPE_DEBUG,
643 "Found a free port %u\n", (unsigned int) open_port);
654 * Release reservation of a TCP or UDP port for a peer
655 * (used during GNUNET_TESTING_peer_destroy).
657 * @param system system to use for reservation tracking
658 * @param port reserved port to release
661 GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
664 uint32_t *port_buckets;
668 port_buckets = system->reserved_ports;
671 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
672 if (0 == (port_buckets[bucket] & (1U << pos)))
674 GNUNET_break(0); /* Port was not reserved by us using reserve_port() */
677 port_buckets[bucket] &= ~(1U << pos);
682 * Testing includes a number of pre-created hostkeys for
683 * faster peer startup. This function can be used to
684 * access the n-th key of those pre-created hostkeys; note
685 * that these keys are ONLY useful for testing and not
686 * secure as the private keys are part of the public
687 * GNUnet source code.
689 * This is primarily a helper function used internally
690 * by 'GNUNET_TESTING_peer_configure'.
692 * @param system the testing system handle
693 * @param key_number desired pre-created hostkey to obtain
694 * @param id set to the peer's identity (hash of the public
695 * key; if NULL, GNUNET_SYSERR is returned immediately
696 * @return NULL on error (not enough keys)
698 struct GNUNET_CRYPTO_EccPrivateKey *
699 GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
701 struct GNUNET_PeerIdentity *id)
703 struct GNUNET_CRYPTO_EccPrivateKey *private_key;
704 struct GNUNET_CRYPTO_EccPublicSignKey public_key;
706 if ((NULL == id) || (NULL == system->hostkeys_data))
708 if (key_number >= system->total_hostkeys)
710 LOG (GNUNET_ERROR_TYPE_ERROR,
711 _("Key number %u does not exist\n"), key_number);
714 private_key = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey);
716 system->hostkeys_data +
717 (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
718 GNUNET_TESTING_HOSTKEYFILESIZE);
719 if (NULL == private_key)
721 LOG (GNUNET_ERROR_TYPE_ERROR,
722 _("Error while decoding key %u\n"), key_number);
725 GNUNET_CRYPTO_ecc_key_get_public_for_signature (private_key, &public_key);
726 GNUNET_CRYPTO_hash (&public_key,
727 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey),
734 * Structure for holding data to build new configurations from a configuration
740 * The system for which we are building configurations
742 struct GNUNET_TESTING_System *system;
745 * The configuration we are building
747 struct GNUNET_CONFIGURATION_Handle *cfg;
750 * The customized service home path for this peer
755 * Array of ports currently allocated to this peer. These ports will be
756 * released upon peer destroy and can be used by other peers which are
762 * The number of ports in the above array
767 * build status - to signal error while building a configuration
774 * Function to iterate over options. Copies
775 * the options to the target configuration,
776 * updating PORT values as needed.
778 * @param cls the UpdateContext
779 * @param section name of the section
780 * @param option name of the option
781 * @param value value of the option
784 update_config (void *cls, const char *section, const char *option,
787 struct UpdateContext *uc = cls;
791 char *single_variable;
792 char *per_host_variable;
793 unsigned long long num_per_host;
796 if (GNUNET_OK != uc->status)
798 if (! ((0 == strcmp (option, "PORT"))
799 || (0 == strcmp (option, "UNIXPATH"))
800 || (0 == strcmp (option, "HOSTNAME"))))
802 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
803 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
804 if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
808 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
811 new_port = GNUNET_TESTING_reserve_port (uc->system);
814 uc->status = GNUNET_SYSERR;
815 GNUNET_free (single_variable);
816 GNUNET_free (per_host_variable);
819 GNUNET_snprintf (cval, sizeof (cval), "%u", new_port);
821 GNUNET_array_append (uc->ports, uc->nports, new_port);
823 else if ((ival != 0) &&
825 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
827 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
831 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
832 /* ival + ctx->fdnum % num_per_host); */
834 GNUNET_break (0); /* FIXME */
837 if (0 == strcmp (option, "UNIXPATH"))
840 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
843 GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock",
844 uc->service_home, section);
847 else if ((GNUNET_YES ==
848 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
853 GNUNET_break(0); /* FIXME */
856 if (0 == strcmp (option, "HOSTNAME"))
858 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
860 GNUNET_free (single_variable);
861 GNUNET_free (per_host_variable);
862 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
867 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
868 * 'trusted_hosts' in all sections
870 * @param cls the UpdateContext
871 * @param section name of the section
874 update_config_sections (void *cls,
877 struct UpdateContext *uc = cls;
881 char *orig_allowed_hosts;
883 char *ACCEPT_FROM_key;
889 /* Ignore certain options from sections. See
890 https://gnunet.org/bugs/view.php?id=2476 */
891 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
892 "TESTING_IGNORE_KEYS"))
896 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section,
897 "TESTING_IGNORE_KEYS", &val));
899 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
905 ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt);
907 for (key = 0; key < ikeys_cnt; key++)
910 ptr = strstr (ptr, ";");
918 for (key = 0; key < ikeys_cnt; key++)
920 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
923 if ((key == ikeys_cnt) &&
924 (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
928 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr))
930 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section,
931 "ADVERTISED_PORT", ptr);
935 for (key = 0; key < ikeys_cnt; key++)
937 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
946 GNUNET_free_non_null (val);
947 ACCEPT_FROM_key = "ACCEPT_FROM";
948 if ((NULL != uc->system->trusted_ip) &&
949 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
950 ACCEPT_FROM_key = "ACCEPT_FROM6";
952 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key,
953 &orig_allowed_hosts))
955 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
957 if (NULL == uc->system->trusted_ip)
958 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
960 GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts,
961 uc->system->trusted_ip);
962 GNUNET_free (orig_allowed_hosts);
963 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key,
965 GNUNET_free (allowed_hosts);
968 static struct SharedServiceInstance *
969 associate_shared_service (struct GNUNET_TESTING_System *system,
970 struct SharedService *ss,
971 struct GNUNET_CONFIGURATION_Handle *cfg)
973 struct SharedServiceInstance *i;
974 struct GNUNET_CONFIGURATION_Handle *temp;
979 if ( ((0 == ss->share) && (NULL == ss->instances))
982 && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) )
984 i = GNUNET_malloc (sizeof (struct SharedServiceInstance));
986 (void) GNUNET_asprintf (&service_home, "%s/shared/%s/%u",
987 system->tmppath, ss->sname, ss->n_instances);
988 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", service_home);
989 port = GNUNET_TESTING_reserve_port (system);
992 GNUNET_free (service_home);
993 cleanup_shared_service_instance (i);
996 GNUNET_array_append (ss->instances, ss->n_instances, i);
997 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
998 (void) GNUNET_asprintf (&i->port_str, "%u", port);
999 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", service_home);
1000 GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "SERVICEHOME",
1002 GNUNET_free (service_home);
1003 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH",
1005 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT",
1007 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1009 GNUNET_CONFIGURATION_destroy (temp);
1010 cleanup_shared_service_instance (i);
1013 GNUNET_CONFIGURATION_destroy (temp);
1017 GNUNET_assert (NULL != ss->instances);
1018 GNUNET_assert (0 < ss->n_instances);
1019 i = ss->instances[ss->n_instances - 1];
1021 GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname,
1022 &cfg_copy_iterator, cfg);
1023 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH",
1025 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1031 * Create a new configuration using the given configuration as a template;
1032 * ports and paths will be modified to select available ports on the local
1033 * system. The default configuration will be available in PATHS section under
1034 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1035 * section to the temporary directory specific to this configuration. If we run
1036 * out of "*port" numbers, return SYSERR.
1038 * This is primarily a helper function used internally
1039 * by 'GNUNET_TESTING_peer_configure'.
1041 * @param system system to use to coordinate resource usage
1042 * @param cfg template configuration to update
1043 * @param ports array with port numbers used in the created configuration.
1044 * Will be updated upon successful return. Can be NULL
1045 * @param nports the size of the `ports' array. Will be updated.
1046 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1047 * be incomplete and should not be used there upon
1050 GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1051 struct GNUNET_CONFIGURATION_Handle *cfg,
1053 unsigned int *nports)
1055 struct UpdateContext uc;
1056 char *default_config;
1060 uc.status = GNUNET_OK;
1063 GNUNET_asprintf (&uc.service_home, "%s/%u", system->tmppath,
1064 system->path_counter++);
1065 GNUNET_asprintf (&default_config, "%s/config", uc.service_home);
1066 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
1068 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
1070 GNUNET_free (default_config);
1071 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "SERVICEHOME",
1073 /* make PORTs and UNIXPATHs unique */
1074 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1075 /* allow connections to services from system trusted_ip host */
1076 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1077 /* enable loopback-based connections between peers */
1078 GNUNET_CONFIGURATION_set_value_string (cfg,
1080 "USE_LOCALADDR", "YES");
1081 GNUNET_free (uc.service_home);
1082 if ((NULL != ports) && (NULL != nports))
1085 *nports = uc.nports;
1088 GNUNET_free_non_null (uc.ports);
1094 * Create a new configuration using the given configuration as a template;
1095 * ports and paths will be modified to select available ports on the local
1096 * system. The default configuration will be available in PATHS section under
1097 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1098 * section to the temporary directory specific to this configuration. If we run
1099 * out of "*port" numbers, return SYSERR.
1101 * This is primarily a helper function used internally
1102 * by 'GNUNET_TESTING_peer_configure'.
1104 * @param system system to use to coordinate resource usage
1105 * @param cfg template configuration to update
1106 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1107 * be incomplete and should not be used there upon
1110 GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1111 struct GNUNET_CONFIGURATION_Handle *cfg)
1113 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1118 * Configure a GNUnet peer. GNUnet must be installed on the local
1119 * system and available in the PATH.
1121 * @param system system to use to coordinate resource usage
1122 * @param cfg configuration to use; will be UPDATED (to reflect needed
1123 * changes in port numbers and paths)
1124 * @param key_number number of the hostkey to use for the peer
1125 * @param id identifier for the daemon, will be set, can be NULL
1126 * @param emsg set to freshly allocated error message (set to NULL on success),
1128 * @return handle to the peer, NULL on error
1130 struct GNUNET_TESTING_Peer *
1131 GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1132 struct GNUNET_CONFIGURATION_Handle *cfg,
1133 uint32_t key_number,
1134 struct GNUNET_PeerIdentity *id,
1137 struct GNUNET_TESTING_Peer *peer;
1138 struct GNUNET_DISK_FileHandle *fd;
1139 char *hostkey_filename;
1140 char *config_filename;
1141 char *libexec_binary;
1143 struct GNUNET_CRYPTO_EccPrivateKey *pk;
1145 struct SharedService *ss;
1146 struct SharedServiceInstance **ss_instances;
1148 unsigned int nports;
1152 ss_instances = NULL;
1155 if (key_number >= system->total_hostkeys)
1157 GNUNET_asprintf (&emsg_,
1158 _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1159 (unsigned int) system->total_hostkeys);
1164 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1166 GNUNET_asprintf (&emsg_,
1167 _("Failed to initialize hostkey for peer %u\n"),
1168 (unsigned int) key_number);
1174 GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1176 GNUNET_asprintf (&emsg_,
1177 _("PRIVATE_KEY option in PEER section missing in configuration\n"));
1180 /* Remove sections for shared services */
1181 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1183 ss = system->shared_services[cnt];
1184 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1186 if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg,
1189 GNUNET_asprintf (&emsg_,
1190 _("Failed to create configuration for peer "
1191 "(not enough free ports?)\n"));
1194 GNUNET_assert (GNUNET_OK ==
1195 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER",
1197 &hostkey_filename));
1198 fd = GNUNET_DISK_file_open (hostkey_filename,
1199 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1200 GNUNET_DISK_PERM_USER_READ
1201 | GNUNET_DISK_PERM_USER_WRITE);
1204 GNUNET_asprintf (&emsg_, _("Cannot open hostkey file `%s': %s\n"),
1205 hostkey_filename, STRERROR (errno));
1206 GNUNET_free (hostkey_filename);
1209 GNUNET_free (hostkey_filename);
1210 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1211 GNUNET_DISK_file_write (fd, system->hostkeys_data
1212 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1213 GNUNET_TESTING_HOSTKEYFILESIZE))
1215 GNUNET_asprintf (&emsg_,
1216 _("Failed to write hostkey file for peer %u: %s\n"),
1217 (unsigned int) key_number,
1219 GNUNET_DISK_file_close (fd);
1222 GNUNET_DISK_file_close (fd);
1223 ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *)
1224 * system->n_shared_services);
1225 for (cnt=0; cnt < system->n_shared_services; cnt++)
1227 ss = system->shared_services[cnt];
1228 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1229 if (NULL == ss_instances[cnt])
1232 GNUNET_assert (GNUNET_OK ==
1233 GNUNET_CONFIGURATION_get_value_string
1234 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1235 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1237 GNUNET_asprintf (&emsg_,
1238 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1240 (unsigned int) key_number,
1242 GNUNET_free (config_filename);
1245 peer = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Peer));
1246 peer->ss_instances = ss_instances;
1247 peer->cfgfile = config_filename; /* Free in peer_destroy */
1248 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1249 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1250 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1253 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1254 peer->args = strdup ("");
1257 peer->args = strdup (libexec_binary);
1258 peer->system = system;
1259 peer->key_number = key_number;
1260 GNUNET_free (libexec_binary);
1261 peer->ports = ports; /* Free in peer_destroy */
1262 peer->nports = nports;
1266 GNUNET_free_non_null (ss_instances);
1267 GNUNET_free_non_null (ports);
1268 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1272 GNUNET_free (emsg_);
1278 * Obtain the peer identity from a peer handle.
1280 * @param peer peer handle for which we want the peer's identity
1281 * @param id identifier for the daemon, will be set
1284 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1285 struct GNUNET_PeerIdentity *id)
1287 if (NULL != peer->id)
1289 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1292 peer->id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1293 GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system,
1296 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1303 * @param peer peer to start
1304 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1307 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1309 struct SharedServiceInstance *i;
1312 if (NULL != peer->main_process)
1315 return GNUNET_SYSERR;
1317 GNUNET_assert (NULL != peer->cfgfile);
1318 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1320 i = peer->ss_instances[cnt];
1321 if ((0 == i->n_refs)
1322 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1323 return GNUNET_SYSERR;
1326 peer->main_process = GNUNET_OS_start_process (PIPE_CONTROL,
1327 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1335 if (NULL == peer->main_process)
1337 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1338 _("Failed to start `%s': %s\n"),
1341 return GNUNET_SYSERR;
1348 * Start a service at a peer using its ARM service
1350 * @param peer the peer whose service has to be started
1351 * @param service_name name of the service to start
1352 * @param timeout how long should the ARM API try to send the request to start
1354 * @param cont the callback to call with result and status from ARM API
1355 * @param cont_cls the closure for the above callback
1356 * @return GNUNET_OK upon successfully queuing the service start request;
1357 * GNUNET_SYSERR upon error
1360 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1361 const char *service_name,
1362 struct GNUNET_TIME_Relative timeout,
1363 GNUNET_ARM_ResultCallback cont,
1366 if (NULL == peer->ah)
1367 return GNUNET_SYSERR;
1368 GNUNET_ARM_request_service_start (peer->ah,
1370 GNUNET_OS_INHERIT_STD_ALL,
1378 * Stop a service at a peer using its ARM service
1380 * @param peer the peer whose service has to be stopped
1381 * @param service_name name of the service to stop
1382 * @param timeout how long should the ARM API try to send the request to stop
1384 * @param cont the callback to call with result and status from ARM API
1385 * @param cont_cls the closure for the above callback
1386 * @return GNUNET_OK upon successfully queuing the service stop request;
1387 * GNUNET_SYSERR upon error
1390 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1391 const char *service_name,
1392 struct GNUNET_TIME_Relative timeout,
1393 GNUNET_ARM_ResultCallback cont,
1396 if (NULL == peer->ah)
1397 return GNUNET_SYSERR;
1398 GNUNET_ARM_request_service_stop (peer->ah,
1407 * Sends SIGTERM to the peer's main process
1409 * @param peer the handle to the peer
1410 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1411 * or upon any error while sending SIGTERM
1414 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1416 struct SharedServiceInstance *i;
1419 if (NULL == peer->main_process)
1422 return GNUNET_SYSERR;
1424 if (0 != GNUNET_OS_process_kill (peer->main_process, SIGTERM))
1425 return GNUNET_SYSERR;
1426 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1428 i = peer->ss_instances[cnt];
1429 GNUNET_assert (0 != i->n_refs);
1432 stop_shared_service_instance (i);
1439 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1441 * @param peer the handle to the peer
1442 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1443 * or upon any error while waiting
1446 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1450 if (NULL == peer->main_process)
1453 return GNUNET_SYSERR;
1455 ret = GNUNET_OS_process_wait (peer->main_process);
1456 GNUNET_OS_process_destroy (peer->main_process);
1457 peer->main_process = NULL;
1465 * @param peer peer to stop
1466 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1469 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1471 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1472 return GNUNET_SYSERR;
1473 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1474 return GNUNET_SYSERR;
1480 * Function called whenever we connect to or disconnect from ARM.
1482 * @param cls closure
1483 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1484 * GNUNET_SYSERR on error.
1487 disconn_status (void *cls,
1490 struct GNUNET_TESTING_Peer *peer = cls;
1492 if (GNUNET_SYSERR == connected)
1494 peer->cb (peer->cb_cls, peer, connected);
1497 if (GNUNET_YES == connected)
1499 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1502 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1503 GNUNET_ARM_disconnect_and_free (peer->ah);
1505 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1510 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1511 * through the GNUNET_TESTING_PeerStopCallback().
1513 * @param peer the peer to stop
1514 * @param cb the callback to signal peer shutdown
1515 * @param cb_cls closure for the above callback
1516 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1517 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1521 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1522 GNUNET_TESTING_PeerStopCallback cb,
1525 if (NULL == peer->main_process)
1526 return GNUNET_SYSERR;
1527 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1528 if (NULL == peer->ah)
1529 return GNUNET_SYSERR;
1531 peer->cb_cls = cb_cls;
1537 * Cancel a previous asynchronous peer stop request.
1538 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1539 * peer. It is an error to call this function if the peer stop callback was
1542 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1546 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1548 GNUNET_assert (NULL != peer->ah);
1549 GNUNET_ARM_disconnect_and_free (peer->ah);
1555 * Destroy the peer. Releases resources locked during peer configuration.
1556 * If the peer is still running, it will be stopped AND a warning will be
1557 * printed (users of the API should stop the peer explicitly first).
1559 * @param peer peer to destroy
1562 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1566 if (NULL != peer->main_process)
1567 GNUNET_TESTING_peer_stop (peer);
1568 if (NULL != peer->ah)
1569 GNUNET_ARM_disconnect_and_free (peer->ah);
1570 if (NULL != peer->mh)
1571 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1572 GNUNET_free (peer->cfgfile);
1573 if (NULL != peer->cfg)
1574 GNUNET_CONFIGURATION_destroy (peer->cfg);
1575 GNUNET_free (peer->main_binary);
1576 GNUNET_free (peer->args);
1577 GNUNET_free_non_null (peer->id);
1578 GNUNET_free_non_null (peer->ss_instances);
1579 if (NULL != peer->ports)
1581 for (cnt = 0; cnt < peer->nports; cnt++)
1582 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1583 GNUNET_free (peer->ports);
1590 * Start a single peer and run a test using the testing library.
1591 * Starts a peer using the given configuration and then invokes the
1592 * given callback. This function ALSO initializes the scheduler loop
1593 * and should thus be called directly from "main". The testcase
1594 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1596 * @param testdir only the directory name without any path. This is used for
1597 * all service homes; the directory will be created in a temporary
1598 * location depending on the underlying OS
1599 * @param cfgfilename name of the configuration file to use;
1600 * use NULL to only run with defaults
1601 * @param tm main function of the testcase
1602 * @param tm_cls closure for 'tm'
1603 * @return 0 on success, 1 on error
1606 GNUNET_TESTING_peer_run (const char *testdir,
1607 const char *cfgfilename,
1608 GNUNET_TESTING_TestMain tm,
1611 return GNUNET_TESTING_service_run (testdir, "arm",
1612 cfgfilename, tm, tm_cls);
1617 * Structure for holding service data
1619 struct ServiceContext
1622 * The configuration of the peer in which the service is run
1624 const struct GNUNET_CONFIGURATION_Handle *cfg;
1627 * Callback to signal service startup
1629 GNUNET_TESTING_TestMain tm;
1632 * The peer in which the service is run.
1634 struct GNUNET_TESTING_Peer *peer;
1637 * Closure for the above callback
1644 * Callback to be called when SCHEDULER has been started
1646 * @param cls the ServiceContext
1647 * @param tc the TaskContext
1650 service_run_main (void *cls,
1651 const struct GNUNET_SCHEDULER_TaskContext *tc)
1653 struct ServiceContext *sc = cls;
1655 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1660 * Start a single service (no ARM, except of course if the given
1661 * service name is 'arm') and run a test using the testing library.
1662 * Starts a service using the given configuration and then invokes the
1663 * given callback. This function ALSO initializes the scheduler loop
1664 * and should thus be called directly from "main". The testcase
1665 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1667 * This function is useful if the testcase is for a single service
1668 * and if that service doesn't itself depend on other services.
1670 * @param testdir only the directory name without any path. This is used for
1671 * all service homes; the directory will be created in a temporary
1672 * location depending on the underlying OS
1673 * @param service_name name of the service to run
1674 * @param cfgfilename name of the configuration file to use;
1675 * use NULL to only run with defaults
1676 * @param tm main function of the testcase
1677 * @param tm_cls closure for 'tm'
1678 * @return 0 on success, 1 on error
1681 GNUNET_TESTING_service_run (const char *testdir,
1682 const char *service_name,
1683 const char *cfgfilename,
1684 GNUNET_TESTING_TestMain tm,
1687 struct ServiceContext sc;
1688 struct GNUNET_TESTING_System *system;
1689 struct GNUNET_TESTING_Peer *peer;
1690 struct GNUNET_CONFIGURATION_Handle *cfg;
1692 char *libexec_binary;
1694 GNUNET_log_setup (testdir, "WARNING", NULL);
1695 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1698 cfg = GNUNET_CONFIGURATION_create ();
1699 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1701 LOG (GNUNET_ERROR_TYPE_ERROR,
1702 _("Failed to load configuration from %s\n"), cfgfilename);
1703 GNUNET_CONFIGURATION_destroy (cfg);
1704 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1707 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1710 GNUNET_CONFIGURATION_destroy (cfg);
1711 hostkeys_unload (system);
1712 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1715 GNUNET_free (peer->main_binary);
1716 GNUNET_free (peer->args);
1717 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1718 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1719 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1722 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1723 peer->args = strdup ("");
1726 peer->args = strdup (libexec_binary);
1728 GNUNET_free (libexec_binary);
1729 GNUNET_free (binary);
1730 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1732 GNUNET_TESTING_peer_destroy (peer);
1733 GNUNET_CONFIGURATION_destroy (cfg);
1734 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1741 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1742 if ((NULL != peer->main_process) &&
1743 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1745 GNUNET_TESTING_peer_destroy (peer);
1746 GNUNET_CONFIGURATION_destroy (cfg);
1747 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1750 GNUNET_TESTING_peer_destroy (peer);
1751 GNUNET_CONFIGURATION_destroy (cfg);
1752 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1758 * Sometimes we use the binary name to determine which specific
1759 * test to run. In those cases, the string after the last "_"
1760 * in 'argv[0]' specifies a string that determines the configuration
1761 * file or plugin to use.
1763 * This function returns the respective substring, taking care
1764 * of issues such as binaries ending in '.exe' on W32.
1766 * @param argv0 the name of the binary
1767 * @return string between the last '_' and the '.exe' (or the end of the string),
1768 * NULL if argv0 has no '_'
1771 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1773 size_t slen = strlen (argv0) + 1;
1778 memcpy (sbuf, argv0, slen);
1779 ret = strrchr (sbuf, '_');
1782 ret++; /* skip underscore */
1783 dot = strchr (ret, '.');
1786 return GNUNET_strdup (ret);
1790 /* end of testing.c */