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:
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);
+}