/*
This file is part of GNUnet
Copyright (C) 2021 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
* @brief API for writing an interpreter to test GNUnet components
* @author Christian Grothoff
* @author Marcello Stanisci
* @author t3sserakt
*/
#ifndef GNUNET_TESTING_NETJAIL_LIB_H
#define GNUNET_TESTING_NETJAIL_LIB_H
#include "gnunet_util_lib.h"
#include "gnunet_testing_plugin.h"
#include "gnunet_testing_ng_lib.h"
/**
* Router of a netjail subnet.
*/
struct GNUNET_TESTING_NetjailRouter
{
/**
* Will tcp be forwarded?
*/
unsigned int tcp_port;
/**
* Will udp be forwarded?
*/
unsigned int udp_port;
};
/**
* Enum for the different types of nodes.
*/
enum GNUNET_TESTING_NODE_TYPE
{
/**
* Node in a subnet.
*/
GNUNET_TESTING_SUBNET_NODE,
/**
* Global known node.
*/
GNUNET_TESTING_GLOBAL_NODE
};
/**
* Protocol address prefix für a connection between nodes.
*/
struct GNUNET_TESTING_AddressPrefix
{
/**
* Pointer to the previous prefix in the DLL.
*/
struct GNUNET_TESTING_AddressPrefix *prev;
/**
* Pointer to the next prefix in the DLL.
*/
struct GNUNET_TESTING_AddressPrefix *next;
/**
* The address prefix.
*/
char *address_prefix;
};
/**
* Node in a netjail topology.
*/
struct GNUNET_TESTING_NetjailNode;
/**
* Connection to another node.
*/
struct GNUNET_TESTING_NodeConnection
{
/**
* Pointer to the previous connection in the DLL.
*/
struct GNUNET_TESTING_NodeConnection *prev;
/**
* Pointer to the next connection in the DLL.
*/
struct GNUNET_TESTING_NodeConnection *next;
/**
* The number of the subnet of the node this connection points to. This is 0,
* if the node is a global known node.
*/
unsigned int namespace_n;
/**
* The number of the node this connection points to.
*/
unsigned int node_n;
/**
* The type of the node this connection points to.
*/
enum GNUNET_TESTING_NODE_TYPE node_type;
/**
* The node which establish the connection
*/
struct GNUNET_TESTING_NetjailNode *node;
/**
* Head of the DLL with the address prefixes for the protocolls this node is reachable.
*/
struct GNUNET_TESTING_AddressPrefix *address_prefixes_head;
/**
* Tail of the DLL with the address prefixes for the protocolls this node is reachable.
*/
struct GNUNET_TESTING_AddressPrefix *address_prefixes_tail;
};
/**
* Node in the netjail topology.
*/
struct GNUNET_TESTING_NetjailNode
{
/**
* Plugin for the test case to be run on this node.
*/
char *plugin;
/**
* Flag indicating if this node is a global known node.
*/
unsigned int is_global;
/**
* The number of the subnet this node is running in.
*/
unsigned int namespace_n;
/**
* The number of this node in the subnet.
*/
unsigned int node_n;
/**
* Head of the DLL with the connections which shall be established to other nodes.
*/
struct GNUNET_TESTING_NodeConnection *node_connections_head;
/**
* Tail of the DLL with the connections which shall be established to other nodes.
*/
struct GNUNET_TESTING_NodeConnection *node_connections_tail;
};
/**
* Subnet in a topology.
*/
struct GNUNET_TESTING_NetjailNamespace
{
/**
* The number of the subnet.
*/
unsigned int namespace_n;
/**
* Router of the subnet.
*/
struct GNUNET_TESTING_NetjailRouter *router;
/**
* Hash map containing the nodes in this subnet.
*/
struct GNUNET_CONTAINER_MultiShortmap *nodes;
};
/**
* Toplogy of our netjail setup.
*/
struct GNUNET_TESTING_NetjailTopology
{
/**
* Default plugin for the test case to be run on nodes.
*/
char *plugin;
/**
* Number of subnets.
*/
unsigned int namespaces_n;
/**
* Number of nodes per subnet.
*/
unsigned int nodes_m;
/**
* Number of global known nodes.
*/
unsigned int nodes_x;
/**
* Hash map containing the subnets (for natted nodes) of the topology.
*/
struct GNUNET_CONTAINER_MultiShortmap *map_namespaces;
/**
* Hash map containing the global known nodes which are not natted.
*/
struct GNUNET_CONTAINER_MultiShortmap *map_globals;
/**
* Additional connects we do expect, beside the connects which are configured in the topology.
*/
unsigned int additional_connects;
};
/**
* Getting the topology from file.
*
* @param filename The name of the topology file.
* @return The GNUNET_TESTING_NetjailTopology
*/
struct GNUNET_TESTING_NetjailTopology *
GNUNET_TESTING_get_topo_from_file (const char *filename);
/**
* Parse the topology data.
*
* @param data The topology data.
* @return The GNUNET_TESTING_NetjailTopology
*/
struct GNUNET_TESTING_NetjailTopology *
GNUNET_TESTING_get_topo_from_string (char *data);
/**
* Get the connections to other nodes for a specific node.
*
* @param num The specific node we want the connections for.
* @param topology The topology we get the connections from.
* @return The connections of the node.
*/
struct GNUNET_TESTING_NodeConnection *
GNUNET_TESTING_get_connections (unsigned int num, struct
GNUNET_TESTING_NetjailTopology *topology);
/**
* Get the address for a specific communicator from a connection.
*
* @param connection The connection we like to have the address from.
* @param prefix The communicator protocol prefix.
* @return The address of the communicator.
*/
char *
GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection,
char *prefix);
/**
* Deallocate memory of the struct GNUNET_TESTING_NetjailTopology.
*
* @param topology The GNUNET_TESTING_NetjailTopology to be deallocated.
*/
void
GNUNET_TESTING_free_topology (struct GNUNET_TESTING_NetjailTopology *topology);
/**
* Calculate the unique id identifying a node from a given connction.
*
* @param node_connection The connection we calculate the id from.
* @param topology The topology we get all needed information from.
* @return The unique id of the node from the connection.
*/
unsigned int
GNUNET_TESTING_calculate_num (struct
GNUNET_TESTING_NodeConnection *node_connection,
struct GNUNET_TESTING_NetjailTopology *topology);
/**
* Struct with information for callbacks.
*
*/
struct BlockState
{
/**
* Context for our asynchronous completion.
*/
struct GNUNET_TESTING_AsyncContext ac;
/**
* The label of this command.
*/
const char *label;
/**
* If this command will block.
*/
unsigned int asynchronous_finish;
};
/**
* Struct to hold information for callbacks.
*
*/
struct LocalPreparedState
{
/**
* Context for our asynchronous completion.
*/
struct GNUNET_TESTING_AsyncContext ac;
/**
* Callback to write messages to the master loop.
*
*/
TESTING_CMD_HELPER_write_cb write_message;
};
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_system_destroy (const char *label,
const char *create_label);
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_system_create (const char *label,
const char *testdir);
/**
* Create command.
*
* @param label name for command.
* @param topology_config Configuration file for the test topology.
* @param read_file Flag indicating if the the name of the topology file is send to the helper, or a string with the topology data.
* @return command.
*/
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_netjail_start (const char *label,
char *topology_config,
unsigned int *read_file);
/**
* Create command.
*
* @param label name for command.
* @param topology_config Configuration file for the test topology.
* @param read_file Flag indicating if the the name of the topology file is send to the helper, or a string with the topology data.
* @return command.
*/
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_netjail_stop (const char *label,
char *topology_config,
unsigned int *read_file);
/**
* Create command.
*
* @param label Name for the command.
* @param topology The complete topology information.
* @param read_file Flag indicating if the the name of the topology file is send to the helper, or a string with the topology data.
* @param topology_data If read_file is GNUNET_NO, topology_data holds the string with the topology.
* @param timeout Before this timeout is reached this cmd MUST finish.
* @return command.
*/
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_netjail_start_testing_system (
const char *label,
struct GNUNET_TESTING_NetjailTopology *topology,
unsigned int *read_file,
char *topology_data,
struct GNUNET_TIME_Relative timeout);
/**
* Create command.
*
* @param label name for command.
* @param helper_start_label label of the cmd to start the test system.
* @param topology The complete topology information.
* @return command.
*/
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_stop_testing_system (
const char *label,
const char *helper_start_label,
struct GNUNET_TESTING_NetjailTopology *topology);
/**
* Create a GNUNET_CMDS_LOCAL_FINISHED message.
*
* @param rv The result of the local test as GNUNET_GenericReturnValue.
* @return The GNUNET_CMDS_LOCAL_FINISHED message.
*/
struct GNUNET_MessageHeader *
GNUNET_TESTING_send_local_test_finished_msg (enum GNUNET_GenericReturnValue rv);
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_barrier_create (
const char *label);
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_barrier_setup_finished (
const char *label);
// Wait for barrier to be reached by all;
// async version implies reached but does not
// wait on other peers to reach it.
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_barrier_reached (
const char *label,
const char *barrier_label);
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_block_until_all_peers_started (
const char *label,
unsigned int *all_peers_started);
/**
* Create command.
*
* @param label name for command.
* @param all_peers_started Flag which will be set from outside.
* @param asynchronous_finish If GNUNET_YES this command will not block.
* @return command.
*/
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_block_until_external_trigger (
const char *label);
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_send_peer_ready (const char *label,
TESTING_CMD_HELPER_write_cb write_message);
/**
* Create command.
*
* @param label name for command.
* @param write_message Callback to write messages to the master loop.
* @return command.
*/
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_local_test_finished (
const char *label,
TESTING_CMD_HELPER_write_cb write_message);
/**
* Create command.
*
* @param label name for command.
* @param write_message Callback to write messages to the master loop.
* @param all_local_tests_prepared Flag which will be set from outside.
* @return command.
*/
struct GNUNET_TESTING_Command
GNUNET_TESTING_cmd_local_test_prepared (const char *label,
TESTING_CMD_HELPER_write_cb
write_message);
/* ***** Netjail trait support ***** */
/**
* Call #op on all simple traits.
*/
#define GNUNET_TESTING_SIMPLE_NETJAIL_TRAITS(op) \
op (test_system, const struct GNUNET_TESTING_System) \
op (async_context, const struct GNUNET_TESTING_AsyncContext) \
op (helper_handles, const struct GNUNET_HELPER_Handle *) \
op (local_prepared_state, const struct LocalPreparedState) \
op (block_state, const struct BlockState)
GNUNET_TESTING_SIMPLE_NETJAIL_TRAITS (GNUNET_TESTING_MAKE_DECL_SIMPLE_TRAIT)
#endif