- Developer Corner
- Recent posts
The TESTING library is used for writing testcases which involve starting a single or multiple peers. While peers can also be started by testcases using the ARM subsystem, using TESTING library provides an elegant way to do this. The configurations of the peers are auto-generated from a given template to have non-conflicting port numbers ensuring that peers' services do not run into bind errors. This is achieved by testing ports' availability by binding a listening socket to them before allocating them to services in the generated configurations.
An another advantage while using TESTING is that it shortens the testcase startup time as the hostkeys for peers are copied from a pre-computed set of hostkeys instead of generating them at peer startup which may take a considerable amount of time when starting multiple peers or on an embedded processor.
TESTING also allows for certain services to be shared among peers. This feature is invaluable when testing with multiple peers as it helps to reduce the number of services run per each peer and hence the total number of processes run per testcase.
TESTING library only handles creating, starting and stopping peers. Features useful for testcases such as connecting peers in a topology are not available in TESTING but are available in the TESTBED subsystem. Furthermore, TESTING only creates peers on the localhost, however by using TESTBED testcases can benefit from creating peers across multiple hosts.
TESTING abstracts a group of peers as a TESTING system. All peers in a system have common hostname and no two services of these peers have a same port or a UNIX domain socket path.
TESTING system can be created with the function
GNUNET_TESTING_system_create() which returns a handle to the system. This function takes a directory path which is used for generating the configurations of peers, an IP address from which connections to the peers' services should be allowed, the hostname to be used in peers' configuration, and an array of shared service specifications of type
The shared service specification must specify the name of the service to share, the configuration pertaining to that shared service and the maximum number of peers that are allowed to share a single instance of the shared service.
TESTING system created with
GNUNET_TESTING_system_create() chooses ports from the default range 12000 - 56000 while auto-generating configurations for peers. This range can be customised with the function
GNUNET_TESTING_system_create_with_portrange(). This function is similar to
GNUNET_TESTING_system_create() except that it take 2 additional parameters -- the start and end of the port range to use.
A TESTING system is destroyed with the funciton
GNUNET_TESTING_system_destory(). This function takes the handle of the system and a flag to remove the files created in the directory used to generate configurations.
A peer is created with the function
GNUNET_TESTING_peer_configure(). This functions takes the system handle, a configuration template from which the configuration for the peer is auto-generated and the index from where the hostkey for the peer has to be copied from. When successfull, this function returs a handle to the peer which can be used to start and stop it and to obtain the identity of the peer. If unsuccessful, a NULL pointer is returned with an error message. This function handles the generated configuration to have non-conflicting ports and paths.
Peers can be started and stopped by calling the functions
GNUNET_TESTING_peer_stop() respectively. A peer can be destroyed by calling the function
GNUNET_TESTING_peer_destroy. When a peer is destroyed, the ports and paths in allocated in its configuration are reclaimed for usage in new peers.
GNUNET_TESTING_peer_stop() is normally fine for testcases. However, calling this function for each peer is inefficient when trying to shutdown multiple peers as this function sends the termination signal to the given peer process and waits for it to terminate. It would be faster in this case to send the termination signals to the peers first and then wait on them. This is accomplished by the functions
GNUNET_TESTING_peer_kill() which sends a termination signal to the peer, and the function
GNUNET_TESTING_peer_wait() which waits on the peer.
Further finer control can be achieved by choosing to stop a peer asynchronously with the function
GNUNET_TESTING_peer_stop_async(). This function takes a callback parameter and a closure for it in addition to the handle to the peer to stop. The callback function is called with the given closure when the peer is stopped. Using this function eliminates blocking while waiting for the peer to terminate.
An asynchronous peer stop can be cancelled by calling the function
GNUNET_TESTING_peer_stop_async_cancel(). Note that calling this function does not prevent the peer from terminating if the termination signal has already been sent to it. It does, however, cancels the callback to be called when the peer is stopped.
Most of the testcases can benefit from an abstraction which configures a peer and starts it. This is provided by the function
GNUNET_TESTING_peer_run(). This function takes the testing directory pathname, a configuration template, a callback and its closure. This function creates a peer in the given testing directory by using the configuration template, starts the peer and calls the given callback with the given closure.
GNUNET_TESTING_peer_run() starts the ARM service of the peer which starts the rest of the configured services. A similar function
GNUNET_TESTING_service_run can be used to just start a single service of a peer. In this case, the peer's ARM service is not started; instead, only the given service is run.