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 port that has already been reserved for some GNUnet peer
136 * is recorded. Note that we make no distinction between TCP and UDP ports
137 * and test if a port is already in use before assigning it to a peer/service.
138 * If we detect that a port is already in use, we also mark it in this bitmap.
139 * So all the bits that are zero merely indicate ports that MIGHT be available
142 uint32_t reserved_ports[65536 / 32];
145 * Counter we use to make service home paths unique on this system;
146 * the full path consists of the tmppath and this number. Each
147 * UNIXPATH for a peer is also modified to include the respective
148 * path counter to ensure uniqueness. This field is incremented
149 * by one for each configured peer. Even if peers are destroyed,
150 * we never re-use path counters.
152 uint32_t path_counter;
155 * The number of hostkeys
157 uint32_t total_hostkeys;
160 * Lowest port we are allowed to use.
165 * Highest port we are allowed to use.
172 * Handle for a GNUnet peer controlled by testing.
174 struct GNUNET_TESTING_Peer
177 * The TESTING system associated with this peer
179 struct GNUNET_TESTING_System *system;
182 * Path to the configuration file for this peer.
187 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
188 * Typically 'gnunet-service-arm' (but can be set to a
189 * specific service by 'GNUNET_TESTING_service_run' if
196 * Handle to the running binary of the service, NULL if the
197 * peer/service is currently not running.
199 struct GNUNET_OS_Process *main_process;
202 * The handle to the peer's ARM service
204 struct GNUNET_ARM_Handle *ah;
207 * Handle to ARM monitoring
209 struct GNUNET_ARM_MonitorHandle *mh;
212 * The config of the peer
214 struct GNUNET_CONFIGURATION_Handle *cfg;
217 * The callback to call asynchronously when a peer is stopped
219 GNUNET_TESTING_PeerStopCallback cb;
222 * The closure for the above callback
227 * The cached identity of this peer. Will be populated on call to
228 * GNUNET_TESTING_peer_get_identity()
230 struct GNUNET_PeerIdentity *id;
232 struct SharedServiceInstance **ss_instances;
235 * Array of ports currently allocated to this peer. These ports will be
236 * released upon peer destroy and can be used by other peers which are
242 * The number of ports in the above array
247 * The keynumber of this peer's hostkey
254 * Testing includes a number of pre-created hostkeys for faster peer
255 * startup. This function loads such keys into memory from a file.
257 * @param system the testing system handle
258 * @return GNUNET_OK on success; GNUNET_SYSERR on error
261 hostkeys_load (struct GNUNET_TESTING_System *system)
266 struct GNUNET_DISK_FileHandle *fd;
268 GNUNET_assert (NULL == system->hostkeys_data);
269 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
270 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
271 GNUNET_free (data_dir);
273 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
275 LOG (GNUNET_ERROR_TYPE_ERROR,
276 _("Hostkeys file not found: %s\n"), filename);
277 GNUNET_free (filename);
278 return GNUNET_SYSERR;
280 /* Check hostkey file size, read entire thing into memory */
282 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
286 GNUNET_free (filename);
287 return GNUNET_SYSERR; /* File is empty */
289 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
291 LOG (GNUNET_ERROR_TYPE_ERROR,
292 _("Incorrect hostkey file format: %s\n"), filename);
293 GNUNET_free (filename);
294 return GNUNET_SYSERR;
296 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
297 GNUNET_DISK_PERM_NONE);
300 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
301 GNUNET_free (filename);
302 return GNUNET_SYSERR;
304 GNUNET_free (filename);
305 system->hostkeys_data = GNUNET_DISK_file_map (fd,
307 GNUNET_DISK_MAP_TYPE_READ,
309 GNUNET_DISK_file_close (fd);
310 if (NULL == system->hostkeys_data)
311 return GNUNET_SYSERR;
312 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
318 * Function to remove the loaded hostkeys
320 * @param system the testing system handle
323 hostkeys_unload (struct GNUNET_TESTING_System *system)
325 GNUNET_break (NULL != system->hostkeys_data);
326 system->hostkeys_data = NULL;
327 GNUNET_DISK_file_unmap (system->map);
329 system->hostkeys_data = NULL;
330 system->total_hostkeys = 0;
335 * Function to iterate over options.
338 * @param section name of the section
339 * @param option name of the option
340 * @param value value of the option
343 cfg_copy_iterator (void *cls, const char *section,
344 const char *option, const char *value)
346 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
348 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
353 * Create a system handle. There must only be one system
354 * handle per operating system.
356 * @param testdir only the directory name without any path. This is used for
357 * all service homes; the directory will be created in a temporary
358 * location depending on the underlying OS. This variable will be
359 * overridden with the value of the environmental variable
360 * GNUNET_TESTING_PREFIX, if it exists.
361 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
362 * service configurations generated to allow control connections from
363 * this ip. This can either be a single ip address or a network address
365 * @param hostname the hostname of the system we are using for testing; NULL for
367 * @param shared_services NULL terminated array describing services that are to
368 * be shared among peers
369 * @param lowport lowest port number this system is allowed to allocate (inclusive)
370 * @param highport highest port number this system is allowed to allocate (exclusive)
371 * @return handle to this system, NULL on error
373 struct GNUNET_TESTING_System *
374 GNUNET_TESTING_system_create_with_portrange (const char *testdir,
375 const char *trusted_ip,
376 const char *hostname,
378 GNUNET_TESTING_SharedService *
383 struct GNUNET_TESTING_System *system;
384 struct GNUNET_TESTING_SharedService tss;
385 struct SharedService *ss;
388 GNUNET_assert (NULL != testdir);
389 system = GNUNET_malloc (sizeof (struct GNUNET_TESTING_System));
390 if (NULL == (system->tmppath = getenv ("GNUNET_TESTING_PREFIX")))
391 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
393 system->tmppath = GNUNET_strdup (system->tmppath);
394 system->lowport = lowport;
395 system->highport = highport;
396 if (NULL == system->tmppath)
398 GNUNET_free (system);
401 if (NULL != trusted_ip)
402 system->trusted_ip = GNUNET_strdup (trusted_ip);
403 if (NULL != hostname)
404 system->hostname = GNUNET_strdup (hostname);
405 if (GNUNET_OK != hostkeys_load (system))
407 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
410 if (NULL == shared_services)
412 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
414 tss = shared_services[cnt];
415 ss = GNUNET_malloc (sizeof (struct SharedService));
416 ss->sname = GNUNET_strdup (tss.service);
417 ss->cfg = GNUNET_CONFIGURATION_create ();
418 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, ss->sname,
419 &cfg_copy_iterator, ss->cfg);
420 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "TESTING",
421 &cfg_copy_iterator, ss->cfg);
422 ss->share = tss.share;
423 GNUNET_array_append (system->shared_services, system->n_shared_services,
431 * Create a system handle. There must only be one system handle per operating
432 * system. Uses a default range for allowed ports. Ports are still tested for
435 * @param testdir only the directory name without any path. This is used for all
436 * service homes; the directory will be created in a temporary location
437 * depending on the underlying OS. This variable will be
438 * overridden with the value of the environmental variable
439 * GNUNET_TESTING_PREFIX, if it exists.
440 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
441 * service configurations generated to allow control connections from
442 * this ip. This can either be a single ip address or a network address
444 * @param hostname the hostname of the system we are using for testing; NULL for
446 * @param shared_services NULL terminated array describing services that are to
447 * be shared among peers
448 * @return handle to this system, NULL on error
450 struct GNUNET_TESTING_System *
451 GNUNET_TESTING_system_create (const char *testdir,
452 const char *trusted_ip,
453 const char *hostname,
454 const struct GNUNET_TESTING_SharedService *
457 return GNUNET_TESTING_system_create_with_portrange (testdir,
466 cleanup_shared_service_instance (struct SharedServiceInstance *i)
468 if (NULL != i->cfg_fn)
470 (void) unlink (i->cfg_fn);
471 GNUNET_free (i->cfg_fn);
473 GNUNET_free_non_null (i->unix_sock);
474 GNUNET_free_non_null (i->port_str);
475 GNUNET_break (NULL == i->proc);
476 GNUNET_break (0 == i->n_refs);
481 start_shared_service_instance (struct SharedServiceInstance *i)
484 char *libexec_binary;
486 GNUNET_assert (NULL == i->proc);
487 GNUNET_assert (NULL != i->cfg_fn);
488 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
489 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
490 GNUNET_free (binary);
491 i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
492 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
499 GNUNET_free (libexec_binary);
501 return GNUNET_SYSERR;
507 stop_shared_service_instance (struct SharedServiceInstance *i)
509 GNUNET_break (0 == i->n_refs);
510 if (0 != GNUNET_OS_process_kill (i->proc, SIGTERM))
511 LOG (GNUNET_ERROR_TYPE_WARNING,
512 "Killing shared service instance (%s) failed\n", i->ss->sname);
513 (void) GNUNET_OS_process_wait (i->proc);
514 GNUNET_OS_process_destroy (i->proc);
520 * Free system resources.
522 * @param system system to be freed
523 * @param remove_paths should the 'testdir' and all subdirectories
524 * be removed (clean up on shutdown)?
527 GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
530 struct SharedService *ss;
531 struct SharedServiceInstance *i;
535 if (NULL != system->hostkeys_data)
536 hostkeys_unload (system);
537 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
539 ss = system->shared_services[ss_cnt];
540 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
542 i = ss->instances[i_cnt];
544 stop_shared_service_instance (i);
545 cleanup_shared_service_instance (i);
547 GNUNET_free_non_null (ss->instances);
548 GNUNET_CONFIGURATION_destroy (ss->cfg);
549 GNUNET_free (ss->sname);
552 GNUNET_free_non_null (system->shared_services);
553 if (GNUNET_YES == remove_paths)
554 GNUNET_DISK_directory_remove (system->tmppath);
555 GNUNET_free (system->tmppath);
556 GNUNET_free_non_null (system->trusted_ip);
557 GNUNET_free_non_null (system->hostname);
558 GNUNET_free (system);
563 * Reserve a TCP or UDP port for a peer.
565 * @param system system to use for reservation tracking
566 * @return 0 if no free port was available
569 GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
571 struct GNUNET_NETWORK_Handle *socket;
572 struct addrinfo hint;
573 struct addrinfo *ret;
575 uint32_t *port_buckets;
584 FIXME: Instead of using getaddrinfo we should try to determine the port
585 status by the following heurestics.
587 On systems which support both IPv4 and IPv6, only ports open on both
588 address families are considered open.
589 On system with either IPv4 or IPv6. A port is considered open if it's
590 open in the respective address family
592 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
593 hint.ai_socktype = 0;
594 hint.ai_protocol = 0;
597 hint.ai_canonname = NULL;
599 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
600 port_buckets = system->reserved_ports;
601 for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++)
603 xor_image = (UINT32_MAX ^ port_buckets[index]);
604 if (0 == xor_image) /* Ports in the bucket are full */
606 pos = system->lowport % 32;
609 if (0 == ((xor_image >> pos) & 1U))
614 open_port = (index * 32) + pos;
615 if (open_port >= system->highport)
617 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
619 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
620 GNUNET_free (open_port_str);
621 bind_status = GNUNET_NO;
622 for (ai = ret; NULL != ai; ai = ai->ai_next)
624 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
627 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,
641 GNUNET_NETWORK_socket_close (socket);
642 if (GNUNET_OK != bind_status)
645 port_buckets[index] |= (1U << pos); /* Set the port bit */
647 if (GNUNET_OK == bind_status)
649 LOG (GNUNET_ERROR_TYPE_DEBUG,
650 "Found a free port %u\n", (unsigned int) open_port);
661 * Release reservation of a TCP or UDP port for a peer
662 * (used during GNUNET_TESTING_peer_destroy).
664 * @param system system to use for reservation tracking
665 * @param port reserved port to release
668 GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
671 uint32_t *port_buckets;
675 port_buckets = system->reserved_ports;
678 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
679 if (0 == (port_buckets[bucket] & (1U << pos)))
681 GNUNET_break(0); /* Port was not reserved by us using reserve_port() */
684 port_buckets[bucket] &= ~(1U << pos);
689 * Testing includes a number of pre-created hostkeys for
690 * faster peer startup. This function can be used to
691 * access the n-th key of those pre-created hostkeys; note
692 * that these keys are ONLY useful for testing and not
693 * secure as the private keys are part of the public
694 * GNUnet source code.
696 * This is primarily a helper function used internally
697 * by #GNUNET_TESTING_peer_configure.
699 * @param system the testing system handle
700 * @param key_number desired pre-created hostkey to obtain
701 * @param id set to the peer's identity (hash of the public
702 * key; if NULL, GNUNET_SYSERR is returned immediately
703 * @return NULL on error (not enough keys)
705 struct GNUNET_CRYPTO_EccPrivateKey *
706 GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
708 struct GNUNET_PeerIdentity *id)
710 struct GNUNET_CRYPTO_EccPrivateKey *private_key;
712 if ((NULL == id) || (NULL == system->hostkeys_data))
714 if (key_number >= system->total_hostkeys)
716 LOG (GNUNET_ERROR_TYPE_ERROR,
717 _("Key number %u does not exist\n"), key_number);
720 private_key = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey);
722 system->hostkeys_data +
723 (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
724 GNUNET_TESTING_HOSTKEYFILESIZE);
725 GNUNET_CRYPTO_ecc_key_get_public_for_signature (private_key,
732 * Structure for holding data to build new configurations from a configuration
738 * The system for which we are building configurations
740 struct GNUNET_TESTING_System *system;
743 * The configuration we are building
745 struct GNUNET_CONFIGURATION_Handle *cfg;
748 * The customized service home path for this peer
753 * Array of ports currently allocated to this peer. These ports will be
754 * released upon peer destroy and can be used by other peers which are
760 * The number of ports in the above array
765 * build status - to signal error while building a configuration
772 * Function to iterate over options. Copies
773 * the options to the target configuration,
774 * updating PORT values as needed.
776 * @param cls the UpdateContext
777 * @param section name of the section
778 * @param option name of the option
779 * @param value value of the option
782 update_config (void *cls, const char *section, const char *option,
785 struct UpdateContext *uc = cls;
789 char *single_variable;
790 char *per_host_variable;
791 unsigned long long num_per_host;
794 if (GNUNET_OK != uc->status)
796 if (! ((0 == strcmp (option, "PORT"))
797 || (0 == strcmp (option, "UNIXPATH"))
798 || (0 == strcmp (option, "HOSTNAME"))))
800 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
801 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
802 if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
806 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
809 new_port = GNUNET_TESTING_reserve_port (uc->system);
812 uc->status = GNUNET_SYSERR;
813 GNUNET_free (single_variable);
814 GNUNET_free (per_host_variable);
817 GNUNET_snprintf (cval, sizeof (cval), "%u", new_port);
819 GNUNET_array_append (uc->ports, uc->nports, new_port);
821 else if ((ival != 0) &&
823 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
825 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
829 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
830 /* ival + ctx->fdnum % num_per_host); */
832 GNUNET_break (0); /* FIXME */
835 if (0 == strcmp (option, "UNIXPATH"))
838 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing",
841 GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock",
842 uc->service_home, section);
845 else if ((GNUNET_YES ==
846 GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing",
851 GNUNET_break(0); /* FIXME */
854 if (0 == strcmp (option, "HOSTNAME"))
856 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
858 GNUNET_free (single_variable);
859 GNUNET_free (per_host_variable);
860 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
865 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
866 * 'trusted_hosts' in all sections
868 * @param cls the UpdateContext
869 * @param section name of the section
872 update_config_sections (void *cls,
875 struct UpdateContext *uc = cls;
879 char *orig_allowed_hosts;
881 char *ACCEPT_FROM_key;
887 /* Ignore certain options from sections. See
888 https://gnunet.org/bugs/view.php?id=2476 */
889 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
890 "TESTING_IGNORE_KEYS"))
894 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section,
895 "TESTING_IGNORE_KEYS", &val));
897 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
903 ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt);
905 for (key = 0; key < ikeys_cnt; key++)
908 ptr = strstr (ptr, ";");
916 for (key = 0; key < ikeys_cnt; key++)
918 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
921 if ((key == ikeys_cnt) &&
922 (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section,
926 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr))
928 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section,
929 "ADVERTISED_PORT", ptr);
933 for (key = 0; key < ikeys_cnt; key++)
935 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
944 GNUNET_free_non_null (val);
945 ACCEPT_FROM_key = "ACCEPT_FROM";
946 if ((NULL != uc->system->trusted_ip) &&
947 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
948 ACCEPT_FROM_key = "ACCEPT_FROM6";
950 GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key,
951 &orig_allowed_hosts))
953 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
955 if (NULL == uc->system->trusted_ip)
956 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
958 GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts,
959 uc->system->trusted_ip);
960 GNUNET_free (orig_allowed_hosts);
961 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key,
963 GNUNET_free (allowed_hosts);
966 static struct SharedServiceInstance *
967 associate_shared_service (struct GNUNET_TESTING_System *system,
968 struct SharedService *ss,
969 struct GNUNET_CONFIGURATION_Handle *cfg)
971 struct SharedServiceInstance *i;
972 struct GNUNET_CONFIGURATION_Handle *temp;
977 if ( ((0 == ss->share) && (NULL == ss->instances))
980 && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) )
982 i = GNUNET_malloc (sizeof (struct SharedServiceInstance));
984 (void) GNUNET_asprintf (&service_home, "%s/shared/%s/%u",
985 system->tmppath, ss->sname, ss->n_instances);
986 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", service_home);
987 port = GNUNET_TESTING_reserve_port (system);
990 GNUNET_free (service_home);
991 cleanup_shared_service_instance (i);
994 GNUNET_array_append (ss->instances, ss->n_instances, i);
995 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
996 (void) GNUNET_asprintf (&i->port_str, "%u", port);
997 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", service_home);
998 GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "SERVICEHOME",
1000 GNUNET_free (service_home);
1001 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH",
1003 GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT",
1005 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1007 GNUNET_CONFIGURATION_destroy (temp);
1008 cleanup_shared_service_instance (i);
1011 GNUNET_CONFIGURATION_destroy (temp);
1015 GNUNET_assert (NULL != ss->instances);
1016 GNUNET_assert (0 < ss->n_instances);
1017 i = ss->instances[ss->n_instances - 1];
1019 GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname,
1020 &cfg_copy_iterator, cfg);
1021 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH",
1023 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1029 * Create a new configuration using the given configuration as a template;
1030 * ports and paths will be modified to select available ports on the local
1031 * system. The default configuration will be available in PATHS section under
1032 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1033 * section to the temporary directory specific to this configuration. If we run
1034 * out of "*port" numbers, return SYSERR.
1036 * This is primarily a helper function used internally
1037 * by 'GNUNET_TESTING_peer_configure'.
1039 * @param system system to use to coordinate resource usage
1040 * @param cfg template configuration to update
1041 * @param ports array with port numbers used in the created configuration.
1042 * Will be updated upon successful return. Can be NULL
1043 * @param nports the size of the `ports' array. Will be updated.
1044 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1045 * be incomplete and should not be used there upon
1048 GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1049 struct GNUNET_CONFIGURATION_Handle *cfg,
1051 unsigned int *nports)
1053 struct UpdateContext uc;
1054 char *default_config;
1058 uc.status = GNUNET_OK;
1061 GNUNET_asprintf (&uc.service_home, "%s/%u", system->tmppath,
1062 system->path_counter++);
1063 GNUNET_asprintf (&default_config, "%s/config", uc.service_home);
1064 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
1066 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
1068 GNUNET_free (default_config);
1069 GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "SERVICEHOME",
1071 /* make PORTs and UNIXPATHs unique */
1072 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1073 /* allow connections to services from system trusted_ip host */
1074 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1075 /* enable loopback-based connections between peers */
1076 GNUNET_CONFIGURATION_set_value_string (cfg,
1078 "USE_LOCALADDR", "YES");
1079 GNUNET_free (uc.service_home);
1080 if ((NULL != ports) && (NULL != nports))
1083 *nports = uc.nports;
1086 GNUNET_free_non_null (uc.ports);
1092 * Create a new configuration using the given configuration as a template;
1093 * ports and paths will be modified to select available ports on the local
1094 * system. The default configuration will be available in PATHS section under
1095 * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
1096 * section to the temporary directory specific to this configuration. If we run
1097 * out of "*port" numbers, return SYSERR.
1099 * This is primarily a helper function used internally
1100 * by 'GNUNET_TESTING_peer_configure'.
1102 * @param system system to use to coordinate resource usage
1103 * @param cfg template configuration to update
1104 * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will
1105 * be incomplete and should not be used there upon
1108 GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1109 struct GNUNET_CONFIGURATION_Handle *cfg)
1111 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1116 * Configure a GNUnet peer. GNUnet must be installed on the local
1117 * system and available in the PATH.
1119 * @param system system to use to coordinate resource usage
1120 * @param cfg configuration to use; will be UPDATED (to reflect needed
1121 * changes in port numbers and paths)
1122 * @param key_number number of the hostkey to use for the peer
1123 * @param id identifier for the daemon, will be set, can be NULL
1124 * @param emsg set to freshly allocated error message (set to NULL on success),
1126 * @return handle to the peer, NULL on error
1128 struct GNUNET_TESTING_Peer *
1129 GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1130 struct GNUNET_CONFIGURATION_Handle *cfg,
1131 uint32_t key_number,
1132 struct GNUNET_PeerIdentity *id,
1135 struct GNUNET_TESTING_Peer *peer;
1136 struct GNUNET_DISK_FileHandle *fd;
1137 char *hostkey_filename;
1138 char *config_filename;
1139 char *libexec_binary;
1141 struct GNUNET_CRYPTO_EccPrivateKey *pk;
1143 struct SharedService *ss;
1144 struct SharedServiceInstance **ss_instances;
1146 unsigned int nports;
1150 ss_instances = NULL;
1153 if (key_number >= system->total_hostkeys)
1155 GNUNET_asprintf (&emsg_,
1156 _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1157 (unsigned int) system->total_hostkeys);
1162 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1164 GNUNET_asprintf (&emsg_,
1165 _("Failed to initialize hostkey for peer %u\n"),
1166 (unsigned int) key_number);
1172 GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1174 GNUNET_asprintf (&emsg_,
1175 _("PRIVATE_KEY option in PEER section missing in configuration\n"));
1178 /* Remove sections for shared services */
1179 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1181 ss = system->shared_services[cnt];
1182 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1184 if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg,
1187 GNUNET_asprintf (&emsg_,
1188 _("Failed to create configuration for peer "
1189 "(not enough free ports?)\n"));
1192 GNUNET_assert (GNUNET_OK ==
1193 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER",
1195 &hostkey_filename));
1196 fd = GNUNET_DISK_file_open (hostkey_filename,
1197 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1198 GNUNET_DISK_PERM_USER_READ
1199 | GNUNET_DISK_PERM_USER_WRITE);
1202 GNUNET_asprintf (&emsg_, _("Cannot open hostkey file `%s': %s\n"),
1203 hostkey_filename, STRERROR (errno));
1204 GNUNET_free (hostkey_filename);
1207 GNUNET_free (hostkey_filename);
1208 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1209 GNUNET_DISK_file_write (fd, system->hostkeys_data
1210 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1211 GNUNET_TESTING_HOSTKEYFILESIZE))
1213 GNUNET_asprintf (&emsg_,
1214 _("Failed to write hostkey file for peer %u: %s\n"),
1215 (unsigned int) key_number,
1217 GNUNET_DISK_file_close (fd);
1220 GNUNET_DISK_file_close (fd);
1221 ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *)
1222 * system->n_shared_services);
1223 for (cnt=0; cnt < system->n_shared_services; cnt++)
1225 ss = system->shared_services[cnt];
1226 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1227 if (NULL == ss_instances[cnt])
1230 GNUNET_assert (GNUNET_OK ==
1231 GNUNET_CONFIGURATION_get_value_string
1232 (cfg, "PATHS", "DEFAULTCONFIG", &config_filename));
1233 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1235 GNUNET_asprintf (&emsg_,
1236 _("Failed to write configuration file `%s' for peer %u: %s\n"),
1238 (unsigned int) key_number,
1240 GNUNET_free (config_filename);
1243 peer = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Peer));
1244 peer->ss_instances = ss_instances;
1245 peer->cfgfile = config_filename; /* Free in peer_destroy */
1246 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1247 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1248 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary))
1251 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1252 peer->args = strdup ("");
1255 peer->args = strdup (libexec_binary);
1256 peer->system = system;
1257 peer->key_number = key_number;
1258 GNUNET_free (libexec_binary);
1259 peer->ports = ports; /* Free in peer_destroy */
1260 peer->nports = nports;
1264 GNUNET_free_non_null (ss_instances);
1265 GNUNET_free_non_null (ports);
1266 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1270 GNUNET_free (emsg_);
1276 * Obtain the peer identity from a peer handle.
1278 * @param peer peer handle for which we want the peer's identity
1279 * @param id identifier for the daemon, will be set
1282 GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1283 struct GNUNET_PeerIdentity *id)
1285 if (NULL != peer->id)
1287 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1290 peer->id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1291 GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system,
1294 memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity));
1301 * @param peer peer to start
1302 * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running)
1305 GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1307 struct SharedServiceInstance *i;
1310 if (NULL != peer->main_process)
1313 return GNUNET_SYSERR;
1315 GNUNET_assert (NULL != peer->cfgfile);
1316 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1318 i = peer->ss_instances[cnt];
1319 if ((0 == i->n_refs)
1320 && (GNUNET_SYSERR == start_shared_service_instance (i)) )
1321 return GNUNET_SYSERR;
1324 peer->main_process = GNUNET_OS_start_process (PIPE_CONTROL,
1325 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1333 if (NULL == peer->main_process)
1335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1336 _("Failed to start `%s': %s\n"),
1339 return GNUNET_SYSERR;
1346 * Start a service at a peer using its ARM service
1348 * @param peer the peer whose service has to be started
1349 * @param service_name name of the service to start
1350 * @param timeout how long should the ARM API try to send the request to start
1352 * @param cont the callback to call with result and status from ARM API
1353 * @param cont_cls the closure for the above callback
1354 * @return GNUNET_OK upon successfully queuing the service start request;
1355 * GNUNET_SYSERR upon error
1358 GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
1359 const char *service_name,
1360 struct GNUNET_TIME_Relative timeout,
1361 GNUNET_ARM_ResultCallback cont,
1364 if (NULL == peer->ah)
1365 return GNUNET_SYSERR;
1366 GNUNET_ARM_request_service_start (peer->ah,
1368 GNUNET_OS_INHERIT_STD_ALL,
1376 * Stop a service at a peer using its ARM service
1378 * @param peer the peer whose service has to be stopped
1379 * @param service_name name of the service to stop
1380 * @param timeout how long should the ARM API try to send the request to stop
1382 * @param cont the callback to call with result and status from ARM API
1383 * @param cont_cls the closure for the above callback
1384 * @return GNUNET_OK upon successfully queuing the service stop request;
1385 * GNUNET_SYSERR upon error
1388 GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
1389 const char *service_name,
1390 struct GNUNET_TIME_Relative timeout,
1391 GNUNET_ARM_ResultCallback cont,
1394 if (NULL == peer->ah)
1395 return GNUNET_SYSERR;
1396 GNUNET_ARM_request_service_stop (peer->ah,
1405 * Sends SIGTERM to the peer's main process
1407 * @param peer the handle to the peer
1408 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1409 * or upon any error while sending SIGTERM
1412 GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1414 struct SharedServiceInstance *i;
1417 if (NULL == peer->main_process)
1420 return GNUNET_SYSERR;
1422 if (0 != GNUNET_OS_process_kill (peer->main_process, SIGTERM))
1423 return GNUNET_SYSERR;
1424 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1426 i = peer->ss_instances[cnt];
1427 GNUNET_assert (0 != i->n_refs);
1430 stop_shared_service_instance (i);
1437 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1439 * @param peer the handle to the peer
1440 * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL
1441 * or upon any error while waiting
1444 GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1448 if (NULL == peer->main_process)
1451 return GNUNET_SYSERR;
1453 ret = GNUNET_OS_process_wait (peer->main_process);
1454 GNUNET_OS_process_destroy (peer->main_process);
1455 peer->main_process = NULL;
1463 * @param peer peer to stop
1464 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1467 GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1469 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1470 return GNUNET_SYSERR;
1471 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1472 return GNUNET_SYSERR;
1478 * Function called whenever we connect to or disconnect from ARM.
1480 * @param cls closure
1481 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
1482 * GNUNET_SYSERR on error.
1485 disconn_status (void *cls,
1488 struct GNUNET_TESTING_Peer *peer = cls;
1490 if (GNUNET_SYSERR == connected)
1492 peer->cb (peer->cb_cls, peer, connected);
1495 if (GNUNET_YES == connected)
1497 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1500 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1501 GNUNET_ARM_disconnect_and_free (peer->ah);
1503 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1508 * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled
1509 * through the GNUNET_TESTING_PeerStopCallback().
1511 * @param peer the peer to stop
1512 * @param cb the callback to signal peer shutdown
1513 * @param cb_cls closure for the above callback
1514 * @return GNUNET_OK upon successfully giving the request to the ARM API (this
1515 * does not mean that the peer is successfully stopped); GNUNET_SYSERR
1519 GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1520 GNUNET_TESTING_PeerStopCallback cb,
1523 if (NULL == peer->main_process)
1524 return GNUNET_SYSERR;
1525 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1526 if (NULL == peer->ah)
1527 return GNUNET_SYSERR;
1529 peer->cb_cls = cb_cls;
1535 * Cancel a previous asynchronous peer stop request.
1536 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1537 * peer. It is an error to call this function if the peer stop callback was
1540 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1544 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1546 GNUNET_assert (NULL != peer->ah);
1547 GNUNET_ARM_disconnect_and_free (peer->ah);
1553 * Destroy the peer. Releases resources locked during peer configuration.
1554 * If the peer is still running, it will be stopped AND a warning will be
1555 * printed (users of the API should stop the peer explicitly first).
1557 * @param peer peer to destroy
1560 GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1564 if (NULL != peer->main_process)
1565 GNUNET_TESTING_peer_stop (peer);
1566 if (NULL != peer->ah)
1567 GNUNET_ARM_disconnect_and_free (peer->ah);
1568 if (NULL != peer->mh)
1569 GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
1570 GNUNET_free (peer->cfgfile);
1571 if (NULL != peer->cfg)
1572 GNUNET_CONFIGURATION_destroy (peer->cfg);
1573 GNUNET_free (peer->main_binary);
1574 GNUNET_free (peer->args);
1575 GNUNET_free_non_null (peer->id);
1576 GNUNET_free_non_null (peer->ss_instances);
1577 if (NULL != peer->ports)
1579 for (cnt = 0; cnt < peer->nports; cnt++)
1580 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1581 GNUNET_free (peer->ports);
1588 * Start a single peer and run a test using the testing library.
1589 * Starts a peer using the given configuration and then invokes the
1590 * given callback. This function ALSO initializes the scheduler loop
1591 * and should thus be called directly from "main". The testcase
1592 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1594 * @param testdir only the directory name without any path. This is used for
1595 * all service homes; the directory will be created in a temporary
1596 * location depending on the underlying OS
1597 * @param cfgfilename name of the configuration file to use;
1598 * use NULL to only run with defaults
1599 * @param tm main function of the testcase
1600 * @param tm_cls closure for 'tm'
1601 * @return 0 on success, 1 on error
1604 GNUNET_TESTING_peer_run (const char *testdir,
1605 const char *cfgfilename,
1606 GNUNET_TESTING_TestMain tm,
1609 return GNUNET_TESTING_service_run (testdir, "arm",
1610 cfgfilename, tm, tm_cls);
1615 * Structure for holding service data
1617 struct ServiceContext
1620 * The configuration of the peer in which the service is run
1622 const struct GNUNET_CONFIGURATION_Handle *cfg;
1625 * Callback to signal service startup
1627 GNUNET_TESTING_TestMain tm;
1630 * The peer in which the service is run.
1632 struct GNUNET_TESTING_Peer *peer;
1635 * Closure for the above callback
1642 * Callback to be called when SCHEDULER has been started
1644 * @param cls the ServiceContext
1645 * @param tc the TaskContext
1648 service_run_main (void *cls,
1649 const struct GNUNET_SCHEDULER_TaskContext *tc)
1651 struct ServiceContext *sc = cls;
1653 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1658 * Start a single service (no ARM, except of course if the given
1659 * service name is 'arm') and run a test using the testing library.
1660 * Starts a service using the given configuration and then invokes the
1661 * given callback. This function ALSO initializes the scheduler loop
1662 * and should thus be called directly from "main". The testcase
1663 * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'.
1665 * This function is useful if the testcase is for a single service
1666 * and if that service doesn't itself depend on other services.
1668 * @param testdir only the directory name without any path. This is used for
1669 * all service homes; the directory will be created in a temporary
1670 * location depending on the underlying OS
1671 * @param service_name name of the service to run
1672 * @param cfgfilename name of the configuration file to use;
1673 * use NULL to only run with defaults
1674 * @param tm main function of the testcase
1675 * @param tm_cls closure for 'tm'
1676 * @return 0 on success, 1 on error
1679 GNUNET_TESTING_service_run (const char *testdir,
1680 const char *service_name,
1681 const char *cfgfilename,
1682 GNUNET_TESTING_TestMain tm,
1685 struct ServiceContext sc;
1686 struct GNUNET_TESTING_System *system;
1687 struct GNUNET_TESTING_Peer *peer;
1688 struct GNUNET_CONFIGURATION_Handle *cfg;
1690 char *libexec_binary;
1692 GNUNET_log_setup (testdir, "WARNING", NULL);
1693 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1696 cfg = GNUNET_CONFIGURATION_create ();
1697 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1699 LOG (GNUNET_ERROR_TYPE_ERROR,
1700 _("Failed to load configuration from %s\n"), cfgfilename);
1701 GNUNET_CONFIGURATION_destroy (cfg);
1702 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1705 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1708 GNUNET_CONFIGURATION_destroy (cfg);
1709 hostkeys_unload (system);
1710 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1713 GNUNET_free (peer->main_binary);
1714 GNUNET_free (peer->args);
1715 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1716 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1717 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary))
1720 GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary);
1721 peer->args = strdup ("");
1724 peer->args = strdup (libexec_binary);
1726 GNUNET_free (libexec_binary);
1727 GNUNET_free (binary);
1728 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1730 GNUNET_TESTING_peer_destroy (peer);
1731 GNUNET_CONFIGURATION_destroy (cfg);
1732 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1739 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1740 if ((NULL != peer->main_process) &&
1741 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1743 GNUNET_TESTING_peer_destroy (peer);
1744 GNUNET_CONFIGURATION_destroy (cfg);
1745 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1748 GNUNET_TESTING_peer_destroy (peer);
1749 GNUNET_CONFIGURATION_destroy (cfg);
1750 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1756 * Sometimes we use the binary name to determine which specific
1757 * test to run. In those cases, the string after the last "_"
1758 * in 'argv[0]' specifies a string that determines the configuration
1759 * file or plugin to use.
1761 * This function returns the respective substring, taking care
1762 * of issues such as binaries ending in '.exe' on W32.
1764 * @param argv0 the name of the binary
1765 * @return string between the last '_' and the '.exe' (or the end of the string),
1766 * NULL if argv0 has no '_'
1769 GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
1771 size_t slen = strlen (argv0) + 1;
1776 memcpy (sbuf, argv0, slen);
1777 ret = strrchr (sbuf, '_');
1780 ret++; /* skip underscore */
1781 dot = strchr (ret, '.');
1784 return GNUNET_strdup (ret);
1788 /* end of testing.c */