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
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_malloc (sizeof (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_malloc (sizeof (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 ss->share = tss.share;
424 GNUNET_array_append (system->shared_services, system->n_shared_services,
432 * Create a system handle. There must only be one system handle per operating
433 * system. Uses a default range for allowed ports. Ports are still tested for
436 * @param testdir only the directory name without any path. This is used for all
437 * service homes; the directory will be created in a temporary location
438 * depending on the underlying OS. This variable will be
439 * overridden with the value of the environmental variable
440 * GNUNET_TESTING_PREFIX, if it exists.
441 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
442 * service configurations generated to allow control connections from
443 * this ip. This can either be a single ip address or a network address
445 * @param hostname the hostname of the system we are using for testing; NULL for
447 * @param shared_services NULL terminated array describing services that are to
448 * be shared among peers
449 * @return handle to this system, NULL on error
451 struct GNUNET_TESTING_System *
452 GNUNET_TESTING_system_create (const char *testdir,
453 const char *trusted_ip,
454 const char *hostname,
455 const struct GNUNET_TESTING_SharedService *
458 return GNUNET_TESTING_system_create_with_portrange (testdir,
467 cleanup_shared_service_instance (struct SharedServiceInstance *i)
469 if (NULL != i->cfg_fn)
471 (void) unlink (i->cfg_fn);
472 GNUNET_free (i->cfg_fn);
474 GNUNET_free_non_null (i->unix_sock);
475 GNUNET_free_non_null (i->port_str);
476 GNUNET_break (NULL == i->proc);
477 GNUNET_break (0 == i->n_refs);
482 start_shared_service_instance (struct SharedServiceInstance *i)
485 char *libexec_binary;
487 GNUNET_assert (NULL == i->proc);
488 GNUNET_assert (NULL != i->cfg_fn);
489 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
490 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
491 GNUNET_free (binary);
492 i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
493 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
500 GNUNET_free (libexec_binary);
502 return GNUNET_SYSERR;
508 stop_shared_service_instance (struct SharedServiceInstance *i)
510 GNUNET_break (0 == i->n_refs);
511 if (0 != GNUNET_OS_process_kill (i->proc, GNUNET_TERM_SIG))
512 LOG (GNUNET_ERROR_TYPE_WARNING,
513 "Killing shared service instance (%s) failed\n", i->ss->sname);
514 (void) GNUNET_OS_process_wait (i->proc);
515 GNUNET_OS_process_destroy (i->proc);
521 * Free system resources.
523 * @param system system to be freed
524 * @param remove_paths should the 'testdir' and all subdirectories
525 * be removed (clean up on shutdown)?
528 GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
531 struct SharedService *ss;
532 struct SharedServiceInstance *i;
536 if (NULL != system->hostkeys_data)
537 hostkeys_unload (system);
538 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
540 ss = system->shared_services[ss_cnt];
541 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
543 i = ss->instances[i_cnt];
545 stop_shared_service_instance (i);
546 cleanup_shared_service_instance (i);
548 GNUNET_free_non_null (ss->instances);
549 GNUNET_CONFIGURATION_destroy (ss->cfg);
550 GNUNET_free (ss->sname);
553 GNUNET_free_non_null (system->shared_services);
554 if (GNUNET_YES == remove_paths)
555 GNUNET_DISK_directory_remove (system->tmppath);
556 GNUNET_free (system->tmppath);
557 GNUNET_free_non_null (system->trusted_ip);
558 GNUNET_free_non_null (system->hostname);
559 GNUNET_free (system);
564 * Reserve a TCP or UDP port for a peer.
566 * @param system system to use for reservation tracking
567 * @return 0 if no free port was available
570 GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
572 struct GNUNET_NETWORK_Handle *socket;
573 struct addrinfo hint;
574 struct addrinfo *ret;
576 uint32_t *port_buckets;
585 FIXME: Instead of using getaddrinfo we should try to determine the port
586 status by the following heurestics.
588 On systems which support both IPv4 and IPv6, only ports open on both
589 address families are considered open.
590 On system with either IPv4 or IPv6. A port is considered open if it's
591 open in the respective address family
593 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
594 hint.ai_socktype = 0;
595 hint.ai_protocol = 0;
598 hint.ai_canonname = NULL;
600 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
601 port_buckets = system->reserved_ports;
602 for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++)
604 xor_image = (UINT32_MAX ^ port_buckets[index]);
605 if (0 == xor_image) /* Ports in the bucket are full */
607 pos = system->lowport % 32;
610 if (0 == ((xor_image >> pos) & 1U))
615 open_port = (index * 32) + pos;
616 if (open_port >= system->highport)
618 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
620 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
621 GNUNET_free (open_port_str);
622 bind_status = GNUNET_NO;
623 for (ai = ret; NULL != ai; ai = ai->ai_next)
625 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
628 bind_status = GNUNET_NETWORK_socket_bind (socket,
631 GNUNET_NETWORK_socket_close (socket);
632 if (GNUNET_OK != bind_status)
634 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0);
637 bind_status = GNUNET_NETWORK_socket_bind (socket,
640 GNUNET_NETWORK_socket_close (socket);
641 if (GNUNET_OK != bind_status)
644 port_buckets[index] |= (1U << pos); /* Set the port bit */
646 if (GNUNET_OK == bind_status)
648 LOG (GNUNET_ERROR_TYPE_DEBUG,
649 "Found a free port %u\n", (unsigned int) open_port);
660 * Release reservation of a TCP or UDP port for a peer
661 * (used during GNUNET_TESTING_peer_destroy).
663 * @param system system to use for reservation tracking
664 * @param port reserved port to release
667 GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
670 uint32_t *port_buckets;
674 port_buckets = system->reserved_ports;
677 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
678 if (0 == (port_buckets[bucket] & (1U << pos)))
680 GNUNET_break(0); /* Port was not reserved by us using reserve_port() */
683 port_buckets[bucket] &= ~(1U << pos);
688 * Testing includes a number of pre-created hostkeys for
689 * faster peer startup. This function can be used to
690 * access the n-th key of those pre-created hostkeys; note
691 * that these keys are ONLY useful for testing and not
692 * secure as the private keys are part of the public
693 * GNUnet source code.
695 * This is primarily a helper function used internally
696 * by #GNUNET_TESTING_peer_configure.
698 * @param system the testing system handle
699 * @param key_number desired pre-created hostkey to obtain
700 * @param id set to the peer's identity (hash of the public
701 * key; if NULL, GNUNET_SYSERR is returned immediately
702 * @return NULL on error (not enough keys)
704 struct GNUNET_CRYPTO_EddsaPrivateKey *
705 GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
707 struct GNUNET_PeerIdentity *id)
709 struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
711 if ((NULL == id) || (NULL == system->hostkeys_data))
713 if (key_number >= system->total_hostkeys)
715 LOG (GNUNET_ERROR_TYPE_ERROR,
716 _("Key number %u does not exist\n"), key_number);
719 private_key = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
721 system->hostkeys_data +
722 (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
723 GNUNET_TESTING_HOSTKEYFILESIZE);
724 GNUNET_CRYPTO_eddsa_key_get_public (private_key,
731 * Structure for holding data to build new configurations from a configuration
737 * The system for which we are building configurations
739 struct GNUNET_TESTING_System *system;
742 * The configuration we are building
744 struct GNUNET_CONFIGURATION_Handle *cfg;
747 * The customized service home path for this peer
752 * Array of ports currently allocated to this peer. These ports will be
753 * released upon peer destroy and can be used by other peers which are
759 * The number of ports in the above array
764 * build status - to signal error while building a configuration
771 * Function to iterate over options. Copies
772 * the options to the target configuration,
773 * updating PORT values as needed.
775 * @param cls the UpdateContext
776 * @param section name of the section
777 * @param option name of the option
778 * @param value value of the option
781 update_config (void *cls, const char *section, const char *option,
784 struct UpdateContext *uc = cls;
788 char *single_variable;
789 char *per_host_variable;
790 unsigned long long num_per_host;
793 if (GNUNET_OK != uc->status)
795 if (! ((0 == strcmp (option, "PORT"))
796 || (0 == strcmp (option, "UNIXPATH"))
797 || (0 == strcmp (option, "HOSTNAME"))))
799 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
800 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
801 if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
805 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
808 new_port = GNUNET_TESTING_reserve_port (uc->system);
811 uc->status = GNUNET_SYSERR;
812 GNUNET_free (single_variable);
813 GNUNET_free (per_host_variable);
816 GNUNET_snprintf (cval, sizeof (cval), "%u", new_port);
818 GNUNET_array_append (uc->ports, uc->nports, new_port);
820 else if ((ival != 0) &&
822 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
824 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
828 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
829 /* ival + ctx->fdnum % num_per_host); */
831 GNUNET_break (0); /* FIXME */
834 if (0 == strcmp (option, "UNIXPATH"))
837 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
840 GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock",
841 uc->gnunet_home, section);
844 else if ((GNUNET_YES ==
845 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
850 GNUNET_break(0); /* FIXME */
853 if (0 == strcmp (option, "HOSTNAME"))
855 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
857 GNUNET_free (single_variable);
858 GNUNET_free (per_host_variable);
859 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
864 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
865 * 'trusted_hosts' in all sections
867 * @param cls the UpdateContext
868 * @param section name of the section
871 update_config_sections (void *cls,
874 struct UpdateContext *uc = cls;
878 char *orig_allowed_hosts;
880 char *ACCEPT_FROM_key;
886 /* Ignore certain options from sections. See
887 https://gnunet.org/bugs/view.php?id=2476 */
888 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
889 "TESTING_IGNORE_KEYS"))
893 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section,
894 "TESTING_IGNORE_KEYS", &val));
896 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
902 ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt);
904 for (key = 0; key < ikeys_cnt; key++)
907 ptr = strstr (ptr, ";");
915 for (key = 0; key < ikeys_cnt; key++)
917 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
920 if ((key == ikeys_cnt) &&
921 (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
925 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr))
927 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section,
928 "ADVERTISED_PORT", ptr);
932 for (key = 0; key < ikeys_cnt; key++)
934 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
943 GNUNET_free_non_null (val);
944 ACCEPT_FROM_key = "ACCEPT_FROM";
945 if ((NULL != uc->system->trusted_ip) &&
946 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
947 ACCEPT_FROM_key = "ACCEPT_FROM6";
949 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key,
950 &orig_allowed_hosts))
952 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
954 if (NULL == uc->system->trusted_ip)
955 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
957 GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts,
958 uc->system->trusted_ip);
959 GNUNET_free (orig_allowed_hosts);
960 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key,
962 GNUNET_free (allowed_hosts);
965 static struct SharedServiceInstance *
966 associate_shared_service (struct GNUNET_TESTING_System *system,
967 struct SharedService *ss,
968 struct GNUNET_CONFIGURATION_Handle *cfg)
970 struct SharedServiceInstance *i;
971 struct GNUNET_CONFIGURATION_Handle *temp;
976 if ( ((0 == ss->share) && (NULL == ss->instances))
979 && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) )
981 i = GNUNET_new (struct SharedServiceInstance);
983 (void) GNUNET_asprintf (&gnunet_home, "%s/shared/%s/%u",
984 system->tmppath, ss->sname, ss->n_instances);
985 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", gnunet_home);
986 port = GNUNET_TESTING_reserve_port (system);
989 GNUNET_free (gnunet_home);
990 cleanup_shared_service_instance (i);
993 GNUNET_array_append (ss->instances, ss->n_instances, i);
994 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
995 (void) GNUNET_asprintf (&i->port_str, "%u", port);
996 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", gnunet_home);
997 GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "GNUNET_HOME",
999 GNUNET_free (gnunet_home);
1000 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH",
1002 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT",
1004 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1006 GNUNET_CONFIGURATION_destroy (temp);
1007 cleanup_shared_service_instance (i);
1010 GNUNET_CONFIGURATION_destroy (temp);
1014 GNUNET_assert (NULL != ss->instances);
1015 GNUNET_assert (0 < ss->n_instances);
1016 i = ss->instances[ss->n_instances - 1];
1018 GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname,
1019 &cfg_copy_iterator, cfg);
1020 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH",
1022 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1028 * Create a new configuration using the given configuration as a template;
1029 * ports and paths will be modified to select available ports on the local
1030 * system. The default configuration will be available in PATHS section under
1031 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1032 * section to the temporary directory specific to this configuration. If we run
1033 * out of "*port" numbers, return #GNUNET_SYSERR.
1035 * This is primarily a helper function used internally
1036 * by 'GNUNET_TESTING_peer_configure'.
1038 * @param system system to use to coordinate resource usage
1039 * @param cfg template configuration to update
1040 * @param ports array with port numbers used in the created configuration.
1041 * Will be updated upon successful return. Can be NULL
1042 * @param nports the size of the `ports' array. Will be updated.
1043 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1044 * be incomplete and should not be used there upon
1047 GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1048 struct GNUNET_CONFIGURATION_Handle *cfg,
1050 unsigned int *nports)
1052 struct UpdateContext uc;
1053 char *default_config;
1057 uc.status = GNUNET_OK;
1060 GNUNET_asprintf (&uc.gnunet_home, "%s/%u", system->tmppath,
1061 system->path_counter++);
1062 GNUNET_asprintf (&default_config, "%s/config", uc.gnunet_home);
1063 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
1065 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
1067 GNUNET_free (default_config);
1068 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "GNUNET_HOME",
1070 /* make PORTs and UNIXPATHs unique */
1071 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1072 /* allow connections to services from system trusted_ip host */
1073 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1074 /* enable loopback-based connections between peers */
1075 GNUNET_CONFIGURATION_set_value_string (cfg,
1077 "USE_LOCALADDR", "YES");
1078 GNUNET_free (uc.gnunet_home);
1079 if ((NULL != ports) && (NULL != nports))
1082 *nports = uc.nports;
1085 GNUNET_free_non_null (uc.ports);
1091 * Create a new configuration using the given configuration as a template;
1092 * ports and paths will be modified to select available ports on the local
1093 * system. The default configuration will be available in PATHS section under
1094 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1095 * section to the temporary directory specific to this configuration. If we run
1096 * out of "*port" numbers, return SYSERR.
1098 * This is primarily a helper function used internally
1099 * by 'GNUNET_TESTING_peer_configure'.
1101 * @param system system to use to coordinate resource usage
1102 * @param cfg template configuration to update
1103 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1104 * be incomplete and should not be used there upon
1107 GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1108 struct GNUNET_CONFIGURATION_Handle *cfg)
1110 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1115 * Configure a GNUnet peer. GNUnet must be installed on the local
1116 * system and available in the PATH.
1118 * @param system system to use to coordinate resource usage
1119 * @param cfg configuration to use; will be UPDATED (to reflect needed
1120 * changes in port numbers and paths)
1121 * @param key_number number of the hostkey to use for the peer
1122 * @param id identifier for the daemon, will be set, can be NULL
1123 * @param emsg set to freshly allocated error message (set to NULL on success),
1125 * @return handle to the peer, NULL on error
1127 struct GNUNET_TESTING_Peer *
1128 GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1129 struct GNUNET_CONFIGURATION_Handle *cfg,
1130 uint32_t key_number,
1131 struct GNUNET_PeerIdentity *id,
1134 struct GNUNET_TESTING_Peer *peer;
1135 struct GNUNET_DISK_FileHandle *fd;
1136 char *hostkey_filename;
1137 char *config_filename;
1138 char *libexec_binary;
1140 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
1142 struct SharedService *ss;
1143 struct SharedServiceInstance **ss_instances;
1145 unsigned int nports;
1149 ss_instances = NULL;
1152 if (key_number >= system->total_hostkeys)
1154 GNUNET_asprintf (&emsg_,
1155 _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1156 (unsigned int) system->total_hostkeys);
1161 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1163 GNUNET_asprintf (&emsg_,
1164 _("Failed to initialize hostkey for peer %u\n"),
1165 (unsigned int) key_number);
1171 GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1173 GNUNET_asprintf (&emsg_,
1174 _("PRIVATE_KEY option in PEER section missing in configuration\n"));
1177 /* Remove sections for shared services */
1178 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1180 ss = system->shared_services[cnt];
1181 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1183 if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg,
1186 GNUNET_asprintf (&emsg_,
1187 _("Failed to create configuration for peer "
1188 "(not enough free ports?)\n"));
1191 GNUNET_assert (GNUNET_OK ==
1192 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER",
1194 &hostkey_filename));
1195 fd = GNUNET_DISK_file_open (hostkey_filename,
1196 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1197 GNUNET_DISK_PERM_USER_READ
1198 | GNUNET_DISK_PERM_USER_WRITE);
1201 GNUNET_asprintf (&emsg_, _("Cannot open hostkey file `%s': %s\n"),
1202 hostkey_filename, STRERROR (errno));
1203 GNUNET_free (hostkey_filename);
1206 GNUNET_free (hostkey_filename);
1207 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1208 GNUNET_DISK_file_write (fd, system->hostkeys_data
1209 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1210 GNUNET_TESTING_HOSTKEYFILESIZE))
1212 GNUNET_asprintf (&emsg_,
1213 _("Failed to write hostkey file for peer %u: %s\n"),
1214 (unsigned int) key_number,
1216 GNUNET_DISK_file_close (fd);
1219 GNUNET_DISK_file_close (fd);
1220 ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *)
1221 * system->n_shared_services);
1222 for (cnt=0; cnt < system->n_shared_services; cnt++)
1224 ss = system->shared_services[cnt];
1225 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1226 if (NULL == ss_instances[cnt])
1229 GNUNET_assert (GNUNET_OK ==
1230 GNUNET_CONFIGURATION_get_value_string
1231 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1232 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1234 GNUNET_asprintf (&emsg_,
1235 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1237 (unsigned int) key_number,
1239 GNUNET_free (config_filename);
1242 peer = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Peer));
1243 peer->ss_instances = ss_instances;
1244 peer->cfgfile = config_filename; /* Free in peer_destroy */
1245 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1246 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1247 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1250 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1251 peer->args = strdup ("");
1254 peer->args = strdup (libexec_binary);
1255 peer->system = system;
1256 peer->key_number = key_number;
1257 GNUNET_free (libexec_binary);
1258 peer->ports = ports; /* Free in peer_destroy */
1259 peer->nports = nports;
1263 GNUNET_free_non_null (ss_instances);
1264 GNUNET_free_non_null (ports);
1265 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1269 GNUNET_free (emsg_);
1275 * Obtain the peer identity from a peer handle.
1277 * @param peer peer handle for which we want the peer's identity
1278 * @param id identifier for the daemon, will be set
1281 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1282 struct GNUNET_PeerIdentity *id)
1284 if (NULL != peer->id)
1286 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1289 peer->id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1290 GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system,
1293 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1300 * @param peer peer to start
1301 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1304 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1306 struct SharedServiceInstance *i;
1309 if (NULL != peer->main_process)
1312 return GNUNET_SYSERR;
1314 GNUNET_assert (NULL != peer->cfgfile);
1315 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1317 i = peer->ss_instances[cnt];
1318 if ((0 == i->n_refs)
1319 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1320 return GNUNET_SYSERR;
1323 peer->main_process = GNUNET_OS_start_process (PIPE_CONTROL,
1324 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1332 if (NULL == peer->main_process)
1334 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1335 _("Failed to start `%s': %s\n"),
1338 return GNUNET_SYSERR;
1345 * Start a service at a peer using its ARM service
1347 * @param peer the peer whose service has to be started
1348 * @param service_name name of the service to start
1349 * @param timeout how long should the ARM API try to send the request to start
1351 * @param cont the callback to call with result and status from ARM API
1352 * @param cont_cls the closure for the above callback
1353 * @return GNUNET_OK upon successfully queuing the service start request;
1354 * GNUNET_SYSERR upon error
1357 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1358 const char *service_name,
1359 struct GNUNET_TIME_Relative timeout,
1360 GNUNET_ARM_ResultCallback cont,
1363 if (NULL == peer->ah)
1364 return GNUNET_SYSERR;
1365 GNUNET_ARM_request_service_start (peer->ah,
1367 GNUNET_OS_INHERIT_STD_ALL,
1375 * Stop a service at a peer using its ARM service
1377 * @param peer the peer whose service has to be stopped
1378 * @param service_name name of the service to stop
1379 * @param timeout how long should the ARM API try to send the request to stop
1381 * @param cont the callback to call with result and status from ARM API
1382 * @param cont_cls the closure for the above callback
1383 * @return GNUNET_OK upon successfully queuing the service stop request;
1384 * GNUNET_SYSERR upon error
1387 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1388 const char *service_name,
1389 struct GNUNET_TIME_Relative timeout,
1390 GNUNET_ARM_ResultCallback cont,
1393 if (NULL == peer->ah)
1394 return GNUNET_SYSERR;
1395 GNUNET_ARM_request_service_stop (peer->ah,
1404 * Sends SIGTERM to the peer's main process
1406 * @param peer the handle to the peer
1407 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1408 * or upon any error while sending SIGTERM
1411 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1413 struct SharedServiceInstance *i;
1416 if (NULL == peer->main_process)
1419 return GNUNET_SYSERR;
1421 if (0 != GNUNET_OS_process_kill (peer->main_process, GNUNET_TERM_SIG))
1422 return GNUNET_SYSERR;
1423 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1425 i = peer->ss_instances[cnt];
1426 GNUNET_assert (0 != i->n_refs);
1429 stop_shared_service_instance (i);
1436 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1438 * @param peer the handle to the peer
1439 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1440 * or upon any error while waiting
1443 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1447 if (NULL == peer->main_process)
1450 return GNUNET_SYSERR;
1452 ret = GNUNET_OS_process_wait (peer->main_process);
1453 GNUNET_OS_process_destroy (peer->main_process);
1454 peer->main_process = NULL;
1462 * @param peer peer to stop
1463 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1466 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1468 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1469 return GNUNET_SYSERR;
1470 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1471 return GNUNET_SYSERR;
1477 * Function called whenever we connect to or disconnect from ARM.
1479 * @param cls closure
1480 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1481 * GNUNET_SYSERR on error.
1484 disconn_status (void *cls,
1487 struct GNUNET_TESTING_Peer *peer = cls;
1489 if (GNUNET_SYSERR == connected)
1491 peer->cb (peer->cb_cls, peer, connected);
1494 if (GNUNET_YES == connected)
1496 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1499 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1500 GNUNET_ARM_disconnect_and_free (peer->ah);
1502 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1507 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1508 * through the GNUNET_TESTING_PeerStopCallback().
1510 * @param peer the peer to stop
1511 * @param cb the callback to signal peer shutdown
1512 * @param cb_cls closure for the above callback
1513 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1514 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1518 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1519 GNUNET_TESTING_PeerStopCallback cb,
1522 if (NULL == peer->main_process)
1523 return GNUNET_SYSERR;
1524 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1525 if (NULL == peer->ah)
1526 return GNUNET_SYSERR;
1528 peer->cb_cls = cb_cls;
1534 * Cancel a previous asynchronous peer stop request.
1535 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1536 * peer. It is an error to call this function if the peer stop callback was
1539 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1543 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1545 GNUNET_assert (NULL != peer->ah);
1546 GNUNET_ARM_disconnect_and_free (peer->ah);
1552 * Destroy the peer. Releases resources locked during peer configuration.
1553 * If the peer is still running, it will be stopped AND a warning will be
1554 * printed (users of the API should stop the peer explicitly first).
1556 * @param peer peer to destroy
1559 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1563 if (NULL != peer->main_process)
1564 GNUNET_TESTING_peer_stop (peer);
1565 if (NULL != peer->ah)
1566 GNUNET_ARM_disconnect_and_free (peer->ah);
1567 if (NULL != peer->mh)
1568 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1569 GNUNET_free (peer->cfgfile);
1570 if (NULL != peer->cfg)
1571 GNUNET_CONFIGURATION_destroy (peer->cfg);
1572 GNUNET_free (peer->main_binary);
1573 GNUNET_free (peer->args);
1574 GNUNET_free_non_null (peer->id);
1575 GNUNET_free_non_null (peer->ss_instances);
1576 if (NULL != peer->ports)
1578 for (cnt = 0; cnt < peer->nports; cnt++)
1579 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1580 GNUNET_free (peer->ports);
1587 * Start a single peer and run a test using the testing library.
1588 * Starts a peer using the given configuration and then invokes the
1589 * given callback. This function ALSO initializes the scheduler loop
1590 * and should thus be called directly from "main". The testcase
1591 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1593 * @param testdir only the directory name without any path. This is used for
1594 * all service homes; the directory will be created in a temporary
1595 * location depending on the underlying OS
1596 * @param cfgfilename name of the configuration file to use;
1597 * use NULL to only run with defaults
1598 * @param tm main function of the testcase
1599 * @param tm_cls closure for 'tm'
1600 * @return 0 on success, 1 on error
1603 GNUNET_TESTING_peer_run (const char *testdir,
1604 const char *cfgfilename,
1605 GNUNET_TESTING_TestMain tm,
1608 return GNUNET_TESTING_service_run (testdir, "arm",
1609 cfgfilename, tm, tm_cls);
1614 * Structure for holding service data
1616 struct ServiceContext
1619 * The configuration of the peer in which the service is run
1621 const struct GNUNET_CONFIGURATION_Handle *cfg;
1624 * Callback to signal service startup
1626 GNUNET_TESTING_TestMain tm;
1629 * The peer in which the service is run.
1631 struct GNUNET_TESTING_Peer *peer;
1634 * Closure for the above callback
1641 * Callback to be called when SCHEDULER has been started
1643 * @param cls the ServiceContext
1644 * @param tc the TaskContext
1647 service_run_main (void *cls,
1648 const struct GNUNET_SCHEDULER_TaskContext *tc)
1650 struct ServiceContext *sc = cls;
1652 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1657 * Start a single service (no ARM, except of course if the given
1658 * service name is 'arm') and run a test using the testing library.
1659 * Starts a service using the given configuration and then invokes the
1660 * given callback. This function ALSO initializes the scheduler loop
1661 * and should thus be called directly from "main". The testcase
1662 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1664 * This function is useful if the testcase is for a single service
1665 * and if that service doesn't itself depend on other services.
1667 * @param testdir only the directory name without any path. This is used for
1668 * all service homes; the directory will be created in a temporary
1669 * location depending on the underlying OS
1670 * @param service_name name of the service to run
1671 * @param cfgfilename name of the configuration file to use;
1672 * use NULL to only run with defaults
1673 * @param tm main function of the testcase
1674 * @param tm_cls closure for 'tm'
1675 * @return 0 on success, 1 on error
1678 GNUNET_TESTING_service_run (const char *testdir,
1679 const char *service_name,
1680 const char *cfgfilename,
1681 GNUNET_TESTING_TestMain tm,
1684 struct ServiceContext sc;
1685 struct GNUNET_TESTING_System *system;
1686 struct GNUNET_TESTING_Peer *peer;
1687 struct GNUNET_CONFIGURATION_Handle *cfg;
1689 char *libexec_binary;
1691 GNUNET_log_setup (testdir, "WARNING", NULL);
1692 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1695 cfg = GNUNET_CONFIGURATION_create ();
1696 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1698 LOG (GNUNET_ERROR_TYPE_ERROR,
1699 _("Failed to load configuration from %s\n"), cfgfilename);
1700 GNUNET_CONFIGURATION_destroy (cfg);
1701 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1704 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1707 GNUNET_CONFIGURATION_destroy (cfg);
1708 hostkeys_unload (system);
1709 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1712 GNUNET_free (peer->main_binary);
1713 GNUNET_free (peer->args);
1714 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1715 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1716 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1719 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1720 peer->args = strdup ("");
1723 peer->args = strdup (libexec_binary);
1725 GNUNET_free (libexec_binary);
1726 GNUNET_free (binary);
1727 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1729 GNUNET_TESTING_peer_destroy (peer);
1730 GNUNET_CONFIGURATION_destroy (cfg);
1731 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1738 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1739 if ((NULL != peer->main_process) &&
1740 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1742 GNUNET_TESTING_peer_destroy (peer);
1743 GNUNET_CONFIGURATION_destroy (cfg);
1744 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1747 GNUNET_TESTING_peer_destroy (peer);
1748 GNUNET_CONFIGURATION_destroy (cfg);
1749 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1755 * Sometimes we use the binary name to determine which specific
1756 * test to run. In those cases, the string after the last "_"
1757 * in 'argv[0]' specifies a string that determines the configuration
1758 * file or plugin to use.
1760 * This function returns the respective substring, taking care
1761 * of issues such as binaries ending in '.exe' on W32.
1763 * @param argv0 the name of the binary
1764 * @return string between the last '_' and the '.exe' (or the end of the string),
1765 * NULL if argv0 has no '_'
1768 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1770 size_t slen = strlen (argv0) + 1;
1775 memcpy (sbuf, argv0, slen);
1776 ret = strrchr (sbuf, '_');
1779 ret++; /* skip underscore */
1780 dot = strchr (ret, '.');
1783 return GNUNET_strdup (ret);
1787 /* end of testing.c */