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 const 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 != (tss = shared_services[cnt]); cnt++)
421 ss = GNUNET_malloc (sizeof (struct SharedService));
422 ss->sname = GNUNET_strdup (tss->service);
423 ss->cfg = GNUNET_CONFIGURATION_dup (tss->cfg);
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)
490 GNUNET_assert (NULL == i->proc);
491 GNUNET_assert (NULL != i->cfg_fn);
492 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
493 i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
494 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
502 return GNUNET_SYSERR;
508 stop_shared_service_instance (struct SharedServiceInstance *i)
510 GNUNET_break (0 == i->n_refs);
511 GNUNET_OS_process_kill (i->proc, SIGTERM);
512 (void) GNUNET_OS_process_wait (i->proc);
513 GNUNET_OS_process_destroy (i->proc);
519 * Free system resources.
521 * @param system system to be freed
522 * @param remove_paths should the 'testdir' and all subdirectories
523 * be removed (clean up on shutdown)?
526 GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
529 struct SharedService *ss;
530 struct SharedServiceInstance *i;
534 if (NULL != system->hostkeys_data)
535 hostkeys_unload (system);
536 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
538 ss = system->shared_services[ss_cnt];
539 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
541 i = ss->instances[i_cnt];
543 stop_shared_service_instance (i);
544 cleanup_shared_service_instance (i);
546 GNUNET_free_non_null (ss->instances);
547 GNUNET_CONFIGURATION_destroy (ss->cfg);
548 GNUNET_free (ss->sname);
551 GNUNET_free_non_null (system->shared_services);
552 if (GNUNET_YES == remove_paths)
553 GNUNET_DISK_directory_remove (system->tmppath);
554 GNUNET_free (system->tmppath);
555 GNUNET_free_non_null (system->trusted_ip);
556 GNUNET_free_non_null (system->hostname);
557 GNUNET_free (system);
562 * Reserve a TCP or UDP port for a peer.
564 * @param system system to use for reservation tracking
565 * @param is_tcp GNUNET_YES for TCP ports, GNUNET_NO for UDP
566 * @return 0 if no free port was available
569 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 = (GNUNET_YES == is_tcp)? SOCK_STREAM : SOCK_DGRAM;
595 hint.ai_protocol = 0;
598 hint.ai_canonname = NULL;
600 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
601 port_buckets = (GNUNET_YES == is_tcp) ?
602 system->reserved_tcp_ports : system->reserved_udp_ports;
603 for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++)
605 xor_image = (UINT32_MAX ^ port_buckets[index]);
606 if (0 == xor_image) /* Ports in the bucket are full */
608 pos = system->lowport % 32;
611 if (0 == ((xor_image >> pos) & 1U))
616 open_port = (index * 32) + pos;
617 if (open_port >= system->highport)
619 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
621 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
622 GNUNET_free (open_port_str);
623 bind_status = GNUNET_NO;
624 for (ai = ret; NULL != ai; ai = ai->ai_next)
626 socket = GNUNET_NETWORK_socket_create (ai->ai_family,
627 (GNUNET_YES == is_tcp) ?
628 SOCK_STREAM : SOCK_DGRAM,
632 bind_status = GNUNET_NETWORK_socket_bind (socket,
635 GNUNET_NETWORK_socket_close (socket);
636 if (GNUNET_OK != bind_status)
639 port_buckets[index] |= (1U << pos); /* Set the port bit */
641 if (GNUNET_OK == bind_status)
643 LOG (GNUNET_ERROR_TYPE_DEBUG,
644 "Found a free port %u\n", (unsigned int) open_port);
655 * Release reservation of a TCP or UDP port for a peer
656 * (used during GNUNET_TESTING_peer_destroy).
658 * @param system system to use for reservation tracking
659 * @param is_tcp GNUNET_YES for TCP ports, GNUNET_NO for UDP
660 * @param port reserved port to release
663 GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
667 uint32_t *port_buckets;
671 port_buckets = (GNUNET_YES == is_tcp) ?
672 system->reserved_tcp_ports : system->reserved_udp_ports;
675 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
676 if (0 == (port_buckets[bucket] & (1U << pos)))
678 GNUNET_break(0); /* Port was not reserved by us using reserve_port() */
681 port_buckets[bucket] &= ~(1U << pos);
686 * Testing includes a number of pre-created hostkeys for
687 * faster peer startup. This function can be used to
688 * access the n-th key of those pre-created hostkeys; note
689 * that these keys are ONLY useful for testing and not
690 * secure as the private keys are part of the public
691 * GNUnet source code.
693 * This is primarily a helper function used internally
694 * by 'GNUNET_TESTING_peer_configure'.
696 * @param system the testing system handle
697 * @param key_number desired pre-created hostkey to obtain
698 * @param id set to the peer's identity (hash of the public
699 * key; if NULL, GNUNET_SYSERR is returned immediately
700 * @return NULL on error (not enough keys)
702 struct GNUNET_CRYPTO_EccPrivateKey *
703 GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
705 struct GNUNET_PeerIdentity *id)
707 struct GNUNET_CRYPTO_EccPrivateKey *private_key;
708 struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded public_key;
710 if ((NULL == id) || (NULL == system->hostkeys_data))
712 if (key_number >= system->total_hostkeys)
714 LOG (GNUNET_ERROR_TYPE_ERROR,
715 _("Key number %u does not exist\n"), key_number);
718 private_key = GNUNET_CRYPTO_ecc_decode_key (system->hostkeys_data +
720 GNUNET_TESTING_HOSTKEYFILESIZE),
721 GNUNET_TESTING_HOSTKEYFILESIZE,
723 if (NULL == private_key)
725 LOG (GNUNET_ERROR_TYPE_ERROR,
726 _("Error while decoding key %u\n"), key_number);
729 GNUNET_CRYPTO_ecc_key_get_public (private_key, &public_key);
730 GNUNET_CRYPTO_hash (&public_key,
731 sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded),
738 * Structure for holding data to build new configurations from a configuration
744 * The system for which we are building configurations
746 struct GNUNET_TESTING_System *system;
749 * The configuration we are building
751 struct GNUNET_CONFIGURATION_Handle *cfg;
754 * The customized service home path for this peer
759 * Array of ports currently allocated to this peer. These ports will be
760 * released upon peer destroy and can be used by other peers which are
766 * The number of ports in the above array
771 * build status - to signal error while building a configuration
778 * Function to iterate over options. Copies
779 * the options to the target configuration,
780 * updating PORT values as needed.
782 * @param cls the UpdateContext
783 * @param section name of the section
784 * @param option name of the option
785 * @param value value of the option
788 update_config (void *cls, const char *section, const char *option,
791 struct UpdateContext *uc = cls;
795 char *single_variable;
796 char *per_host_variable;
797 unsigned long long num_per_host;
800 if (GNUNET_OK != uc->status)
802 if (! ((0 == strcmp (option, "PORT"))
803 || (0 == strcmp (option, "UNIXPATH"))
804 || (0 == strcmp (option, "HOSTNAME"))))
806 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
807 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
808 if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
812 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
815 /* FIXME: What about UDP? */
816 new_port = GNUNET_TESTING_reserve_port (uc->system, GNUNET_YES);
819 uc->status = GNUNET_SYSERR;
820 GNUNET_free (single_variable);
821 GNUNET_free (per_host_variable);
824 GNUNET_snprintf (cval, sizeof (cval), "%u", new_port);
826 GNUNET_array_append (uc->ports, uc->nports, new_port);
828 else if ((ival != 0) &&
830 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
832 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
836 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
837 /* ival + ctx->fdnum % num_per_host); */
839 GNUNET_break (0); /* FIXME */
842 if (0 == strcmp (option, "UNIXPATH"))
845 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
848 GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock",
849 uc->service_home, section);
852 else if ((GNUNET_YES ==
853 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
858 GNUNET_break(0); /* FIXME */
861 if (0 == strcmp (option, "HOSTNAME"))
863 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
865 GNUNET_free (single_variable);
866 GNUNET_free (per_host_variable);
867 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
872 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
873 * 'trusted_hosts' in all sections
875 * @param cls the UpdateContext
876 * @param section name of the section
879 update_config_sections (void *cls,
882 struct UpdateContext *uc = cls;
886 char *orig_allowed_hosts;
888 char *ACCEPT_FROM_key;
894 /* Ignore certain options from sections. See
895 https://gnunet.org/bugs/view.php?id=2476 */
896 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
897 "TESTING_IGNORE_KEYS"))
901 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section,
902 "TESTING_IGNORE_KEYS", &val));
904 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
910 ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt);
912 for (key = 0; key < ikeys_cnt; key++)
915 ptr = strstr (ptr, ";");
923 for (key = 0; key < ikeys_cnt; key++)
925 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
928 if ((key == ikeys_cnt) &&
929 (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
933 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr))
935 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section,
936 "ADVERTISED_PORT", ptr);
940 for (key = 0; key < ikeys_cnt; key++)
942 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
951 GNUNET_free_non_null (val);
952 ACCEPT_FROM_key = "ACCEPT_FROM";
953 if ((NULL != uc->system->trusted_ip) &&
954 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
955 ACCEPT_FROM_key = "ACCEPT_FROM6";
957 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key,
958 &orig_allowed_hosts))
960 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
962 if (NULL == uc->system->trusted_ip)
963 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
965 GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts,
966 uc->system->trusted_ip);
967 GNUNET_free (orig_allowed_hosts);
968 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key,
970 GNUNET_free (allowed_hosts);
973 static struct SharedServiceInstance *
974 associate_shared_service (struct GNUNET_TESTING_System *system,
975 struct SharedService *ss,
976 struct GNUNET_CONFIGURATION_Handle *cfg)
978 struct SharedServiceInstance *i;
979 struct GNUNET_CONFIGURATION_Handle *temp;
984 if ( ((0 == ss->share) && (NULL == ss->instances))
987 && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) )
989 i = GNUNET_malloc (sizeof (struct SharedServiceInstance));
991 (void) GNUNET_asprintf (&service_home, "%s/shared/%s/%u",
992 system->tmppath, ss->sname, ss->n_instances);
993 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", service_home);
994 port = GNUNET_TESTING_reserve_port (system, GNUNET_YES);
997 GNUNET_free (service_home);
998 cleanup_shared_service_instance (i);
1001 GNUNET_array_append (ss->instances, ss->n_instances, i);
1002 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
1003 (void) GNUNET_asprintf (&i->port_str, "%u", port);
1004 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", service_home);
1005 GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "SERVICEHOME",
1007 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH",
1009 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT",
1011 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1013 GNUNET_CONFIGURATION_destroy (temp);
1014 cleanup_shared_service_instance (i);
1017 GNUNET_CONFIGURATION_destroy (temp);
1021 GNUNET_assert (NULL != ss->instances);
1022 GNUNET_assert (0 < ss->n_instances);
1023 i = ss->instances[ss->n_instances - 1];
1025 GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname,
1026 &cfg_copy_iterator, cfg);
1027 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH",
1029 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1035 * Create a new configuration using the given configuration as a template;
1036 * ports and paths will be modified to select available ports on the local
1037 * system. The default configuration will be available in PATHS section under
1038 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1039 * section to the temporary directory specific to this configuration. If we run
1040 * out of "*port" numbers, return SYSERR.
1042 * This is primarily a helper function used internally
1043 * by 'GNUNET_TESTING_peer_configure'.
1045 * @param system system to use to coordinate resource usage
1046 * @param cfg template configuration to update
1047 * @param ports array with port numbers used in the created configuration.
1048 * Will be updated upon successful return. Can be NULL
1049 * @param nports the size of the `ports' array. Will be updated.
1050 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1051 * be incomplete and should not be used there upon
1054 GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1055 struct GNUNET_CONFIGURATION_Handle *cfg,
1057 unsigned int *nports)
1059 struct UpdateContext uc;
1060 char *default_config;
1064 uc.status = GNUNET_OK;
1067 GNUNET_asprintf (&uc.service_home, "%s/%u", system->tmppath,
1068 system->path_counter++);
1069 GNUNET_asprintf (&default_config, "%s/config", uc.service_home);
1070 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
1072 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
1074 GNUNET_free (default_config);
1075 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "SERVICEHOME",
1077 /* make PORTs and UNIXPATHs unique */
1078 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1079 /* allow connections to services from system trusted_ip host */
1080 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1081 /* enable loopback-based connections between peers */
1082 GNUNET_CONFIGURATION_set_value_string (cfg,
1084 "USE_LOCALADDR", "YES");
1085 GNUNET_free (uc.service_home);
1086 if ((NULL != ports) && (NULL != nports))
1089 *nports = uc.nports;
1092 GNUNET_free_non_null (uc.ports);
1098 * Create a new configuration using the given configuration as a template;
1099 * ports and paths will be modified to select available ports on the local
1100 * system. The default configuration will be available in PATHS section under
1101 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1102 * section to the temporary directory specific to this configuration. If we run
1103 * out of "*port" numbers, return SYSERR.
1105 * This is primarily a helper function used internally
1106 * by 'GNUNET_TESTING_peer_configure'.
1108 * @param system system to use to coordinate resource usage
1109 * @param cfg template configuration to update
1110 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1111 * be incomplete and should not be used there upon
1114 GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1115 struct GNUNET_CONFIGURATION_Handle *cfg)
1117 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1122 * Configure a GNUnet peer. GNUnet must be installed on the local
1123 * system and available in the PATH.
1125 * @param system system to use to coordinate resource usage
1126 * @param cfg configuration to use; will be UPDATED (to reflect needed
1127 * changes in port numbers and paths)
1128 * @param key_number number of the hostkey to use for the peer
1129 * @param id identifier for the daemon, will be set, can be NULL
1130 * @param emsg set to freshly allocated error message (set to NULL on success),
1132 * @return handle to the peer, NULL on error
1134 struct GNUNET_TESTING_Peer *
1135 GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1136 struct GNUNET_CONFIGURATION_Handle *cfg,
1137 uint32_t key_number,
1138 struct GNUNET_PeerIdentity *id,
1141 struct GNUNET_TESTING_Peer *peer;
1142 struct GNUNET_DISK_FileHandle *fd;
1144 char hostkey_filename[128];
1145 char *config_filename;
1146 char *libexec_binary;
1148 struct GNUNET_CRYPTO_EccPrivateKey *pk;
1150 struct SharedService *ss;
1151 struct SharedServiceInstance **ss_instances;
1153 unsigned int nports;
1157 ss_instances = NULL;
1160 /* Remove sections for shared services */
1161 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1163 ss = system->shared_services[cnt];
1164 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1166 if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg,
1169 GNUNET_asprintf (&emsg_,
1170 _("Failed to create configuration for peer "
1171 "(not enough free ports?)\n"));
1174 if (key_number >= system->total_hostkeys)
1176 GNUNET_asprintf (&emsg_,
1177 _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1178 (unsigned int) system->total_hostkeys);
1183 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1185 GNUNET_asprintf (&emsg_,
1186 _("Failed to initialize hostkey for peer %u\n"),
1187 (unsigned int) key_number);
1191 GNUNET_CRYPTO_ecc_key_free (pk);
1192 GNUNET_assert (GNUNET_OK ==
1193 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS",
1196 /* FIXME: might be better to evaluate actual configuration option here... */
1197 GNUNET_snprintf (hostkey_filename, sizeof (hostkey_filename), "%s/private.ecc",
1199 GNUNET_free (service_home);
1200 fd = GNUNET_DISK_file_open (hostkey_filename,
1201 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1202 GNUNET_DISK_PERM_USER_READ
1203 | GNUNET_DISK_PERM_USER_WRITE);
1206 GNUNET_asprintf (&emsg_, _("Cannot open hostkey file: %s\n"),
1210 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1211 GNUNET_DISK_file_write (fd, system->hostkeys_data
1212 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1213 GNUNET_TESTING_HOSTKEYFILESIZE))
1215 GNUNET_asprintf (&emsg_,
1216 _("Failed to write hostkey file for peer %u: %s\n"),
1217 (unsigned int) key_number,
1219 GNUNET_DISK_file_close (fd);
1222 GNUNET_DISK_file_close (fd);
1223 ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *)
1224 * system->n_shared_services);
1225 for (cnt=0; cnt < system->n_shared_services; cnt++)
1227 ss = system->shared_services[cnt];
1228 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1229 if (NULL == ss_instances[cnt])
1232 GNUNET_assert (GNUNET_OK ==
1233 GNUNET_CONFIGURATION_get_value_string
1234 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1235 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1237 GNUNET_asprintf (&emsg_,
1238 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1240 (unsigned int) key_number,
1242 GNUNET_free (config_filename);
1245 peer = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Peer));
1246 peer->ss_instances = ss_instances;
1247 peer->cfgfile = config_filename; /* Free in peer_destroy */
1248 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1249 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1250 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1253 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1254 peer->args = strdup ("");
1257 peer->args = strdup (libexec_binary);
1258 peer->system = system;
1259 peer->key_number = key_number;
1260 GNUNET_free (libexec_binary);
1261 peer->ports = ports; /* Free in peer_destroy */
1262 peer->nports = nports;
1266 GNUNET_free_non_null (ss_instances);
1267 GNUNET_free_non_null (ports);
1268 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1272 GNUNET_free (emsg_);
1278 * Obtain the peer identity from a peer handle.
1280 * @param peer peer handle for which we want the peer's identity
1281 * @param id identifier for the daemon, will be set
1284 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1285 struct GNUNET_PeerIdentity *id)
1287 if (NULL != peer->id)
1289 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1292 peer->id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1293 GNUNET_CRYPTO_ecc_key_free (GNUNET_TESTING_hostkey_get (peer->system,
1296 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1303 * @param peer peer to start
1304 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1307 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1309 struct SharedServiceInstance *i;
1312 if (NULL != peer->main_process)
1315 return GNUNET_SYSERR;
1317 GNUNET_assert (NULL != peer->cfgfile);
1318 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1320 i = peer->ss_instances[cnt];
1321 if ((0 == i->n_refs)
1322 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1323 return GNUNET_SYSERR;
1326 peer->main_process = GNUNET_OS_start_process (PIPE_CONTROL,
1327 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1335 if (NULL == peer->main_process)
1337 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1338 _("Failed to start `%s': %s\n"),
1341 return GNUNET_SYSERR;
1348 * Start a service at a peer using its ARM service
1350 * @param peer the peer whose service has to be started
1351 * @param service_name name of the service to start
1352 * @param timeout how long should the ARM API try to send the request to start
1354 * @param cont the callback to call with result and status from ARM API
1355 * @param cont_cls the closure for the above callback
1356 * @return GNUNET_OK upon successfully queuing the service start request;
1357 * GNUNET_SYSERR upon error
1360 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1361 const char *service_name,
1362 struct GNUNET_TIME_Relative timeout,
1363 GNUNET_ARM_ResultCallback cont,
1366 if (NULL == peer->ah)
1367 return GNUNET_SYSERR;
1368 GNUNET_ARM_request_service_start (peer->ah,
1370 GNUNET_OS_INHERIT_STD_ALL,
1378 * Stop a service at a peer using its ARM service
1380 * @param peer the peer whose service has to be stopped
1381 * @param service_name name of the service to stop
1382 * @param timeout how long should the ARM API try to send the request to stop
1384 * @param cont the callback to call with result and status from ARM API
1385 * @param cont_cls the closure for the above callback
1386 * @return GNUNET_OK upon successfully queuing the service stop request;
1387 * GNUNET_SYSERR upon error
1390 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1391 const char *service_name,
1392 struct GNUNET_TIME_Relative timeout,
1393 GNUNET_ARM_ResultCallback cont,
1396 if (NULL == peer->ah)
1397 return GNUNET_SYSERR;
1398 GNUNET_ARM_request_service_stop (peer->ah,
1407 * Sends SIGTERM to the peer's main process
1409 * @param peer the handle to the peer
1410 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1411 * or upon any error while sending SIGTERM
1414 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1416 struct SharedServiceInstance *i;
1419 if (NULL == peer->main_process)
1422 return GNUNET_SYSERR;
1424 if (0 != GNUNET_OS_process_kill (peer->main_process, SIGTERM))
1425 return GNUNET_SYSERR;
1426 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1428 i = peer->ss_instances[cnt];
1429 GNUNET_assert (0 != i->n_refs);
1432 stop_shared_service_instance (i);
1439 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1441 * @param peer the handle to the peer
1442 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1443 * or upon any error while waiting
1446 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1450 if (NULL == peer->main_process)
1453 return GNUNET_SYSERR;
1455 ret = GNUNET_OS_process_wait (peer->main_process);
1456 GNUNET_OS_process_destroy (peer->main_process);
1457 peer->main_process = NULL;
1465 * @param peer peer to stop
1466 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1469 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1471 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1472 return GNUNET_SYSERR;
1473 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1474 return GNUNET_SYSERR;
1480 * Function called whenever we connect to or disconnect from ARM.
1482 * @param cls closure
1483 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1484 * GNUNET_SYSERR on error.
1487 disconn_status (void *cls,
1490 struct GNUNET_TESTING_Peer *peer = cls;
1492 if (GNUNET_SYSERR == connected)
1494 peer->cb (peer->cb_cls, peer, connected);
1497 if (GNUNET_YES == connected)
1499 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1502 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1503 GNUNET_ARM_disconnect_and_free (peer->ah);
1505 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1510 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1511 * through the GNUNET_TESTING_PeerStopCallback().
1513 * @param peer the peer to stop
1514 * @param cb the callback to signal peer shutdown
1515 * @param cb_cls closure for the above callback
1516 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1517 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1521 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1522 GNUNET_TESTING_PeerStopCallback cb,
1525 if (NULL == peer->main_process)
1526 return GNUNET_SYSERR;
1527 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1528 if (NULL == peer->ah)
1529 return GNUNET_SYSERR;
1531 peer->cb_cls = cb_cls;
1537 * Destroy the peer. Releases resources locked during peer configuration.
1538 * If the peer is still running, it will be stopped AND a warning will be
1539 * printed (users of the API should stop the peer explicitly first).
1541 * @param peer peer to destroy
1544 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1548 if (NULL != peer->main_process)
1549 GNUNET_TESTING_peer_stop (peer);
1550 if (NULL != peer->ah)
1551 GNUNET_ARM_disconnect_and_free (peer->ah);
1552 if (NULL != peer->mh)
1553 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1554 GNUNET_free (peer->cfgfile);
1555 if (NULL != peer->cfg)
1556 GNUNET_CONFIGURATION_destroy (peer->cfg);
1557 GNUNET_free (peer->main_binary);
1558 GNUNET_free (peer->args);
1559 GNUNET_free_non_null (peer->id);
1560 GNUNET_free_non_null (peer->ss_instances);
1561 if (NULL != peer->ports)
1563 for (cnt = 0; cnt < peer->nports; cnt++)
1564 GNUNET_TESTING_release_port (peer->system,
1567 GNUNET_free (peer->ports);
1574 * Start a single peer and run a test using the testing library.
1575 * Starts a peer using the given configuration and then invokes the
1576 * given callback. This function ALSO initializes the scheduler loop
1577 * and should thus be called directly from "main". The testcase
1578 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1580 * @param testdir only the directory name without any path. This is used for
1581 * all service homes; the directory will be created in a temporary
1582 * location depending on the underlying OS
1583 * @param cfgfilename name of the configuration file to use;
1584 * use NULL to only run with defaults
1585 * @param tm main function of the testcase
1586 * @param tm_cls closure for 'tm'
1587 * @return 0 on success, 1 on error
1590 GNUNET_TESTING_peer_run (const char *testdir,
1591 const char *cfgfilename,
1592 GNUNET_TESTING_TestMain tm,
1595 return GNUNET_TESTING_service_run (testdir, "arm",
1596 cfgfilename, tm, tm_cls);
1601 * Structure for holding service data
1603 struct ServiceContext
1606 * The configuration of the peer in which the service is run
1608 const struct GNUNET_CONFIGURATION_Handle *cfg;
1611 * Callback to signal service startup
1613 GNUNET_TESTING_TestMain tm;
1616 * The peer in which the service is run.
1618 struct GNUNET_TESTING_Peer *peer;
1621 * Closure for the above callback
1628 * Callback to be called when SCHEDULER has been started
1630 * @param cls the ServiceContext
1631 * @param tc the TaskContext
1634 service_run_main (void *cls,
1635 const struct GNUNET_SCHEDULER_TaskContext *tc)
1637 struct ServiceContext *sc = cls;
1639 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1644 * Start a single service (no ARM, except of course if the given
1645 * service name is 'arm') and run a test using the testing library.
1646 * Starts a service using the given configuration and then invokes the
1647 * given callback. This function ALSO initializes the scheduler loop
1648 * and should thus be called directly from "main". The testcase
1649 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1651 * This function is useful if the testcase is for a single service
1652 * and if that service doesn't itself depend on other services.
1654 * @param testdir only the directory name without any path. This is used for
1655 * all service homes; the directory will be created in a temporary
1656 * location depending on the underlying OS
1657 * @param service_name name of the service to run
1658 * @param cfgfilename name of the configuration file to use;
1659 * use NULL to only run with defaults
1660 * @param tm main function of the testcase
1661 * @param tm_cls closure for 'tm'
1662 * @return 0 on success, 1 on error
1665 GNUNET_TESTING_service_run (const char *testdir,
1666 const char *service_name,
1667 const char *cfgfilename,
1668 GNUNET_TESTING_TestMain tm,
1671 struct ServiceContext sc;
1672 struct GNUNET_TESTING_System *system;
1673 struct GNUNET_TESTING_Peer *peer;
1674 struct GNUNET_CONFIGURATION_Handle *cfg;
1676 char *libexec_binary;
1678 GNUNET_log_setup (testdir, "WARNING", NULL);
1679 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1682 cfg = GNUNET_CONFIGURATION_create ();
1683 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1685 LOG (GNUNET_ERROR_TYPE_ERROR,
1686 _("Failed to load configuration from %s\n"), cfgfilename);
1687 GNUNET_CONFIGURATION_destroy (cfg);
1688 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1691 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1694 GNUNET_CONFIGURATION_destroy (cfg);
1695 hostkeys_unload (system);
1696 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1699 GNUNET_free (peer->main_binary);
1700 GNUNET_free (peer->args);
1701 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1702 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1703 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1706 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1707 peer->args = strdup ("");
1710 peer->args = strdup (libexec_binary);
1712 GNUNET_free (libexec_binary);
1713 GNUNET_free (binary);
1714 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1716 GNUNET_TESTING_peer_destroy (peer);
1717 GNUNET_CONFIGURATION_destroy (cfg);
1718 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1725 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1726 if ((NULL != peer->main_process) &&
1727 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1729 GNUNET_TESTING_peer_destroy (peer);
1730 GNUNET_CONFIGURATION_destroy (cfg);
1731 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1734 GNUNET_TESTING_peer_destroy (peer);
1735 GNUNET_CONFIGURATION_destroy (cfg);
1736 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1742 * Sometimes we use the binary name to determine which specific
1743 * test to run. In those cases, the string after the last "_"
1744 * in 'argv[0]' specifies a string that determines the configuration
1745 * file or plugin to use.
1747 * This function returns the respective substring, taking care
1748 * of issues such as binaries ending in '.exe' on W32.
1750 * @param argv0 the name of the binary
1751 * @return string between the last '_' and the '.exe' (or the end of the string),
1752 * NULL if argv0 has no '_'
1755 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1757 size_t slen = strlen (argv0) + 1;
1762 memcpy (sbuf, argv0, slen);
1763 ret = strrchr (sbuf, '_');
1766 ret++; /* skip underscore */
1767 dot = strchr (ret, '.');
1770 return GNUNET_strdup (ret);
1774 /* end of testing.c */