summaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2021-08-17 19:57:12 +0200
committert3sserakt <t3ss@posteo.de>2021-08-17 19:57:12 +0200
commit32a8c505c1fa27bb43c4e7c8d288566d51417f56 (patch)
tree0328fe50b6a099b5020fe6d1e01cbd6b96ecd18a /src/testing
parent1e063cd73452396778cf00127346b9b08a922317 (diff)
- moved test code from testbed to testing
Diffstat (limited to 'src/testing')
-rw-r--r--src/testing/Makefile.am41
-rw-r--r--src/testing/gnunet-cmds-helper.c662
-rw-r--r--src/testing/test_testing_api_cmd_netjail.c79
-rw-r--r--src/testing/test_testing_plugin_testcmd.c116
-rw-r--r--src/testing/testing_api_cmd_block_until_all_peers_started.c128
-rw-r--r--src/testing/testing_api_cmd_local_test_finished.c131
-rw-r--r--src/testing/testing_api_cmd_netjail_start.c217
-rw-r--r--src/testing/testing_api_cmd_netjail_start_testsystem.c541
-rw-r--r--src/testing/testing_api_cmd_netjail_stop.c215
-rw-r--r--src/testing/testing_api_cmd_netjail_stop_testsystem.c141
-rw-r--r--src/testing/testing_api_cmd_send_peer_ready.c5
-rw-r--r--src/testing/testing_cmds.h90
12 files changed, 2363 insertions, 3 deletions
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 8b28e6e23..15469a310 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -11,10 +11,43 @@ pkgcfgdir= $(pkgdatadir)/config.d/
dist_pkgcfg_DATA = \
testing.conf
+libexec_PROGRAMS = \
+ gnunet-cmds-helper
+
+plugindir = $(libdir)/gnunet
+
+plugin_LTLIBRARIES = \
+ libgnunet_test_testing_plugin_testcmd.la
+
lib_LTLIBRARIES = \
libgnunettesting.la
+gnunet_cmds_helper_SOURCES = \
+ gnunet-cmds-helper.c
+gnunet_cmds_helper_LDADD = $(XLIB) \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ libgnunettesting.la \
+ $(LTLIBINTL) $(Z_LIBS)
+
+libgnunet_test_testing_plugin_testcmd_la_SOURCES = \
+ test_testing_plugin_testcmd.c
+libgnunet_test_testing_plugin_testcmd_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/arm/libgnunetarm.la \
+ libgnunettesting.la \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(LTLIBINTL)
+libgnunet_test_testing_plugin_testcmd_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
libgnunettesting_la_SOURCES = \
+ testing_api_cmd_local_test_finished.c \
+ testing_api_cmd_send_peer_ready.c \
+ testing_api_cmd_block_until_all_peers_started.c \
+ testing_api_cmd_netjail_start.c \
+ testing_api_cmd_netjail_start_testsystem.c \
+ testing_api_cmd_netjail_stop_testsystem.c \
+ testing_api_cmd_netjail_stop.c \
testing.c testing.h \
testing_api_cmd_system_create.c \
testing_api_cmd_batch.c \
@@ -56,6 +89,7 @@ list_keys_LDADD = \
check_PROGRAMS = \
+ test_testing_api_cmd_netjail \
test_testing_hello_world \
test_testing_portreservation \
test_testing_servicestartup \
@@ -66,6 +100,7 @@ check_PROGRAMS = \
if ENABLE_TEST_RUN
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
TESTS = \
+ test_testing_api_cmd_netjail \
test_testing_hello_world \
test_testing_portreservation \
test_testing_peerstartup \
@@ -73,6 +108,12 @@ TESTS = \
test_testing_servicestartup
endif
+test_testing_api_cmd_netjail_SOURCES = \
+ test_testing_api_cmd_netjail.c
+test_testing_api_cmd_netjail_LDADD = \
+ libgnunettesting.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
test_testing_hello_world_SOURCES = \
test_testing_hello_world.c
test_testing_hello_world_LDADD = \
diff --git a/src/testing/gnunet-cmds-helper.c b/src/testing/gnunet-cmds-helper.c
new file mode 100644
index 000000000..d9fcf3541
--- /dev/null
+++ b/src/testing/gnunet-cmds-helper.c
@@ -0,0 +1,662 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2008--2013, 2016 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 testbed/gnunet-cmds-helper.c
+ * @brief Helper binary that is started from a remote interpreter loop to start
+ * a local interpreter loop.
+ *
+ * This helper monitors for three termination events. They are: (1)The
+ * stdin of the helper is closed for reading; (2)the helper received
+ * SIGTERM/SIGINT; (3)the local loop crashed. In case of events 1 and 2
+ * the helper kills the interpreter loop. When the interpreter loop
+ * crashed (event 3), the helper should send a SIGTERM to its own process
+ * group; this behaviour will help terminate any child processes the loop
+ * has started and prevents them from leaking and running forever.
+ *
+ * @author t3sserakt
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ */
+
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_testing_ng_lib.h"
+#include "testing_cmds.h"
+#include "gnunet_testing_plugin.h"
+#include <zlib.h>
+
+
+/**
+ * Generic logging shortcut
+ */
+#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
+
+/**
+ * Debug logging shorthand
+ */
+#define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
+
+#define NODE_BASE_IP "192.168.15."
+
+#define ROUTER_BASE_IP "92.68.150."
+
+/**
+ * Handle for a plugin.
+ */
+struct Plugin
+{
+ /**
+ * Name of the shared library.
+ */
+ char *library_name;
+
+ /**
+ * Plugin API.
+ */
+ struct GNUNET_TESTING_PluginFunctions *api;
+
+ char *node_ip;
+
+ char *plugin_name;
+
+ char *global_n;
+
+ char *local_m;
+
+ char *n;
+
+ char *m;
+};
+
+struct NodeIdentifier
+{
+ char *n;
+
+ char *m;
+
+ char *global_n;
+
+ char *local_m;
+};
+
+/**
+ * Context for a single write on a chunk of memory
+ */
+struct WriteContext
+{
+ /**
+ * The data to write
+ */
+ void *data;
+
+ /**
+ * The length of the data
+ */
+ size_t length;
+
+ /**
+ * The current position from where the write operation should begin
+ */
+ size_t pos;
+};
+
+struct Plugin *plugin;
+
+/**
+ * The process handle to the testbed service
+
+static struct GNUNET_OS_Process *cmd_binary_process;*/
+
+/**
+ * Handle to the testing system
+ */
+static struct GNUNET_TESTING_System *test_system;
+
+/**
+ * Our message stream tokenizer
+ */
+struct GNUNET_MessageStreamTokenizer *tokenizer;
+
+/**
+ * Disk handle from stdin
+ */
+static struct GNUNET_DISK_FileHandle *stdin_fd;
+
+/**
+ * Disk handle for stdout
+ */
+static struct GNUNET_DISK_FileHandle *stdout_fd;
+
+/**
+ * Pipe used to communicate shutdown via signal.
+ */
+static struct GNUNET_DISK_PipeHandle *sigpipe;
+
+/**
+ * Task identifier for the read task
+ */
+static struct GNUNET_SCHEDULER_Task *read_task_id;
+
+/**
+ * Task identifier for the write task
+ */
+static struct GNUNET_SCHEDULER_Task *write_task_id;
+
+/**
+ * Task to kill the child
+ */
+static struct GNUNET_SCHEDULER_Task *child_death_task_id;
+
+/**
+ * Are we done reading messages from stdin?
+ */
+static int done_reading;
+
+/**
+ * Result to return in case we fail
+ */
+static int status;
+
+
+/**
+ * Task to shut down cleanly
+ *
+ * @param cls NULL
+ */
+static void
+shutdown_task (void *cls)
+{
+
+ LOG_DEBUG ("Shutting down.\n");
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Shutting down tokenizer!\n");
+
+ if (NULL != read_task_id)
+ {
+ GNUNET_SCHEDULER_cancel (read_task_id);
+ read_task_id = NULL;
+ }
+ if (NULL != write_task_id)
+ {
+ struct WriteContext *wc;
+
+ wc = GNUNET_SCHEDULER_cancel (write_task_id);
+ write_task_id = NULL;
+ GNUNET_free (wc->data);
+ GNUNET_free (wc);
+ }
+ if (NULL != child_death_task_id)
+ {
+ GNUNET_SCHEDULER_cancel (child_death_task_id);
+ child_death_task_id = NULL;
+ }
+ if (NULL != stdin_fd)
+ (void) GNUNET_DISK_file_close (stdin_fd);
+ if (NULL != stdout_fd)
+ (void) GNUNET_DISK_file_close (stdout_fd);
+ GNUNET_MST_destroy (tokenizer);
+ tokenizer = NULL;
+
+ if (NULL != test_system)
+ {
+ GNUNET_TESTING_system_destroy (test_system, GNUNET_YES);
+ test_system = NULL;
+ }
+}
+
+
+/**
+ * Task to write to the standard out
+ *
+ * @param cls the WriteContext
+ */
+static void
+write_task (void *cls)
+{
+ struct WriteContext *wc = cls;
+ ssize_t bytes_wrote;
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Writing data!\n");
+
+ GNUNET_assert (NULL != wc);
+ write_task_id = NULL;
+ bytes_wrote = GNUNET_DISK_file_write (stdout_fd,
+ wc->data + wc->pos,
+ wc->length - wc->pos);
+ if (GNUNET_SYSERR == bytes_wrote)
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Cannot reply back successful initialization\n");
+ GNUNET_free (wc->data);
+ GNUNET_free (wc);
+ return;
+ }
+ wc->pos += bytes_wrote;
+ if (wc->pos == wc->length)
+ {
+ GNUNET_free (wc->data);
+ GNUNET_free (wc);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Written successfully!\n");
+ return;
+ }
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Written data!\n");
+ write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+ stdout_fd,
+ &write_task,
+ wc);
+}
+
+
+/**
+ * Task triggered whenever we receive a SIGCHLD (child
+ * process died).
+ *
+ * @param cls closure, NULL if we need to self-restart
+ */
+/*static void
+child_death_task (void *cls)
+{
+ const struct GNUNET_DISK_FileHandle *pr;
+ char c[16];
+
+ pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
+ child_death_task_id = NULL;
+ // consume the signal
+ GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c)));
+ LOG_DEBUG ("Got SIGCHLD\n");
+
+ LOG_DEBUG ("Child hasn't died. Resuming to monitor its status\n");
+ child_death_task_id =
+ GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+ pr,
+ &child_death_task,
+ NULL);
+}*/
+
+
+static void
+write_message (struct GNUNET_MessageHeader *message, size_t msg_length)
+{
+ struct WriteContext *wc;
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "enter write_message!\n");
+ wc = GNUNET_new (struct WriteContext);
+ wc->length = msg_length;
+ wc->data = message;
+ write_task_id = GNUNET_SCHEDULER_add_write_file (
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ stdout_fd,
+ &write_task,
+ wc);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "leave write_message!\n");
+}
+
+
+/**
+ * Function to run the test cases.
+ *
+ * @param cls plugin to use.
+ *
+ */
+/*static void
+run_plugin (void *cls)
+{
+ struct Plugin *plugin = cls;
+ char *router_ip;
+ char *node_ip;
+
+ router_ip = GNUNET_malloc (strlen (ROUTER_BASE_IP) + strlen (plugin->m) + 1);
+ strcpy (router_ip, ROUTER_BASE_IP);
+ strcat (router_ip, plugin->m);
+
+ node_ip = GNUNET_malloc (strlen (NODE_BASE_IP) + strlen (plugin->n) + 1);
+ strcat (node_ip, NODE_BASE_IP);
+ strcat (node_ip, plugin->n);
+
+ plugin->api->start_testcase (&write_message, router_ip, node_ip);
+
+}*/
+
+
+/**
+ * Functions with this signature are called whenever a
+ * complete message is received by the tokenizer.
+ *
+ * Do not call #GNUNET_mst_destroy() in this callback
+ *
+ * @param cls identification of the client
+ * @param message the actual message
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO to stop further processing (no error)
+ * #GNUNET_SYSERR to stop further processing with error
+ */
+static int
+tokenizer_cb (void *cls, const struct GNUNET_MessageHeader *message)
+{
+ struct NodeIdentifier *ni = cls;
+ const struct GNUNET_CMDS_HelperInit *msg;
+ struct GNUNET_CMDS_HelperReply *reply;
+ char *binary;
+ char *plugin_name;
+ size_t plugin_name_size;
+ uint16_t msize;
+ size_t msg_length;
+ char *router_ip;
+ char *node_ip;
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "tokenizer \n");
+
+ msize = ntohs (message->size);
+ if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT == ntohs (message->type))
+ {
+ msg = (const struct GNUNET_CMDS_HelperInit *) message;
+ plugin_name_size = ntohs (msg->plugin_name_size);
+ if ((sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_size) > msize)
+ {
+ GNUNET_break (0);
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Received unexpected message -- exiting\n");
+ goto error;
+ }
+ plugin_name = GNUNET_malloc (plugin_name_size + 1);
+ GNUNET_strlcpy (plugin_name,
+ ((char *) &msg[1]),
+ plugin_name_size + 1);
+
+ binary = GNUNET_OS_get_libexec_binary_path ("gnunet-cmd");
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "plugin_name: %s \n",
+ plugin_name);
+
+ // cmd_binary_process = GNUNET_OS_start_process (
+ /*GNUNET_OS_INHERIT_STD_ERR verbose? ,
+ NULL,
+ NULL,
+ NULL,
+ binary,
+ plugin_name,
+ ni->global_n,
+ ni->local_m,
+ ni->n,
+ ni->m,
+ NULL);*/
+
+ plugin = GNUNET_new (struct Plugin);
+ plugin->api = GNUNET_PLUGIN_load (plugin_name,
+ NULL);
+ plugin->library_name = GNUNET_strdup (basename (plugin_name));
+
+ plugin->global_n = ni->global_n;
+ plugin->local_m = ni->local_m;
+ plugin->n = ni->n;
+ plugin->m = ni->m;
+
+ router_ip = GNUNET_malloc (strlen (ROUTER_BASE_IP) + strlen (plugin->m)
+ + 1);
+ strcpy (router_ip, ROUTER_BASE_IP);
+ strcat (router_ip, plugin->m);
+
+ node_ip = GNUNET_malloc (strlen (NODE_BASE_IP) + strlen (plugin->n) + 1);
+ strcat (node_ip, NODE_BASE_IP);
+ strcat (node_ip, plugin->n);
+
+ plugin->api->start_testcase (&write_message, router_ip, node_ip, plugin->m,
+ plugin->n, plugin->local_m);
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here!\n");
+
+ /*if (NULL == cmd_binary_process)
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Starting plugin failed!\n");
+ return GNUNET_SYSERR;
+ }*/
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 2!\n");
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "global_n: %s local_n: %s n: %s m: %s.\n",
+ ni->global_n,
+ ni->local_m,
+ ni->n,
+ ni->m);
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 3!\n");
+
+ GNUNET_free (binary);
+
+ // done_reading = GNUNET_YES;
+
+ msg_length = sizeof(struct GNUNET_CMDS_HelperReply);
+ reply = GNUNET_new (struct GNUNET_CMDS_HelperReply);
+ reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY);
+ reply->header.size = htons ((uint16_t) msg_length);
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 4!\n");
+
+ write_message ((struct GNUNET_MessageHeader *) reply, msg_length);
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 5!\n");
+
+ /*child_death_task_id = GNUNET_SCHEDULER_add_read_file (
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ),
+ &child_death_task,
+ NULL);*/
+ return GNUNET_OK;
+ }
+ else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED == ntohs (
+ message->type))
+ {
+ plugin->api->all_peers_started ();
+ return GNUNET_OK;
+ }
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n");
+ goto error;
+ }
+
+
+ error:
+ status = GNUNET_SYSERR;
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "tokenizer shutting down!\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Task to read from stdin
+ *
+ * @param cls NULL
+ */
+static void
+read_task (void *cls)
+{
+ char buf[GNUNET_MAX_MESSAGE_SIZE];
+ ssize_t sread;
+
+ read_task_id = NULL;
+ sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof(buf));
+ if ((GNUNET_SYSERR == sread) || (0 == sread))
+ {
+ LOG_DEBUG ("STDIN closed\n");
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "tokenizer shutting down during reading!\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_YES == done_reading)
+ {
+ /* didn't expect any more data! */
+ GNUNET_break_op (0);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "tokenizer shutting down during reading, didn't expect any more data!\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ LOG_DEBUG ("Read %u bytes\n", (unsigned int) sread);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Read %u bytes\n", (unsigned int) sread);
+ /* FIXME: could introduce a GNUNET_MST_read2 to read
+ directly from 'stdin_fd' and save a memcpy() here */
+ if (GNUNET_OK !=
+ GNUNET_MST_from_buffer (tokenizer, buf, sread, GNUNET_NO, GNUNET_NO))
+ {
+ GNUNET_break (0);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "tokenizer shutting down during reading, writing to buffer failed!\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ read_task_id /* No timeout while reading */
+ = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+ stdin_fd,
+ &read_task,
+ NULL);
+}
+
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct NodeIdentifier *ni = cls;
+
+ LOG_DEBUG ("Starting interpreter loop helper...\n");
+
+ tokenizer = GNUNET_MST_create (&tokenizer_cb, ni);
+ stdin_fd = GNUNET_DISK_get_handle_from_native (stdin);
+ stdout_fd = GNUNET_DISK_get_handle_from_native (stdout);
+ read_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+ stdin_fd,
+ &read_task,
+ NULL);
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+}
+
+
+/**
+ * Signal handler called for SIGCHLD.
+ */
+static void
+sighandler_child_death ()
+{
+ static char c;
+ int old_errno; /* back-up errno */
+
+ old_errno = errno;
+ GNUNET_break (
+ 1 ==
+ GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe,
+ GNUNET_DISK_PIPE_END_WRITE),
+ &c,
+ sizeof(c)));
+ errno = old_errno;
+}
+
+
+/**
+ * Main function
+ *
+ * @param argc the number of command line arguments
+ * @param argv command line arg array
+ * @return return code
+ */
+int
+main (int argc, char **argv)
+{
+ struct NodeIdentifier *ni;
+ struct GNUNET_SIGNAL_Context *shc_chld;
+ struct GNUNET_GETOPT_CommandLineOption options[] =
+ { GNUNET_GETOPT_OPTION_END };
+ int ret;
+
+ GNUNET_log_setup ("gnunet-cmds-helper",
+ "DEBUG",
+ NULL);
+ ni = GNUNET_new (struct NodeIdentifier);
+ ni->global_n = argv[1];
+ ni->local_m = argv[2];
+ ni->n = argv[3];
+ ni->m = argv[4];
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "global_n: %s local_n: %s n: %s m: %s.\n",
+ ni->global_n,
+ ni->local_m,
+ ni->n,
+ ni->m);
+
+ status = GNUNET_OK;
+ if (NULL ==
+ (sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE)))
+ {
+ GNUNET_break (0);
+ return 1;
+ }
+ shc_chld =
+ GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
+ ret = GNUNET_PROGRAM_run (argc,
+ argv,
+ "gnunet-cmds-helper",
+ "Helper for starting a local interpreter loop",
+ options,
+ &run,
+ ni);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "run finished\n");
+ GNUNET_SIGNAL_handler_uninstall (shc_chld);
+ shc_chld = NULL;
+ GNUNET_DISK_pipe_close (sigpipe);
+ GNUNET_free (ni);
+ if (GNUNET_OK != ret)
+ return 1;
+ return (GNUNET_OK == status) ? 0 : 1;
+}
+
+
+/* end of gnunet-cmds-helper.c */
diff --git a/src/testing/test_testing_api_cmd_netjail.c b/src/testing/test_testing_api_cmd_netjail.c
new file mode 100644
index 000000000..543642109
--- /dev/null
+++ b/src/testing/test_testing_api_cmd_netjail.c
@@ -0,0 +1,79 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/test_testbed_api_cmd_netjail.c
+ * @brief Test case executing a script in a network name space.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_testing_ng_lib.h"
+#include "gnunet_util_lib.h"
+
+
+/**
+ * Main function to run the test cases.
+ *
+ * @param cls not used.
+ *
+ */
+static void
+run (void *cls)
+{
+ struct GNUNET_TESTING_Command commands[] = {
+ GNUNET_TESTING_cmd_netjail_start ("netjail-start-1",
+ "2",
+ "2"),
+ GNUNET_TESTING_cmd_netjail_start_testing_system ("netjail-start-testbed-1",
+ "2",
+ "2",
+ "libgnunet_plugin_testcmd"),
+ GNUNET_TESTING_cmd_stop_testing_system ("stop-testbed",
+ "netjail-start-testbed-1",
+ "2",
+ "2"),
+ GNUNET_TESTING_cmd_netjail_stop ("netjail-stop-1",
+ "2",
+ "2"),
+ GNUNET_TESTING_cmd_end ()
+ };
+
+ GNUNET_TESTING_run (NULL,
+ commands,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
+
+int
+main (int argc,
+ char *const *argv)
+{
+ int rv = 0;
+
+ GNUNET_log_setup ("test-netjail",
+ "DEBUG",
+ NULL);
+ GNUNET_SCHEDULER_run (&run,
+ NULL);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Test finished!\n");
+ return rv;
+}
diff --git a/src/testing/test_testing_plugin_testcmd.c b/src/testing/test_testing_plugin_testcmd.c
new file mode 100644
index 000000000..aeb0db5dc
--- /dev/null
+++ b/src/testing/test_testing_plugin_testcmd.c
@@ -0,0 +1,116 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2013, 2014 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 testbed/plugin_testcmd.c
+ * @brief a plugin to provide the API for running test cases.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_testing_ng_lib.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testing_ng_lib.h"
+
+/**
+ * Generic logging shortcut
+ */
+#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
+
+unsigned int are_all_peers_started;
+
+static void
+all_peers_started ()
+{
+ are_all_peers_started = GNUNET_YES;
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "setting are_all_peers_started: %d\n",
+ are_all_peers_started);
+}
+
+static void
+start_testcase (TESTING_CMD_HELPER_write_cb write_message, char *router_ip,
+ char *node_ip,
+ char *n,
+ char *m,
+ char *local_m)
+{
+ struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 6!\n");
+
+ are_all_peers_started = GNUNET_NO;
+
+ struct GNUNET_TESTING_Command commands[] = {
+ GNUNET_TESTING_cmd_hello_world_birth ("hello-world-birth-0",
+ &now),
+ GNUNET_TESTING_cmd_hello_world ("hello-world-0","hello-world-birth-0",""),
+ GNUNET_TESTING_cmd_send_peer_ready ("send-peer-ready-1",
+ write_message),
+ GNUNET_TESTING_cmd_block_until_all_peers_started ("block-1",
+ &are_all_peers_started),
+ GNUNET_TESTING_cmd_local_test_finished ("local-test-finished-1",
+ write_message)
+ };
+
+ GNUNET_TESTING_run (NULL,
+ commands,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 7!\n");
+
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls NULL
+ * @return the exported block API
+ */
+void *
+libgnunet_plugin_testcmd_init (void *cls)
+{
+ struct GNUNET_TESTING_PluginFunctions *api;
+
+ api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions);
+ api->start_testcase = &start_testcase;
+ api->all_peers_started = &all_peers_started;
+ return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the return value from #libgnunet_plugin_block_test_init
+ * @return NULL
+ */
+void *
+libgnunet_plugin_testcmd_done (void *cls)
+{
+ struct GNUNET_TESTING_PluginFunctions *api = cls;
+
+ GNUNET_free (api);
+ return NULL;
+}
+
+
+/* end of plugin_testcmd.c */
diff --git a/src/testing/testing_api_cmd_block_until_all_peers_started.c b/src/testing/testing_api_cmd_block_until_all_peers_started.c
new file mode 100644
index 000000000..8659fbb46
--- /dev/null
+++ b/src/testing/testing_api_cmd_block_until_all_peers_started.c
@@ -0,0 +1,128 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing_api_cmd_block_until_all_peers_started.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"
+
+/**
+ * Generic logging shortcut
+ */
+#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
+
+struct BlockState
+{
+ unsigned int *all_peers_started;
+};
+
+
+static int
+block_until_all_peers_started_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ return GNUNET_OK;
+}
+
+
+static void
+block_until_all_peers_started_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+ struct BlockState *bs = cls;
+
+ GNUNET_free (bs);
+}
+
+
+static void
+block_until_all_peers_started_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "block_until_all_peers_started_run!\n");
+}
+
+
+static int
+block_until_all_peers_started_finish (void *cls,
+ GNUNET_SCHEDULER_TaskCallback cont,
+ void *cont_cls)
+{
+ struct BlockState *bs = cls;
+ unsigned int *ret = bs->all_peers_started;
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 10\n");
+
+ if (GNUNET_YES == *ret)
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We do not need to block anymore!\n");
+ cont (cont_cls);
+ }
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "You shall not pass!\n");
+ }
+
+ return *ret;
+}
+
+
+/**
+ * Create command.
+ *
+ * @param label name for command.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_block_until_all_peers_started (const char *label,
+ unsigned int *
+ all_peers_started)
+{
+ struct BlockState *bs;
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "we have all_peers_started: %u\n",
+ *all_peers_started);
+
+ bs = GNUNET_new (struct BlockState);
+ bs->all_peers_started = all_peers_started;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = bs,
+ .label = label,
+ .run = &block_until_all_peers_started_run,
+ .finish = &block_until_all_peers_started_finish,
+ .cleanup = &block_until_all_peers_started_cleanup,
+ .traits = &block_until_all_peers_started_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/testing_api_cmd_local_test_finished.c b/src/testing/testing_api_cmd_local_test_finished.c
new file mode 100644
index 000000000..5b74d4e04
--- /dev/null
+++ b/src/testing/testing_api_cmd_local_test_finished.c
@@ -0,0 +1,131 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing_api_cmd_block_until_all_peers_started.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"
+#include "testing_cmds.h"
+
+/**
+ * Generic logging shortcut
+ */
+#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
+
+struct LocalFinishedState
+{
+ TESTING_CMD_HELPER_write_cb write_message;
+
+ struct GNUNET_CMDS_LOCAL_FINISHED *reply;
+};
+
+
+static int
+local_test_finished_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ return GNUNET_OK;
+}
+
+
+static void
+local_test_finished_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+ struct LocalFinishedState *lfs = cls;
+
+ GNUNET_free (lfs->reply);
+ GNUNET_free (lfs);
+}
+
+
+static void
+local_test_finished_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ struct LocalFinishedState *lfs = cls;
+
+ struct GNUNET_CMDS_LOCAL_FINISHED *reply;
+ size_t msg_length;
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 12!\n");
+
+ msg_length = sizeof(struct GNUNET_CMDS_LOCAL_FINISHED);
+ reply = GNUNET_new (struct GNUNET_CMDS_LOCAL_FINISHED);
+ reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED);
+ reply->header.size = htons ((uint16_t) msg_length);
+ lfs->reply = reply;
+ lfs->write_message ((struct GNUNET_MessageHeader *) reply, msg_length);
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 13!\n");
+}
+
+
+static int
+local_test_finished_finish (void *cls,
+ GNUNET_SCHEDULER_TaskCallback cont,
+ void *cont_cls)
+{
+ // This will stop the local loop without shutting down the scheduler, because we do not call the continuation, which is the interpreter_next method.
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Stopping local loop\n");
+ return GNUNET_YES;
+}
+
+
+/**
+ * Create command.
+ *
+ * @param label name for command.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_local_test_finished (const char *label,
+ TESTING_CMD_HELPER_write_cb
+ write_message)
+{
+ struct LocalFinishedState *lfs;
+
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "We got here 11!\n");
+
+ lfs = GNUNET_new (struct LocalFinishedState);
+ lfs->write_message = write_message;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = lfs,
+ .label = label,
+ .run = &local_test_finished_run,
+ .finish = &local_test_finished_finish,
+ .cleanup = &local_test_finished_cleanup,
+ .traits = &local_test_finished_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/testing_api_cmd_netjail_start.c b/src/testing/testing_api_cmd_netjail_start.c
new file mode 100644
index 000000000..c82392a08
--- /dev/null
+++ b/src/testing/testing_api_cmd_netjail_start.c
@@ -0,0 +1,217 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/testing_api_cmd_hello_world.c
+ * @brief Command to start the netjail script.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testing_ng_lib.h"
+
+#define NETJAIL_START_SCRIPT "./../testing/netjail_start.sh"
+
+struct NetJailState
+{
+ struct GNUNET_ChildWaitHandle *cwh;
+
+ char *local_m;
+
+ char *global_n;
+
+ /**
+ * The process id of the start script.
+ */
+ struct GNUNET_OS_Process *start_proc;
+
+ unsigned int finished;
+};
+
+
+/**
+*
+*
+* @param cls closure
+* @param cmd current CMD being cleaned up.
+*/
+static void
+netjail_start_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+ struct NetJailState *ns = cls;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "netjail_start_cleanup!\n");
+
+ if (NULL != ns->cwh)
+ {
+ GNUNET_wait_child_cancel (ns->cwh);
+ ns->cwh = NULL;
+ }
+ if (NULL != ns->start_proc)
+ {
+ GNUNET_assert (0 ==
+ GNUNET_OS_process_kill (ns->start_proc,
+ SIGKILL));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_OS_process_wait (ns->start_proc));
+ GNUNET_OS_process_destroy (ns->start_proc);
+ ns->start_proc = NULL;
+ }
+ GNUNET_free (ns);
+}
+
+
+/**
+*
+*
+* @param cls closure.
+* @param[out] ret result
+* @param trait name of the trait.
+* @param index index number of the object to offer.
+* @return #GNUNET_OK on success.
+*/
+static int
+netjail_start_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ return GNUNET_OK;
+}
+
+static void
+child_completed_callback (void *cls,
+ enum GNUNET_OS_ProcessStatusType type,
+ long unsigned int exit_code)
+{
+ struct NetJailState *ns = cls;
+
+ if (0 == exit_code)
+ {
+ ns->finished = GNUNET_YES;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Child completed with an error!\n");
+ ns->finished = GNUNET_SYSERR;
+ }
+ GNUNET_OS_process_destroy (ns->start_proc);
+ ns->start_proc = NULL;
+}
+
+
+
+/**
+* Run the "hello world" CMD.
+*
+* @param cls closure.
+* @param cmd CMD being run.
+* @param is interpreter state.
+*/
+static void
+netjail_start_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ struct NetJailState *ns = cls;
+ char *const script_argv[] = {NETJAIL_START_SCRIPT,
+ ns->local_m,
+ ns->global_n,
+ NULL};
+ unsigned int helper_check = GNUNET_OS_check_helper_binary (
+ NETJAIL_START_SCRIPT,
+ GNUNET_YES,
+ NULL);
+
+ if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No SUID for %s!\n",
+ NETJAIL_START_SCRIPT);
+ GNUNET_TESTING_interpreter_fail ();
+ }
+ else if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%s not found!\n",
+ NETJAIL_START_SCRIPT);
+ GNUNET_TESTING_interpreter_fail ();
+ }
+
+ ns->start_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
+ NULL,
+ NULL,
+ NULL,
+ NETJAIL_START_SCRIPT,
+ script_argv);
+
+ ns->cwh = GNUNET_wait_child (ns->start_proc,
+ &child_completed_callback,
+ ns);
+ GNUNET_break (NULL != ns->cwh);
+}
+
+static int
+netjail_start_finish (void *cls,
+ GNUNET_SCHEDULER_TaskCallback cont,
+ void *cont_cls)
+{
+ struct NetJailState *ns = cls;
+
+ if (ns->finished)
+ {
+ cont (cont_cls);
+ }
+ return ns->finished;
+}
+
+/**
+ * Create command.
+ *
+ * @param label name for command.
+ * @param binaryname to start.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_netjail_start (const char *label,
+ char *local_m,
+ char *global_n)
+{
+ struct NetJailState *ns;
+
+ ns = GNUNET_new (struct NetJailState);
+ ns->local_m = local_m;
+ ns->global_n = global_n;
+ ns->finished = GNUNET_NO;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = ns,
+ .label = label,
+ .run = &netjail_start_run,
+ .finish = &netjail_start_finish,
+ .cleanup = &netjail_start_cleanup,
+ .traits = &netjail_start_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/testing_api_cmd_netjail_start_testsystem.c b/src/testing/testing_api_cmd_netjail_start_testsystem.c
new file mode 100644
index 000000000..5c2f71168
--- /dev/null
+++ b/src/testing/testing_api_cmd_netjail_start_testsystem.c
@@ -0,0 +1,541 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/testing_api_cmd_hello_world.c
+ * @brief Command to start the netjail peers.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_testing_ng_lib.h"
+#include "testing_cmds.h"
+
+#define NETJAIL_EXEC_SCRIPT "./../testing/netjail_exec.sh"
+
+struct HelperMessage;
+
+struct HelperMessage
+{
+
+ struct HelperMessage *next;
+
+ struct HelperMessage *prev;
+
+ /**
+ * Size of the original message.
+ */
+ uint16_t bytes_msg;
+
+ /* Followed by @e bytes_msg of msg.*/
+};
+
+
+
+struct NetJailState
+{
+
+ unsigned int *rv;
+
+ struct HelperMessage *hp_messages_head;
+
+ struct HelperMessage *hp_messages_tail;
+
+ /**
+ * The process handle
+ */
+ struct GNUNET_HELPER_Handle **helper;
+
+ unsigned int n_helper;
+
+ char *binary_name;
+
+ char *local_m;
+
+ char *global_n;
+
+ /**
+ * The send handle for the helper
+ */
+ struct GNUNET_HELPER_SendHandle **shandle;
+
+ unsigned int n_shandle;
+
+ /**
+ * The message corresponding to send handle
+ */
+ struct GNUNET_MessageHeader **msg;
+
+ unsigned int n_msg;
+
+ unsigned int number_of_testsystems_started;
+
+ unsigned int number_of_peers_started;
+
+ unsigned int number_of_local_test_finished;
+
+ char *plugin_name;
+};
+
+struct TestingSystemCount
+{
+ unsigned int count;
+
+ struct NetJailState *ns;
+};
+
+/**
+*
+*
+* @param cls closure
+* @param cmd current CMD being cleaned up.
+*/
+static void
+netjail_exec_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+ struct NetJailState *ns = cls;
+
+ GNUNET_free (ns->binary_name);
+}
+
+
+/**
+*
+*
+* @param cls closure.
+* @param[out] ret result
+* @param trait name of the trait.
+* @param index index number of the object to offer.
+* @return #GNUNET_OK on success.
+*/
+static int
+netjail_exec_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ struct NetJailState *ns = cls;
+ struct GNUNET_HELPER_Handle **helper = ns->helper;
+ struct HelperMessage *hp_messages_head = ns->hp_messages_head;
+
+
+ struct GNUNET_TESTING_Trait traits[] = {
+ {
+ .index = 0,
+ .trait_name = "helper_handles",
+ .ptr = (const void *) helper,
+ },
+ {
+ .index = 1,
+ .trait_name = "hp_msgs_head",
+ .ptr = (const void *) hp_messages_head,
+ },
+ GNUNET_TESTING_trait_end ()
+ };
+
+ return GNUNET_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+}
+
+
+/**
+ * Offer handles to testing cmd helper from trait
+ *
+ * @param cmd command to extract the message from.
+ * @param pt pointer to message.
+ * @return #GNUNET_OK on success.
+ */
+int
+GNUNET_TESTING_get_trait_helper_handles (const struct
+ GNUNET_TESTING_Command *cmd,
+ struct GNUNET_HELPER_Handle ***helper)
+{
+ return cmd->traits (cmd->cls,
+ (const void **) helper,
+ "helper_handles",
+ (unsigned int) 0);
+}
+
+/**
+ * Offer messages received via testing cmd helper from trait
+ *
+ * @param cmd command to extract the message from.
+ * @param pt pointer to message.
+ * @return #GNUNET_OK on success.
+ */
+int
+GNUNET_TESTING_get_trait_helper_messages (const struct
+ GNUNET_TESTING_Command *cmd,
+ struct HelperMessage ***
+ hp_messages_head)
+{
+ return cmd->traits (cmd->cls,
+ (const void **) hp_messages_head,
+ "hp_msgs_head",
+ (unsigned int) 1);
+}
+
+
+/**
+ * Continuation function from GNUNET_HELPER_send()
+ *
+ * @param cls closure
+ * @param result GNUNET_OK on success,
+ * GNUNET_NO if helper process died
+ * GNUNET_SYSERR during GNUNET_HELPER_stop
+ */
+static void
+clear_msg (void *cls, int result)
+{
+ struct TestingSystemCount *tbc = cls;
+ struct NetJailState *ns = tbc->ns;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "clear_msg tbc->count: %d\n",
+ tbc->count);
+ GNUNET_assert (NULL != ns->shandle[tbc->count - 1]);
+ ns->shandle[tbc->count - 1] = NULL;
+ GNUNET_free (ns->msg[tbc->count - 1]);
+ ns->msg[tbc->count - 1] = NULL;
+}
+
+
+/**
+ * Functions with this signature are called whenever a
+ * complete message is received by the tokenizer.
+ *
+ * Do not call GNUNET_SERVER_mst_destroy in callback
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ *
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
+ */
+static int
+helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
+{
+ struct TestingSystemCount *tbc = cls;
+ struct NetJailState *ns = tbc->ns;
+ struct HelperMessage *hp_msg;
+
+ if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY == ntohs (message->type))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "helper_mst tbc->count: %d\n",
+ tbc->count);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received message from helper.\n");
+ ns->number_of_testsystems_started++;
+ }
+ else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED == ntohs (
+ message->type))
+ {
+ ns->number_of_peers_started++;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "number_of_peers_started: %d\n",
+ ns->number_of_peers_started);
+ }
+ else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED == ntohs (
+ message->type))
+ {
+ ns->number_of_local_test_finished++;
+ }
+ else
+ {
+ hp_msg = GNUNET_new (struct HelperMessage);
+ hp_msg->bytes_msg = message->size;
+ memcpy (&hp_msg[1], message, message->size);
+ GNUNET_CONTAINER_DLL_insert (ns->hp_messages_head, ns->hp_messages_tail,
+ hp_msg);
+ }
+
+ return GNUNET_OK;
+}
+
+
+static void
+exp_cb (void *cls)
+{
+ struct NetJailState *ns = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
+ *ns->rv = 1;
+}
+
+
+static struct GNUNET_CMDS_HelperInit *
+create_helper_init_msg_ (char *m_char,
+ char *n_char,
+ const char *plugin_name)
+{
+ struct GNUNET_CMDS_HelperInit *msg;
+ uint16_t plugin_name_len;
+ uint16_t msg_size;
+
+ GNUNET_assert (NULL != plugin_name);
+ plugin_name_len = strlen (plugin_name);
+ msg_size = sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_len;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "msg_size: %d \n",
+ msg_size);
+ msg = GNUNET_malloc (msg_size);
+ msg->header.size = htons (msg_size);
+ msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT);
+ msg->plugin_name_size = htons (plugin_name_len);
+ GNUNET_memcpy ((char *) &msg[1],
+ plugin_name,
+ plugin_name_len);
+ return msg;
+}
+
+
+static void
+start_helper (struct NetJailState *ns, struct
+ GNUNET_CONFIGURATION_Handle *config,
+ char *m_char,
+ char *n_char)
+{
+ // struct GNUNET_CONFIGURATION_Handle *cfg;
+ struct GNUNET_CMDS_HelperInit *msg;
+ struct TestingSystemCount *tbc;
+ char *const script_argv[] = {NETJAIL_EXEC_SCRIPT,
+ m_char,
+ n_char,
+ GNUNET_OS_get_libexec_binary_path (
+ HELPER_CMDS_BINARY),
+ ns->global_n,
+ ns->local_m,
+ NULL};
+ unsigned int m = atoi (m_char);
+ unsigned int n = atoi (n_char);
+ unsigned int helper_check = GNUNET_OS_check_helper_binary (
+ NETJAIL_EXEC_SCRIPT,
+ GNUNET_YES,
+ NULL);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "m: %d n: %d\n",
+ m,
+ n);
+
+ tbc = GNUNET_new (struct TestingSystemCount);
+ tbc->ns = ns;
+ tbc->count = (n - 1) * atoi (ns->local_m) + m;
+
+
+ if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No SUID for %s!\n",
+ NETJAIL_EXEC_SCRIPT);
+ *ns->rv = 1;
+ }
+ else if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%s not found!\n",
+ NETJAIL_EXEC_SCRIPT);
+ *ns->rv = 1;
+ }
+
+ GNUNET_array_append (ns->helper, ns->n_helper, GNUNET_HELPER_start (
+ GNUNET_YES,
+ NETJAIL_EXEC_SCRIPT,
+ script_argv,
+ &helper_mst,
+ &exp_cb,
+ tbc));
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "First using helper %d %d\n",
+ tbc->count - 1,
+ ns->n_helper);
+ struct GNUNET_HELPER_Handle *helper = ns->helper[tbc->count - 1];
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "First using helper %d %d %p\n",
+ tbc->count - 1,
+ ns->n_helper,
+ helper);
+
+ msg = create_helper_init_msg_ (m_char,
+ n_char,
+ ns->plugin_name);
+ GNUNET_array_append (ns->msg, ns->n_msg, &msg->header);
+
+ GNUNET_array_append (ns->shandle, ns->n_shandle, GNUNET_HELPER_send (
+ helper,
+ &msg->header,
+ GNUNET_NO,
+ &clear_msg,
+ tbc));
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Message %d send!\n",
+ tbc->count);
+
+ if (NULL == ns->shandle[tbc->count - 1])
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Send handle is NULL!\n");
+ GNUNET_free (msg);
+ *ns->rv = 1;
+ }
+}
+
+
+/**
+* Run the "hello world" CMD.
+*
+* @param cls closure.
+* @param cmd CMD being run.
+* @param is interpreter state.
+*/
+static void
+netjail_exec_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ char str_m[12];
+ char str_n[12];
+ struct NetJailState *ns = cls;
+ struct GNUNET_CONFIGURATION_Handle *config =
+ GNUNET_CONFIGURATION_create ();
+
+ for (int i = 1; i <= atoi (ns->global_n); i++) {
+ for (int j = 1; j <= atoi (ns->local_m); j++)
+ {
+ sprintf (str_n, "%d", i);
+ sprintf (str_m, "%d", j);
+ start_helper (ns, config,
+ str_m,
+ str_n);
+ }
+ }
+}
+
+
+static int
+netjail_start_finish (void *cls,
+ GNUNET_SCHEDULER_TaskCallback cont,
+ void *cont_cls)
+{
+ unsigned int ret = GNUNET_NO;
+ struct NetJailState *ns = cls;
+ unsigned int total_number = atoi (ns->local_m) * atoi (ns->global_n);
+ struct GNUNET_CMDS_ALL_PEERS_STARTED *reply;
+ size_t msg_length;
+ struct GNUNET_HELPER_Handle *helper;
+ struct TestingSystemCount *tbc;
+
+ if (ns->number_of_local_test_finished == total_number)
+ {
+ ret = GNUNET_YES;
+ cont (cont_cls);
+ }
+
+ if (ns->number_of_testsystems_started == total_number)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "All helpers started!\n");
+ ns->number_of_testsystems_started = 0;
+ }
+
+ if (ns->number_of_peers_started == total_number)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "All peers started!\n");
+
+ for (int i = 1; i <= atoi (ns->global_n); i++) {
+ for (int j = 1; j <= atoi (ns->local_m); j++)
+ {
+ tbc = GNUNET_new (struct TestingSystemCount);
+ tbc->ns = ns;
+ // TODO This needs to be more generic. As we send more messages back and forth, we can not grow the arrays again and again, because this is to error prone.
+ tbc->count = (i - 1) * atoi (ns->local_m) + j + total_number;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Second using helper %d %d %d\n",
+ tbc->count - 1 - total_number,
+ i,
+ j);
+ helper = ns->helper[tbc->count - 1 - total_number];
+ msg_length = sizeof(struct GNUNET_CMDS_ALL_PEERS_STARTED);
+ reply = GNUNET_new (struct GNUNET_CMDS_ALL_PEERS_STARTED);
+ reply->header.type = htons (
+ GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
+ reply->header.size = htons ((uint16_t) msg_length);
+
+ GNUNET_array_append (ns->msg, ns->n_msg, &reply->header);
+
+ struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
+ helper,
+ &reply->header,
+ GNUNET_NO,
+ &clear_msg,
+ tbc);
+
+ GNUNET_array_append (ns->shandle, ns->n_shandle, sh);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "All peers started message %d send!\n",
+ tbc->count);
+ }
+ }
+ ns->number_of_peers_started = 0;
+ }
+ return ret;
+}
+
+
+/**
+ * Create command.
+ *
+ * @param label name for command.
+ * @param binaryname to exec.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_netjail_start_testing_system (const char *label,
+ char *local_m,
+ char *global_n,
+ char *plugin_name,
+ unsigned int *rv)
+{
+ struct NetJailState *ns;
+
+ ns = GNUNET_new (struct NetJailState);
+ ns->local_m = local_m;
+ ns->global_n = global_n;
+ ns->plugin_name = plugin_name;
+ ns->rv = rv;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = ns,
+ .label = label,
+ .run = &netjail_exec_run,
+ .finish = &netjail_start_finish,
+ .cleanup = &netjail_exec_cleanup,
+ .traits = &netjail_exec_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/testing_api_cmd_netjail_stop.c b/src/testing/testing_api_cmd_netjail_stop.c
new file mode 100644
index 000000000..710b4fbf4
--- /dev/null
+++ b/src/testing/testing_api_cmd_netjail_stop.c
@@ -0,0 +1,215 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/testing_api_cmd_hello_world.c
+ * @brief Command to stop the netjail script.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testing_ng_lib.h"
+
+
+#define NETJAIL_STOP_SCRIPT "./../testing/netjail_stop.sh"
+
+struct GNUNET_ChildWaitHandle *cwh;
+
+struct NetJailState
+{
+ char *local_m;
+
+ char *global_n;
+
+ /**
+ * The process id of the start script.
+ */
+ struct GNUNET_OS_Process *stop_proc;
+
+ unsigned int finished;
+};
+
+
+/**
+*
+*
+* @param cls closure
+* @param cmd current CMD being cleaned up.
+*/
+static void
+netjail_stop_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+ struct NetJailState *ns = cls;
+
+ if (NULL != cwh)
+ {
+ GNUNET_wait_child_cancel (cwh);
+ cwh = NULL;
+ }
+ if (NULL != ns->stop_proc)
+ {
+ GNUNET_assert (0 ==
+ GNUNET_OS_process_kill (ns->stop_proc,
+ SIGKILL));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_OS_process_wait (ns->stop_proc));
+ GNUNET_OS_process_destroy (ns->stop_proc);
+ ns->stop_proc = NULL;
+ }
+}
+
+
+/**
+*
+*
+* @param cls closure.
+* @param[out] ret result
+* @param trait name of the trait.
+* @param index index number of the object to offer.
+* @return #GNUNET_OK on success.
+*/
+static int
+netjail_stop_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ return GNUNET_OK;
+}
+
+
+static void
+child_completed_callback (void *cls,
+ enum GNUNET_OS_ProcessStatusType type,
+ long unsigned int exit_code)
+{
+ struct NetJailState *ns = cls;
+
+ cwh = NULL;
+ if (0 == exit_code)
+ {
+ ns->finished = GNUNET_YES;
+ }
+ else
+ {
+ ns->finished = GNUNET_SYSERR;
+ }
+ GNUNET_OS_process_destroy (ns->stop_proc);
+ ns->stop_proc = NULL;
+}
+
+
+/**
+* Run the "hello world" CMD.
+*
+* @param cls closure.
+* @param cmd CMD being run.
+* @param is interpreter state.
+*/
+static void
+netjail_stop_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ struct NetJailState *ns = cls;
+ char *const script_argv[] = {NETJAIL_STOP_SCRIPT,
+ ns->local_m,
+ ns->global_n,
+ NULL};
+ unsigned int helper_check = GNUNET_OS_check_helper_binary (
+ NETJAIL_STOP_SCRIPT,
+ GNUNET_YES,
+ NULL);
+
+ if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No SUID for %s!\n",
+ NETJAIL_STOP_SCRIPT);
+ GNUNET_TESTING_interpreter_fail ();
+ }
+ else if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%s not found!\n",
+ NETJAIL_STOP_SCRIPT);
+ GNUNET_TESTING_interpreter_fail ();
+ }
+
+ ns->stop_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
+ NULL,
+ NULL,
+ NULL,
+ NETJAIL_STOP_SCRIPT,
+ script_argv);
+
+ cwh = GNUNET_wait_child (ns->stop_proc,
+ &child_completed_callback,
+ ns);
+ GNUNET_break (NULL != cwh);
+
+}
+
+
+static int
+netjail_stop_finish (void *cls,
+ GNUNET_SCHEDULER_TaskCallback cont,
+ void *cont_cls)
+{
+ struct NetJailState *ns = cls;
+
+ if (ns->finished)
+ {
+ cont (cont_cls);
+ }
+ return ns->finished;
+}
+
+
+/**
+ * Create command.
+ *
+ * @param label name for command.
+ * @param binaryname to stop.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_netjail_stop (const char *label,
+ char *local_m,
+ char *global_n)
+{
+ struct NetJailState *ns;
+
+ ns = GNUNET_new (struct NetJailState);
+ ns->local_m = local_m;
+ ns->global_n = global_n;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = ns,
+ .label = label,
+ .run = &netjail_stop_run,
+ .finish = &netjail_stop_finish,
+ .cleanup = &netjail_stop_cleanup,
+ .traits = &netjail_stop_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/testing_api_cmd_netjail_stop_testsystem.c b/src/testing/testing_api_cmd_netjail_stop_testsystem.c
new file mode 100644
index 000000000..bed9f3ebf
--- /dev/null
+++ b/src/testing/testing_api_cmd_netjail_stop_testsystem.c
@@ -0,0 +1,141 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/testing_api_cmd_hello_world.c
+ * @brief Command to start the netjail peers.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_testing_ng_lib.h"
+#include "testing_cmds.h"
+
+
+struct StopHelperState
+{
+
+ const char *helper_start_label;
+
+ /**
+ * The process handle
+ */
+ struct GNUNET_HELPER_Handle **helper;
+
+ char *local_m;
+
+ char *global_n;
+};
+
+
+/**
+*
+*
+* @param cls closure
+* @param cmd current CMD being cleaned up.
+*/
+static void
+stop_testing_system_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+
+}
+
+
+/**
+*
+*
+* @param cls closure.
+* @param[out] ret result
+* @param trait name of the trait.
+* @param index index number of the object to offer.
+* @return #GNUNET_OK on success.
+*/
+static int
+stop_testing_system_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ return GNUNET_OK;
+}
+
+
+/**
+* Run the "hello world" CMD.
+*
+* @param cls closure.
+* @param cmd CMD being run.
+* @param is interpreter state.
+*/
+static void
+stop_testing_system_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ struct StopHelperState *shs = cls;
+ struct GNUNET_HELPER_Handle **helper;
+ const struct GNUNET_TESTING_Command *start_helper_cmd;
+
+ start_helper_cmd = GNUNET_TESTING_interpreter_lookup_command (
+ shs->helper_start_label);
+ GNUNET_TESTING_get_trait_helper_handles (start_helper_cmd,
+ &helper);
+
+ for (int i = 1; i <= atoi (shs->global_n); i++) {
+ for (int j = 1; j <= atoi (shs->local_m); j++)
+ {
+ GNUNET_HELPER_stop (helper[(i - 1) * atoi (shs->local_m) + j - 1],
+ GNUNET_YES);
+ }
+ }
+}
+
+
+/**
+ * Create command.
+ *
+ * @param label name for command.
+ * @param binaryname to exec.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_stop_testing_system (const char *label,
+ const char *helper_start_label,
+ char *local_m,
+ char *global_n
+ )
+{
+ struct StopHelperState *shs;
+
+ shs = GNUNET_new (struct StopHelperState);
+ shs->helper_start_label = helper_start_label;
+ shs->local_m = local_m;
+ shs->global_n = global_n;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = shs,
+ .label = label,
+ .run = &stop_testing_system_run,
+ .cleanup = &stop_testing_system_cleanup,
+ .traits = &stop_testing_system_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/testing_api_cmd_send_peer_ready.c b/src/testing/testing_api_cmd_send_peer_ready.c
index e5e004924..afe28de77 100644
--- a/src/testing/testing_api_cmd_send_peer_ready.c
+++ b/src/testing/testing_api_cmd_send_peer_ready.c
@@ -26,8 +26,7 @@
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_testing_ng_lib.h"
-#include "testbed_api.h"
-#include "testbed_helper.h"
+#include "testing_cmds.h"
struct SendPeerReadyState
@@ -68,7 +67,7 @@ send_peer_ready_run (void *cls,
struct GNUNET_CMDS_PEER_STARTED *reply;
size_t msg_length;
- msg_length = sizeof(struct GNUNET_CMDS_HelperInit);// GNUNET_CMDS_PEER_STARTED);
+ msg_length = sizeof(struct GNUNET_CMDS_PEER_STARTED);
reply = GNUNET_new (struct GNUNET_CMDS_PEER_STARTED);
reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED);
reply->header.size = htons ((uint16_t) msg_length);
diff --git a/src/testing/testing_cmds.h b/src/testing/testing_cmds.h
new file mode 100644
index 000000000..7a5860aea
--- /dev/null
+++ b/src/testing/testing_cmds.h
@@ -0,0 +1,90 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/testing_cmds.h
+ * @brief Message formats for communication between testing cmds helper and testcase plugins.
+ * @author t3sserakt
+ */
+
+#ifndef TESTING_CMDS_H
+#define TESTING_CMDS_H
+
+#define HELPER_CMDS_BINARY "gnunet-cmds-helper"
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Initialization message for gnunet-cmds-testbed to start cmd binary.
+ */
+struct GNUNET_CMDS_HelperInit
+{
+ /**
+ * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ *
+ */
+ uint16_t plugin_name_size GNUNET_PACKED;
+
+ /* Followed by plugin name of the plugin running the test case. This is not NULL
+ * terminated */
+};
+
+/**
+ * Reply message from cmds helper process
+ */
+struct GNUNET_CMDS_HelperReply
+{
+ /**
+ * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY
+ */
+ struct GNUNET_MessageHeader header;
+};
+
+struct GNUNET_CMDS_PEER_STARTED
+{
+ /**
+ * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED
+ */
+ struct GNUNET_MessageHeader header;
+};
+
+struct GNUNET_CMDS_ALL_PEERS_STARTED
+{
+ /**
+ * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED
+ */
+ struct GNUNET_MessageHeader header;
+};
+
+struct GNUNET_CMDS_LOCAL_FINISHED
+{
+ /**
+ * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED
+ */
+ struct GNUNET_MessageHeader header;
+};
+
+GNUNET_NETWORK_STRUCT_END
+#endif
+/* end of testing_cmds.h */