2 This file is part of GNUnet
3 Copyright (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
111 * The trusted ip. Can either be a single ip address or a network address in
122 * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes.
127 * memory map for 'hostkeys_data'.
129 struct GNUNET_DISK_MapHandle *map;
131 struct SharedService **shared_services;
133 unsigned int n_shared_services;
136 * Bitmap where each port that has already been reserved for some GNUnet peer
137 * is recorded. Note that we make no distinction between TCP and UDP ports
138 * and test if a port is already in use before assigning it to a peer/service.
139 * If we detect that a port is already in use, we also mark it in this bitmap.
140 * So all the bits that are zero merely indicate ports that MIGHT be available
143 uint32_t reserved_ports[65536 / 32];
146 * Counter we use to make service home paths unique on this system;
147 * the full path consists of the tmppath and this number. Each
148 * UNIXPATH for a peer is also modified to include the respective
149 * path counter to ensure uniqueness. This field is incremented
150 * by one for each configured peer. Even if peers are destroyed,
151 * we never re-use path counters.
153 uint32_t path_counter;
156 * The number of hostkeys
158 uint32_t total_hostkeys;
161 * Lowest port we are allowed to use.
166 * Highest port we are allowed to use.
173 * Handle for a GNUnet peer controlled by testing.
175 struct GNUNET_TESTING_Peer
178 * The TESTING system associated with this peer
180 struct GNUNET_TESTING_System *system;
183 * Path to the configuration file for this peer.
188 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
189 * Typically 'gnunet-service-arm' (but can be set to a
190 * specific service by 'GNUNET_TESTING_service_run' if
197 * Handle to the running binary of the service, NULL if the
198 * peer/service is currently not running.
200 struct GNUNET_OS_Process *main_process;
203 * The handle to the peer's ARM service
205 struct GNUNET_ARM_Handle *ah;
208 * Handle to ARM monitoring
210 struct GNUNET_ARM_MonitorHandle *mh;
213 * The config of the peer
215 struct GNUNET_CONFIGURATION_Handle *cfg;
218 * The callback to call asynchronously when a peer is stopped
220 GNUNET_TESTING_PeerStopCallback cb;
223 * The closure for the above callback
228 * The cached identity of this peer. Will be populated on call to
229 * GNUNET_TESTING_peer_get_identity()
231 struct GNUNET_PeerIdentity *id;
233 struct SharedServiceInstance **ss_instances;
236 * Array of ports currently allocated to this peer. These ports will be
237 * released upon peer destroy and can be used by other peers which are
243 * The number of ports in the above array
248 * The keynumber of this peer's hostkey
255 * Testing includes a number of pre-created hostkeys for faster peer
256 * startup. This function loads such keys into memory from a file.
258 * @param system the testing system handle
259 * @return GNUNET_OK on success; GNUNET_SYSERR on error
262 hostkeys_load (struct GNUNET_TESTING_System *system)
267 struct GNUNET_DISK_FileHandle *fd;
269 GNUNET_assert (NULL == system->hostkeys_data);
270 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
271 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
272 GNUNET_free (data_dir);
274 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
276 LOG (GNUNET_ERROR_TYPE_ERROR,
277 _("Hostkeys file not found: %s\n"), filename);
278 GNUNET_free (filename);
279 return GNUNET_SYSERR;
281 /* Check hostkey file size, read entire thing into memory */
283 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
287 GNUNET_free (filename);
288 return GNUNET_SYSERR; /* File is empty */
290 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
292 LOG (GNUNET_ERROR_TYPE_ERROR,
293 _("Incorrect hostkey file format: %s\n"), filename);
294 GNUNET_free (filename);
295 return GNUNET_SYSERR;
297 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
298 GNUNET_DISK_PERM_NONE);
301 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
302 GNUNET_free (filename);
303 return GNUNET_SYSERR;
305 GNUNET_free (filename);
306 system->hostkeys_data = GNUNET_DISK_file_map (fd,
308 GNUNET_DISK_MAP_TYPE_READ,
310 GNUNET_DISK_file_close (fd);
311 if (NULL == system->hostkeys_data)
312 return GNUNET_SYSERR;
313 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
319 * Function to remove the loaded hostkeys
321 * @param system the testing system handle
324 hostkeys_unload (struct GNUNET_TESTING_System *system)
326 GNUNET_break (NULL != system->hostkeys_data);
327 system->hostkeys_data = NULL;
328 GNUNET_DISK_file_unmap (system->map);
330 system->hostkeys_data = NULL;
331 system->total_hostkeys = 0;
336 * Function to iterate over options.
339 * @param section name of the section
340 * @param option name of the option
341 * @param value value of the option
344 cfg_copy_iterator (void *cls, const char *section,
345 const char *option, const char *value)
347 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
349 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
354 * Create a system handle. There must only be one system
355 * handle per operating system.
357 * @param testdir only the directory name without any path. This is used for
358 * all service homes; the directory will be created in a temporary
359 * location depending on the underlying OS. This variable will be
360 * overridden with the value of the environmental variable
361 * GNUNET_TESTING_PREFIX, if it exists.
362 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
363 * service configurations generated to allow control connections from
364 * this ip. This can either be a single ip address or a network address
366 * @param hostname the hostname of the system we are using for testing; NULL for
368 * @param shared_services NULL terminated array describing services that are to
369 * be shared among peers
370 * @param lowport lowest port number this system is allowed to allocate (inclusive)
371 * @param highport highest port number this system is allowed to allocate (exclusive)
372 * @return handle to this system, NULL on error
374 struct GNUNET_TESTING_System *
375 GNUNET_TESTING_system_create_with_portrange (const char *testdir,
376 const char *trusted_ip,
377 const char *hostname,
379 GNUNET_TESTING_SharedService *
384 struct GNUNET_TESTING_System *system;
385 struct GNUNET_TESTING_SharedService tss;
386 struct SharedService *ss;
389 GNUNET_assert (NULL != testdir);
390 system = GNUNET_new (struct GNUNET_TESTING_System);
391 if (NULL == (system->tmppath = getenv (GNUNET_TESTING_PREFIX)))
392 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
394 system->tmppath = GNUNET_strdup (system->tmppath);
395 system->lowport = lowport;
396 system->highport = highport;
397 if (NULL == system->tmppath)
399 GNUNET_free (system);
402 if (NULL != trusted_ip)
403 system->trusted_ip = GNUNET_strdup (trusted_ip);
404 if (NULL != hostname)
405 system->hostname = GNUNET_strdup (hostname);
406 if (GNUNET_OK != hostkeys_load (system))
408 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
411 if (NULL == shared_services)
413 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
415 tss = shared_services[cnt];
416 ss = GNUNET_new (struct SharedService);
417 ss->sname = GNUNET_strdup (tss.service);
418 ss->cfg = GNUNET_CONFIGURATION_create ();
419 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, ss->sname,
420 &cfg_copy_iterator, ss->cfg);
421 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "TESTING",
422 &cfg_copy_iterator, ss->cfg);
423 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "PATHS",
424 &cfg_copy_iterator, ss->cfg);
425 ss->share = tss.share;
426 GNUNET_array_append (system->shared_services, system->n_shared_services,
434 * Create a system handle. There must only be one system handle per operating
435 * system. Uses a default range for allowed ports. Ports are still tested for
438 * @param testdir only the directory name without any path. This is used for all
439 * service homes; the directory will be created in a temporary location
440 * depending on the underlying OS. This variable will be
441 * overridden with the value of the environmental variable
442 * GNUNET_TESTING_PREFIX, if it exists.
443 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
444 * service configurations generated to allow control connections from
445 * this ip. This can either be a single ip address or a network address
447 * @param hostname the hostname of the system we are using for testing; NULL for
449 * @param shared_services NULL terminated array describing services that are to
450 * be shared among peers
451 * @return handle to this system, NULL on error
453 struct GNUNET_TESTING_System *
454 GNUNET_TESTING_system_create (const char *testdir,
455 const char *trusted_ip,
456 const char *hostname,
457 const struct GNUNET_TESTING_SharedService *
460 return GNUNET_TESTING_system_create_with_portrange (testdir,
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])
1230 emsg_ = GNUNET_strdup ("FIXME");
1234 GNUNET_assert (GNUNET_OK ==
1235 GNUNET_CONFIGURATION_get_value_filename
1236 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1237 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1239 GNUNET_asprintf (&emsg_,
1240 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1242 (unsigned int) key_number,
1244 GNUNET_free (config_filename);
1247 peer = GNUNET_new (struct GNUNET_TESTING_Peer);
1248 peer->ss_instances = ss_instances;
1249 peer->cfgfile = config_filename; /* Free in peer_destroy */
1250 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1251 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1252 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1255 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1256 peer->args = GNUNET_strdup ("");
1260 peer->args = GNUNET_strdup (libexec_binary);
1262 peer->system = system;
1263 peer->key_number = key_number;
1264 GNUNET_free (libexec_binary);
1265 peer->ports = ports; /* Free in peer_destroy */
1266 peer->nports = nports;
1270 GNUNET_free_non_null (ss_instances);
1271 GNUNET_free_non_null (ports);
1272 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1276 GNUNET_free (emsg_);
1282 * Obtain the peer identity from a peer handle.
1284 * @param peer peer handle for which we want the peer's identity
1285 * @param id identifier for the daemon, will be set
1288 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1289 struct GNUNET_PeerIdentity *id)
1291 if (NULL != peer->id)
1293 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1296 peer->id = GNUNET_new (struct GNUNET_PeerIdentity);
1297 GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system,
1300 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1307 * @param peer peer to start
1308 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1311 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1313 struct SharedServiceInstance *i;
1316 if (NULL != peer->main_process)
1319 return GNUNET_SYSERR;
1321 GNUNET_assert (NULL != peer->cfgfile);
1322 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1324 i = peer->ss_instances[cnt];
1325 if ((0 == i->n_refs)
1326 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1327 return GNUNET_SYSERR;
1330 peer->main_binary = GNUNET_CONFIGURATION_expand_dollar (peer->cfg, peer->main_binary);
1331 peer->main_process = GNUNET_OS_start_process_s (PIPE_CONTROL,
1332 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1339 if (NULL == peer->main_process)
1341 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1342 _("Failed to start `%s': %s\n"),
1345 return GNUNET_SYSERR;
1352 * Start a service at a peer using its ARM service
1354 * @param peer the peer whose service has to be started
1355 * @param service_name name of the service to start
1356 * @param timeout how long should the ARM API try to send the request to start
1358 * @param cont the callback to call with result and status from ARM API
1359 * @param cont_cls the closure for the above callback
1360 * @return GNUNET_OK upon successfully queuing the service start request;
1361 * GNUNET_SYSERR upon error
1364 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1365 const char *service_name,
1366 struct GNUNET_TIME_Relative timeout,
1367 GNUNET_ARM_ResultCallback cont,
1370 if (NULL == peer->ah)
1371 return GNUNET_SYSERR;
1372 GNUNET_ARM_request_service_start (peer->ah,
1374 GNUNET_OS_INHERIT_STD_ALL,
1382 * Stop a service at a peer using its ARM service
1384 * @param peer the peer whose service has to be stopped
1385 * @param service_name name of the service to stop
1386 * @param timeout how long should the ARM API try to send the request to stop
1388 * @param cont the callback to call with result and status from ARM API
1389 * @param cont_cls the closure for the above callback
1390 * @return GNUNET_OK upon successfully queuing the service stop request;
1391 * GNUNET_SYSERR upon error
1394 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1395 const char *service_name,
1396 struct GNUNET_TIME_Relative timeout,
1397 GNUNET_ARM_ResultCallback cont,
1400 if (NULL == peer->ah)
1401 return GNUNET_SYSERR;
1402 GNUNET_ARM_request_service_stop (peer->ah,
1411 * Sends SIGTERM to the peer's main process
1413 * @param peer the handle to the peer
1414 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1415 * or upon any error while sending SIGTERM
1418 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1420 struct SharedServiceInstance *i;
1423 if (NULL == peer->main_process)
1426 return GNUNET_SYSERR;
1428 if (0 != GNUNET_OS_process_kill (peer->main_process, GNUNET_TERM_SIG))
1429 return GNUNET_SYSERR;
1430 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1432 i = peer->ss_instances[cnt];
1433 GNUNET_assert (0 != i->n_refs);
1436 stop_shared_service_instance (i);
1443 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1445 * @param peer the handle to the peer
1446 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1447 * or upon any error while waiting
1450 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1454 if (NULL == peer->main_process)
1457 return GNUNET_SYSERR;
1459 ret = GNUNET_OS_process_wait (peer->main_process);
1460 GNUNET_OS_process_destroy (peer->main_process);
1461 peer->main_process = NULL;
1469 * @param peer peer to stop
1470 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1473 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1475 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1476 return GNUNET_SYSERR;
1477 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1478 return GNUNET_SYSERR;
1484 * Function called whenever we connect to or disconnect from ARM.
1486 * @param cls closure
1487 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1488 * GNUNET_SYSERR on error.
1491 disconn_status (void *cls,
1494 struct GNUNET_TESTING_Peer *peer = cls;
1496 if (GNUNET_SYSERR == connected)
1498 peer->cb (peer->cb_cls, peer, connected);
1501 if (GNUNET_YES == connected)
1503 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1506 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1507 GNUNET_ARM_disconnect_and_free (peer->ah);
1509 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1514 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1515 * through the GNUNET_TESTING_PeerStopCallback().
1517 * @param peer the peer to stop
1518 * @param cb the callback to signal peer shutdown
1519 * @param cb_cls closure for the above callback
1520 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1521 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1525 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1526 GNUNET_TESTING_PeerStopCallback cb,
1529 if (NULL == peer->main_process)
1530 return GNUNET_SYSERR;
1531 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1532 if (NULL == peer->ah)
1533 return GNUNET_SYSERR;
1535 peer->cb_cls = cb_cls;
1541 * Cancel a previous asynchronous peer stop request.
1542 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1543 * peer. It is an error to call this function if the peer stop callback was
1546 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1550 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1552 GNUNET_assert (NULL != peer->ah);
1553 GNUNET_ARM_disconnect_and_free (peer->ah);
1559 * Destroy the peer. Releases resources locked during peer configuration.
1560 * If the peer is still running, it will be stopped AND a warning will be
1561 * printed (users of the API should stop the peer explicitly first).
1563 * @param peer peer to destroy
1566 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1570 if (NULL != peer->main_process)
1571 GNUNET_TESTING_peer_stop (peer);
1572 if (NULL != peer->ah)
1573 GNUNET_ARM_disconnect_and_free (peer->ah);
1574 if (NULL != peer->mh)
1575 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1576 GNUNET_free (peer->cfgfile);
1577 if (NULL != peer->cfg)
1578 GNUNET_CONFIGURATION_destroy (peer->cfg);
1579 GNUNET_free (peer->main_binary);
1580 GNUNET_free (peer->args);
1581 GNUNET_free_non_null (peer->id);
1582 GNUNET_free_non_null (peer->ss_instances);
1583 if (NULL != peer->ports)
1585 for (cnt = 0; cnt < peer->nports; cnt++)
1586 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1587 GNUNET_free (peer->ports);
1594 * Start a single peer and run a test using the testing library.
1595 * Starts a peer using the given configuration and then invokes the
1596 * given callback. This function ALSO initializes the scheduler loop
1597 * and should thus be called directly from "main". The testcase
1598 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1600 * @param testdir only the directory name without any path. This is used for
1601 * all service homes; the directory will be created in a temporary
1602 * location depending on the underlying OS
1603 * @param cfgfilename name of the configuration file to use;
1604 * use NULL to only run with defaults
1605 * @param tm main function of the testcase
1606 * @param tm_cls closure for 'tm'
1607 * @return 0 on success, 1 on error
1610 GNUNET_TESTING_peer_run (const char *testdir,
1611 const char *cfgfilename,
1612 GNUNET_TESTING_TestMain tm,
1615 return GNUNET_TESTING_service_run (testdir, "arm",
1616 cfgfilename, tm, tm_cls);
1621 * Structure for holding service data
1623 struct ServiceContext
1626 * The configuration of the peer in which the service is run
1628 const struct GNUNET_CONFIGURATION_Handle *cfg;
1631 * Callback to signal service startup
1633 GNUNET_TESTING_TestMain tm;
1636 * The peer in which the service is run.
1638 struct GNUNET_TESTING_Peer *peer;
1641 * Closure for the above callback
1648 * Callback to be called when SCHEDULER has been started
1650 * @param cls the ServiceContext
1651 * @param tc the TaskContext
1654 service_run_main (void *cls,
1655 const struct GNUNET_SCHEDULER_TaskContext *tc)
1657 struct ServiceContext *sc = cls;
1659 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1664 * Start a single service (no ARM, except of course if the given
1665 * service name is 'arm') and run a test using the testing library.
1666 * Starts a service using the given configuration and then invokes the
1667 * given callback. This function ALSO initializes the scheduler loop
1668 * and should thus be called directly from "main". The testcase
1669 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1671 * This function is useful if the testcase is for a single service
1672 * and if that service doesn't itself depend on other services.
1674 * @param testdir only the directory name without any path. This is used for
1675 * all service homes; the directory will be created in a temporary
1676 * location depending on the underlying OS
1677 * @param service_name name of the service to run
1678 * @param cfgfilename name of the configuration file to use;
1679 * use NULL to only run with defaults
1680 * @param tm main function of the testcase
1681 * @param tm_cls closure for 'tm'
1682 * @return 0 on success, 1 on error
1685 GNUNET_TESTING_service_run (const char *testdir,
1686 const char *service_name,
1687 const char *cfgfilename,
1688 GNUNET_TESTING_TestMain tm,
1691 struct ServiceContext sc;
1692 struct GNUNET_TESTING_System *system;
1693 struct GNUNET_TESTING_Peer *peer;
1694 struct GNUNET_CONFIGURATION_Handle *cfg;
1696 char *libexec_binary;
1698 GNUNET_log_setup (testdir, "WARNING", NULL);
1699 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1702 cfg = GNUNET_CONFIGURATION_create ();
1703 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1705 LOG (GNUNET_ERROR_TYPE_ERROR,
1706 _("Failed to load configuration from %s\n"), cfgfilename);
1707 GNUNET_CONFIGURATION_destroy (cfg);
1708 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1711 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1714 GNUNET_CONFIGURATION_destroy (cfg);
1715 hostkeys_unload (system);
1716 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1719 GNUNET_free (peer->main_binary);
1720 GNUNET_free (peer->args);
1721 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1722 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1723 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1726 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1727 peer->args = GNUNET_strdup ("");
1730 peer->args = GNUNET_strdup (libexec_binary);
1732 GNUNET_free (libexec_binary);
1733 GNUNET_free (binary);
1734 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1736 GNUNET_TESTING_peer_destroy (peer);
1737 GNUNET_CONFIGURATION_destroy (cfg);
1738 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1745 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1746 if ((NULL != peer->main_process) &&
1747 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1749 GNUNET_TESTING_peer_destroy (peer);
1750 GNUNET_CONFIGURATION_destroy (cfg);
1751 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1754 GNUNET_TESTING_peer_destroy (peer);
1755 GNUNET_CONFIGURATION_destroy (cfg);
1756 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1762 * Sometimes we use the binary name to determine which specific
1763 * test to run. In those cases, the string after the last "_"
1764 * in 'argv[0]' specifies a string that determines the configuration
1765 * file or plugin to use.
1767 * This function returns the respective substring, taking care
1768 * of issues such as binaries ending in '.exe' on W32.
1770 * @param argv0 the name of the binary
1771 * @return string between the last '_' and the '.exe' (or the end of the string),
1772 * NULL if argv0 has no '_'
1775 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1777 size_t slen = strlen (argv0) + 1;
1782 memcpy (sbuf, argv0, slen);
1783 ret = strrchr (sbuf, '_');
1786 ret++; /* skip underscore */
1787 dot = strchr (ret, '.');
1790 return GNUNET_strdup (ret);
1794 /* end of testing.c */