gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

commit 40a5a650d3b61aca9474692416adeba7272e61b3
parent b138491b9e4878607ea954254f84f1106202017b
Author: t3sserakt <t3ss@posteo.de>
Date:   Fri, 14 Jul 2023 16:59:30 +0200

NEWS: Added command to execute a script.

Diffstat:
Msrc/include/gnunet_testing_ng_lib.h | 206++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Asrc/testing/testing_api_cmd_exec_bash_script.c | 217+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 422 insertions(+), 1 deletion(-)

diff --git a/src/include/gnunet_testing_ng_lib.h b/src/include/gnunet_testing_ng_lib.h @@ -519,6 +519,20 @@ struct GNUNET_TESTING_Timer unsigned int num_retries; }; +/** + * Command to execute a script synchronously. + * + * @param label Label of the command. + * @param script The name of the script. + * @param script_argv The arguments of the script. +*/ +const struct GNUNET_TESTING_Command +GNUNET_TESTING_cmd_exec_bash_script (const char *label, + const char *script, + char *const script_argv[], + int argc, + GNUNET_ChildCompletedCallback cb); + /** * Retrieve peer identity from the test system with the unique node id. @@ -603,6 +617,188 @@ GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits, /* ****** Specific traits supported by this component ******* */ +typedef void * +(*GNUNET_TESTING_notify_connect_cb) (struct GNUNET_TESTING_Interpreter *is, + const struct GNUNET_PeerIdentity *peer); + + +/** + * Struct to store information needed in callbacks. + * + */ +struct ConnectPeersState +{ + /** + * Context for our asynchronous completion. + */ + struct GNUNET_TESTING_AsyncContext ac; + + GNUNET_TESTING_notify_connect_cb notify_connect; + + /** + * The testing system of this node. + */ + const struct GNUNET_TESTING_System *tl_system; + + // Label of the cmd which started the test system. + const char *create_label; + + /** + * Number globally identifying the node. + * + */ + uint32_t num; + + /** + * Label of the cmd to start a peer. + * + */ + const char *start_peer_label; + + /** + * The topology of the test setup. + */ + struct GNUNET_TESTING_NetjailTopology *topology; + + /** + * Connections to other peers. + */ + struct GNUNET_TESTING_NodeConnection *node_connections_head; + + struct GNUNET_TESTING_Interpreter *is; + + /** + * Number of connections. + */ + unsigned int con_num; + + /** + * Number of additional connects this cmd will wait for not triggered by this cmd. + */ + unsigned int additional_connects; + + /** + * Number of connections we already have a notification for. + */ + unsigned int con_num_notified; + + /** + * Number of additional connects this cmd will wait for not triggered by this cmd we already have a notification for. + */ + unsigned int additional_connects_notified; + + /** + * Flag indicating, whether the command is waiting for peers to connect that are configured to connect. + */ + unsigned int wait_for_connect; +}; + + +struct GNUNET_TESTING_StartPeerState +{ + /** + * Context for our asynchronous completion. + */ + struct GNUNET_TESTING_AsyncContext ac; + + /** + * The ip of a node. + */ + char *node_ip; + + /** + * Receive callback + */ + struct GNUNET_MQ_MessageHandler *handlers; + + /** + * GNUnet configuration file used to start a peer. + */ + char *cfgname; + + /** + * Peer's configuration + */ + struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * struct GNUNET_TESTING_Peer returned by GNUNET_TESTING_peer_configure. + */ + struct GNUNET_TESTING_Peer *peer; + + /** + * Peer identity + */ + struct GNUNET_PeerIdentity id; + + /** + * Peer's transport service handle + */ + struct GNUNET_TRANSPORT_CoreHandle *th; + + /** + * Application handle + */ + struct GNUNET_TRANSPORT_ApplicationHandle *ah; + + /** + * Peer's PEERSTORE Handle + */ + struct GNUNET_PEERSTORE_Handle *ph; + + /** + * Hello get task + */ + struct GNUNET_SCHEDULER_Task *rh_task; + + /** + * Peer's transport get hello handle to retrieve peer's HELLO message + */ + struct GNUNET_PEERSTORE_IterateContext *pic; + + /** + * Hello + */ + char *hello; + + /** + * Hello size + */ + size_t hello_size; + + /** + * The label of the command which was started by calling GNUNET_TESTING_cmd_system_create. + */ + char *system_label; + + /** + * An unique number to identify the peer + */ + unsigned int no; + + /** + * A map with struct GNUNET_MQ_Handle values for each peer this peer + * is connected to. + */ + struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map; + + /** + * Test setup for this peer. + */ + const struct GNUNET_TESTING_System *tl_system; + + /** + * Callback which is called on neighbour connect events. + */ + GNUNET_TESTING_notify_connect_cb notify_connect; + + /** + * Flag indicating, if udp broadcast should be switched on. + */ + enum GNUNET_GenericReturnValue broadcast; +}; + + /** * Create headers for a trait with name @a name for * statically allocated data of type @a type. @@ -697,7 +893,15 @@ GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits, */ #define GNUNET_TESTING_SIMPLE_TRAITS(op) \ op (batch_cmds, struct GNUNET_TESTING_Command *) \ - op (process, struct GNUNET_OS_Process *) + op (process, struct GNUNET_OS_Process *) \ + op (peer_id, const struct GNUNET_PeerIdentity) \ + op (connected_peers_map, const struct GNUNET_CONTAINER_MultiShortmap) \ + op (hello_size, const size_t) \ + op (hello, const char) \ + op (application_handle, const struct GNUNET_TRANSPORT_ApplicationHandle) \ + op (connect_peer_state, const struct ConnectPeersState) \ + op (state, const struct GNUNET_TESTING_StartPeerState) \ + op (broadcast, const enum GNUNET_GenericReturnValue) /** diff --git a/src/testing/testing_api_cmd_exec_bash_script.c b/src/testing/testing_api_cmd_exec_bash_script.c @@ -0,0 +1,217 @@ +/* + This file is part of GNUnet + Copyright (C) 2023 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 <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: AGPL3.0-or-later + */ + +/** + * @file testing_api_cmd_local_test_prepared.c + * @brief cmd to block the interpreter loop until all peers started. + * @author t3sserakt + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_ng_lib.h" + +#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) + +struct BashScriptState +{ + /** + * Context for our asynchronous completion. + */ + struct GNUNET_TESTING_AsyncContext ac; + + /** + * Callback handed over to the command, which should + * be called upon death or completion of the script. + */ + GNUNET_ChildCompletedCallback cb; + + // Child Wait handle + struct GNUNET_ChildWaitHandle *cwh; + + /** + * The process id of the script. + */ + struct GNUNET_OS_Process *start_proc; + + /** + * Script this cmd will execute. + */ + const char *script; + + + /** + * Arguments for the script + */ + char **script_argv; + + /** + * Size of script_argv. + */ + int argc; +}; + +/** + * The cleanup function of this cmd frees resources the cmd allocated. + * + */ +static void +exec_bash_script_cleanup (void *cls) +{ + struct BashScriptState *bss = cls; + + if (NULL != bss->cwh) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cancel child\n"); + GNUNET_wait_child_cancel (bss->cwh); + bss->cwh = NULL; + } + if (NULL != bss->start_proc) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Kill process\n"); + GNUNET_assert (0 == + GNUNET_OS_process_kill (bss->start_proc, + SIGKILL)); + GNUNET_assert (GNUNET_OK == + GNUNET_OS_process_wait (bss->start_proc)); + GNUNET_OS_process_destroy (bss->start_proc); + bss->start_proc = NULL; + } + GNUNET_free (bss); +} + +/** + * Callback which will be called if the setup script finished. + * + */ +static void +child_completed_callback (void *cls, + enum GNUNET_OS_ProcessStatusType type, + long unsigned int exit_code) +{ + struct BashScriptState *bss = cls; + + GNUNET_OS_process_destroy (bss->start_proc); + bss->start_proc = NULL; + bss->cwh = NULL; + if (0 == exit_code) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Child succeeded!\n", + exit_code); + GNUNET_TESTING_async_finish (&bss->ac); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Child failed with error %lu!\n", + exit_code); + GNUNET_TESTING_async_fail (&bss->ac); + } + bss->cb (cls, type, exit_code); +} + +/** + * Run method of the command created by the interpreter to wait for another + * command to finish. + * + */ +static void +exec_bash_script_run (void *cls, + struct GNUNET_TESTING_Interpreter *is) +{ + struct BashScriptState *bss = cls; + enum GNUNET_GenericReturnValue helper_check; + char *argv[bss->argc + 2]; + + char *data_dir; + char *script_name; + + data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); + GNUNET_asprintf (&script_name, "%s%s", data_dir, bss->script); + + helper_check = GNUNET_OS_check_helper_binary ( + script_name, + GNUNET_YES, + NULL); + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "script_name %s\n", + script_name); + + if (GNUNET_NO == helper_check) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No SUID for %s!\n", + script_name); + GNUNET_TESTING_interpreter_fail (is); + return; + } + if (GNUNET_SYSERR == helper_check) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "%s not found!\n", + script_name); + GNUNET_TESTING_interpreter_fail (is); + return; + } + argv[0] = script_name; + if (NULL != bss->script_argv) + { + for (int i = 0; i < bss->argc;i++) + argv[i + 1] = bss->script_argv[i]; + } + argv[bss->argc] = NULL; + + bss->start_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR, + NULL, + NULL, + NULL, + script_name, + argv); + bss->cwh = GNUNET_wait_child (bss->start_proc, + &child_completed_callback, + bss); + GNUNET_break (NULL != bss->cwh); +} + +const struct GNUNET_TESTING_Command +GNUNET_TESTING_cmd_exec_bash_script (const char *label, + const char *script, + char *const script_argv[], + int argc, + GNUNET_ChildCompletedCallback cb) +{ + struct BashScriptState *bss; + + bss = GNUNET_new (struct BashScriptState); + bss->script = script; + bss->script_argv = script_argv; + bss->argc = argc; + bss->cb = cb; + + return GNUNET_TESTING_command_new (bss, + label, + &exec_bash_script_run, + &exec_bash_script_cleanup, + NULL, + &bss->ac); +}