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 ("");
1256 peer->args = strdup (libexec_binary);
1257 peer->system = system;
1258 peer->key_number = key_number;
1259 GNUNET_free (libexec_binary);
1260 peer->ports = ports; /* Free in peer_destroy */
1261 peer->nports = nports;
1265 GNUNET_free_non_null (ss_instances);
1266 GNUNET_free_non_null (ports);
1267 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1271 GNUNET_free (emsg_);
1277 * Obtain the peer identity from a peer handle.
1279 * @param peer peer handle for which we want the peer's identity
1280 * @param id identifier for the daemon, will be set
1283 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1284 struct GNUNET_PeerIdentity *id)
1286 if (NULL != peer->id)
1288 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1291 peer->id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1292 GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system,
1295 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1302 * @param peer peer to start
1303 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1306 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1308 struct SharedServiceInstance *i;
1311 if (NULL != peer->main_process)
1314 return GNUNET_SYSERR;
1316 GNUNET_assert (NULL != peer->cfgfile);
1317 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1319 i = peer->ss_instances[cnt];
1320 if ((0 == i->n_refs)
1321 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1322 return GNUNET_SYSERR;
1325 peer->main_process = do_start_process (PIPE_CONTROL,
1326 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1333 if (NULL == peer->main_process)
1335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1336 _("Failed to start `%s': %s\n"),
1339 return GNUNET_SYSERR;
1346 * Start a service at a peer using its ARM service
1348 * @param peer the peer whose service has to be started
1349 * @param service_name name of the service to start
1350 * @param timeout how long should the ARM API try to send the request to start
1352 * @param cont the callback to call with result and status from ARM API
1353 * @param cont_cls the closure for the above callback
1354 * @return GNUNET_OK upon successfully queuing the service start request;
1355 * GNUNET_SYSERR upon error
1358 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1359 const char *service_name,
1360 struct GNUNET_TIME_Relative timeout,
1361 GNUNET_ARM_ResultCallback cont,
1364 if (NULL == peer->ah)
1365 return GNUNET_SYSERR;
1366 GNUNET_ARM_request_service_start (peer->ah,
1368 GNUNET_OS_INHERIT_STD_ALL,
1376 * Stop a service at a peer using its ARM service
1378 * @param peer the peer whose service has to be stopped
1379 * @param service_name name of the service to stop
1380 * @param timeout how long should the ARM API try to send the request to stop
1382 * @param cont the callback to call with result and status from ARM API
1383 * @param cont_cls the closure for the above callback
1384 * @return GNUNET_OK upon successfully queuing the service stop request;
1385 * GNUNET_SYSERR upon error
1388 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1389 const char *service_name,
1390 struct GNUNET_TIME_Relative timeout,
1391 GNUNET_ARM_ResultCallback cont,
1394 if (NULL == peer->ah)
1395 return GNUNET_SYSERR;
1396 GNUNET_ARM_request_service_stop (peer->ah,
1405 * Sends SIGTERM to the peer's main process
1407 * @param peer the handle to the peer
1408 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1409 * or upon any error while sending SIGTERM
1412 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1414 struct SharedServiceInstance *i;
1417 if (NULL == peer->main_process)
1420 return GNUNET_SYSERR;
1422 if (0 != GNUNET_OS_process_kill (peer->main_process, GNUNET_TERM_SIG))
1423 return GNUNET_SYSERR;
1424 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1426 i = peer->ss_instances[cnt];
1427 GNUNET_assert (0 != i->n_refs);
1430 stop_shared_service_instance (i);
1437 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1439 * @param peer the handle to the peer
1440 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1441 * or upon any error while waiting
1444 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1448 if (NULL == peer->main_process)
1451 return GNUNET_SYSERR;
1453 ret = GNUNET_OS_process_wait (peer->main_process);
1454 GNUNET_OS_process_destroy (peer->main_process);
1455 peer->main_process = NULL;
1463 * @param peer peer to stop
1464 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1467 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1469 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1470 return GNUNET_SYSERR;
1471 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1472 return GNUNET_SYSERR;
1478 * Function called whenever we connect to or disconnect from ARM.
1480 * @param cls closure
1481 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1482 * GNUNET_SYSERR on error.
1485 disconn_status (void *cls,
1488 struct GNUNET_TESTING_Peer *peer = cls;
1490 if (GNUNET_SYSERR == connected)
1492 peer->cb (peer->cb_cls, peer, connected);
1495 if (GNUNET_YES == connected)
1497 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1500 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1501 GNUNET_ARM_disconnect_and_free (peer->ah);
1503 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1508 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1509 * through the GNUNET_TESTING_PeerStopCallback().
1511 * @param peer the peer to stop
1512 * @param cb the callback to signal peer shutdown
1513 * @param cb_cls closure for the above callback
1514 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1515 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1519 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1520 GNUNET_TESTING_PeerStopCallback cb,
1523 if (NULL == peer->main_process)
1524 return GNUNET_SYSERR;
1525 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1526 if (NULL == peer->ah)
1527 return GNUNET_SYSERR;
1529 peer->cb_cls = cb_cls;
1535 * Cancel a previous asynchronous peer stop request.
1536 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1537 * peer. It is an error to call this function if the peer stop callback was
1540 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1544 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1546 GNUNET_assert (NULL != peer->ah);
1547 GNUNET_ARM_disconnect_and_free (peer->ah);
1553 * Destroy the peer. Releases resources locked during peer configuration.
1554 * If the peer is still running, it will be stopped AND a warning will be
1555 * printed (users of the API should stop the peer explicitly first).
1557 * @param peer peer to destroy
1560 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1564 if (NULL != peer->main_process)
1565 GNUNET_TESTING_peer_stop (peer);
1566 if (NULL != peer->ah)
1567 GNUNET_ARM_disconnect_and_free (peer->ah);
1568 if (NULL != peer->mh)
1569 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1570 GNUNET_free (peer->cfgfile);
1571 if (NULL != peer->cfg)
1572 GNUNET_CONFIGURATION_destroy (peer->cfg);
1573 GNUNET_free (peer->main_binary);
1574 GNUNET_free (peer->args);
1575 GNUNET_free_non_null (peer->id);
1576 GNUNET_free_non_null (peer->ss_instances);
1577 if (NULL != peer->ports)
1579 for (cnt = 0; cnt < peer->nports; cnt++)
1580 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1581 GNUNET_free (peer->ports);
1588 * Start a single peer and run a test using the testing library.
1589 * Starts a peer using the given configuration and then invokes the
1590 * given callback. This function ALSO initializes the scheduler loop
1591 * and should thus be called directly from "main". The testcase
1592 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1594 * @param testdir only the directory name without any path. This is used for
1595 * all service homes; the directory will be created in a temporary
1596 * location depending on the underlying OS
1597 * @param cfgfilename name of the configuration file to use;
1598 * use NULL to only run with defaults
1599 * @param tm main function of the testcase
1600 * @param tm_cls closure for 'tm'
1601 * @return 0 on success, 1 on error
1604 GNUNET_TESTING_peer_run (const char *testdir,
1605 const char *cfgfilename,
1606 GNUNET_TESTING_TestMain tm,
1609 return GNUNET_TESTING_service_run (testdir, "arm",
1610 cfgfilename, tm, tm_cls);
1615 * Structure for holding service data
1617 struct ServiceContext
1620 * The configuration of the peer in which the service is run
1622 const struct GNUNET_CONFIGURATION_Handle *cfg;
1625 * Callback to signal service startup
1627 GNUNET_TESTING_TestMain tm;
1630 * The peer in which the service is run.
1632 struct GNUNET_TESTING_Peer *peer;
1635 * Closure for the above callback
1642 * Callback to be called when SCHEDULER has been started
1644 * @param cls the ServiceContext
1645 * @param tc the TaskContext
1648 service_run_main (void *cls,
1649 const struct GNUNET_SCHEDULER_TaskContext *tc)
1651 struct ServiceContext *sc = cls;
1653 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1658 * Start a single service (no ARM, except of course if the given
1659 * service name is 'arm') and run a test using the testing library.
1660 * Starts a service using the given configuration and then invokes the
1661 * given callback. This function ALSO initializes the scheduler loop
1662 * and should thus be called directly from "main". The testcase
1663 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1665 * This function is useful if the testcase is for a single service
1666 * and if that service doesn't itself depend on other services.
1668 * @param testdir only the directory name without any path. This is used for
1669 * all service homes; the directory will be created in a temporary
1670 * location depending on the underlying OS
1671 * @param service_name name of the service to run
1672 * @param cfgfilename name of the configuration file to use;
1673 * use NULL to only run with defaults
1674 * @param tm main function of the testcase
1675 * @param tm_cls closure for 'tm'
1676 * @return 0 on success, 1 on error
1679 GNUNET_TESTING_service_run (const char *testdir,
1680 const char *service_name,
1681 const char *cfgfilename,
1682 GNUNET_TESTING_TestMain tm,
1685 struct ServiceContext sc;
1686 struct GNUNET_TESTING_System *system;
1687 struct GNUNET_TESTING_Peer *peer;
1688 struct GNUNET_CONFIGURATION_Handle *cfg;
1690 char *libexec_binary;
1692 GNUNET_log_setup (testdir, "WARNING", NULL);
1693 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1696 cfg = GNUNET_CONFIGURATION_create ();
1697 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1699 LOG (GNUNET_ERROR_TYPE_ERROR,
1700 _("Failed to load configuration from %s\n"), cfgfilename);
1701 GNUNET_CONFIGURATION_destroy (cfg);
1702 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1705 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1708 GNUNET_CONFIGURATION_destroy (cfg);
1709 hostkeys_unload (system);
1710 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1713 GNUNET_free (peer->main_binary);
1714 GNUNET_free (peer->args);
1715 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1716 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1717 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1720 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1721 peer->args = strdup ("");
1724 peer->args = strdup (libexec_binary);
1726 GNUNET_free (libexec_binary);
1727 GNUNET_free (binary);
1728 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1730 GNUNET_TESTING_peer_destroy (peer);
1731 GNUNET_CONFIGURATION_destroy (cfg);
1732 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1739 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1740 if ((NULL != peer->main_process) &&
1741 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1743 GNUNET_TESTING_peer_destroy (peer);
1744 GNUNET_CONFIGURATION_destroy (cfg);
1745 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1748 GNUNET_TESTING_peer_destroy (peer);
1749 GNUNET_CONFIGURATION_destroy (cfg);
1750 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1756 * Sometimes we use the binary name to determine which specific
1757 * test to run. In those cases, the string after the last "_"
1758 * in 'argv[0]' specifies a string that determines the configuration
1759 * file or plugin to use.
1761 * This function returns the respective substring, taking care
1762 * of issues such as binaries ending in '.exe' on W32.
1764 * @param argv0 the name of the binary
1765 * @return string between the last '_' and the '.exe' (or the end of the string),
1766 * NULL if argv0 has no '_'
1769 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1771 size_t slen = strlen (argv0) + 1;
1776 memcpy (sbuf, argv0, slen);
1777 ret = strrchr (sbuf, '_');
1780 ret++; /* skip underscore */
1781 dot = strchr (ret, '.');
1784 return GNUNET_strdup (ret);
1788 /* end of testing.c */