2 This file is part of GNUnet
3 (C) 2008, 2009, 2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testing/testing.c
23 * @brief convenience API for writing testcases for GNUnet
24 * Many testcases need to start and stop a peer/service
25 * and this library is supposed to make that easier
26 * for TESTCASES. Normal programs should always
27 * use functions from gnunet_{util,arm}_lib.h. This API is
28 * ONLY for writing testcases (or internal use of the testbed).
29 * @author Christian Grothoff
33 #include "gnunet_util_lib.h"
34 #include "gnunet_arm_service.h"
35 #include "gnunet_testing_lib.h"
37 #define LOG(kind,...) \
38 GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
42 * We need pipe control only on WINDOWS
45 #define PIPE_CONTROL GNUNET_YES
47 #define PIPE_CONTROL GNUNET_NO
52 * Lowest port used for GNUnet testing. Should be high enough to not
53 * conflict with other applications running on the hosts but be low
54 * enough to not conflict with client-ports (typically starting around
57 #define LOW_PORT 12000
60 * Highest port used for GNUnet testing. Should be low enough to not
61 * conflict with the port range for "local" ports (client apps; see
62 * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
64 #define HIGH_PORT 56000
67 struct SharedServiceInstance
69 struct SharedService *ss;
73 struct GNUNET_OS_Process *proc;
86 struct SharedServiceInstance **instances;
88 struct GNUNET_CONFIGURATION_Handle *cfg;
94 unsigned int n_instances;
99 * Handle for a system on which GNUnet peers are executed;
100 * a system is used for reserving unique paths and ports.
102 struct GNUNET_TESTING_System
105 * Prefix (i.e. "/tmp/gnunet-testing/") we prepend to each
110 * The trusted ip. Can either be a single ip address or a network address in
121 * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes.
126 * memory map for 'hostkeys_data'.
128 struct GNUNET_DISK_MapHandle *map;
130 struct SharedService **shared_services;
132 unsigned int n_shared_services;
135 * Bitmap where each TCP port that has already been reserved for
136 * some GNUnet peer is recorded. Note that we additionally need to
137 * test if a port is already in use by non-GNUnet components before
138 * assigning it to a peer/service. If we detect that a port is
139 * already in use, we also mark it in this bitmap. So all the bits
140 * that are zero merely indicate ports that MIGHT be available for
143 uint32_t reserved_tcp_ports[65536 / 32];
146 * Bitmap where each UDP port that has already been reserved for
147 * some GNUnet peer is recorded. Note that we additionally need to
148 * test if a port is already in use by non-GNUnet components before
149 * assigning it to a peer/service. If we detect that a port is
150 * already in use, we also mark it in this bitmap. So all the bits
151 * that are zero merely indicate ports that MIGHT be available for
154 uint32_t reserved_udp_ports[65536 / 32];
157 * Counter we use to make service home paths unique on this system;
158 * the full path consists of the tmppath and this number. Each
159 * UNIXPATH for a peer is also modified to include the respective
160 * path counter to ensure uniqueness. This field is incremented
161 * by one for each configured peer. Even if peers are destroyed,
162 * we never re-use path counters.
164 uint32_t path_counter;
167 * The number of hostkeys
169 uint32_t total_hostkeys;
172 * Lowest port we are allowed to use.
177 * Highest port we are allowed to use.
184 * Handle for a GNUnet peer controlled by testing.
186 struct GNUNET_TESTING_Peer
189 * The TESTING system associated with this peer
191 struct GNUNET_TESTING_System *system;
194 * Path to the configuration file for this peer.
199 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
200 * Typically 'gnunet-service-arm' (but can be set to a
201 * specific service by 'GNUNET_TESTING_service_run' if
208 * Handle to the running binary of the service, NULL if the
209 * peer/service is currently not running.
211 struct GNUNET_OS_Process *main_process;
214 * The handle to the peer's ARM service
216 struct GNUNET_ARM_Handle *ah;
219 * Handle to ARM monitoring
221 struct GNUNET_ARM_MonitorHandle *mh;
224 * The config of the peer
226 struct GNUNET_CONFIGURATION_Handle *cfg;
229 * The callback to call asynchronously when a peer is stopped
231 GNUNET_TESTING_PeerStopCallback cb;
234 * The closure for the above callback
239 * The cached identity of this peer. Will be populated on call to
240 * GNUNET_TESTING_peer_get_identity()
242 struct GNUNET_PeerIdentity *id;
244 struct SharedServiceInstance **ss_instances;
247 * Array of ports currently allocated to this peer. These ports will be
248 * released upon peer destroy and can be used by other peers which are
254 * The number of ports in the above array
259 * The keynumber of this peer's hostkey
266 * Testing includes a number of pre-created hostkeys for faster peer
267 * startup. This function loads such keys into memory from a file.
269 * @param system the testing system handle
270 * @return GNUNET_OK on success; GNUNET_SYSERR on error
273 hostkeys_load (struct GNUNET_TESTING_System *system)
278 struct GNUNET_DISK_FileHandle *fd;
280 GNUNET_assert (NULL == system->hostkeys_data);
281 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
282 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
283 GNUNET_free (data_dir);
285 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
287 LOG (GNUNET_ERROR_TYPE_ERROR,
288 _("Hostkeys file not found: %s\n"), filename);
289 GNUNET_free (filename);
290 return GNUNET_SYSERR;
292 /* Check hostkey file size, read entire thing into memory */
294 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
298 GNUNET_free (filename);
299 return GNUNET_SYSERR; /* File is empty */
301 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
303 LOG (GNUNET_ERROR_TYPE_ERROR,
304 _("Incorrect hostkey file format: %s\n"), filename);
305 GNUNET_free (filename);
306 return GNUNET_SYSERR;
308 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
309 GNUNET_DISK_PERM_NONE);
312 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
313 GNUNET_free (filename);
314 return GNUNET_SYSERR;
316 GNUNET_free (filename);
317 system->hostkeys_data = GNUNET_DISK_file_map (fd,
319 GNUNET_DISK_MAP_TYPE_READ,
321 GNUNET_DISK_file_close (fd);
322 if (NULL == system->hostkeys_data)
323 return GNUNET_SYSERR;
324 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
330 * Function to remove the loaded hostkeys
332 * @param system the testing system handle
335 hostkeys_unload (struct GNUNET_TESTING_System *system)
337 GNUNET_break (NULL != system->hostkeys_data);
338 system->hostkeys_data = NULL;
339 GNUNET_DISK_file_unmap (system->map);
341 system->hostkeys_data = NULL;
342 system->total_hostkeys = 0;
347 * Function to iterate over options.
350 * @param section name of the section
351 * @param option name of the option
352 * @param value value of the option
355 cfg_copy_iterator (void *cls, const char *section,
356 const char *option, const char *value)
358 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
360 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
365 * Create a system handle. There must only be one system
366 * handle per operating system.
368 * @param testdir only the directory name without any path. This is used for
369 * all service homes; the directory will be created in a temporary
370 * location depending on the underlying OS
371 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
372 * service configurations generated to allow control connections from
373 * this ip. This can either be a single ip address or a network address
375 * @param hostname the hostname of the system we are using for testing; NULL for
377 * @param shared_services NULL terminated array describing services that are to
378 * be shared among peers
379 * @param lowport lowest port number this system is allowed to allocate (inclusive)
380 * @param highport highest port number this system is allowed to allocate (exclusive)
381 * @return handle to this system, NULL on error
383 struct GNUNET_TESTING_System *
384 GNUNET_TESTING_system_create_with_portrange (const char *testdir,
385 const char *trusted_ip,
386 const char *hostname,
388 GNUNET_TESTING_SharedService *
393 struct GNUNET_TESTING_System *system;
394 struct GNUNET_TESTING_SharedService tss;
395 struct SharedService *ss;
398 GNUNET_assert (NULL != testdir);
399 system = GNUNET_malloc (sizeof (struct GNUNET_TESTING_System));
400 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
401 system->lowport = lowport;
402 system->highport = highport;
403 if (NULL == system->tmppath)
405 GNUNET_free (system);
408 if (NULL != trusted_ip)
409 system->trusted_ip = GNUNET_strdup (trusted_ip);
410 if (NULL != hostname)
411 system->hostname = GNUNET_strdup (hostname);
412 if (GNUNET_OK != hostkeys_load (system))
414 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
417 if (NULL == shared_services)
419 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
421 tss = shared_services[cnt];
422 ss = GNUNET_malloc (sizeof (struct SharedService));
423 ss->sname = GNUNET_strdup (tss.service);
424 ss->cfg = GNUNET_CONFIGURATION_create ();
425 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, ss->sname,
426 &cfg_copy_iterator, ss->cfg);
427 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "TESTING",
428 &cfg_copy_iterator, ss->cfg);
429 ss->share = tss.share;
430 GNUNET_array_append (system->shared_services, system->n_shared_services,
438 * Create a system handle. There must only be one system handle per operating
439 * system. Uses a default range for allowed ports. Ports are still tested for
442 * @param testdir only the directory name without any path. This is used for all
443 * service homes; the directory will be created in a temporary location
444 * depending on the underlying OS
445 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
446 * service configurations generated to allow control connections from
447 * this ip. This can either be a single ip address or a network address
449 * @param hostname the hostname of the system we are using for testing; NULL for
451 * @param shared_services NULL terminated array describing services that are to
452 * be shared among peers
453 * @return handle to this system, NULL on error
455 struct GNUNET_TESTING_System *
456 GNUNET_TESTING_system_create (const char *testdir,
457 const char *trusted_ip,
458 const char *hostname,
459 const struct GNUNET_TESTING_SharedService *
462 return GNUNET_TESTING_system_create_with_portrange (testdir,
471 cleanup_shared_service_instance (struct SharedServiceInstance *i)
473 if (NULL != i->cfg_fn)
475 (void) unlink (i->cfg_fn);
476 GNUNET_free (i->cfg_fn);
478 GNUNET_free_non_null (i->unix_sock);
479 GNUNET_free_non_null (i->port_str);
480 GNUNET_break (NULL == i->proc);
481 GNUNET_break (0 == i->n_refs);
486 start_shared_service_instance (struct SharedServiceInstance *i)
489 char *libexec_binary;
491 GNUNET_assert (NULL == i->proc);
492 GNUNET_assert (NULL != i->cfg_fn);
493 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
494 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
495 GNUNET_free (binary);
496 i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
497 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
504 GNUNET_free (libexec_binary);
506 return GNUNET_SYSERR;
512 stop_shared_service_instance (struct SharedServiceInstance *i)
514 GNUNET_break (0 == i->n_refs);
515 if (0 != GNUNET_OS_process_kill (i->proc, SIGTERM))
516 LOG (GNUNET_ERROR_TYPE_WARNING,
517 "Killing shared service instance (%s) failed\n", i->ss->sname);
518 (void) GNUNET_OS_process_wait (i->proc);
519 GNUNET_OS_process_destroy (i->proc);
525 * Free system resources.
527 * @param system system to be freed
528 * @param remove_paths should the 'testdir' and all subdirectories
529 * be removed (clean up on shutdown)?
532 GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
535 struct SharedService *ss;
536 struct SharedServiceInstance *i;
540 if (NULL != system->hostkeys_data)
541 hostkeys_unload (system);
542 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
544 ss = system->shared_services[ss_cnt];
545 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
547 i = ss->instances[i_cnt];
549 stop_shared_service_instance (i);
550 cleanup_shared_service_instance (i);
552 GNUNET_free_non_null (ss->instances);
553 GNUNET_CONFIGURATION_destroy (ss->cfg);
554 GNUNET_free (ss->sname);
557 GNUNET_free_non_null (system->shared_services);
558 if (GNUNET_YES == remove_paths)
559 GNUNET_DISK_directory_remove (system->tmppath);
560 GNUNET_free (system->tmppath);
561 GNUNET_free_non_null (system->trusted_ip);
562 GNUNET_free_non_null (system->hostname);
563 GNUNET_free (system);
568 * Reserve a TCP or UDP port for a peer.
570 * @param system system to use for reservation tracking
571 * @param is_tcp GNUNET_YES for TCP ports, GNUNET_NO for UDP
572 * @return 0 if no free port was available
575 GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system,
578 struct GNUNET_NETWORK_Handle *socket;
579 struct addrinfo hint;
580 struct addrinfo *ret;
582 uint32_t *port_buckets;
591 FIXME: Instead of using getaddrinfo we should try to determine the port
592 status by the following heurestics.
594 On systems which support both IPv4 and IPv6, only ports open on both
595 address families are considered open.
596 On system with either IPv4 or IPv6. A port is considered open if it's
597 open in the respective address family
599 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
600 hint.ai_socktype = (GNUNET_YES == is_tcp)? SOCK_STREAM : SOCK_DGRAM;
601 hint.ai_protocol = 0;
604 hint.ai_canonname = NULL;
606 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
607 port_buckets = (GNUNET_YES == is_tcp) ?
608 system->reserved_tcp_ports : system->reserved_udp_ports;
609 for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++)
611 xor_image = (UINT32_MAX ^ port_buckets[index]);
612 if (0 == xor_image) /* Ports in the bucket are full */
614 pos = system->lowport % 32;
617 if (0 == ((xor_image >> pos) & 1U))
622 open_port = (index * 32) + pos;
623 if (open_port >= system->highport)
625 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
627 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
628 GNUNET_free (open_port_str);
629 bind_status = GNUNET_NO;
630 for (ai = ret; NULL != ai; ai = ai->ai_next)
632 socket = GNUNET_NETWORK_socket_create (ai->ai_family,
633 (GNUNET_YES == is_tcp) ?
634 SOCK_STREAM : SOCK_DGRAM,
638 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 is_tcp GNUNET_YES for TCP ports, GNUNET_NO for UDP
667 * @param port reserved port to release
670 GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
674 uint32_t *port_buckets;
678 port_buckets = (GNUNET_YES == is_tcp) ?
679 system->reserved_tcp_ports : system->reserved_udp_ports;
682 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
683 if (0 == (port_buckets[bucket] & (1U << pos)))
685 GNUNET_break(0); /* Port was not reserved by us using reserve_port() */
688 port_buckets[bucket] &= ~(1U << pos);
693 * Testing includes a number of pre-created hostkeys for
694 * faster peer startup. This function can be used to
695 * access the n-th key of those pre-created hostkeys; note
696 * that these keys are ONLY useful for testing and not
697 * secure as the private keys are part of the public
698 * GNUnet source code.
700 * This is primarily a helper function used internally
701 * by 'GNUNET_TESTING_peer_configure'.
703 * @param system the testing system handle
704 * @param key_number desired pre-created hostkey to obtain
705 * @param id set to the peer's identity (hash of the public
706 * key; if NULL, GNUNET_SYSERR is returned immediately
707 * @return NULL on error (not enough keys)
709 struct GNUNET_CRYPTO_EccPrivateKey *
710 GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
712 struct GNUNET_PeerIdentity *id)
714 struct GNUNET_CRYPTO_EccPrivateKey *private_key;
715 struct GNUNET_CRYPTO_EccPublicKey public_key;
717 if ((NULL == id) || (NULL == system->hostkeys_data))
719 if (key_number >= system->total_hostkeys)
721 LOG (GNUNET_ERROR_TYPE_ERROR,
722 _("Key number %u does not exist\n"), key_number);
725 private_key = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey);
727 system->hostkeys_data +
728 (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
729 GNUNET_TESTING_HOSTKEYFILESIZE);
730 if (NULL == private_key)
732 LOG (GNUNET_ERROR_TYPE_ERROR,
733 _("Error while decoding key %u\n"), key_number);
736 GNUNET_CRYPTO_ecc_key_get_public (private_key, &public_key);
737 GNUNET_CRYPTO_hash (&public_key,
738 sizeof (struct GNUNET_CRYPTO_EccPublicKey),
745 * Structure for holding data to build new configurations from a configuration
751 * The system for which we are building configurations
753 struct GNUNET_TESTING_System *system;
756 * The configuration we are building
758 struct GNUNET_CONFIGURATION_Handle *cfg;
761 * The customized service home path for this peer
766 * Array of ports currently allocated to this peer. These ports will be
767 * released upon peer destroy and can be used by other peers which are
773 * The number of ports in the above array
778 * build status - to signal error while building a configuration
785 * Function to iterate over options. Copies
786 * the options to the target configuration,
787 * updating PORT values as needed.
789 * @param cls the UpdateContext
790 * @param section name of the section
791 * @param option name of the option
792 * @param value value of the option
795 update_config (void *cls, const char *section, const char *option,
798 struct UpdateContext *uc = cls;
802 char *single_variable;
803 char *per_host_variable;
804 unsigned long long num_per_host;
807 if (GNUNET_OK != uc->status)
809 if (! ((0 == strcmp (option, "PORT"))
810 || (0 == strcmp (option, "UNIXPATH"))
811 || (0 == strcmp (option, "HOSTNAME"))))
813 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
814 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
815 if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
819 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
822 /* FIXME: What about UDP? */
823 new_port = GNUNET_TESTING_reserve_port (uc->system, GNUNET_YES);
826 uc->status = GNUNET_SYSERR;
827 GNUNET_free (single_variable);
828 GNUNET_free (per_host_variable);
831 GNUNET_snprintf (cval, sizeof (cval), "%u", new_port);
833 GNUNET_array_append (uc->ports, uc->nports, new_port);
835 else if ((ival != 0) &&
837 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
839 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
843 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
844 /* ival + ctx->fdnum % num_per_host); */
846 GNUNET_break (0); /* FIXME */
849 if (0 == strcmp (option, "UNIXPATH"))
852 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
855 GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock",
856 uc->service_home, section);
859 else if ((GNUNET_YES ==
860 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
865 GNUNET_break(0); /* FIXME */
868 if (0 == strcmp (option, "HOSTNAME"))
870 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
872 GNUNET_free (single_variable);
873 GNUNET_free (per_host_variable);
874 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
879 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
880 * 'trusted_hosts' in all sections
882 * @param cls the UpdateContext
883 * @param section name of the section
886 update_config_sections (void *cls,
889 struct UpdateContext *uc = cls;
893 char *orig_allowed_hosts;
895 char *ACCEPT_FROM_key;
901 /* Ignore certain options from sections. See
902 https://gnunet.org/bugs/view.php?id=2476 */
903 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
904 "TESTING_IGNORE_KEYS"))
908 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section,
909 "TESTING_IGNORE_KEYS", &val));
911 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
917 ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt);
919 for (key = 0; key < ikeys_cnt; key++)
922 ptr = strstr (ptr, ";");
930 for (key = 0; key < ikeys_cnt; key++)
932 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
935 if ((key == ikeys_cnt) &&
936 (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
940 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr))
942 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section,
943 "ADVERTISED_PORT", ptr);
947 for (key = 0; key < ikeys_cnt; key++)
949 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
958 GNUNET_free_non_null (val);
959 ACCEPT_FROM_key = "ACCEPT_FROM";
960 if ((NULL != uc->system->trusted_ip) &&
961 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
962 ACCEPT_FROM_key = "ACCEPT_FROM6";
964 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key,
965 &orig_allowed_hosts))
967 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
969 if (NULL == uc->system->trusted_ip)
970 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
972 GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts,
973 uc->system->trusted_ip);
974 GNUNET_free (orig_allowed_hosts);
975 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key,
977 GNUNET_free (allowed_hosts);
980 static struct SharedServiceInstance *
981 associate_shared_service (struct GNUNET_TESTING_System *system,
982 struct SharedService *ss,
983 struct GNUNET_CONFIGURATION_Handle *cfg)
985 struct SharedServiceInstance *i;
986 struct GNUNET_CONFIGURATION_Handle *temp;
991 if ( ((0 == ss->share) && (NULL == ss->instances))
994 && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) )
996 i = GNUNET_malloc (sizeof (struct SharedServiceInstance));
998 (void) GNUNET_asprintf (&service_home, "%s/shared/%s/%u",
999 system->tmppath, ss->sname, ss->n_instances);
1000 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", service_home);
1001 port = GNUNET_TESTING_reserve_port (system, GNUNET_YES);
1004 GNUNET_free (service_home);
1005 cleanup_shared_service_instance (i);
1008 GNUNET_array_append (ss->instances, ss->n_instances, i);
1009 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
1010 (void) GNUNET_asprintf (&i->port_str, "%u", port);
1011 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", service_home);
1012 GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "SERVICEHOME",
1014 GNUNET_free (service_home);
1015 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH",
1017 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT",
1019 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1021 GNUNET_CONFIGURATION_destroy (temp);
1022 cleanup_shared_service_instance (i);
1025 GNUNET_CONFIGURATION_destroy (temp);
1029 GNUNET_assert (NULL != ss->instances);
1030 GNUNET_assert (0 < ss->n_instances);
1031 i = ss->instances[ss->n_instances - 1];
1033 GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname,
1034 &cfg_copy_iterator, cfg);
1035 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH",
1037 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1043 * Create a new configuration using the given configuration as a template;
1044 * ports and paths will be modified to select available ports on the local
1045 * system. The default configuration will be available in PATHS section under
1046 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1047 * section to the temporary directory specific to this configuration. If we run
1048 * out of "*port" numbers, return SYSERR.
1050 * This is primarily a helper function used internally
1051 * by 'GNUNET_TESTING_peer_configure'.
1053 * @param system system to use to coordinate resource usage
1054 * @param cfg template configuration to update
1055 * @param ports array with port numbers used in the created configuration.
1056 * Will be updated upon successful return. Can be NULL
1057 * @param nports the size of the `ports' array. Will be updated.
1058 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1059 * be incomplete and should not be used there upon
1062 GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1063 struct GNUNET_CONFIGURATION_Handle *cfg,
1065 unsigned int *nports)
1067 struct UpdateContext uc;
1068 char *default_config;
1072 uc.status = GNUNET_OK;
1075 GNUNET_asprintf (&uc.service_home, "%s/%u", system->tmppath,
1076 system->path_counter++);
1077 GNUNET_asprintf (&default_config, "%s/config", uc.service_home);
1078 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
1080 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
1082 GNUNET_free (default_config);
1083 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "SERVICEHOME",
1085 /* make PORTs and UNIXPATHs unique */
1086 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1087 /* allow connections to services from system trusted_ip host */
1088 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1089 /* enable loopback-based connections between peers */
1090 GNUNET_CONFIGURATION_set_value_string (cfg,
1092 "USE_LOCALADDR", "YES");
1093 GNUNET_free (uc.service_home);
1094 if ((NULL != ports) && (NULL != nports))
1097 *nports = uc.nports;
1100 GNUNET_free_non_null (uc.ports);
1106 * Create a new configuration using the given configuration as a template;
1107 * ports and paths will be modified to select available ports on the local
1108 * system. The default configuration will be available in PATHS section under
1109 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1110 * section to the temporary directory specific to this configuration. If we run
1111 * out of "*port" numbers, return SYSERR.
1113 * This is primarily a helper function used internally
1114 * by 'GNUNET_TESTING_peer_configure'.
1116 * @param system system to use to coordinate resource usage
1117 * @param cfg template configuration to update
1118 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1119 * be incomplete and should not be used there upon
1122 GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1123 struct GNUNET_CONFIGURATION_Handle *cfg)
1125 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1130 * Configure a GNUnet peer. GNUnet must be installed on the local
1131 * system and available in the PATH.
1133 * @param system system to use to coordinate resource usage
1134 * @param cfg configuration to use; will be UPDATED (to reflect needed
1135 * changes in port numbers and paths)
1136 * @param key_number number of the hostkey to use for the peer
1137 * @param id identifier for the daemon, will be set, can be NULL
1138 * @param emsg set to freshly allocated error message (set to NULL on success),
1140 * @return handle to the peer, NULL on error
1142 struct GNUNET_TESTING_Peer *
1143 GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1144 struct GNUNET_CONFIGURATION_Handle *cfg,
1145 uint32_t key_number,
1146 struct GNUNET_PeerIdentity *id,
1149 struct GNUNET_TESTING_Peer *peer;
1150 struct GNUNET_DISK_FileHandle *fd;
1151 char *hostkey_filename;
1152 char *config_filename;
1153 char *libexec_binary;
1155 struct GNUNET_CRYPTO_EccPrivateKey *pk;
1157 struct SharedService *ss;
1158 struct SharedServiceInstance **ss_instances;
1160 unsigned int nports;
1164 ss_instances = NULL;
1167 if (key_number >= system->total_hostkeys)
1169 GNUNET_asprintf (&emsg_,
1170 _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1171 (unsigned int) system->total_hostkeys);
1176 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1178 GNUNET_asprintf (&emsg_,
1179 _("Failed to initialize hostkey for peer %u\n"),
1180 (unsigned int) key_number);
1184 GNUNET_CRYPTO_ecc_key_free (pk);
1186 GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1188 GNUNET_asprintf (&emsg_,
1189 _("PRIVATE_KEY option in PEER section missing in configuration\n"));
1192 /* Remove sections for shared services */
1193 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1195 ss = system->shared_services[cnt];
1196 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1198 if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg,
1201 GNUNET_asprintf (&emsg_,
1202 _("Failed to create configuration for peer "
1203 "(not enough free ports?)\n"));
1206 GNUNET_assert (GNUNET_OK ==
1207 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER",
1209 &hostkey_filename));
1210 fd = GNUNET_DISK_file_open (hostkey_filename,
1211 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1212 GNUNET_DISK_PERM_USER_READ
1213 | GNUNET_DISK_PERM_USER_WRITE);
1216 GNUNET_asprintf (&emsg_, _("Cannot open hostkey file: %s\n"),
1220 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1221 GNUNET_DISK_file_write (fd, system->hostkeys_data
1222 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1223 GNUNET_TESTING_HOSTKEYFILESIZE))
1225 GNUNET_asprintf (&emsg_,
1226 _("Failed to write hostkey file for peer %u: %s\n"),
1227 (unsigned int) key_number,
1229 GNUNET_DISK_file_close (fd);
1232 GNUNET_DISK_file_close (fd);
1233 ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *)
1234 * system->n_shared_services);
1235 for (cnt=0; cnt < system->n_shared_services; cnt++)
1237 ss = system->shared_services[cnt];
1238 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1239 if (NULL == ss_instances[cnt])
1242 GNUNET_assert (GNUNET_OK ==
1243 GNUNET_CONFIGURATION_get_value_string
1244 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1245 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1247 GNUNET_asprintf (&emsg_,
1248 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1250 (unsigned int) key_number,
1252 GNUNET_free (config_filename);
1255 peer = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Peer));
1256 peer->ss_instances = ss_instances;
1257 peer->cfgfile = config_filename; /* Free in peer_destroy */
1258 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1259 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1260 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1263 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1264 peer->args = strdup ("");
1267 peer->args = strdup (libexec_binary);
1268 peer->system = system;
1269 peer->key_number = key_number;
1270 GNUNET_free (libexec_binary);
1271 peer->ports = ports; /* Free in peer_destroy */
1272 peer->nports = nports;
1276 GNUNET_free_non_null (ss_instances);
1277 GNUNET_free_non_null (ports);
1278 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1282 GNUNET_free (emsg_);
1288 * Obtain the peer identity from a peer handle.
1290 * @param peer peer handle for which we want the peer's identity
1291 * @param id identifier for the daemon, will be set
1294 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1295 struct GNUNET_PeerIdentity *id)
1297 if (NULL != peer->id)
1299 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1302 peer->id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1303 GNUNET_CRYPTO_ecc_key_free (GNUNET_TESTING_hostkey_get (peer->system,
1306 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1313 * @param peer peer to start
1314 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1317 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1319 struct SharedServiceInstance *i;
1322 if (NULL != peer->main_process)
1325 return GNUNET_SYSERR;
1327 GNUNET_assert (NULL != peer->cfgfile);
1328 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1330 i = peer->ss_instances[cnt];
1331 if ((0 == i->n_refs)
1332 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1333 return GNUNET_SYSERR;
1336 peer->main_process = GNUNET_OS_start_process (PIPE_CONTROL,
1337 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1345 if (NULL == peer->main_process)
1347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1348 _("Failed to start `%s': %s\n"),
1351 return GNUNET_SYSERR;
1358 * Start a service at a peer using its ARM service
1360 * @param peer the peer whose service has to be started
1361 * @param service_name name of the service to start
1362 * @param timeout how long should the ARM API try to send the request to start
1364 * @param cont the callback to call with result and status from ARM API
1365 * @param cont_cls the closure for the above callback
1366 * @return GNUNET_OK upon successfully queuing the service start request;
1367 * GNUNET_SYSERR upon error
1370 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1371 const char *service_name,
1372 struct GNUNET_TIME_Relative timeout,
1373 GNUNET_ARM_ResultCallback cont,
1376 if (NULL == peer->ah)
1377 return GNUNET_SYSERR;
1378 GNUNET_ARM_request_service_start (peer->ah,
1380 GNUNET_OS_INHERIT_STD_ALL,
1388 * Stop a service at a peer using its ARM service
1390 * @param peer the peer whose service has to be stopped
1391 * @param service_name name of the service to stop
1392 * @param timeout how long should the ARM API try to send the request to stop
1394 * @param cont the callback to call with result and status from ARM API
1395 * @param cont_cls the closure for the above callback
1396 * @return GNUNET_OK upon successfully queuing the service stop request;
1397 * GNUNET_SYSERR upon error
1400 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1401 const char *service_name,
1402 struct GNUNET_TIME_Relative timeout,
1403 GNUNET_ARM_ResultCallback cont,
1406 if (NULL == peer->ah)
1407 return GNUNET_SYSERR;
1408 GNUNET_ARM_request_service_stop (peer->ah,
1417 * Sends SIGTERM to the peer's main process
1419 * @param peer the handle to the peer
1420 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1421 * or upon any error while sending SIGTERM
1424 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1426 struct SharedServiceInstance *i;
1429 if (NULL == peer->main_process)
1432 return GNUNET_SYSERR;
1434 if (0 != GNUNET_OS_process_kill (peer->main_process, SIGTERM))
1435 return GNUNET_SYSERR;
1436 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1438 i = peer->ss_instances[cnt];
1439 GNUNET_assert (0 != i->n_refs);
1442 stop_shared_service_instance (i);
1449 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1451 * @param peer the handle to the peer
1452 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1453 * or upon any error while waiting
1456 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1460 if (NULL == peer->main_process)
1463 return GNUNET_SYSERR;
1465 ret = GNUNET_OS_process_wait (peer->main_process);
1466 GNUNET_OS_process_destroy (peer->main_process);
1467 peer->main_process = NULL;
1475 * @param peer peer to stop
1476 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1479 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1481 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1482 return GNUNET_SYSERR;
1483 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1484 return GNUNET_SYSERR;
1490 * Function called whenever we connect to or disconnect from ARM.
1492 * @param cls closure
1493 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1494 * GNUNET_SYSERR on error.
1497 disconn_status (void *cls,
1500 struct GNUNET_TESTING_Peer *peer = cls;
1502 if (GNUNET_SYSERR == connected)
1504 peer->cb (peer->cb_cls, peer, connected);
1507 if (GNUNET_YES == connected)
1509 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1512 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1513 GNUNET_ARM_disconnect_and_free (peer->ah);
1515 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1520 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1521 * through the GNUNET_TESTING_PeerStopCallback().
1523 * @param peer the peer to stop
1524 * @param cb the callback to signal peer shutdown
1525 * @param cb_cls closure for the above callback
1526 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1527 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1531 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1532 GNUNET_TESTING_PeerStopCallback cb,
1535 if (NULL == peer->main_process)
1536 return GNUNET_SYSERR;
1537 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1538 if (NULL == peer->ah)
1539 return GNUNET_SYSERR;
1541 peer->cb_cls = cb_cls;
1547 * Cancel a previous asynchronous peer stop request.
1548 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1549 * peer. It is an error to call this function if the peer stop callback was
1552 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1556 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1558 GNUNET_assert (NULL != peer->ah);
1559 GNUNET_ARM_disconnect_and_free (peer->ah);
1565 * Destroy the peer. Releases resources locked during peer configuration.
1566 * If the peer is still running, it will be stopped AND a warning will be
1567 * printed (users of the API should stop the peer explicitly first).
1569 * @param peer peer to destroy
1572 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1576 if (NULL != peer->main_process)
1577 GNUNET_TESTING_peer_stop (peer);
1578 if (NULL != peer->ah)
1579 GNUNET_ARM_disconnect_and_free (peer->ah);
1580 if (NULL != peer->mh)
1581 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1582 GNUNET_free (peer->cfgfile);
1583 if (NULL != peer->cfg)
1584 GNUNET_CONFIGURATION_destroy (peer->cfg);
1585 GNUNET_free (peer->main_binary);
1586 GNUNET_free (peer->args);
1587 GNUNET_free_non_null (peer->id);
1588 GNUNET_free_non_null (peer->ss_instances);
1589 if (NULL != peer->ports)
1591 for (cnt = 0; cnt < peer->nports; cnt++)
1592 GNUNET_TESTING_release_port (peer->system,
1595 GNUNET_free (peer->ports);
1602 * Start a single peer and run a test using the testing library.
1603 * Starts a peer using the given configuration and then invokes the
1604 * given callback. This function ALSO initializes the scheduler loop
1605 * and should thus be called directly from "main". The testcase
1606 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1608 * @param testdir only the directory name without any path. This is used for
1609 * all service homes; the directory will be created in a temporary
1610 * location depending on the underlying OS
1611 * @param cfgfilename name of the configuration file to use;
1612 * use NULL to only run with defaults
1613 * @param tm main function of the testcase
1614 * @param tm_cls closure for 'tm'
1615 * @return 0 on success, 1 on error
1618 GNUNET_TESTING_peer_run (const char *testdir,
1619 const char *cfgfilename,
1620 GNUNET_TESTING_TestMain tm,
1623 return GNUNET_TESTING_service_run (testdir, "arm",
1624 cfgfilename, tm, tm_cls);
1629 * Structure for holding service data
1631 struct ServiceContext
1634 * The configuration of the peer in which the service is run
1636 const struct GNUNET_CONFIGURATION_Handle *cfg;
1639 * Callback to signal service startup
1641 GNUNET_TESTING_TestMain tm;
1644 * The peer in which the service is run.
1646 struct GNUNET_TESTING_Peer *peer;
1649 * Closure for the above callback
1656 * Callback to be called when SCHEDULER has been started
1658 * @param cls the ServiceContext
1659 * @param tc the TaskContext
1662 service_run_main (void *cls,
1663 const struct GNUNET_SCHEDULER_TaskContext *tc)
1665 struct ServiceContext *sc = cls;
1667 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1672 * Start a single service (no ARM, except of course if the given
1673 * service name is 'arm') and run a test using the testing library.
1674 * Starts a service using the given configuration and then invokes the
1675 * given callback. This function ALSO initializes the scheduler loop
1676 * and should thus be called directly from "main". The testcase
1677 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1679 * This function is useful if the testcase is for a single service
1680 * and if that service doesn't itself depend on other services.
1682 * @param testdir only the directory name without any path. This is used for
1683 * all service homes; the directory will be created in a temporary
1684 * location depending on the underlying OS
1685 * @param service_name name of the service to run
1686 * @param cfgfilename name of the configuration file to use;
1687 * use NULL to only run with defaults
1688 * @param tm main function of the testcase
1689 * @param tm_cls closure for 'tm'
1690 * @return 0 on success, 1 on error
1693 GNUNET_TESTING_service_run (const char *testdir,
1694 const char *service_name,
1695 const char *cfgfilename,
1696 GNUNET_TESTING_TestMain tm,
1699 struct ServiceContext sc;
1700 struct GNUNET_TESTING_System *system;
1701 struct GNUNET_TESTING_Peer *peer;
1702 struct GNUNET_CONFIGURATION_Handle *cfg;
1704 char *libexec_binary;
1706 GNUNET_log_setup (testdir, "WARNING", NULL);
1707 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1710 cfg = GNUNET_CONFIGURATION_create ();
1711 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1713 LOG (GNUNET_ERROR_TYPE_ERROR,
1714 _("Failed to load configuration from %s\n"), cfgfilename);
1715 GNUNET_CONFIGURATION_destroy (cfg);
1716 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1719 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1722 GNUNET_CONFIGURATION_destroy (cfg);
1723 hostkeys_unload (system);
1724 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1727 GNUNET_free (peer->main_binary);
1728 GNUNET_free (peer->args);
1729 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1730 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1731 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1734 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1735 peer->args = strdup ("");
1738 peer->args = strdup (libexec_binary);
1740 GNUNET_free (libexec_binary);
1741 GNUNET_free (binary);
1742 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1744 GNUNET_TESTING_peer_destroy (peer);
1745 GNUNET_CONFIGURATION_destroy (cfg);
1746 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1753 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1754 if ((NULL != peer->main_process) &&
1755 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1757 GNUNET_TESTING_peer_destroy (peer);
1758 GNUNET_CONFIGURATION_destroy (cfg);
1759 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1762 GNUNET_TESTING_peer_destroy (peer);
1763 GNUNET_CONFIGURATION_destroy (cfg);
1764 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1770 * Sometimes we use the binary name to determine which specific
1771 * test to run. In those cases, the string after the last "_"
1772 * in 'argv[0]' specifies a string that determines the configuration
1773 * file or plugin to use.
1775 * This function returns the respective substring, taking care
1776 * of issues such as binaries ending in '.exe' on W32.
1778 * @param argv0 the name of the binary
1779 * @return string between the last '_' and the '.exe' (or the end of the string),
1780 * NULL if argv0 has no '_'
1783 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1785 size_t slen = strlen (argv0) + 1;
1790 memcpy (sbuf, argv0, slen);
1791 ret = strrchr (sbuf, '_');
1794 ret++; /* skip underscore */
1795 dot = strchr (ret, '.');
1798 return GNUNET_strdup (ret);
1802 /* end of testing.c */