aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Makefile.am3
-rw-r--r--src/lib/testing/.gitignore8
-rw-r--r--src/lib/testing/Makefile.am136
-rw-r--r--src/lib/testing/gnunet-cmds-helper.c713
-rw-r--r--src/lib/testing/gnunet-testing.c444
-rw-r--r--src/lib/testing/list-keys.c112
-rw-r--r--src/lib/testing/meson.build68
-rw-r--r--src/lib/testing/test_testing_defaults.conf25
-rw-r--r--src/lib/testing/test_testing_peerstartup.c143
-rw-r--r--src/lib/testing/test_testing_peerstartup2.c222
-rw-r--r--src/lib/testing/test_testing_portreservation.c105
-rw-r--r--src/lib/testing/test_testing_servicestartup.c75
-rw-r--r--src/lib/testing/test_testing_sharedservices.c167
-rw-r--r--src/lib/testing/test_testing_sharedservices.conf30
-rw-r--r--src/lib/testing/test_testing_start_with_config.c121
-rw-r--r--src/lib/testing/testing.c2830
-rw-r--r--src/lib/testing/testing.conf11
-rw-r--r--src/lib/testing/testing.h352
-rw-r--r--src/lib/testing/testing_api_cmd_barrier.c202
-rw-r--r--src/lib/testing/testing_api_cmd_barrier_reached.c229
-rw-r--r--src/lib/testing/testing_api_cmd_batch.c223
-rw-r--r--src/lib/testing/testing_api_cmd_block_until_external_trigger.c119
-rw-r--r--src/lib/testing/testing_api_cmd_exec_bash_script.c216
-rw-r--r--src/lib/testing/testing_api_cmd_finish.c195
-rw-r--r--src/lib/testing/testing_api_cmd_local_test_prepared.c112
-rw-r--r--src/lib/testing/testing_api_cmd_netjail_start.c231
-rw-r--r--src/lib/testing/testing_api_cmd_netjail_start_cmds_helper.c913
-rw-r--r--src/lib/testing/testing_api_cmd_netjail_stop.c200
-rw-r--r--src/lib/testing/testing_api_cmd_netjail_stop_cmds_helper.c157
-rw-r--r--src/lib/testing/testing_api_cmd_send_peer_ready.c123
-rw-r--r--src/lib/testing/testing_api_cmd_start_peer.c298
-rw-r--r--src/lib/testing/testing_api_cmd_stop_peer.c130
-rw-r--r--src/lib/testing/testing_api_cmd_system_create.c124
-rw-r--r--src/lib/testing/testing_api_cmd_system_destroy.c111
-rw-r--r--src/lib/testing/testing_api_loop.c937
-rw-r--r--src/lib/testing/testing_api_traits.c90
-rw-r--r--src/lib/testing/testing_cmds.h143
-rwxr-xr-xsrc/lib/testing/topo.sh99
38 files changed, 1 insertions, 10416 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 8ab0d6993..c9871d8c7 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -10,5 +10,4 @@ SUBDIRS = \
10 curl \ 10 curl \
11 json \ 11 json \
12 sq \ 12 sq \
13 $(POSTGRES_DIR) \ 13 $(POSTGRES_DIR)
14 testing
diff --git a/src/lib/testing/.gitignore b/src/lib/testing/.gitignore
deleted file mode 100644
index d75315c79..000000000
--- a/src/lib/testing/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
1list-keys
2gnunet-testing
3test_testing_peerstartup
4test_testing_peerstartup2
5test_testing_portreservation
6test_testing_servicestartup
7test_testing_sharedservices
8gnunet-cmds-helper
diff --git a/src/lib/testing/Makefile.am b/src/lib/testing/Makefile.am
deleted file mode 100644
index 9ad48c619..000000000
--- a/src/lib/testing/Makefile.am
+++ /dev/null
@@ -1,136 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage -O0
6 XLIB = -lgcov
7endif
8
9libexecdir= $(pkglibdir)/libexec/
10
11pkgcfgdir= $(pkgdatadir)/config.d/
12
13dist_pkgcfg_DATA = \
14 testing.conf
15
16libexec_PROGRAMS = \
17 test_testing_start_with_config \
18 gnunet-cmds-helper
19
20plugindir = $(libdir)/gnunet
21
22lib_LTLIBRARIES = \
23 libgnunettesting.la
24
25gnunet_cmds_helper_SOURCES = \
26 gnunet-cmds-helper.c
27gnunet_cmds_helper_LDADD = $(XLIB) \
28 $(top_builddir)/src/lib/util/libgnunetutil.la \
29 libgnunettesting.la \
30 $(LTLIBINTL) $(Z_LIBS)
31
32libgnunettesting_la_SOURCES = \
33 testing_api_cmd_stop_peer.c \
34 testing_api_cmd_start_peer.c \
35 testing_api_cmd_exec_bash_script.c \
36 testing_api_cmd_barrier.c \
37 testing_api_cmd_barrier_reached.c \
38 testing_api_cmd_finish.c \
39 testing_api_cmd_local_test_prepared.c \
40 testing_api_cmd_send_peer_ready.c \
41 testing_api_cmd_block_until_external_trigger.c \
42 testing_api_cmd_netjail_start.c \
43 testing_api_cmd_netjail_start_cmds_helper.c \
44 testing_api_cmd_netjail_stop_cmds_helper.c \
45 testing_api_cmd_netjail_stop.c \
46 testing.c testing.h \
47 testing_api_cmd_system_create.c \
48 testing_api_cmd_system_destroy.c \
49 testing_api_cmd_batch.c \
50 testing_api_loop.c \
51 testing_api_traits.c
52libgnunettesting_la_LIBADD = \
53 $(top_builddir)/src/service/arm/libgnunetarm.la \
54 $(top_builddir)/src/lib/util/libgnunetutil.la \
55 $(LTLIBINTL)
56libgnunettesting_la_LDFLAGS = \
57 $(GN_LIB_LDFLAGS) \
58 -version-info 2:0:1
59
60bin_PROGRAMS = \
61 gnunet-testing
62
63noinst_PROGRAMS = \
64 list-keys
65
66gnunet_testing_SOURCES = \
67 gnunet-testing.c
68gnunet_testing_LDADD = \
69 libgnunettesting.la \
70 $(top_builddir)/src/lib/util/libgnunetutil.la \
71 $(GN_LIBINTL)
72
73list_keys_SOURCES = \
74 list-keys.c
75list_keys_LDADD = \
76 $(top_builddir)/src/lib/util/libgnunetutil.la \
77 $(GN_LIBINTL)
78
79
80check_PROGRAMS = \
81 test_testing_portreservation \
82 test_testing_servicestartup \
83 test_testing_peerstartup \
84 test_testing_peerstartup2 \
85 test_testing_sharedservices
86
87# if ENABLE_TEST_RUN_TESTING
88# AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
89# TESTS = \
90# test_testing_portreservation \
91# test_testing_peerstartup \
92# test_testing_peerstartup2 \
93# test_testing_servicestartup
94# endif
95
96test_testing_start_with_config_SOURCES = \
97 test_testing_start_with_config.c
98test_testing_start_with_config_LDADD = \
99 libgnunettesting.la \
100 $(top_builddir)/src/lib/util/libgnunetutil.la \
101 $(top_builddir)/src/lib/hello/libgnunethello.la
102
103test_testing_portreservation_SOURCES = \
104 test_testing_portreservation.c
105test_testing_portreservation_LDADD = \
106 libgnunettesting.la \
107 $(top_builddir)/src/lib/util/libgnunetutil.la
108
109test_testing_peerstartup_SOURCES = \
110 test_testing_peerstartup.c
111test_testing_peerstartup_LDADD = \
112 libgnunettesting.la \
113 $(top_builddir)/src/lib/util/libgnunetutil.la
114
115test_testing_peerstartup2_SOURCES = \
116 test_testing_peerstartup2.c
117test_testing_peerstartup2_LDADD = \
118 libgnunettesting.la \
119 $(top_builddir)/src/lib/util/libgnunetutil.la
120
121test_testing_servicestartup_SOURCES = \
122 test_testing_servicestartup.c
123test_testing_servicestartup_LDADD = \
124 libgnunettesting.la \
125 $(top_builddir)/src/lib/util/libgnunetutil.la
126
127test_testing_sharedservices_SOURCES = \
128 test_testing_sharedservices.c
129test_testing_sharedservices_LDADD = \
130 libgnunettesting.la \
131 $(top_builddir)/src/lib/util/libgnunetutil.la
132
133EXTRA_DIST = \
134 test_testing_defaults.conf \
135 test_testing_sharedservices.conf \
136 testing_cmds.h
diff --git a/src/lib/testing/gnunet-cmds-helper.c b/src/lib/testing/gnunet-cmds-helper.c
deleted file mode 100644
index 4428d4402..000000000
--- a/src/lib/testing/gnunet-cmds-helper.c
+++ /dev/null
@@ -1,713 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testbed/gnunet-cmds-helper.c
23 * @brief Helper binary that is started from a remote interpreter loop to start
24 * a local interpreter loop.
25 *
26 * This helper monitors for three termination events. They are: (1)The
27 * stdin of the helper is closed for reading; (2)the helper received
28 * SIGTERM/SIGINT; (3)the local loop crashed. In case of events 1 and 2
29 * the helper kills the interpreter loop. When the interpreter loop
30 * crashed (event 3), the helper should send a SIGTERM to its own process
31 * group; this behaviour will help terminate any child processes the loop
32 * has started and prevents them from leaking and running forever.
33 *
34 * @author t3sserakt
35 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
36 */
37
38
39#include "platform.h"
40#include "gnunet_util_lib.h"
41#include "gnunet_testing_lib.h"
42#include "gnunet_testing_ng_lib.h"
43#include "gnunet_testing_plugin.h"
44#include "gnunet_testing_netjail_lib.h"
45#include "testing.h"
46#include "testing_cmds.h"
47#include "gnunet_testing_plugin.h"
48#include "gnunet_testing_barrier.h"
49#include <zlib.h>
50
51
52/**
53 * Generic logging shortcut
54 */
55#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
56
57/**
58 * Debug logging shorthand
59 */
60#define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
61
62#define NODE_BASE_IP "192.168.15."
63
64#define KNOWN_BASE_IP "92.68.151."
65
66#define ROUTER_BASE_IP "92.68.150."
67
68/* Use the IP addresses below instead of the public ones,
69 * if the start script was not started from within a new namespace
70 * created by unshare. The UPNP test case needs public IP
71 * addresse for miniupnpd to function.
72 * FIXME We should introduce a switch indicating if public
73 * addresses should be used or not. This info has to be
74 * propagated from the start script to the c code.
75#define KNOWN_BASE_IP "172.16.151."
76
77#define ROUTER_BASE_IP "172.16.150."
78*/
79
80struct GNUNET_SCHEDULER_Task *finished_task;
81
82struct GNUNET_TESTING_Interpreter *is;
83
84/**
85 * Struct with information about a specific node and the whole network namespace setup.
86 *
87 */
88struct NodeIdentifier
89{
90 /**
91 * The number of the namespace this node is in.
92 *
93 */
94 char *n;
95
96 /**
97 * The number of the node in the namespace.
98 *
99 */
100 char *m;
101
102 /**
103 * The number of namespaces
104 *
105 */
106 char *global_n;
107
108 /**
109 * The number of local nodes per namespace.
110 *
111 */
112 char *local_m;
113
114 /**
115 * Shall we read the topology from file, or from a string.
116 */
117 unsigned int *read_file;
118
119 /**
120 * String with topology data or name of topology file.
121 */
122 char *topology_data;
123};
124
125/**
126 * Context for a single write on a chunk of memory
127 */
128struct WriteContext
129{
130 /**
131 * The data to write
132 */
133 void *data;
134
135 /**
136 * The length of the data
137 */
138 size_t length;
139
140 /**
141 * The current position from where the write operation should begin
142 */
143 size_t pos;
144};
145
146/**
147 * The process handle to the testbed service
148
149static struct GNUNET_OS_Process *cmd_binary_process;*/
150
151/**
152 * Plugin to dynamically load a test case.
153 */
154struct TestcasePlugin *plugin;
155
156/**
157 * Our message stream tokenizer
158 */
159struct GNUNET_MessageStreamTokenizer *tokenizer;
160
161/**
162 * Disk handle from stdin
163 */
164static struct GNUNET_DISK_FileHandle *stdin_fd;
165
166/**
167 * Disk handle for stdout
168 */
169static struct GNUNET_DISK_FileHandle *stdout_fd;
170
171/**
172 * Pipe used to communicate shutdown via signal.
173 */
174static struct GNUNET_DISK_PipeHandle *sigpipe;
175
176/**
177 * Task identifier for the read task
178 */
179static struct GNUNET_SCHEDULER_Task *read_task_id;
180
181/**
182 * Task identifier for the write task
183 */
184static struct GNUNET_SCHEDULER_Task *write_task_id;
185
186/**
187 * Are we done reading messages from stdin?
188 */
189static int done_reading;
190
191/**
192 * Result to return in case we fail
193 */
194static int status;
195
196
197/**
198 * Task to shut down cleanly
199 *
200 * @param cls NULL
201 */
202static void
203do_shutdown (void *cls)
204{
205
206 LOG_DEBUG ("Shutting down.\n");
207
208 if (NULL != read_task_id)
209 {
210 GNUNET_SCHEDULER_cancel (read_task_id);
211 read_task_id = NULL;
212 }
213 if (NULL != write_task_id)
214 {
215 struct WriteContext *wc;
216
217 wc = GNUNET_SCHEDULER_cancel (write_task_id);
218 write_task_id = NULL;
219 GNUNET_free (wc->data);
220 GNUNET_free (wc);
221 }
222 if (NULL != stdin_fd)
223 (void) GNUNET_DISK_file_close (stdin_fd);
224 if (NULL != stdout_fd)
225 (void) GNUNET_DISK_file_close (stdout_fd);
226 GNUNET_MST_destroy (tokenizer);
227 tokenizer = NULL;
228 GNUNET_PLUGIN_unload (plugin->library_name,
229 NULL);
230 GNUNET_free (plugin);
231}
232
233
234/**
235 * Task to write to the standard out
236 *
237 * @param cls the WriteContext
238 */
239static void
240write_task (void *cls)
241{
242 struct WriteContext *wc = cls;
243 ssize_t bytes_wrote;
244
245 GNUNET_assert (NULL != wc);
246 write_task_id = NULL;
247 bytes_wrote = GNUNET_DISK_file_write (stdout_fd,
248 wc->data + wc->pos,
249 wc->length - wc->pos);
250 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
251 "message send to master loop\n");
252 if (GNUNET_SYSERR == bytes_wrote)
253 {
254 LOG (GNUNET_ERROR_TYPE_WARNING,
255 "Cannot reply back successful initialization\n");
256 GNUNET_free (wc->data);
257 GNUNET_free (wc);
258 return;
259 }
260 wc->pos += bytes_wrote;
261 if (wc->pos == wc->length)
262 {
263 GNUNET_free (wc->data);
264 GNUNET_free (wc);
265 return;
266 }
267 write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
268 stdout_fd,
269 &write_task,
270 wc);
271}
272
273
274/**
275 * Callback to write a message to the master loop.
276 *
277 */
278static void
279write_message (struct GNUNET_MessageHeader *message,
280 size_t msg_length)
281{
282 struct WriteContext *wc;
283
284 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
285 "write message to master loop\n");
286 wc = GNUNET_new (struct WriteContext);
287 wc->length = msg_length;
288 wc->data = message;
289 write_task_id = GNUNET_SCHEDULER_add_write_file (
290 GNUNET_TIME_UNIT_FOREVER_REL,
291 stdout_fd,
292 &write_task,
293 wc);
294}
295
296
297static void
298delay_shutdown_cb ()
299{
300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
301 "doing shutdown after delay\n");
302 GNUNET_SCHEDULER_shutdown ();
303}
304
305
306struct GNUNET_MessageHeader *
307GNUNET_TESTING_send_local_test_finished_msg ()
308{
309 struct GNUNET_TESTING_CommandLocalFinished *reply;
310 size_t msg_length;
311
312 msg_length = sizeof(struct GNUNET_TESTING_CommandLocalFinished);
313 reply = GNUNET_new (struct GNUNET_TESTING_CommandLocalFinished);
314 reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED);
315 reply->header.size = htons ((uint16_t) msg_length);
316
317 return (struct GNUNET_MessageHeader *) reply;
318}
319
320
321static void
322finished_cb (enum GNUNET_GenericReturnValue rv)
323{
324 struct GNUNET_TESTING_CommandLocalFinished *reply;
325 size_t msg_length;
326
327 msg_length = sizeof(struct GNUNET_TESTING_CommandLocalFinished);
328 reply = GNUNET_new (struct GNUNET_TESTING_CommandLocalFinished);
329 reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED);
330 reply->header.size = htons ((uint16_t) msg_length);
331 reply->rv = rv;
332
333 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
334 "message prepared\n");
335 write_message ((struct GNUNET_MessageHeader *) reply, msg_length);
336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
337 "message send\n");
338 // FIXME: bad hack, do not write 1s, have continuation after write_message() is done!
339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
340 "delaying shutdown\n");
341 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
342 &delay_shutdown_cb,
343 NULL);
344}
345
346
347/**
348 * Functions with this signature are called whenever a
349 * complete message is received by the tokenizer.
350 *
351 * Do not call #GNUNET_mst_destroy() in this callback
352 *
353 * @param cls identification of the client
354 * @param message the actual message
355 * @return #GNUNET_OK on success,
356 * #GNUNET_NO to stop further processing (no error)
357 * #GNUNET_SYSERR to stop further processing with error
358 */
359static enum GNUNET_GenericReturnValue
360tokenizer_cb (void *cls,
361 const struct GNUNET_MessageHeader *message)
362{
363 struct NodeIdentifier *ni = cls;
364 const struct GNUNET_TESTING_CommandHelperInit *msg;
365 struct GNUNET_TESTING_CommandHelperReply *reply;
366 char *binary;
367 char *plugin_name;
368 size_t plugin_name_size;
369 uint16_t msize;
370 uint16_t type;
371 size_t msg_length;
372 char *router_ip;
373 char *node_ip;
374 unsigned int namespace_n;
375
376 type = ntohs (message->type);
377 msize = ntohs (message->size);
378 LOG (GNUNET_ERROR_TYPE_ERROR,
379 "Received message type %u and size %u\n",
380 type,
381 msize);
382 switch (type)
383 {
384 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT:
385 {
386 msg = (const struct GNUNET_TESTING_CommandHelperInit *) message;
387 plugin_name_size = ntohs (msg->plugin_name_size);
388 if ((sizeof(struct GNUNET_TESTING_CommandHelperInit) + plugin_name_size) >
389 msize)
390 {
391 GNUNET_break (0);
392 LOG (GNUNET_ERROR_TYPE_WARNING,
393 "Received unexpected message -- exiting\n");
394 goto error;
395 }
396 plugin_name = GNUNET_malloc (plugin_name_size + 1);
397 GNUNET_strlcpy (plugin_name,
398 ((char *) &msg[1]),
399 plugin_name_size + 1);
400
401 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-cmd");
402
403 plugin = GNUNET_new (struct TestcasePlugin);
404 plugin->api = GNUNET_PLUGIN_load (plugin_name,
405 NULL);
406 plugin->library_name = GNUNET_strdup (basename (plugin_name));
407
408 plugin->global_n = ni->global_n;
409 plugin->local_m = ni->local_m;
410 plugin->n = ni->n;
411 plugin->m = ni->m;
412
413 GNUNET_asprintf (&router_ip,
414 ROUTER_BASE_IP "%s",
415 plugin->n);
416 {
417 char dummy;
418
419 if (1 !=
420 sscanf (plugin->n,
421 "%u%c",
422 &namespace_n,
423 &dummy))
424 {
425 // FIXME: how to handle error nicely?
426 GNUNET_break (0);
427 namespace_n = 0;
428 }
429 }
430
431 if (0 == namespace_n)
432 {
433 LOG (GNUNET_ERROR_TYPE_DEBUG,
434 "known node n: %s\n",
435 plugin->n);
436 GNUNET_asprintf (&node_ip,
437 KNOWN_BASE_IP "%s",
438 plugin->m);
439 }
440 else
441 {
442 LOG (GNUNET_ERROR_TYPE_DEBUG,
443 "subnet node n: %s\n",
444 plugin->n);
445 GNUNET_asprintf (&node_ip,
446 NODE_BASE_IP "%s",
447 plugin->m);
448 }
449
450 is = plugin->api->start_testcase (&write_message,
451 router_ip,
452 node_ip,
453 plugin->m,
454 plugin->n,
455 plugin->local_m,
456 ni->topology_data,
457 ni->read_file,
458 &finished_cb);
459 GNUNET_free (node_ip);
460 GNUNET_free (binary);
461 GNUNET_free (router_ip);
462 GNUNET_free (plugin_name);
463
464 msg_length = sizeof(struct GNUNET_TESTING_CommandHelperReply);
465 reply = GNUNET_new (struct GNUNET_TESTING_CommandHelperReply);
466 reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY);
467 reply->header.size = htons ((uint16_t) msg_length);
468 write_message (&reply->header,
469 msg_length);
470 return GNUNET_OK;
471 }
472 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_CROSSABLE:
473 {
474 const char *barrier_name;
475 struct CommandBarrierCrossable *adm = (struct
476 CommandBarrierCrossable *) message;
477
478 barrier_name = (const char *) &adm[1];
479 LOG (GNUNET_ERROR_TYPE_DEBUG,
480 "cross barrier %s\n",
481 barrier_name);
482 TST_interpreter_finish_attached_cmds (is,
483 barrier_name);
484 return GNUNET_OK;
485 }
486 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED:
487 {
488 LOG (GNUNET_ERROR_TYPE_DEBUG,
489 "all peers started\n");
490 plugin->api->all_peers_started ();
491 return GNUNET_OK;
492 }
493 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_LOCAL_TESTS_PREPARED:
494 {
495 LOG (GNUNET_ERROR_TYPE_DEBUG,
496 "all local tests prepared\n");
497 plugin->api->all_local_tests_prepared ();
498 return GNUNET_OK;
499 }
500 default:
501 LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n");
502 goto error;
503 }
504
505error:
506 status = GNUNET_SYSERR;
507 LOG (GNUNET_ERROR_TYPE_ERROR,
508 "tokenizer shutting down!\n");
509 GNUNET_SCHEDULER_shutdown ();
510 return GNUNET_SYSERR;
511}
512
513
514/**
515 * Task to read from stdin
516 *
517 * @param cls NULL
518 */
519static void
520read_task (void *cls)
521{
522 char buf[GNUNET_MAX_MESSAGE_SIZE];
523 ssize_t sread;
524
525 read_task_id = NULL;
526 sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof(buf));
527 if ((GNUNET_SYSERR == sread) || (0 == sread))
528 {
529 LOG_DEBUG ("STDIN closed\n");
530 GNUNET_SCHEDULER_shutdown ();
531 return;
532 }
533 if (GNUNET_YES == done_reading)
534 {
535 /* didn't expect any more data! */
536 GNUNET_break_op (0);
537 LOG (GNUNET_ERROR_TYPE_ERROR,
538 "tokenizer shutting down during reading, didn't expect any more data!\n");
539 GNUNET_SCHEDULER_shutdown ();
540 return;
541 }
542 LOG_DEBUG ("Read %u bytes\n", (unsigned int) sread);
543 /* FIXME: could introduce a GNUNET_MST_read2 to read
544 directly from 'stdin_fd' and save a memcpy() here */
545 if (GNUNET_OK !=
546 GNUNET_MST_from_buffer (tokenizer, buf, sread, GNUNET_NO, GNUNET_NO))
547 {
548 GNUNET_break (0);
549 LOG (GNUNET_ERROR_TYPE_ERROR,
550 "tokenizer shutting down during reading, writing to buffer failed!\n");
551 GNUNET_SCHEDULER_shutdown ();
552 return;
553 }
554 read_task_id /* No timeout while reading */
555 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
556 stdin_fd,
557 &read_task,
558 NULL);
559}
560
561
562/**
563 * Main function that will be run.
564 *
565 * @param cls closure
566 * @param args remaining command-line arguments
567 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
568 * @param cfg configuration
569 */
570static void
571run (void *cls,
572 char *const *args,
573 const char *cfgfile,
574 const struct GNUNET_CONFIGURATION_Handle *cfg)
575{
576 struct NodeIdentifier *ni = cls;
577
578 LOG (GNUNET_ERROR_TYPE_DEBUG,
579 "Starting interpreter loop helper...\n");
580
581 tokenizer = GNUNET_MST_create (&tokenizer_cb,
582 ni);
583 stdin_fd = GNUNET_DISK_get_handle_from_native (stdin);
584 stdout_fd = GNUNET_DISK_get_handle_from_native (stdout);
585 read_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
586 stdin_fd,
587 &read_task,
588 NULL);
589 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
590 NULL);
591 LOG (GNUNET_ERROR_TYPE_DEBUG,
592 "Interpreter loop helper started.\n");
593}
594
595
596/**
597 * Signal handler called for SIGCHLD.
598 */
599static void
600sighandler_child_death ()
601{
602 static char c;
603 int old_errno; /* back-up errno */
604
605 old_errno = errno;
606 GNUNET_break (
607 1 ==
608 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe,
609 GNUNET_DISK_PIPE_END_WRITE),
610 &c,
611 sizeof(c)));
612 errno = old_errno;
613}
614
615
616/**
617 * Main function
618 *
619 * @param argc the number of command line arguments
620 * @param argv command line arg array
621 * @return return code
622 */
623int
624main (int argc, char **argv)
625{
626 struct NodeIdentifier *ni;
627 struct GNUNET_SIGNAL_Context *shc_chld;
628 struct GNUNET_GETOPT_CommandLineOption options[] = {
629 GNUNET_GETOPT_OPTION_END
630 };
631 int ret;
632 unsigned int sscanf_ret;
633 int i;
634 size_t topology_data_length = 0;
635 unsigned int read_file;
636 char cr[2] = "\n\0";
637
638 GNUNET_log_setup ("gnunet-cmds-helper",
639 "DEBUG",
640 NULL);
641 ni = GNUNET_new (struct NodeIdentifier);
642 ni->global_n = argv[1];
643 ni->local_m = argv[2];
644 ni->m = argv[3];
645 ni->n = argv[4];
646
647 errno = 0;
648 sscanf_ret = sscanf (argv[5], "%u", &read_file);
649
650 if (errno != 0)
651 {
652 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
653 }
654 else if (1 == read_file)
655 ni->topology_data = argv[6];
656 else if (0 == read_file)
657 {
658 for (i = 6; i<argc; i++)
659 topology_data_length += strlen (argv[i]) + 1;
660 LOG (GNUNET_ERROR_TYPE_DEBUG,
661 "topo data length %lu\n",
662 topology_data_length);
663 ni->topology_data = GNUNET_malloc (topology_data_length);
664 memset (ni->topology_data, '\0', topology_data_length);
665 for (i = 6; i<argc; i++)
666 {
667 strcat (ni->topology_data, argv[i]);
668 strcat (ni->topology_data, cr);
669 }
670 }
671 else
672 {
673 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
674 "Wrong input for the fourth argument\n");
675 }
676 GNUNET_assert (0 < sscanf_ret);
677 ni->read_file = &read_file;
678 ni->topology_data[topology_data_length - 1] = '\0';
679 LOG (GNUNET_ERROR_TYPE_DEBUG,
680 "topo data %s\n",
681 ni->topology_data);
682
683 status = GNUNET_OK;
684 if (NULL ==
685 (sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE)))
686 {
687 GNUNET_break (0);
688 return 1;
689 }
690 shc_chld =
691 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
692 &sighandler_child_death);
693 ret = GNUNET_PROGRAM_run (argc,
694 argv,
695 "gnunet-cmds-helper",
696 "Helper for starting a local interpreter loop",
697 options,
698 &run,
699 ni);
700
701 LOG (GNUNET_ERROR_TYPE_DEBUG,
702 "Finishing helper\n");
703 GNUNET_SIGNAL_handler_uninstall (shc_chld);
704 shc_chld = NULL;
705 GNUNET_DISK_pipe_close (sigpipe);
706 GNUNET_free (ni);
707 if (GNUNET_OK != ret)
708 return 1;
709 return (GNUNET_OK == status) ? 0 : 1;
710}
711
712
713/* end of gnunet-cmds-helper.c */
diff --git a/src/lib/testing/gnunet-testing.c b/src/lib/testing/gnunet-testing.c
deleted file mode 100644
index 88906e5fa..000000000
--- a/src/lib/testing/gnunet-testing.c
+++ /dev/null
@@ -1,444 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/gnunet-testing.c
23 * @brief tool to use testing functionality from cmd line
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_lib.h"
29
30
31#define LOG(kind, ...) GNUNET_log_from (kind, "gnunet-testing", __VA_ARGS__)
32
33
34/**
35 * Final status code.
36 */
37static int ret;
38
39/**
40 * Filename of the hostkey file we should write,
41 * null if we should not write a hostkey file.
42 */
43static char *create_hostkey;
44
45/**
46 * Non-zero if we should create config files.
47 */
48static int create_cfg;
49
50/**
51 * Number of config files to create.
52 */
53static unsigned int create_no;
54
55/**
56 * Filename of the config template to be written.
57 */
58static char *create_cfg_template;
59
60/**
61 * Service we are supposed to run.
62 */
63static char *run_service_name;
64
65/**
66 * File handle to STDIN, for reading restart/quit commands.
67 */
68static struct GNUNET_DISK_FileHandle *fh;
69
70/**
71 * Temporary filename, used with '-r' to write the configuration to.
72 */
73static char *tmpfilename;
74
75/**
76 * Task identifier of the task that waits for stdin.
77 */
78static struct GNUNET_SCHEDULER_Task *tid;
79
80/**
81 * Peer started for '-r'.
82 */
83static struct GNUNET_TESTING_Peer *my_peer;
84
85
86static int
87create_unique_cfgs (const char *template, const unsigned int no)
88{
89 struct GNUNET_TESTING_System *system;
90 int fail;
91 unsigned int cur;
92 char *cur_file;
93 struct GNUNET_CONFIGURATION_Handle *cfg_new;
94 struct GNUNET_CONFIGURATION_Handle *cfg_tmpl;
95
96 if (GNUNET_NO == GNUNET_DISK_file_test (template))
97 {
98 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
99 "Configuration template `%s': file not found\n",
100 create_cfg_template);
101 return 1;
102 }
103 cfg_tmpl = GNUNET_CONFIGURATION_create ();
104
105 /* load template */
106 if ((create_cfg_template != NULL) &&
107 (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg_tmpl, create_cfg_template)))
108 {
109 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
110 "Could not load template `%s'\n",
111 create_cfg_template);
112 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
113
114 return 1;
115 }
116 /* load defaults */
117 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg_tmpl, NULL))
118 {
119 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
120 "Could not load template `%s'\n",
121 create_cfg_template);
122 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
123 return 1;
124 }
125
126 fail = GNUNET_NO;
127 system =
128 GNUNET_TESTING_system_create ("testing", NULL /* controller */, NULL, NULL);
129 for (cur = 0; cur < no; cur++)
130 {
131 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
132 "Creating configuration no. %u \n",
133 cur);
134 if (create_cfg_template != NULL)
135 GNUNET_asprintf (&cur_file, "%04u-%s", cur, create_cfg_template);
136 else
137 GNUNET_asprintf (&cur_file, "%04u%s", cur, ".conf");
138
139 cfg_new = GNUNET_CONFIGURATION_dup (cfg_tmpl);
140 if (GNUNET_OK != GNUNET_TESTING_configuration_create (system, cfg_new))
141 {
142 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
143 "Could not create another configuration\n");
144 GNUNET_CONFIGURATION_destroy (cfg_new);
145 fail = GNUNET_YES;
146 break;
147 }
148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
149 "Writing configuration no. %u to file `%s' \n",
150 cur,
151 cur_file);
152 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg_new, cur_file))
153 {
154 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
155 "Failed to write configuration no. %u \n",
156 cur);
157 fail = GNUNET_YES;
158 }
159 GNUNET_CONFIGURATION_destroy (cfg_new);
160 GNUNET_free (cur_file);
161 if (GNUNET_YES == fail)
162 break;
163 }
164 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
165 GNUNET_TESTING_system_destroy (system, GNUNET_NO);
166 if (GNUNET_YES == fail)
167 return 1;
168 return 0;
169}
170
171
172static int
173create_hostkeys (const unsigned int no)
174{
175 struct GNUNET_TESTING_System *system;
176 struct GNUNET_PeerIdentity id;
177 struct GNUNET_DISK_FileHandle *fd;
178 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
179
180 system = GNUNET_TESTING_system_create ("testing", NULL, NULL, NULL);
181 pk = GNUNET_TESTING_hostkey_get (system, create_no, &id);
182 if (NULL == pk)
183 {
184 fprintf (stderr,
185 _ ("Could not extract hostkey %u (offset too large?)\n"),
186 create_no);
187 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
188 return 1;
189 }
190 (void) GNUNET_DISK_directory_create_for_file (create_hostkey);
191 fd =
192 GNUNET_DISK_file_open (create_hostkey,
193 GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE,
194 GNUNET_DISK_PERM_USER_READ
195 | GNUNET_DISK_PERM_USER_WRITE);
196 GNUNET_assert (fd != NULL);
197 ret = GNUNET_DISK_file_write (fd,
198 pk,
199 sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
200 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
201 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
202 "transport-testing",
203 "Wrote hostkey to file: `%s'\n",
204 create_hostkey);
205 GNUNET_free (pk);
206 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
207 return 0;
208}
209
210
211/**
212 * Cleanup called by signal handlers and when stdin is closed.
213 * Removes the temporary file.
214 *
215 * @param cls unused
216 */
217static void
218cleanup (void *cls)
219{
220 if (NULL != tmpfilename)
221 {
222 if (0 != unlink (tmpfilename))
223 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
224 "unlink",
225 tmpfilename);
226 }
227 if (NULL != tid)
228 {
229 GNUNET_SCHEDULER_cancel (tid);
230 tid = NULL;
231 }
232 if (NULL != fh)
233 {
234 GNUNET_DISK_file_close (fh);
235 fh = NULL;
236 }
237}
238
239
240/**
241 * Called whenever we can read stdin non-blocking
242 *
243 * @param cls unused
244 */
245static void
246stdin_cb (void *cls)
247{
248 int c;
249
250 tid = NULL;
251 c = getchar ();
252 switch (c)
253 {
254 case EOF:
255 case 'q':
256 GNUNET_SCHEDULER_shutdown ();
257 return;
258
259 case 'r':
260 if (GNUNET_OK != GNUNET_TESTING_peer_stop (my_peer))
261 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to stop the peer\n");
262 if (GNUNET_OK != GNUNET_TESTING_peer_start (my_peer))
263 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to start the peer\n");
264 printf ("restarted\n");
265 fflush (stdout);
266 break;
267
268 case '\n':
269 case '\r':
270 /* ignore whitespace */
271 break;
272
273 default:
274 fprintf (stderr,
275 _ ("Unknown command, use 'q' to quit or 'r' to restart peer\n"));
276 break;
277 }
278 tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
279 fh,
280 &stdin_cb,
281 NULL);
282}
283
284
285/**
286 * Main function called by the testing library.
287 * Executed inside a running scheduler.
288 *
289 * @param cls unused
290 * @param cfg configuration of the peer that was started
291 * @param peer handle to the peer
292 */
293static void
294testing_main (void *cls,
295 const struct GNUNET_CONFIGURATION_Handle *cfg,
296 struct GNUNET_TESTING_Peer *peer)
297{
298 my_peer = peer;
299 if (NULL == (tmpfilename = GNUNET_DISK_mktemp ("gnunet-testing")))
300 {
301 GNUNET_break (0);
302 GNUNET_SCHEDULER_shutdown ();
303 return;
304 }
305 if (GNUNET_SYSERR ==
306 GNUNET_CONFIGURATION_write ((struct GNUNET_CONFIGURATION_Handle *) cfg,
307 tmpfilename))
308 {
309 GNUNET_break (0);
310 return;
311 }
312 printf ("ok\n%s\n", tmpfilename);
313 fflush (stdout);
314 GNUNET_SCHEDULER_add_shutdown (&cleanup, NULL);
315 fh = GNUNET_DISK_get_handle_from_native (stdin);
316 tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
317 fh,
318 &stdin_cb,
319 NULL);
320}
321
322
323/**
324 * Main function that will be running without scheduler.
325 *
326 * @param cls closure
327 * @param args remaining command-line arguments
328 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
329 * @param cfg configuration
330 */
331static void
332run_no_scheduler (void *cls,
333 char *const *args,
334 const char *cfgfile,
335 const struct GNUNET_CONFIGURATION_Handle *cfg)
336{
337 if (NULL != run_service_name)
338 {
339 ret = GNUNET_TESTING_service_run ("gnunet_service_test",
340 run_service_name,
341 cfgfile,
342 &testing_main,
343 NULL);
344 return;
345 }
346
347 if (GNUNET_YES == create_cfg)
348 {
349 if (create_no > 0)
350 {
351 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
352 "Creating %u configuration files based on template `%s'\n",
353 create_no,
354 create_cfg_template);
355 ret = create_unique_cfgs (create_cfg_template, create_no);
356 }
357 else
358 {
359 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n");
360 ret = 1;
361 }
362 }
363 if (NULL != create_hostkey)
364 {
365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Extracting hostkey %u\n", create_no);
366 ret = create_hostkeys (create_no);
367 }
368 GNUNET_free (create_cfg_template);
369}
370
371
372/**
373 * The main function.
374 *
375 * @param argc number of arguments from the command line
376 * @param argv command line arguments
377 * @return 0 ok, 1 on error
378 */
379int
380main (int argc, char *const *argv)
381{
382 struct GNUNET_GETOPT_CommandLineOption options[] =
383 { GNUNET_GETOPT_option_flag ('C',
384 "cfg",
385 gettext_noop (
386 "create unique configuration files"),
387 &create_cfg),
388 GNUNET_GETOPT_option_string (
389 'k',
390 "key",
391 "FILENAME",
392 gettext_noop ("extract hostkey file from pre-computed hostkey list"),
393 &create_hostkey),
394
395 GNUNET_GETOPT_option_uint (
396 'n',
397 "number",
398 "NUMBER",
399 gettext_noop (
400 "number of unique configuration files to create, or number of the hostkey to extract"),
401 &create_no),
402
403
404 GNUNET_GETOPT_option_string ('t',
405 "template",
406 "FILENAME",
407 gettext_noop ("configuration template"),
408 &create_cfg_template),
409
410 GNUNET_GETOPT_option_string (
411 'r',
412 "run",
413 "SERVICE",
414 gettext_noop (
415 "run the given service, wait on stdin for 'r' (restart) or 'q' (quit)"),
416 &run_service_name),
417 GNUNET_GETOPT_OPTION_END };
418
419 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
420 return 2;
421
422 /* Run without scheduler, because we may want to call
423 * GNUNET_TESTING_service_run, which starts the scheduler on its own.
424 * Furthermore, the other functionality currently does not require the scheduler, too,
425 * but beware when extending gnunet-testing. */
426 ret =
427 (GNUNET_OK ==
428 GNUNET_PROGRAM_run2 (argc,
429 argv,
430 "gnunet-testing",
431 gettext_noop (
432 "Command line tool to access the testing library"),
433 options,
434 &run_no_scheduler,
435 NULL,
436 GNUNET_YES))
437 ? ret
438 : 1;
439 GNUNET_free_nz ((void *) argv);
440 return ret;
441}
442
443
444/* end of gnunet-testing.c */
diff --git a/src/lib/testing/list-keys.c b/src/lib/testing/list-keys.c
deleted file mode 100644
index f65b45a77..000000000
--- a/src/lib/testing/list-keys.c
+++ /dev/null
@@ -1,112 +0,0 @@
1#include "platform.h"
2#include "gnunet_util_lib.h"
3#include "gnunet_testing_lib.h"
4
5static unsigned int nkeys;
6static unsigned int nskip;
7static int result;
8
9/**
10 * Main run function.
11 *
12 * @param cls NULL
13 * @param args arguments passed to GNUNET_PROGRAM_run
14 * @param cfgfile the path to configuration file
15 * @param cfg the configuration file handle
16 */
17static void
18run (void *cls,
19 char *const *args,
20 const char *cfgfile,
21 const struct GNUNET_CONFIGURATION_Handle *config)
22{
23 char *idfile;
24 struct GNUNET_DISK_FileHandle *f;
25 void *data;
26 struct GNUNET_DISK_MapHandle *map;
27 struct GNUNET_CRYPTO_EddsaPrivateKey pkey;
28 struct GNUNET_PeerIdentity id;
29 unsigned int cnt;
30 uint64_t fsize;
31 unsigned int nmax;
32
33 if ((NULL == args) || (NULL == args[0]))
34 {
35 fprintf (stderr, "Need the hostkey file\n");
36 return;
37 }
38 idfile = args[0];
39 if (GNUNET_OK !=
40 GNUNET_DISK_file_size (idfile, &fsize, GNUNET_YES, GNUNET_YES))
41 {
42 GNUNET_break (0);
43 return;
44 }
45 if (0 != (fsize % GNUNET_TESTING_HOSTKEYFILESIZE))
46 {
47 fprintf (stderr, _ ("Incorrect hostkey file format: %s\n"), idfile);
48 return;
49 }
50 f = GNUNET_DISK_file_open (idfile,
51 GNUNET_DISK_OPEN_READ,
52 GNUNET_DISK_PERM_NONE);
53 if (NULL == f)
54 {
55 GNUNET_break (0);
56 return;
57 }
58 data = GNUNET_DISK_file_map (f, &map, GNUNET_DISK_MAP_TYPE_READ, fsize);
59 if (NULL == data)
60 {
61 GNUNET_break (0);
62 GNUNET_DISK_file_close (f);
63 return;
64 }
65 nmax = fsize / GNUNET_TESTING_HOSTKEYFILESIZE;
66 for (cnt = nskip; cnt < (nskip + nkeys); cnt++)
67 {
68 if (nskip + cnt >= nmax)
69 {
70 printf ("Max keys %u reached\n", nmax);
71 break;
72 }
73 GNUNET_memcpy (&pkey,
74 data + (cnt * GNUNET_TESTING_HOSTKEYFILESIZE),
75 GNUNET_TESTING_HOSTKEYFILESIZE);
76 GNUNET_CRYPTO_eddsa_key_get_public (&pkey, &id.public_key);
77 printf ("Key %u: %s\n", cnt, GNUNET_i2s_full (&id));
78 }
79 result = GNUNET_OK;
80 GNUNET_DISK_file_unmap (map);
81 GNUNET_DISK_file_close (f);
82}
83
84
85int
86main (int argc, char *argv[])
87{
88 struct GNUNET_GETOPT_CommandLineOption option[] =
89 { GNUNET_GETOPT_option_uint ('n',
90 "num-keys",
91 "COUNT",
92 gettext_noop ("list COUNT number of keys"),
93 &nkeys),
94 GNUNET_GETOPT_OPTION_END };
95 int ret;
96
97 result = GNUNET_SYSERR;
98 nkeys = 10;
99 ret =
100 GNUNET_PROGRAM_run (argc,
101 argv,
102 "list-keys",
103 "Lists the peer IDs corresponding to the given keys file\n",
104 option,
105 &run,
106 NULL);
107 if (GNUNET_OK != ret)
108 return 1;
109 if (GNUNET_SYSERR == result)
110 return 1;
111 return 0;
112}
diff --git a/src/lib/testing/meson.build b/src/lib/testing/meson.build
deleted file mode 100644
index 68b5f5149..000000000
--- a/src/lib/testing/meson.build
+++ /dev/null
@@ -1,68 +0,0 @@
1libgnunettesting_src = [
2 'testing_api_cmd_barrier.c',
3 'testing_api_cmd_barrier_reached.c',
4 'testing_api_cmd_finish.c',
5 'testing_api_cmd_local_test_prepared.c',
6 'testing_api_cmd_send_peer_ready.c',
7 'testing_api_cmd_block_until_external_trigger.c',
8 'testing_api_cmd_netjail_start.c',
9 'testing_api_cmd_netjail_start_cmds_helper.c',
10 'testing_api_cmd_netjail_stop_cmds_helper.c',
11 'testing_api_cmd_netjail_stop.c',
12 'testing.c',
13 'testing_api_cmd_system_create.c',
14 'testing_api_cmd_system_destroy.c',
15 'testing_api_cmd_batch.c',
16 'testing_api_loop.c',
17 'testing_api_traits.c'
18 ]
19
20gnunettesting_src = ['gnunet-testing.c']
21gnunetservicetesting_src = ['gnunet-service-testing.c']
22
23configure_file(input : 'testing.conf',
24 output : 'testing.conf',
25 configuration : cdata,
26 install: true,
27 install_dir: pkgcfgdir)
28
29
30if get_option('monolith')
31 # foreach p : libgnunettesting_src
32 # gnunet_src += 'testing/' + p
33 # endforeach
34 subdir_done()
35endif
36
37libgnunettesting = library('gnunettesting',
38 libgnunettesting_src,
39 soversion: '1',
40 version: '1.1.0',
41 dependencies: [libgnunetutil_dep,
42 m_dep,
43 libgnunetarm_dep],
44 include_directories: [incdir, configuration_inc],
45 install: true,
46 install_dir: get_option('libdir'))
47libgnunettesting_dep = declare_dependency(link_with : libgnunettesting)
48pkg.generate(libgnunettesting, url: 'https://www.gnunet.org',
49 description : 'Provides API for gnunet testing')
50
51executable ('gnunet-testing',
52 gnunettesting_src,
53 dependencies: [libgnunettesting_dep,
54 libgnunetutil_dep,
55 ],
56 include_directories: [incdir, configuration_inc],
57 install: true,
58 install_dir: get_option('bindir'))
59
60executable ('gnunet-cmds-helper',
61 ['gnunet-cmds-helper.c'],
62 dependencies: [libgnunettesting_dep,
63 libgnunetutil_dep,
64 ],
65 include_directories: [incdir, configuration_inc],
66 install: true,
67 install_dir: get_option('libdir')/'gnunet'/'libexec')
68
diff --git a/src/lib/testing/test_testing_defaults.conf b/src/lib/testing/test_testing_defaults.conf
deleted file mode 100644
index 2e7c39113..000000000
--- a/src/lib/testing/test_testing_defaults.conf
+++ /dev/null
@@ -1,25 +0,0 @@
1[PATHS]
2GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-testing/
3
4[transport]
5PLUGINS = tcp
6
7[transport-tcp]
8TESTING_IGNORE_KEYS = SOMETHING;KEY1;ACCEPT_FROM;
9
10[transport-tcp]
11BINDTO = 127.0.0.1
12
13[nat]
14DISABLEV6 = YES
15ENABLE_UPNP = NO
16BEHIND_NAT = NO
17ALLOW_NAT = NO
18INTERNAL_ADDRESS = 127.0.0.1
19EXTERNAL_ADDRESS = 127.0.0.1
20USE_LOCALADDR = NO
21
22
23[rps]
24START_ON_DEMAND = NO
25IMMEDIATE_START = NO
diff --git a/src/lib/testing/test_testing_peerstartup.c b/src/lib/testing/test_testing_peerstartup.c
deleted file mode 100644
index 25cbb2a9f..000000000
--- a/src/lib/testing/test_testing_peerstartup.c
+++ /dev/null
@@ -1,143 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/test_testing_new_peerstartup.c
23 * @brief test case for testing peer startup and shutdown using new testing
24 * library
25 * @author Sree Harsha Totakura
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testing_lib.h"
31
32#define LOG(kind, ...) \
33 GNUNET_log (kind, __VA_ARGS__)
34
35/**
36 * The status of the test
37 */
38int status;
39
40/**
41 * The testing context
42 */
43struct TestingContext
44{
45 /**
46 * The testing system
47 */
48 struct GNUNET_TESTING_System *system;
49
50 /**
51 * The peer which has been started by the testing system
52 */
53 struct GNUNET_TESTING_Peer *peer;
54
55 /**
56 * The running configuration of the peer
57 */
58 struct GNUNET_CONFIGURATION_Handle *cfg;
59};
60
61
62/**
63 * Task for shutdown
64 *
65 * @param cls the testing context
66 */
67static void
68do_shutdown (void *cls)
69{
70 struct TestingContext *test_ctx = cls;
71
72 GNUNET_assert (NULL != test_ctx);
73 if (NULL != test_ctx->peer)
74 {
75 (void) GNUNET_TESTING_peer_stop (test_ctx->peer);
76 GNUNET_TESTING_peer_destroy (test_ctx->peer);
77 }
78 if (NULL != test_ctx->cfg)
79 GNUNET_CONFIGURATION_destroy (test_ctx->cfg);
80 if (NULL != test_ctx->system)
81 GNUNET_TESTING_system_destroy (test_ctx->system, GNUNET_YES);
82 GNUNET_free (test_ctx);
83}
84
85
86/**
87 * Main point of test execution
88 */
89static void
90run (void *cls, char *const *args, const char *cfgfile,
91 const struct GNUNET_CONFIGURATION_Handle *cfg)
92{
93 struct TestingContext *test_ctx;
94 char *emsg;
95 struct GNUNET_PeerIdentity id;
96
97 test_ctx = GNUNET_new (struct TestingContext);
98 test_ctx->system =
99 GNUNET_TESTING_system_create ("test-gnunet-testing",
100 "127.0.0.1", NULL, NULL);
101 emsg = NULL;
102 if (NULL == test_ctx->system)
103 goto end;
104 test_ctx->cfg = GNUNET_CONFIGURATION_dup (cfg);
105 test_ctx->peer =
106 GNUNET_TESTING_peer_configure (test_ctx->system,
107 test_ctx->cfg,
108 0, &id, &emsg);
109 if (NULL == test_ctx->peer)
110 {
111 if (NULL != emsg)
112 printf ("Test failed upon error: %s", emsg);
113 goto end;
114 }
115 if (GNUNET_OK != GNUNET_TESTING_peer_start (test_ctx->peer))
116 goto end;
117 status = GNUNET_OK;
118
119end:
120 GNUNET_SCHEDULER_add_now (&do_shutdown, test_ctx);
121 GNUNET_free (emsg);
122}
123
124
125int
126main (int argc, char *argv[])
127{
128 struct GNUNET_GETOPT_CommandLineOption options[] = {
129 GNUNET_GETOPT_OPTION_END
130 };
131
132 status = GNUNET_SYSERR;
133 if (GNUNET_OK !=
134 GNUNET_PROGRAM_run (argc, argv,
135 "test_testing_peerstartup",
136 "test case for peerstartup using new testing library",
137 options, &run, NULL))
138 return 1;
139 return (GNUNET_OK == status) ? 0 : 1;
140}
141
142
143/* end of test_testing_peerstartup.c */
diff --git a/src/lib/testing/test_testing_peerstartup2.c b/src/lib/testing/test_testing_peerstartup2.c
deleted file mode 100644
index 8d357cb08..000000000
--- a/src/lib/testing/test_testing_peerstartup2.c
+++ /dev/null
@@ -1,222 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/test_testing_new_peerstartup.c
23 * @brief test case for testing peer startup and shutdown using new testing
24 * library
25 * @author Sree Harsha Totakura
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testing_lib.h"
31
32#define LOG(kind, ...) \
33 GNUNET_log (kind, __VA_ARGS__)
34
35
36#define FAIL_TEST(cond) \
37 do { \
38 if (! (cond)) { \
39 GNUNET_break (0); \
40 if (GNUNET_OK == status) { \
41 status = GNUNET_SYSERR; \
42 } \
43 } \
44 } while (0) \
45
46
47/**
48 * The status of the test
49 */
50int status;
51
52/**
53 * The testing context
54 */
55struct TestingContext
56{
57 /**
58 * The testing system
59 */
60 struct GNUNET_TESTING_System *system;
61
62 /**
63 * The peer which has been started by the testing system
64 */
65 struct GNUNET_TESTING_Peer *peer;
66
67 /**
68 * The running configuration of the peer
69 */
70 struct GNUNET_CONFIGURATION_Handle *cfg;
71
72 /**
73 * State
74 */
75 enum
76 {
77 PEER_INIT,
78
79 PEER_STARTED,
80
81 PEER_STOPPED
82 } state;
83};
84
85
86static void
87do_shutdown2 (void *cls)
88{
89 struct TestingContext *test_ctx = cls;
90
91 if (NULL != test_ctx->peer)
92 GNUNET_TESTING_peer_destroy (test_ctx->peer);
93 if (NULL != test_ctx->cfg)
94 GNUNET_CONFIGURATION_destroy (test_ctx->cfg);
95 if (NULL != test_ctx->system)
96 GNUNET_TESTING_system_destroy (test_ctx->system, GNUNET_YES);
97 GNUNET_free (test_ctx);
98}
99
100
101/**
102 * Task for shutdown
103 *
104 * @param cls the testing context
105 */
106static void
107do_shutdown (void *cls);
108
109
110static void
111peer_status_cb (void *cls, struct GNUNET_TESTING_Peer *peer, int success)
112{
113 struct TestingContext *test_ctx = cls;
114
115 switch (test_ctx->state)
116 {
117 case PEER_INIT:
118 FAIL_TEST (0);
119 break;
120
121 case PEER_STARTED:
122 FAIL_TEST (GNUNET_YES == success);
123 test_ctx->state = PEER_STOPPED;
124 GNUNET_SCHEDULER_add_now (&do_shutdown2, cls);
125 break;
126
127 case PEER_STOPPED:
128 FAIL_TEST (0);
129 }
130}
131
132
133/**
134 * Task for shutdown
135 *
136 * @param cls the testing context
137 */
138static void
139do_shutdown (void *cls)
140{
141 struct TestingContext *test_ctx = cls;
142
143 GNUNET_assert (NULL != test_ctx);
144 if (NULL != test_ctx->peer)
145 {
146 FAIL_TEST (GNUNET_OK ==
147 GNUNET_TESTING_peer_stop_async (test_ctx->peer,
148 &peer_status_cb,
149 test_ctx));
150 }
151 else
152 do_shutdown2 (test_ctx);
153}
154
155
156/**
157 * Main point of test execution
158 */
159static void
160run (void *cls, char *const *args, const char *cfgfile,
161 const struct GNUNET_CONFIGURATION_Handle *cfg)
162{
163 struct TestingContext *test_ctx;
164 char *emsg;
165 struct GNUNET_PeerIdentity id;
166
167 test_ctx = GNUNET_new (struct TestingContext);
168 test_ctx->system =
169 GNUNET_TESTING_system_create ("test-gnunet-testing",
170 "127.0.0.1", NULL, NULL);
171 emsg = NULL;
172 if (NULL == test_ctx->system)
173 goto end;
174 test_ctx->cfg = GNUNET_CONFIGURATION_dup (cfg);
175 test_ctx->peer =
176 GNUNET_TESTING_peer_configure (test_ctx->system,
177 test_ctx->cfg,
178 0, &id, &emsg);
179 if (NULL == test_ctx->peer)
180 {
181 if (NULL != emsg)
182 printf ("Test failed upon error: %s", emsg);
183 goto end;
184 }
185 if (GNUNET_OK != GNUNET_TESTING_peer_start (test_ctx->peer))
186 goto end;
187 test_ctx->state = PEER_STARTED;
188 FAIL_TEST (GNUNET_OK ==
189 GNUNET_TESTING_peer_stop_async (test_ctx->peer,
190 &peer_status_cb,
191 test_ctx));
192 GNUNET_TESTING_peer_stop_async_cancel (test_ctx->peer);
193 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
194 &do_shutdown, test_ctx);
195 return;
196
197end:
198 FAIL_TEST (0);
199 GNUNET_SCHEDULER_add_now (&do_shutdown, test_ctx);
200 GNUNET_free (emsg);
201}
202
203
204int
205main (int argc, char *argv[])
206{
207 struct GNUNET_GETOPT_CommandLineOption options[] = {
208 GNUNET_GETOPT_OPTION_END
209 };
210
211 status = GNUNET_OK;
212 if (GNUNET_OK !=
213 GNUNET_PROGRAM_run (argc, argv,
214 "test_testing_new_peerstartup",
215 "test case for peerstartup using new testing library",
216 options, &run, NULL))
217 return 1;
218 return (GNUNET_OK == status) ? 0 : 1;
219}
220
221
222/* end of test_testing_peerstartup.c */
diff --git a/src/lib/testing/test_testing_portreservation.c b/src/lib/testing/test_testing_portreservation.c
deleted file mode 100644
index df3d8d523..000000000
--- a/src/lib/testing/test_testing_portreservation.c
+++ /dev/null
@@ -1,105 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/test_testing_new_portreservation.c
23 * @brief test case for testing port reservation routines from the new testing
24 * library API
25 * @author Sree Harsha Totakura
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testing_lib.h"
31
32#define LOG(kind, ...) \
33 GNUNET_log (kind, __VA_ARGS__)
34
35/**
36 * The status of the test
37 */
38int status;
39
40/**
41 * Main point of test execution
42 */
43static void
44run (void *cls, char *const *args, const char *cfgfile,
45 const struct GNUNET_CONFIGURATION_Handle *cfg)
46{
47 struct GNUNET_TESTING_System *system;
48 uint16_t new_port1;
49 uint16_t new_port2;
50 uint16_t old_port1;
51
52 system = GNUNET_TESTING_system_create ("/tmp/gnunet-testing-new",
53 "localhost", NULL, NULL);
54 GNUNET_assert (NULL != system);
55 new_port1 = GNUNET_TESTING_reserve_port (system);
56 LOG (GNUNET_ERROR_TYPE_DEBUG,
57 "Reserved TCP port %u\n", new_port1);
58 if (0 == new_port1)
59 goto end;
60 new_port2 = GNUNET_TESTING_reserve_port (system);
61 LOG (GNUNET_ERROR_TYPE_DEBUG,
62 "Reserved TCP port %u\n", new_port2);
63 if (0 == new_port2)
64 goto end;
65 GNUNET_assert (new_port1 != new_port2);
66 GNUNET_TESTING_release_port (system, new_port1);
67 old_port1 = new_port1;
68 new_port1 = 0;
69 new_port1 = GNUNET_TESTING_reserve_port (system);
70 LOG (GNUNET_ERROR_TYPE_DEBUG,
71 "Reserved TCP port %u\n", new_port1);
72 GNUNET_assert (0 != new_port1);
73 GNUNET_assert (old_port1 == new_port1);
74 GNUNET_TESTING_release_port (system, new_port1);
75 GNUNET_TESTING_release_port (system, new_port2);
76 status = GNUNET_OK;
77
78end:
79 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
80}
81
82
83int
84main (int argc, char *argv[])
85{
86 struct GNUNET_GETOPT_CommandLineOption options[] = {
87 GNUNET_GETOPT_OPTION_END
88 };
89
90 status = GNUNET_SYSERR;
91 if (GNUNET_OK !=
92 GNUNET_PROGRAM_run (argc,
93 argv,
94 "test_testing_new_portreservation",
95 "test case for testing port reservation routines"
96 " from the new testing library API",
97 options,
98 &run,
99 NULL))
100 return 1;
101 return (GNUNET_OK == status) ? 0 : 1;
102}
103
104
105/* end of test_testing_portreservation.c */
diff --git a/src/lib/testing/test_testing_servicestartup.c b/src/lib/testing/test_testing_servicestartup.c
deleted file mode 100644
index 83458898b..000000000
--- a/src/lib/testing/test_testing_servicestartup.c
+++ /dev/null
@@ -1,75 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/test_testing_new_servicestartup.c
23 * @brief test case for testing service startup using new testing API
24 * @author Sree Harsha Totakura
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_lib.h"
29
30
31#define LOG(kind, ...) \
32 GNUNET_log (kind, __VA_ARGS__)
33
34
35/**
36 * Global test status
37 */
38static int test_success;
39
40
41/**
42 * The testing callback function
43 *
44 * @param cls NULL
45 * @param cfg the configuration with which the current testing service is run
46 */
47static void
48test_run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
49 struct GNUNET_TESTING_Peer *peer)
50{
51 GNUNET_assert (NULL == cls);
52 GNUNET_assert (NULL != cfg);
53 LOG (GNUNET_ERROR_TYPE_DEBUG, "Service arm started successfully\n");
54 test_success = GNUNET_YES;
55 GNUNET_SCHEDULER_shutdown ();
56}
57
58
59/**
60 * The main point of execution
61 */
62int
63main (int argc, char *argv[])
64{
65 test_success = GNUNET_NO;
66 GNUNET_assert (0 == GNUNET_TESTING_service_run ("test-testing-servicestartup",
67 "arm",
68 "test_testing_defaults.conf",
69 &test_run,
70 NULL));
71 return (GNUNET_YES == test_success) ? 0 : 1;
72}
73
74
75/* end of test_testing_servicestartup.c */
diff --git a/src/lib/testing/test_testing_sharedservices.c b/src/lib/testing/test_testing_sharedservices.c
deleted file mode 100644
index d2f760d7a..000000000
--- a/src/lib/testing/test_testing_sharedservices.c
+++ /dev/null
@@ -1,167 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/test_testing_sharedservices.c
23 * @brief test case for testing service sharing among peers started by testing
24 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testing_lib.h"
30
31#define LOG(kind, ...) \
32 GNUNET_log (kind, __VA_ARGS__)
33
34#define NUM_PEERS 4
35
36/**
37 * The status of the test
38 */
39int status;
40
41/**
42 * The testing context
43 */
44struct TestingContext
45{
46 /**
47 * The testing system
48 */
49 struct GNUNET_TESTING_System *system;
50
51 /**
52 * The peer which has been started by the testing system
53 */
54 struct GNUNET_TESTING_Peer *peers[NUM_PEERS];
55
56 /**
57 * The running configuration of the peer
58 */
59 struct GNUNET_CONFIGURATION_Handle *cfg;
60};
61
62
63/**
64 * Task for shutdown
65 *
66 * @param cls the testing context
67 */
68static void
69do_shutdown (void *cls)
70{
71 struct TestingContext *test_ctx = cls;
72 struct GNUNET_TESTING_Peer *peer;
73 unsigned int cnt;
74
75 GNUNET_assert (NULL != test_ctx);
76 for (cnt = 0; cnt < NUM_PEERS; cnt++)
77 {
78 peer = test_ctx->peers[cnt];
79 if (NULL == peer)
80 continue;
81 (void) GNUNET_TESTING_peer_stop (peer);
82 GNUNET_TESTING_peer_destroy (peer);
83 }
84 if (NULL != test_ctx->cfg)
85 GNUNET_CONFIGURATION_destroy (test_ctx->cfg);
86 if (NULL != test_ctx->system)
87 GNUNET_TESTING_system_destroy (test_ctx->system, GNUNET_YES);
88 GNUNET_free (test_ctx);
89}
90
91
92/**
93 * Main point of test execution
94 */
95static void
96run (void *cls, char *const *args, const char *cfgfile,
97 const struct GNUNET_CONFIGURATION_Handle *cfg)
98{
99 struct TestingContext *test_ctx;
100 char *emsg;
101 struct GNUNET_PeerIdentity id;
102 struct GNUNET_TESTING_SharedService ss[] = {
103 { "peerinfo", cfg, 2 },
104 { NULL, NULL, 0 }
105 };
106 struct GNUNET_TESTING_Peer *peer;
107 unsigned int cnt;
108
109 test_ctx = GNUNET_new (struct TestingContext);
110 test_ctx->system =
111 GNUNET_TESTING_system_create ("test-gnunet-testing",
112 "127.0.0.1", NULL, ss);
113 emsg = NULL;
114 if (NULL == test_ctx->system)
115 goto end;
116 test_ctx->cfg = GNUNET_CONFIGURATION_dup (cfg);
117 for (cnt = 0; cnt < NUM_PEERS; cnt++)
118 {
119 peer = GNUNET_TESTING_peer_configure (test_ctx->system,
120 test_ctx->cfg,
121 0, &id, &emsg);
122 if (NULL == peer)
123 {
124 if (NULL != emsg)
125 printf ("Test failed upon error: %s", emsg);
126 goto end;
127 }
128 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
129 {
130 GNUNET_TESTING_peer_destroy (peer);
131 goto end;
132 }
133 test_ctx->peers[cnt] = peer;
134 }
135 status = GNUNET_OK;
136 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
137 &do_shutdown, test_ctx);
138 return;
139
140end:
141 GNUNET_SCHEDULER_add_now (&do_shutdown, test_ctx);
142 GNUNET_free (emsg);
143}
144
145
146int
147main (int argc, char *argv[])
148{
149 struct GNUNET_GETOPT_CommandLineOption options[] = {
150 GNUNET_GETOPT_OPTION_END
151 };
152 char *const argv2[] = { "test_testing_sharedservices",
153 "-c", "test_testing_sharedservices.conf",
154 NULL };
155
156 status = GNUNET_SYSERR;
157 if (GNUNET_OK !=
158 GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2,
159 "test_testing_sharedservices",
160 "test case for testing service sharing among peers started by testing",
161 options, &run, NULL))
162 return 1;
163 return (GNUNET_OK == status) ? 0 : 3;
164}
165
166
167/* end of test_testing_sharedservices.c */
diff --git a/src/lib/testing/test_testing_sharedservices.conf b/src/lib/testing/test_testing_sharedservices.conf
deleted file mode 100644
index 92eac7e71..000000000
--- a/src/lib/testing/test_testing_sharedservices.conf
+++ /dev/null
@@ -1,30 +0,0 @@
1[PATHS]
2GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-testing/
3
4[testbed-logger]
5PORT = 59132
6UNIXPATH = $GNUNET_RUNTIME_DIR/testbed-logger.sock
7DIR = $GNUNET_TMP/testbed-logger
8
9[transport]
10PLUGINS = tcp
11
12[transport-tcp]
13TESTING_IGNORE_KEYS = SOMETHING;KEY1;ACCEPT_FROM;
14
15[transport-tcp]
16BINDTO = 127.0.0.1
17
18[nat]
19DISABLEV6 = YES
20ENABLE_UPNP = NO
21BEHIND_NAT = NO
22ALLOW_NAT = NO
23INTERNAL_ADDRESS = 127.0.0.1
24EXTERNAL_ADDRESS = 127.0.0.1
25USE_LOCALADDR = NO
26
27
28[rps]
29START_ON_DEMAND = NO
30IMMEDIATE_START = NO
diff --git a/src/lib/testing/test_testing_start_with_config.c b/src/lib/testing/test_testing_start_with_config.c
deleted file mode 100644
index a2c692dbc..000000000
--- a/src/lib/testing/test_testing_start_with_config.c
+++ /dev/null
@@ -1,121 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file transport/test_transport_start_with_config.c
23 * @brief Generic program to start testcases in an configurable topology.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30
31#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
32
33
34int
35main (int argc,
36 char *const *argv)
37{
38 char *topology_data;
39 char *topology_data_script;
40 struct GNUNET_TESTING_NetjailTopology *topology;
41 unsigned int read_file = GNUNET_YES;
42 int ret;
43 char *rest = NULL;
44 char *token;
45 size_t single_line_len;
46 size_t data_len;
47
48 GNUNET_log_setup ("test-netjail",
49 "INFO",
50 NULL);
51
52 if (0 == strcmp ("-s", argv[1]))
53 {
54 data_len = strlen (argv[2]);
55 topology_data = GNUNET_malloc (data_len);
56 topology_data_script = GNUNET_malloc (data_len);
57 token = strtok_r (argv[2], "\n", &rest);
58 while (NULL != token)
59 {
60 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
61 "token1 %s\n",
62 token);
63 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
64 "token2 %s\n",
65 token);
66 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
67 "topology_data %s\n",
68 topology_data);
69 strcat (topology_data_script, token);
70 strcat (topology_data_script, " ");
71 strcat (topology_data, token);
72 strcat (topology_data, "\n");
73 token = strtok_r (NULL, "\n", &rest);
74 }
75 single_line_len = strlen (topology_data);
76 topology_data_script [single_line_len - 1] = '\0';
77 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
78 "read from string\n");
79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
80 "topology_data %s\n",
81 topology_data);
82 read_file = GNUNET_NO;
83 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
84 }
85 else
86 {
87 topology_data = argv[1];
88 topology_data_script = argv[1];
89 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
90 }
91
92 struct GNUNET_TESTING_Command commands[] = {
93 GNUNET_TESTING_cmd_netjail_start ("netjail-start",
94 topology_data_script,
95 &read_file),
96 GNUNET_TESTING_cmd_netjail_start_cmds_helper ("netjail-start-testbed",
97 topology,
98 &read_file,
99 topology_data_script,
100 TIMEOUT),
101 GNUNET_TESTING_cmd_stop_cmds_helper ("stop-testbed",
102 "netjail-start-testbed",
103 topology),
104 GNUNET_TESTING_cmd_netjail_stop ("netjail-stop",
105 topology_data_script,
106 &read_file),
107 GNUNET_TESTING_cmd_end ()
108 };
109
110 ret = GNUNET_TESTING_main (commands,
111 TIMEOUT);
112
113 if (0 == strcmp ("-s", argv[1]))
114 {
115 GNUNET_free (topology_data_script);
116 GNUNET_free (topology_data);
117 }
118 GNUNET_TESTING_free_topology (topology);
119
120 return ret;
121}
diff --git a/src/lib/testing/testing.c b/src/lib/testing/testing.c
deleted file mode 100644
index fdfa80d87..000000000
--- a/src/lib/testing/testing.c
+++ /dev/null
@@ -1,2830 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing.c
23 * @brief convenience API for writing testcases for GNUnet
24 * Many testcases need to start and stop a peer/service
25 * and this library is supposed to make that easier
26 * for TESTCASES. Normal programs should always
27 * use functions from gnunet_{util,arm}_lib.h. This API is
28 * ONLY for writing testcases (or internal use of the testbed).
29 * @author Christian Grothoff
30 *
31 */
32#include "platform.h"
33#include "gnunet_util_lib.h"
34#include "gnunet_arm_service.h"
35#include "gnunet_testing_lib.h"
36#include "gnunet_testing_ng_lib.h"
37#include "gnunet_testing_plugin.h"
38#include "gnunet_testing_barrier.h"
39#include "gnunet_testing_netjail_lib.h"
40#include "testing_cmds.h"
41
42#define LOG(kind, ...) GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
43
44#define CONNECT_ADDRESS_TEMPLATE "%s-192.168.15.%u"
45
46#define ROUTER_CONNECT_ADDRESS_TEMPLATE "%s-92.68.150.%u"
47
48#define KNOWN_CONNECT_ADDRESS_TEMPLATE "%s-92.68.151.%u"
49
50/* Use the IP addresses below instead of the public ones,
51 * if the start script was not started from within a new namespace
52 * created by unshare. The UPNP test case needs public IP
53 * addresse for miniupnpd to function.
54 * FIXME We should introduce a switch indicating if public
55 * addresses should be used or not. This info has to be
56 * propagated from the start script to the c code.
57#define ROUTER_CONNECT_ADDRESS_TEMPLATE "%s-172.16.150.%u"
58
59#define KNOWN_CONNECT_ADDRESS_TEMPLATE "%s-172.16.151.%u"
60*/
61
62#define PREFIX_TCP "tcp"
63
64#define PREFIX_UDP "udp"
65
66#define PREFIX_TCP_NATTED "tcp_natted"
67
68#define PREFIX_UDP_NATTED "udp_natted"
69
70/**
71 * Lowest port used for GNUnet testing. Should be high enough to not
72 * conflict with other applications running on the hosts but be low
73 * enough to not conflict with client-ports (typically starting around
74 * 32k).
75 */
76#define LOW_PORT 12000
77
78/**
79 * Highest port used for GNUnet testing. Should be low enough to not
80 * conflict with the port range for "local" ports (client apps; see
81 * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
82 */
83#define HIGH_PORT 56000
84
85
86struct SharedServiceInstance
87{
88 struct SharedService *ss;
89
90 char *cfg_fn;
91
92 struct GNUNET_OS_Process *proc;
93
94 char *unix_sock;
95
96 char *port_str;
97
98 unsigned int n_refs;
99};
100
101struct SharedService
102{
103 char *sname;
104
105 struct SharedServiceInstance **instances;
106
107 struct GNUNET_CONFIGURATION_Handle *cfg;
108
109 unsigned int n_peers;
110
111 unsigned int share;
112
113 unsigned int n_instances;
114};
115
116
117/**
118 * Handle for a system on which GNUnet peers are executed;
119 * a system is used for reserving unique paths and ports.
120 */
121struct GNUNET_TESTING_System
122{
123 /**
124 * Prefix (e.g. "/tmp/gnunet-testing/") we prepend to each
125 * GNUNET_HOME.
126 */
127 char *tmppath;
128
129 /**
130 * The trusted ip. Can either be a single ip address or a network address in
131 * CIDR notation.
132 */
133 char *trusted_ip;
134
135 /**
136 * our hostname
137 */
138 char *hostname;
139
140 /**
141 * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes.
142 */
143 char *hostkeys_data;
144
145 /**
146 * memory map for @e hostkeys_data.
147 */
148 struct GNUNET_DISK_MapHandle *map;
149
150 struct SharedService *shared_services;
151
152 unsigned int n_shared_services;
153
154 /**
155 * Bitmap where each port that has already been reserved for some GNUnet peer
156 * is recorded. Note that we make no distinction between TCP and UDP ports
157 * and test if a port is already in use before assigning it to a peer/service.
158 * If we detect that a port is already in use, we also mark it in this bitmap.
159 * So all the bits that are zero merely indicate ports that MIGHT be available
160 * for peers.
161 */
162 uint32_t reserved_ports[65536 / 32];
163
164 /**
165 * Counter we use to make service home paths unique on this system;
166 * the full path consists of the tmppath and this number. Each
167 * UNIXPATH for a peer is also modified to include the respective
168 * path counter to ensure uniqueness. This field is incremented
169 * by one for each configured peer. Even if peers are destroyed,
170 * we never re-use path counters.
171 */
172 uint32_t path_counter;
173
174 /**
175 * The number of hostkeys
176 */
177 uint32_t total_hostkeys;
178
179 /**
180 * Lowest port we are allowed to use.
181 */
182 uint16_t lowport;
183
184 /**
185 * Highest port we are allowed to use.
186 */
187 uint16_t highport;
188};
189
190
191/**
192 * Handle for a GNUnet peer controlled by testing.
193 */
194struct GNUNET_TESTING_Peer
195{
196 /**
197 * The TESTING system associated with this peer
198 */
199 struct GNUNET_TESTING_System *system;
200
201 /**
202 * Path to the configuration file for this peer.
203 */
204 char *cfgfile;
205
206 /**
207 * Binary to be executed during 'GNUNET_TESTING_peer_start'.
208 * Typically 'gnunet-service-arm' (but can be set to a
209 * specific service by 'GNUNET_TESTING_service_run' if
210 * necessary).
211 */
212 char *main_binary;
213 char *args;
214
215 /**
216 * Handle to the running binary of the service, NULL if the
217 * peer/service is currently not running.
218 */
219 struct GNUNET_OS_Process *main_process;
220
221 /**
222 * The handle to the peer's ARM service
223 */
224 struct GNUNET_ARM_Handle *ah;
225
226 /**
227 * The config of the peer
228 */
229 struct GNUNET_CONFIGURATION_Handle *cfg;
230
231 /**
232 * The callback to call asynchronously when a peer is stopped
233 */
234 GNUNET_TESTING_PeerStopCallback cb;
235
236 /**
237 * The closure for the above callback
238 */
239 void *cb_cls;
240
241 /**
242 * The cached identity of this peer. Will be populated on call to
243 * GNUNET_TESTING_peer_get_identity()
244 */
245 struct GNUNET_PeerIdentity *id;
246
247 struct SharedServiceInstance **ss_instances;
248
249 /**
250 * Array of ports currently allocated to this peer. These ports will be
251 * released upon peer destroy and can be used by other peers which are
252 * configured after.
253 */
254 uint16_t *ports;
255
256 /**
257 * The number of ports in the above array
258 */
259 unsigned int nports;
260
261 /**
262 * The keynumber of this peer's hostkey
263 */
264 uint32_t key_number;
265};
266
267
268/**
269 * Testing includes a number of pre-created hostkeys for faster peer
270 * startup. This function loads such keys into memory from a file.
271 *
272 * @param system the testing system handle
273 * @return #GNUNET_OK on success; #GNUNET_SYSERR on error
274 */
275static enum GNUNET_GenericReturnValue
276hostkeys_load (struct GNUNET_TESTING_System *system)
277{
278 uint64_t fs;
279 char *data_dir;
280 char *filename;
281 struct GNUNET_DISK_FileHandle *fd;
282
283 GNUNET_assert (NULL == system->hostkeys_data);
284 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
285 GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir);
286 GNUNET_free (data_dir);
287
288 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
289 {
290 LOG (GNUNET_ERROR_TYPE_ERROR,
291 _ ("Hostkeys file not found: %s\n"),
292 filename);
293 GNUNET_free (filename);
294 return GNUNET_SYSERR;
295 }
296 /* Check hostkey file size, read entire thing into memory */
297 if (GNUNET_OK !=
298 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
299 fs = 0;
300 if (0 == fs)
301 {
302 GNUNET_free (filename);
303 return GNUNET_SYSERR; /* File is empty */
304 }
305 if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE))
306 {
307 LOG (GNUNET_ERROR_TYPE_ERROR,
308 _ ("Incorrect hostkey file format: %s\n"),
309 filename);
310 GNUNET_free (filename);
311 return GNUNET_SYSERR;
312 }
313 fd = GNUNET_DISK_file_open (filename,
314 GNUNET_DISK_OPEN_READ,
315 GNUNET_DISK_PERM_NONE);
316 if (NULL == fd)
317 {
318 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
319 GNUNET_free (filename);
320 return GNUNET_SYSERR;
321 }
322 GNUNET_free (filename);
323 system->hostkeys_data =
324 GNUNET_DISK_file_map (fd, &system->map, GNUNET_DISK_MAP_TYPE_READ, fs);
325 GNUNET_DISK_file_close (fd);
326 if (NULL == system->hostkeys_data)
327 return GNUNET_SYSERR;
328 system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE;
329 return GNUNET_OK;
330}
331
332
333/**
334 * Function to remove the loaded hostkeys
335 *
336 * @param system the testing system handle
337 */
338static void
339hostkeys_unload (struct GNUNET_TESTING_System *system)
340{
341 GNUNET_break (NULL != system->hostkeys_data);
342 system->hostkeys_data = NULL;
343 GNUNET_DISK_file_unmap (system->map);
344 system->map = NULL;
345 system->hostkeys_data = NULL;
346 system->total_hostkeys = 0;
347}
348
349
350/**
351 * Function to iterate over options.
352 *
353 * @param cls closure
354 * @param section name of the section
355 * @param option name of the option
356 * @param value value of the option
357 */
358static void
359cfg_copy_iterator (void *cls,
360 const char *section,
361 const char *option,
362 const char *value)
363{
364 struct GNUNET_CONFIGURATION_Handle *cfg2 = cls;
365
366 GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value);
367}
368
369
370/**
371 * Create a system handle. There must only be one system
372 * handle per operating system.
373 *
374 * @param testdir only the directory name without any path. This is used for
375 * all service homes; the directory will be created in a temporary
376 * location depending on the underlying OS. This variable will be
377 * overridden with the value of the environmental variable
378 * GNUNET_TESTING_PREFIX, if it exists.
379 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
380 * service configurations generated to allow control connections from
381 * this ip. This can either be a single ip address or a network address
382 * in CIDR notation.
383 * @param hostname the hostname of the system we are using for testing; NULL for
384 * localhost
385 * @param shared_services NULL terminated array describing services that are to
386 * be shared among peers
387 * @param lowport lowest port number this system is allowed to allocate (inclusive)
388 * @param highport highest port number this system is allowed to allocate (exclusive)
389 * @return handle to this system, NULL on error
390 */
391struct GNUNET_TESTING_System *
392GNUNET_TESTING_system_create_with_portrange (
393 const char *testdir,
394 const char *trusted_ip,
395 const char *hostname,
396 const struct GNUNET_TESTING_SharedService *shared_services,
397 uint16_t lowport,
398 uint16_t highport)
399{
400 struct GNUNET_TESTING_System *system;
401 struct GNUNET_TESTING_SharedService tss;
402 struct SharedService ss;
403 unsigned int cnt;
404
405 GNUNET_assert (NULL != testdir);
406 system = GNUNET_new (struct GNUNET_TESTING_System);
407 if (NULL == (system->tmppath = getenv (GNUNET_TESTING_PREFIX)))
408 system->tmppath = GNUNET_DISK_mkdtemp (testdir);
409 else
410 system->tmppath = GNUNET_strdup (system->tmppath);
411 system->lowport = lowport;
412 system->highport = highport;
413 if (NULL == system->tmppath)
414 {
415 GNUNET_free (system);
416 return NULL;
417 }
418 if (NULL != trusted_ip)
419 system->trusted_ip = GNUNET_strdup (trusted_ip);
420 if (NULL != hostname)
421 system->hostname = GNUNET_strdup (hostname);
422 if (GNUNET_OK != hostkeys_load (system))
423 {
424 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
425 return NULL;
426 }
427 if (NULL == shared_services)
428 return system;
429 for (cnt = 0; NULL != shared_services[cnt].service; cnt++)
430 {
431 tss = shared_services[cnt];
432 memset (&ss, 0, sizeof (ss));
433 ss.sname = GNUNET_strdup (tss.service);
434 ss.cfg = GNUNET_CONFIGURATION_create ();
435 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg,
436 ss.sname,
437 &cfg_copy_iterator,
438 ss.cfg);
439 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg,
440 "TESTING",
441 &cfg_copy_iterator,
442 ss.cfg);
443 GNUNET_CONFIGURATION_iterate_section_values (tss.cfg,
444 "PATHS",
445 &cfg_copy_iterator,
446 ss.cfg);
447 ss.share = tss.share;
448 GNUNET_array_append (system->shared_services,
449 system->n_shared_services,
450 ss);
451 }
452 return system;
453}
454
455
456/**
457 * Create a system handle. There must only be one system handle per operating
458 * system. Uses a default range for allowed ports. Ports are still tested for
459 * availability.
460 *
461 * @param testdir only the directory name without any path. This is used for all
462 * service homes; the directory will be created in a temporary location
463 * depending on the underlying OS. This variable will be
464 * overridden with the value of the environmental variable
465 * GNUNET_TESTING_PREFIX, if it exists.
466 * @param trusted_ip the ip address which will be set as TRUSTED HOST in all
467 * service configurations generated to allow control connections from
468 * this ip. This can either be a single ip address or a network address
469 * in CIDR notation.
470 * @param hostname the hostname of the system we are using for testing; NULL for
471 * localhost
472 * @param shared_services NULL terminated array describing services that are to
473 * be shared among peers
474 * @return handle to this system, NULL on error
475 */
476struct GNUNET_TESTING_System *
477GNUNET_TESTING_system_create (
478 const char *testdir,
479 const char *trusted_ip,
480 const char *hostname,
481 const struct GNUNET_TESTING_SharedService *shared_services)
482{
483 return GNUNET_TESTING_system_create_with_portrange (testdir,
484 trusted_ip,
485 hostname,
486 shared_services,
487 LOW_PORT,
488 HIGH_PORT);
489}
490
491
492static void
493cleanup_shared_service_instance (struct SharedServiceInstance *i)
494{
495 if (NULL != i->cfg_fn)
496 {
497 (void) unlink (i->cfg_fn);
498 GNUNET_free (i->cfg_fn);
499 }
500 GNUNET_free (i->unix_sock);
501 GNUNET_free (i->port_str);
502 GNUNET_break (NULL == i->proc);
503 GNUNET_break (0 == i->n_refs);
504 GNUNET_free (i);
505}
506
507
508static enum GNUNET_GenericReturnValue
509start_shared_service_instance (struct SharedServiceInstance *i)
510{
511 char *binary;
512 char *libexec_binary;
513
514 GNUNET_assert (NULL == i->proc);
515 GNUNET_assert (NULL != i->cfg_fn);
516 (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
517 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
518 GNUNET_free (binary);
519 i->proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
520 NULL,
521 NULL,
522 NULL,
523 libexec_binary,
524 libexec_binary,
525 "-c",
526 i->cfg_fn,
527 NULL);
528 GNUNET_free (libexec_binary);
529 if (NULL == i->proc)
530 return GNUNET_SYSERR;
531 return GNUNET_OK;
532}
533
534
535static void
536stop_shared_service_instance (struct SharedServiceInstance *i)
537{
538 GNUNET_break (0 == i->n_refs);
539 if (0 != GNUNET_OS_process_kill (i->proc, GNUNET_TERM_SIG))
540 LOG (GNUNET_ERROR_TYPE_WARNING,
541 "Killing shared service instance (%s) failed\n",
542 i->ss->sname);
543 (void) GNUNET_OS_process_wait (i->proc);
544 GNUNET_OS_process_destroy (i->proc);
545 i->proc = NULL;
546}
547
548
549/**
550 * Free system resources.
551 *
552 * @param system system to be freed
553 * @param remove_paths should the 'testdir' and all subdirectories
554 * be removed (clean up on shutdown)?
555 */
556void
557GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system,
558 int remove_paths)
559{
560 struct SharedService *ss;
561 struct SharedServiceInstance *i;
562 unsigned int ss_cnt;
563 unsigned int i_cnt;
564
565 if (NULL != system->hostkeys_data)
566 hostkeys_unload (system);
567 for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++)
568 {
569 ss = &system->shared_services[ss_cnt];
570 for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++)
571 {
572 i = ss->instances[i_cnt];
573 if (NULL != i->proc)
574 stop_shared_service_instance (i);
575 cleanup_shared_service_instance (i);
576 }
577 GNUNET_free (ss->instances);
578 GNUNET_CONFIGURATION_destroy (ss->cfg);
579 GNUNET_free (ss->sname);
580 }
581 GNUNET_free (system->shared_services);
582 if (GNUNET_YES == remove_paths)
583 GNUNET_DISK_directory_remove (system->tmppath);
584 GNUNET_free (system->tmppath);
585 GNUNET_free (system->trusted_ip);
586 GNUNET_free (system->hostname);
587 GNUNET_free (system);
588}
589
590
591/**
592 * Reserve a TCP or UDP port for a peer.
593 *
594 * @param system system to use for reservation tracking
595 * @return 0 if no free port was available
596 */
597uint16_t
598GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system)
599{
600 struct GNUNET_NETWORK_Handle *socket;
601 struct addrinfo hint;
602 struct addrinfo *ret;
603 struct addrinfo *ai;
604 uint32_t *port_buckets;
605 char *open_port_str;
606 int bind_status;
607 uint32_t xor_image;
608 uint16_t index;
609 uint16_t open_port;
610 uint16_t pos;
611
612 /*
613 FIXME: Instead of using getaddrinfo we should try to determine the port
614 status by the following heurestics.
615
616 On systems which support both IPv4 and IPv6, only ports open on both
617 address families are considered open.
618 On system with either IPv4 or IPv6. A port is considered open if it's
619 open in the respective address family
620 */hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
621 hint.ai_socktype = 0;
622 hint.ai_protocol = 0;
623 hint.ai_addrlen = 0;
624 hint.ai_addr = NULL;
625 hint.ai_canonname = NULL;
626 hint.ai_next = NULL;
627 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
628 port_buckets = system->reserved_ports;
629 for (index = (system->lowport / 32) + 1; index < (system->highport / 32);
630 index++)
631 {
632 xor_image = (UINT32_MAX ^ port_buckets[index]);
633 if (0 == xor_image) /* Ports in the bucket are full */
634 continue;
635 pos = system->lowport % 32;
636 while (pos < 32)
637 {
638 if (0 == ((xor_image >> pos) & 1U))
639 {
640 pos++;
641 continue;
642 }
643 open_port = (index * 32) + pos;
644 if (open_port >= system->highport)
645 return 0;
646 GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port);
647 ret = NULL;
648 GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret));
649 GNUNET_free (open_port_str);
650 bind_status = GNUNET_NO;
651 for (ai = ret; NULL != ai; ai = ai->ai_next)
652 {
653 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0);
654 if (NULL == socket)
655 continue;
656 bind_status =
657 GNUNET_NETWORK_socket_bind (socket, ai->ai_addr, ai->ai_addrlen);
658 GNUNET_NETWORK_socket_close (socket);
659 if (GNUNET_OK != bind_status)
660 break;
661 socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0);
662 if (NULL == socket)
663 continue;
664 bind_status =
665 GNUNET_NETWORK_socket_bind (socket, ai->ai_addr, ai->ai_addrlen);
666 GNUNET_NETWORK_socket_close (socket);
667 if (GNUNET_OK != bind_status)
668 break;
669 }
670 port_buckets[index] |= (1U << pos); /* Set the port bit */
671 freeaddrinfo (ret);
672 if (GNUNET_OK == bind_status)
673 {
674 LOG (GNUNET_ERROR_TYPE_DEBUG,
675 "Found a free port %u\n",
676 (unsigned int) open_port);
677 return open_port;
678 }
679 pos++;
680 }
681 }
682 return 0;
683}
684
685
686/**
687 * Release reservation of a TCP or UDP port for a peer
688 * (used during #GNUNET_TESTING_peer_destroy()).
689 *
690 * @param system system to use for reservation tracking
691 * @param port reserved port to release
692 */
693void
694GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system,
695 uint16_t port)
696{
697 uint32_t *port_buckets;
698 uint16_t bucket;
699 uint16_t pos;
700
701 port_buckets = system->reserved_ports;
702 bucket = port / 32;
703 pos = port % 32;
704 LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port);
705 if (0 == (port_buckets[bucket] & (1U << pos)))
706 {
707 GNUNET_break (0); /* Port was not reserved by us using reserve_port() */
708 return;
709 }
710 port_buckets[bucket] &= ~(1U << pos);
711}
712
713
714/**
715 * Testing includes a number of pre-created hostkeys for
716 * faster peer startup. This function can be used to
717 * access the n-th key of those pre-created hostkeys; note
718 * that these keys are ONLY useful for testing and not
719 * secure as the private keys are part of the public
720 * GNUnet source code.
721 *
722 * This is primarily a helper function used internally
723 * by #GNUNET_TESTING_peer_configure.
724 *
725 * @param system the testing system handle
726 * @param key_number desired pre-created hostkey to obtain
727 * @param id set to the peer's identity (hash of the public
728 * key; if NULL, NULL is returned immediately
729 * @return NULL on error (not enough keys)
730 */
731struct GNUNET_CRYPTO_EddsaPrivateKey *
732GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system,
733 uint32_t key_number,
734 struct GNUNET_PeerIdentity *id)
735{
736 struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
737
738 if ((NULL == id) || (NULL == system->hostkeys_data))
739 return NULL;
740 if (key_number >= system->total_hostkeys)
741 {
742 LOG (GNUNET_ERROR_TYPE_ERROR,
743 _ ("Key number %u does not exist\n"),
744 key_number);
745 return NULL;
746 }
747 private_key = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
748 GNUNET_memcpy (private_key,
749 system->hostkeys_data
750 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
751 GNUNET_TESTING_HOSTKEYFILESIZE);
752 GNUNET_CRYPTO_eddsa_key_get_public (private_key, &id->public_key);
753 return private_key;
754}
755
756
757/**
758 * Structure for holding data to build new configurations from a configuration
759 * template
760 */
761struct UpdateContext
762{
763 /**
764 * The system for which we are building configurations
765 */
766 struct GNUNET_TESTING_System *system;
767
768 /**
769 * The configuration we are building
770 */
771 struct GNUNET_CONFIGURATION_Handle *cfg;
772
773 /**
774 * The customized service home path for this peer
775 */
776 char *gnunet_home;
777
778 /**
779 * Array of ports currently allocated to this peer. These ports will be
780 * released upon peer destroy and can be used by other peers which are
781 * configured after.
782 */
783 uint16_t *ports;
784
785 /**
786 * The number of ports in the above array
787 */
788 unsigned int nports;
789
790 /**
791 * build status - to signal error while building a configuration
792 */
793 int status;
794};
795
796
797/**
798 * Function to iterate over options. Copies
799 * the options to the target configuration,
800 * updating PORT values as needed.
801 *
802 * @param cls the UpdateContext
803 * @param section name of the section
804 * @param option name of the option
805 * @param value value of the option
806 */
807static void
808update_config (void *cls,
809 const char *section,
810 const char *option,
811 const char *value)
812{
813 struct UpdateContext *uc = cls;
814 unsigned int ival;
815 char cval[12];
816 char uval[PATH_MAX];
817 char *single_variable;
818 char *per_host_variable;
819 unsigned long long num_per_host;
820 uint16_t new_port;
821
822 if (GNUNET_OK != uc->status)
823 return;
824 if (! ((0 == strcmp (option, "PORT")) || (0 == strcmp (option, "UNIXPATH")) ||
825 (0 == strcmp (option, "HOSTNAME"))))
826 return;
827 GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
828 GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
829 if ((0 == strcmp (option, "PORT")) && (1 == sscanf (value, "%u", &ival)))
830 {
831 if ((ival != 0) &&
832 (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (uc->cfg,
833 "testing",
834 single_variable)))
835 {
836 new_port = GNUNET_TESTING_reserve_port (uc->system);
837 if (0 == new_port)
838 {
839 uc->status = GNUNET_SYSERR;
840 GNUNET_free (single_variable);
841 GNUNET_free (per_host_variable);
842 return;
843 }
844 GNUNET_snprintf (cval, sizeof(cval), "%u", new_port);
845 value = cval;
846 GNUNET_array_append (uc->ports, uc->nports, new_port);
847 }
848 else if ((ival != 0) &&
849 (GNUNET_YES ==
850 GNUNET_CONFIGURATION_get_value_yesno (uc->cfg,
851 "testing",
852 single_variable)) &&
853 GNUNET_CONFIGURATION_get_value_number (uc->cfg,
854 "testing",
855 per_host_variable,
856 &num_per_host))
857 {
858 /* GNUNET_snprintf (cval, sizeof (cval), "%u", */
859 /* ival + ctx->fdnum % num_per_host); */
860 /* value = cval; */
861 GNUNET_break (0); /* FIXME */
862 }
863 }
864 if (0 == strcmp (option, "UNIXPATH"))
865 {
866 if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (uc->cfg,
867 "testing",
868 single_variable))
869 {
870 GNUNET_snprintf (uval,
871 sizeof(uval),
872 "%s/%s.sock",
873 uc->gnunet_home,
874 section);
875 value = uval;
876 }
877 else if ((GNUNET_YES ==
878 GNUNET_CONFIGURATION_get_value_number (uc->cfg,
879 "testing",
880 per_host_variable,
881 &num_per_host)) &&
882 (num_per_host > 0))
883 {
884 GNUNET_break (0); /* FIXME */
885 }
886 }
887 if (0 == strcmp (option, "HOSTNAME"))
888 {
889 value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname;
890 }
891 GNUNET_free (single_variable);
892 GNUNET_free (per_host_variable);
893 GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value);
894}
895
896
897/**
898 * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of
899 * 'trusted_hosts' in all sections
900 *
901 * @param cls the UpdateContext
902 * @param section name of the section
903 */
904static void
905update_config_sections (void *cls, const char *section)
906{
907 struct UpdateContext *uc = cls;
908 char **ikeys;
909 char *val;
910 char *ptr;
911 char *orig_allowed_hosts;
912 char *allowed_hosts;
913 char *ACCEPT_FROM_key;
914 uint16_t ikeys_cnt;
915 uint16_t key;
916
917 ikeys_cnt = 0;
918 val = NULL;
919 /* Ignore certain options from sections. See
920 https://gnunet.org/bugs/view.php?id=2476 */
921 if (GNUNET_YES ==
922 GNUNET_CONFIGURATION_have_value (uc->cfg, section, "TESTING_IGNORE_KEYS"))
923 {
924 GNUNET_assert (GNUNET_YES ==
925 GNUNET_CONFIGURATION_get_value_string (uc->cfg,
926 section,
927 "TESTING_IGNORE_KEYS",
928 &val));
929 ptr = val;
930 for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++)
931 ptr++;
932 if (0 == ikeys_cnt)
933 GNUNET_break (0);
934 else
935 {
936 ikeys = GNUNET_malloc ((sizeof(char *)) * ikeys_cnt);
937 ptr = val;
938 for (key = 0; key < ikeys_cnt; key++)
939 {
940 ikeys[key] = ptr;
941 ptr = strstr (ptr, ";");
942 GNUNET_assert (NULL != ptr); /* worked just before... */
943 *ptr = '\0';
944 ptr++;
945 }
946 }
947 }
948 if (0 != ikeys_cnt)
949 {
950 for (key = 0; key < ikeys_cnt; key++)
951 {
952 if (NULL != strstr (ikeys[key], "ADVERTISED_PORT"))
953 break;
954 }
955 if ((key == ikeys_cnt) &&
956 (GNUNET_YES ==
957 GNUNET_CONFIGURATION_have_value (uc->cfg, section, "ADVERTISED_PORT")))
958 {
959 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (uc->cfg,
960 section,
961 "PORT",
962 &ptr))
963 {
964 GNUNET_CONFIGURATION_set_value_string (uc->cfg,
965 section,
966 "ADVERTISED_PORT",
967 ptr);
968 GNUNET_free (ptr);
969 }
970 }
971 for (key = 0; key < ikeys_cnt; key++)
972 {
973 if (NULL != strstr (ikeys[key], "ACCEPT_FROM"))
974 {
975 GNUNET_free (ikeys);
976 GNUNET_free (val);
977 return;
978 }
979 }
980 GNUNET_free (ikeys);
981 }
982 GNUNET_free (val);
983 ACCEPT_FROM_key = "ACCEPT_FROM";
984 if ((NULL != uc->system->trusted_ip) &&
985 (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */
986 ACCEPT_FROM_key = "ACCEPT_FROM6";
987 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (uc->cfg,
988 section,
989 ACCEPT_FROM_key,
990 &orig_allowed_hosts))
991 {
992 orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;");
993 }
994 if (NULL == uc->system->trusted_ip)
995 allowed_hosts = GNUNET_strdup (orig_allowed_hosts);
996 else
997 GNUNET_asprintf (&allowed_hosts,
998 "%s%s;",
999 orig_allowed_hosts,
1000 uc->system->trusted_ip);
1001 GNUNET_free (orig_allowed_hosts);
1002 GNUNET_CONFIGURATION_set_value_string (uc->cfg,
1003 section,
1004 ACCEPT_FROM_key,
1005 allowed_hosts);
1006 GNUNET_free (allowed_hosts);
1007}
1008
1009
1010static struct SharedServiceInstance *
1011associate_shared_service (struct GNUNET_TESTING_System *system,
1012 struct SharedService *ss,
1013 struct GNUNET_CONFIGURATION_Handle *cfg)
1014{
1015 struct SharedServiceInstance *i;
1016 struct GNUNET_CONFIGURATION_Handle *temp;
1017 char *gnunet_home;
1018 uint32_t port;
1019
1020 ss->n_peers++;
1021 if (((0 == ss->share) && (NULL == ss->instances)) ||
1022 ((0 != ss->share) &&
1023 (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share))))
1024 {
1025 i = GNUNET_new (struct SharedServiceInstance);
1026 i->ss = ss;
1027 (void) GNUNET_asprintf (&gnunet_home,
1028 "%s/shared/%s/%u",
1029 system->tmppath,
1030 ss->sname,
1031 ss->n_instances);
1032 (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", gnunet_home);
1033 port = GNUNET_TESTING_reserve_port (system);
1034 if (0 == port)
1035 {
1036 GNUNET_free (gnunet_home);
1037 cleanup_shared_service_instance (i);
1038 return NULL;
1039 }
1040 GNUNET_array_append (ss->instances, ss->n_instances, i);
1041 temp = GNUNET_CONFIGURATION_dup (ss->cfg);
1042 (void) GNUNET_asprintf (&i->port_str, "%u", port);
1043 (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", gnunet_home);
1044 GNUNET_CONFIGURATION_set_value_string (temp,
1045 "PATHS",
1046 "GNUNET_HOME",
1047 gnunet_home);
1048 GNUNET_free (gnunet_home);
1049 GNUNET_CONFIGURATION_set_value_string (temp,
1050 ss->sname,
1051 "UNIXPATH",
1052 i->unix_sock);
1053 GNUNET_CONFIGURATION_set_value_string (temp,
1054 ss->sname,
1055 "PORT",
1056 i->port_str);
1057 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn))
1058 {
1059 GNUNET_CONFIGURATION_destroy (temp);
1060 cleanup_shared_service_instance (i);
1061 return NULL;
1062 }
1063 GNUNET_CONFIGURATION_destroy (temp);
1064 }
1065 else
1066 {
1067 GNUNET_assert (NULL != ss->instances);
1068 GNUNET_assert (0 < ss->n_instances);
1069 i = ss->instances[ss->n_instances - 1];
1070 }
1071 GNUNET_CONFIGURATION_iterate_section_values (ss->cfg,
1072 ss->sname,
1073 &cfg_copy_iterator,
1074 cfg);
1075 GNUNET_CONFIGURATION_set_value_string (cfg,
1076 ss->sname,
1077 "UNIXPATH",
1078 i->unix_sock);
1079 GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str);
1080 return i;
1081}
1082
1083
1084/**
1085 * Create a new configuration using the given configuration as a template;
1086 * ports and paths will be modified to select available ports on the local
1087 * system. The default configuration will be available in PATHS section under
1088 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1089 * section to the temporary directory specific to this configuration. If we run
1090 * out of "*port" numbers, return #GNUNET_SYSERR.
1091 *
1092 * This is primarily a helper function used internally
1093 * by 'GNUNET_TESTING_peer_configure'.
1094 *
1095 * @param system system to use to coordinate resource usage
1096 * @param cfg template configuration to update
1097 * @param ports array with port numbers used in the created configuration.
1098 * Will be updated upon successful return. Can be NULL
1099 * @param nports the size of the `ports' array. Will be updated.
1100 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1101 * be incomplete and should not be used there upon
1102 */
1103static int
1104GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system,
1105 struct GNUNET_CONFIGURATION_Handle *cfg,
1106 uint16_t **ports,
1107 unsigned int *nports)
1108{
1109 struct UpdateContext uc;
1110 char *default_config;
1111
1112 uc.system = system;
1113 uc.cfg = cfg;
1114 uc.status = GNUNET_OK;
1115 uc.ports = NULL;
1116 uc.nports = 0;
1117 GNUNET_asprintf (&uc.gnunet_home,
1118 "%s/%u",
1119 system->tmppath,
1120 system->path_counter++);
1121 GNUNET_asprintf (&default_config, "%s/config", uc.gnunet_home);
1122 GNUNET_CONFIGURATION_set_value_string (cfg,
1123 "PATHS",
1124 "DEFAULTCONFIG",
1125 default_config);
1126 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG", default_config);
1127 GNUNET_free (default_config);
1128 GNUNET_CONFIGURATION_set_value_string (cfg,
1129 "PATHS",
1130 "GNUNET_HOME",
1131 uc.gnunet_home);
1132 /* make PORTs and UNIXPATHs unique */
1133 GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
1134 /* allow connections to services from system trusted_ip host */
1135 GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc);
1136 /* enable loopback-based connections between peers */
1137 GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "USE_LOCALADDR", "YES");
1138 GNUNET_free (uc.gnunet_home);
1139 if ((NULL != ports) && (NULL != nports))
1140 {
1141 *ports = uc.ports;
1142 *nports = uc.nports;
1143 }
1144 else
1145 GNUNET_free (uc.ports);
1146 return uc.status;
1147}
1148
1149
1150/**
1151 * Create a new configuration using the given configuration as a template;
1152 * ports and paths will be modified to select available ports on the local
1153 * system. The default configuration will be available in PATHS section under
1154 * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS
1155 * section to the temporary directory specific to this configuration. If we run
1156 * out of "*port" numbers, return #GNUNET_SYSERR.
1157 *
1158 * This is primarily a helper function used internally
1159 * by #GNUNET_TESTING_peer_configure().
1160 *
1161 * @param system system to use to coordinate resource usage
1162 * @param cfg template configuration to update
1163 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will
1164 * be incomplete and should not be used there upon
1165 */
1166int
1167GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system,
1168 struct GNUNET_CONFIGURATION_Handle *cfg)
1169{
1170 return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL);
1171}
1172
1173
1174/**
1175 * Configure a GNUnet peer. GNUnet must be installed on the local
1176 * system and available in the PATH.
1177 *
1178 * @param system system to use to coordinate resource usage
1179 * @param cfg configuration to use; will be UPDATED (to reflect needed
1180 * changes in port numbers and paths)
1181 * @param key_number number of the hostkey to use for the peer
1182 * @param id identifier for the daemon, will be set, can be NULL
1183 * @param emsg set to freshly allocated error message (set to NULL on success),
1184 * can be NULL
1185 * @return handle to the peer, NULL on error
1186 */
1187struct GNUNET_TESTING_Peer *
1188GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
1189 struct GNUNET_CONFIGURATION_Handle *cfg,
1190 uint32_t key_number,
1191 struct GNUNET_PeerIdentity *id,
1192 char **emsg)
1193{
1194 struct GNUNET_TESTING_Peer *peer;
1195 struct GNUNET_DISK_FileHandle *fd;
1196 char *hostkey_filename;
1197 char *config_filename;
1198 char *libexec_binary;
1199 char *emsg_;
1200 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
1201 uint16_t *ports;
1202 struct SharedService *ss;
1203 struct SharedServiceInstance **ss_instances;
1204 unsigned int cnt;
1205 unsigned int nports;
1206
1207 ports = NULL;
1208 nports = 0;
1209 ss_instances = NULL;
1210 if (NULL != emsg)
1211 *emsg = NULL;
1212 if (key_number >= system->total_hostkeys)
1213 {
1214 GNUNET_asprintf (
1215 &emsg_,
1216 _ (
1217 "You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"),
1218 (unsigned int) system->total_hostkeys);
1219 goto err_ret;
1220 }
1221 pk = NULL;
1222 if ((NULL != id) &&
1223 (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id))))
1224 {
1225 GNUNET_asprintf (&emsg_,
1226 _ ("Failed to initialize hostkey for peer %u\n"),
1227 (unsigned int) key_number);
1228 goto err_ret;
1229 }
1230 if (NULL != pk)
1231 GNUNET_free (pk);
1232 if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY"))
1233 {
1234 GNUNET_asprintf (
1235 &emsg_,
1236 _ ("PRIVATE_KEY option in PEER section missing in configuration\n"));
1237 goto err_ret;
1238 }
1239 /* Remove sections for shared services */
1240 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1241 {
1242 ss = &system->shared_services[cnt];
1243 GNUNET_CONFIGURATION_remove_section (cfg, ss->sname);
1244 }
1245 if (GNUNET_OK !=
1246 GNUNET_TESTING_configuration_create_ (system, cfg, &ports, &nports))
1247 {
1248 GNUNET_asprintf (&emsg_,
1249 _ ("Failed to create configuration for peer "
1250 "(not enough free ports?)\n"));
1251 goto err_ret;
1252 }
1253 GNUNET_assert (GNUNET_OK ==
1254 GNUNET_CONFIGURATION_get_value_filename (cfg,
1255 "PEER",
1256 "PRIVATE_KEY",
1257 &hostkey_filename));
1258 fd = GNUNET_DISK_file_open (hostkey_filename,
1259 GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE,
1260 GNUNET_DISK_PERM_USER_READ
1261 | GNUNET_DISK_PERM_USER_WRITE);
1262 if (NULL == fd)
1263 {
1264 GNUNET_asprintf (&emsg_,
1265 _ ("Cannot open hostkey file `%s': %s\n"),
1266 hostkey_filename,
1267 strerror (errno));
1268 GNUNET_free (hostkey_filename);
1269 goto err_ret;
1270 }
1271 GNUNET_free (hostkey_filename);
1272 if (GNUNET_TESTING_HOSTKEYFILESIZE !=
1273 GNUNET_DISK_file_write (fd,
1274 system->hostkeys_data
1275 + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE),
1276 GNUNET_TESTING_HOSTKEYFILESIZE))
1277 {
1278 GNUNET_asprintf (&emsg_,
1279 _ ("Failed to write hostkey file for peer %u: %s\n"),
1280 (unsigned int) key_number,
1281 strerror (errno));
1282 GNUNET_DISK_file_close (fd);
1283 goto err_ret;
1284 }
1285 GNUNET_DISK_file_close (fd);
1286 ss_instances = GNUNET_new_array (system->n_shared_services,
1287 struct SharedServiceInstance*);
1288 for (cnt = 0; cnt < system->n_shared_services; cnt++)
1289 {
1290 ss = &system->shared_services[cnt];
1291 ss_instances[cnt] = associate_shared_service (system, ss, cfg);
1292 if (NULL == ss_instances[cnt])
1293 {
1294 emsg_ = GNUNET_strdup ("FIXME");
1295 goto err_ret;
1296 }
1297 }
1298 GNUNET_assert (GNUNET_OK ==
1299 GNUNET_CONFIGURATION_get_value_filename (cfg,
1300 "PATHS",
1301 "DEFAULTCONFIG",
1302 &config_filename));
1303 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename))
1304 {
1305 GNUNET_asprintf (&emsg_,
1306 _ (
1307 "Failed to write configuration file `%s' for peer %u: %s\n"),
1308 config_filename,
1309 (unsigned int) key_number,
1310 strerror (errno));
1311 GNUNET_free (config_filename);
1312 goto err_ret;
1313 }
1314 peer = GNUNET_new (struct GNUNET_TESTING_Peer);
1315 peer->ss_instances = ss_instances;
1316 peer->cfgfile = config_filename; /* Free in peer_destroy */
1317 peer->cfg = GNUNET_CONFIGURATION_dup (cfg);
1318 libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
1319 if (GNUNET_SYSERR ==
1320 GNUNET_CONFIGURATION_get_value_string (cfg,
1321 "arm",
1322 "PREFIX",
1323 &peer->main_binary))
1324 {
1325 /* No prefix */
1326 GNUNET_asprintf (&peer->main_binary, "%s", libexec_binary);
1327 peer->args = GNUNET_strdup ("");
1328 }
1329 else
1330 {
1331 peer->args = GNUNET_strdup (libexec_binary);
1332 }
1333 peer->system = system;
1334 peer->key_number = key_number;
1335 GNUNET_free (libexec_binary);
1336 peer->ports = ports; /* Free in peer_destroy */
1337 peer->nports = nports;
1338 return peer;
1339
1340err_ret:
1341 GNUNET_free (ss_instances);
1342 GNUNET_free (ports);
1343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
1344 if (NULL != emsg)
1345 *emsg = emsg_;
1346 else
1347 GNUNET_free (emsg_);
1348 return NULL;
1349}
1350
1351
1352/**
1353 * Obtain the peer identity from a peer handle.
1354 *
1355 * @param peer peer handle for which we want the peer's identity
1356 * @param id identifier for the daemon, will be set
1357 */
1358void
1359GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer,
1360 struct GNUNET_PeerIdentity *id)
1361{
1362 if (NULL != peer->id)
1363 {
1364 GNUNET_memcpy (id, peer->id, sizeof(struct GNUNET_PeerIdentity));
1365 return;
1366 }
1367 peer->id = GNUNET_new (struct GNUNET_PeerIdentity);
1368 GNUNET_free_nz (
1369 GNUNET_TESTING_hostkey_get (peer->system, peer->key_number, peer->id));
1370 GNUNET_memcpy (id, peer->id, sizeof(struct GNUNET_PeerIdentity));
1371}
1372
1373
1374/**
1375 * Start the peer.
1376 *
1377 * @param peer peer to start
1378 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (i.e. peer already running)
1379 */
1380int
1381GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
1382{
1383 struct SharedServiceInstance *i;
1384 unsigned int cnt;
1385
1386 if (NULL != peer->main_process)
1387 {
1388 GNUNET_break (0);
1389 return GNUNET_SYSERR;
1390 }
1391 GNUNET_assert (NULL != peer->cfgfile);
1392 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1393 {
1394 i = peer->ss_instances[cnt];
1395 if ((0 == i->n_refs) &&
1396 (GNUNET_SYSERR == start_shared_service_instance (i)))
1397 return GNUNET_SYSERR;
1398 i->n_refs++;
1399 }
1400 peer->main_binary =
1401 GNUNET_CONFIGURATION_expand_dollar (peer->cfg, peer->main_binary);
1402 peer->main_process =
1403 GNUNET_OS_start_process_s (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
1404 NULL,
1405 peer->main_binary,
1406 peer->args,
1407 "-c",
1408 peer->cfgfile,
1409 NULL);
1410 if (NULL == peer->main_process)
1411 {
1412 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1413 _ ("Failed to start `%s': %s\n"),
1414 peer->main_binary,
1415 strerror (errno));
1416 return GNUNET_SYSERR;
1417 }
1418 return GNUNET_OK;
1419}
1420
1421
1422/**
1423 * Sends SIGTERM to the peer's main process
1424 *
1425 * @param peer the handle to the peer
1426 * @return #GNUNET_OK if successful; #GNUNET_SYSERR if the main process is NULL
1427 * or upon any error while sending SIGTERM
1428 */
1429int
1430GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer)
1431{
1432 struct SharedServiceInstance *i;
1433 unsigned int cnt;
1434
1435 if (NULL == peer->main_process)
1436 {
1437 GNUNET_break (0);
1438 return GNUNET_SYSERR;
1439 }
1440 if (0 != GNUNET_OS_process_kill (peer->main_process, GNUNET_TERM_SIG))
1441 return GNUNET_SYSERR;
1442 for (cnt = 0; cnt < peer->system->n_shared_services; cnt++)
1443 {
1444 i = peer->ss_instances[cnt];
1445 GNUNET_assert (0 != i->n_refs);
1446 i->n_refs--;
1447 if (0 == i->n_refs)
1448 stop_shared_service_instance (i);
1449 }
1450 return GNUNET_OK;
1451}
1452
1453
1454/**
1455 * Waits for a peer to terminate. The peer's main process will also be destroyed.
1456 *
1457 * @param peer the handle to the peer
1458 * @return #GNUNET_OK if successful; #GNUNET_SYSERR if the main process is NULL
1459 * or upon any error while waiting
1460 */
1461int
1462GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer)
1463{
1464 int ret;
1465
1466 if (NULL == peer->main_process)
1467 {
1468 GNUNET_break (0);
1469 return GNUNET_SYSERR;
1470 }
1471 ret = GNUNET_OS_process_wait (peer->main_process);
1472 GNUNET_OS_process_destroy (peer->main_process);
1473 peer->main_process = NULL;
1474 return ret;
1475}
1476
1477
1478/**
1479 * Stop the peer.
1480 *
1481 * @param peer peer to stop
1482 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1483 */
1484int
1485GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer)
1486{
1487 if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer))
1488 return GNUNET_SYSERR;
1489 if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer))
1490 return GNUNET_SYSERR;
1491 return GNUNET_OK;
1492}
1493
1494
1495/**
1496 * Function called whenever we connect to or disconnect from ARM.
1497 *
1498 * @param cls closure
1499 * @param connected #GNUNET_YES if connected, #GNUNET_NO if disconnected,
1500 * #GNUNET_SYSERR on error.
1501 */
1502static void
1503disconn_status (void *cls, int connected)
1504{
1505 struct GNUNET_TESTING_Peer *peer = cls;
1506
1507 if (GNUNET_SYSERR == connected)
1508 {
1509 peer->cb (peer->cb_cls, peer, connected);
1510 return;
1511 }
1512 if (GNUNET_YES == connected)
1513 {
1514 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer));
1515 return;
1516 }
1517 GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
1518 GNUNET_ARM_disconnect (peer->ah);
1519 peer->ah = NULL;
1520 peer->cb (peer->cb_cls, peer, GNUNET_YES);
1521}
1522
1523
1524int
1525GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer,
1526 GNUNET_TESTING_PeerStopCallback cb,
1527 void *cb_cls)
1528{
1529 if (NULL == peer->main_process)
1530 return GNUNET_SYSERR;
1531 peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer);
1532 if (NULL == peer->ah)
1533 return GNUNET_SYSERR;
1534 peer->cb = cb;
1535 peer->cb_cls = cb_cls;
1536 return GNUNET_OK;
1537}
1538
1539
1540/**
1541 * Cancel a previous asynchronous peer stop request.
1542 * GNUNET_TESTING_peer_stop_async() should have been called before on the given
1543 * peer. It is an error to call this function if the peer stop callback was
1544 * already called
1545 *
1546 * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called
1547 * before.
1548 */
1549void
1550GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
1551{
1552 GNUNET_assert (NULL != peer->ah);
1553 GNUNET_ARM_disconnect (peer->ah);
1554 peer->ah = NULL;
1555}
1556
1557
1558/**
1559 * Destroy the peer. Releases resources locked during peer configuration.
1560 * If the peer is still running, it will be stopped AND a warning will be
1561 * printed (users of the API should stop the peer explicitly first).
1562 *
1563 * @param peer peer to destroy
1564 */
1565void
1566GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer)
1567{
1568 unsigned int cnt;
1569
1570 if (NULL != peer->main_process)
1571 GNUNET_TESTING_peer_stop (peer);
1572 if (NULL != peer->ah)
1573 GNUNET_ARM_disconnect (peer->ah);
1574 GNUNET_free (peer->cfgfile);
1575 if (NULL != peer->cfg)
1576 GNUNET_CONFIGURATION_destroy (peer->cfg);
1577 GNUNET_free (peer->main_binary);
1578 GNUNET_free (peer->args);
1579 GNUNET_free (peer->id);
1580 GNUNET_free (peer->ss_instances);
1581 if (NULL != peer->ports)
1582 {
1583 for (cnt = 0; cnt < peer->nports; cnt++)
1584 GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]);
1585 GNUNET_free (peer->ports);
1586 }
1587 GNUNET_free (peer);
1588}
1589
1590
1591int
1592GNUNET_TESTING_peer_run (const char *testdir,
1593 const char *cfgfilename,
1594 GNUNET_TESTING_TestMain tm,
1595 void *tm_cls)
1596{
1597 return GNUNET_TESTING_service_run (testdir, "arm", cfgfilename, tm, tm_cls);
1598}
1599
1600
1601/**
1602 * Structure for holding service data
1603 */
1604struct ServiceContext
1605{
1606 /**
1607 * The configuration of the peer in which the service is run
1608 */
1609 const struct GNUNET_CONFIGURATION_Handle *cfg;
1610
1611 /**
1612 * Callback to signal service startup
1613 */
1614 GNUNET_TESTING_TestMain tm;
1615
1616 /**
1617 * The peer in which the service is run.
1618 */
1619 struct GNUNET_TESTING_Peer *peer;
1620
1621 /**
1622 * Closure for the above callback
1623 */
1624 void *tm_cls;
1625};
1626
1627
1628/**
1629 * Callback to be called when SCHEDULER has been started
1630 *
1631 * @param cls the ServiceContext
1632 */
1633static void
1634service_run_main (void *cls)
1635{
1636 struct ServiceContext *sc = cls;
1637
1638 sc->tm (sc->tm_cls, sc->cfg, sc->peer);
1639}
1640
1641
1642int
1643GNUNET_TESTING_service_run (const char *testdir,
1644 const char *service_name,
1645 const char *cfgfilename,
1646 GNUNET_TESTING_TestMain tm,
1647 void *tm_cls)
1648{
1649 struct ServiceContext sc;
1650 struct GNUNET_TESTING_System *system;
1651 struct GNUNET_TESTING_Peer *peer;
1652 struct GNUNET_CONFIGURATION_Handle *cfg;
1653 char *binary;
1654 char *libexec_binary;
1655
1656 GNUNET_log_setup (testdir, "WARNING", NULL);
1657 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1658 if (NULL == system)
1659 return 1;
1660 cfg = GNUNET_CONFIGURATION_create ();
1661 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename))
1662 {
1663 LOG (GNUNET_ERROR_TYPE_ERROR,
1664 _ ("Failed to load configuration from %s\n"),
1665 cfgfilename);
1666 GNUNET_CONFIGURATION_destroy (cfg);
1667 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1668 return 1;
1669 }
1670 peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL);
1671 if (NULL == peer)
1672 {
1673 GNUNET_CONFIGURATION_destroy (cfg);
1674 hostkeys_unload (system);
1675 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1676 return 1;
1677 }
1678 GNUNET_free (peer->main_binary);
1679 GNUNET_free (peer->args);
1680 GNUNET_asprintf (&binary, "gnunet-service-%s", service_name);
1681 libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
1682 if (GNUNET_SYSERR ==
1683 GNUNET_CONFIGURATION_get_value_string (cfg,
1684 service_name,
1685 "PREFIX",
1686 &peer->main_binary))
1687 {
1688 /* No prefix */
1689 GNUNET_asprintf (&peer->main_binary, "%s", libexec_binary);
1690 peer->args = GNUNET_strdup ("");
1691 }
1692 else
1693 peer->args = GNUNET_strdup (libexec_binary);
1694
1695 GNUNET_free (libexec_binary);
1696 GNUNET_free (binary);
1697 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer))
1698 {
1699 GNUNET_TESTING_peer_destroy (peer);
1700 GNUNET_CONFIGURATION_destroy (cfg);
1701 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1702 return 1;
1703 }
1704 sc.cfg = cfg;
1705 sc.tm = tm;
1706 sc.tm_cls = tm_cls;
1707 sc.peer = peer;
1708 GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */
1709 if ((NULL != peer->main_process) &&
1710 (GNUNET_OK != GNUNET_TESTING_peer_stop (peer)))
1711 {
1712 GNUNET_TESTING_peer_destroy (peer);
1713 GNUNET_CONFIGURATION_destroy (cfg);
1714 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1715 return 1;
1716 }
1717 GNUNET_TESTING_peer_destroy (peer);
1718 GNUNET_CONFIGURATION_destroy (cfg);
1719 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
1720 return 0;
1721}
1722
1723
1724/**
1725 * Every line in the topology configuration starts with a string indicating which
1726 * kind of information will be configured with this line. Configuration values following
1727 * this string are seperated by special sequences of characters. An integer value seperated
1728 * by ':' is returned by this function.
1729 *
1730 * @param line The line of configuration.
1731 * @return An integer value.
1732 */
1733static unsigned int
1734get_first_value (const char *line)
1735{
1736 char *copy;
1737 size_t slen;
1738 char *token;
1739 unsigned int ret;
1740 char *rest = NULL;
1741
1742 slen = strlen (line) + 1;
1743 copy = GNUNET_malloc (slen);
1744 memcpy (copy, line, slen);
1745 token = strtok_r (copy, ":", &rest);
1746 token = strtok_r (NULL, ":", &rest);
1747 GNUNET_assert (1 == sscanf (token, "%u", &ret));
1748 GNUNET_free (copy);
1749 return ret;
1750}
1751
1752
1753/**
1754 * Every line in the topology configuration starts with a string indicating which
1755 * kind of information will be configured with this line. This string is returned by this function.
1756 *
1757 * @param line The line of configuration.
1758 * @return The leading string of this configuration line.
1759 */
1760static char *
1761get_key (const char *line)
1762{
1763 char *copy;
1764 size_t slen;
1765 size_t tlen;
1766 char *token;
1767 char *ret;
1768 char *rest = NULL;
1769
1770 slen = strlen (line) + 1;
1771 copy = GNUNET_malloc (slen);
1772 memcpy (copy, line, slen);
1773 token = strtok_r (copy, ":", &rest);
1774 tlen = strlen (token) + 1;
1775 ret = GNUNET_malloc (tlen);
1776 memcpy (ret, token, tlen);
1777 GNUNET_free (copy);
1778 return ret;
1779}
1780
1781
1782/**
1783 * Every line in the topology configuration starts with a string indicating which
1784 * kind of information will be configured with this line. Configuration values following
1785 * this string are seperated by special sequences of characters. A string value seperated
1786 * by ':' is returned by this function.
1787 *
1788 * @param line The line of configuration.
1789 * @return A string value.
1790 */
1791static char *
1792get_first_string_value (const char *line)
1793{
1794 char *copy;
1795 size_t slen, slen_token;
1796 char *token;
1797 char *ret;
1798 char *rest = NULL;
1799
1800 slen = strlen (line) + 1;
1801 copy = GNUNET_malloc (slen);
1802 memcpy (copy, line, slen);
1803 token = strtok_r (copy, ":", &rest);
1804 token = strtok_r (NULL, ":", &rest);
1805 LOG (GNUNET_ERROR_TYPE_DEBUG,
1806 "first token %s\n",
1807 token);
1808 slen_token = strlen (token);
1809 ret = GNUNET_malloc (slen_token + 1);
1810 memcpy (ret, token, slen_token + 1);
1811 GNUNET_free (copy);
1812 return ret;
1813}
1814
1815
1816/**
1817 * Every line in the topology configuration starts with a string indicating which
1818 * kind of information will be configured with this line. Configuration values following
1819 * this string are seperated by special sequences of characters. A second integer value
1820 * seperated by ':' from a first value is returned by this function.
1821 *
1822 * @param line The line of configuration.
1823 * @return An integer value.
1824 */
1825static unsigned int
1826get_second_value (const char *line)
1827{
1828 char *copy;
1829 char *token;
1830 unsigned int ret;
1831 char *rest = NULL;
1832
1833 copy = GNUNET_strdup (line);
1834 token = strtok_r (copy, ":", &rest);
1835 token = strtok_r (NULL, ":", &rest);
1836 token = strtok_r (NULL, ":", &rest);
1837 LOG (GNUNET_ERROR_TYPE_ERROR,
1838 "Format error in configuration line: %s\n",
1839 line);
1840 GNUNET_assert (1 == sscanf (token, "%u", &ret));
1841 GNUNET_free (copy);
1842 return ret;
1843}
1844
1845
1846/**
1847 * Every line in the topology configuration starts with a string indicating which
1848 * kind of information will be configured with this line. Configuration values following
1849 * this string are seperated by special sequences of characters. A value might be
1850 * a key value pair.
1851 * This function returns the value for a specific key in a configuration line.
1852 *
1853 * @param key The key of the key value pair.
1854 * @return The value of the key value pair.
1855 */
1856static char *
1857get_value (const char *key, const char *line)
1858{
1859 char copy[strlen (line) + 1];
1860 size_t slen;
1861 char *token;
1862 char *token2;
1863 char *temp;
1864 char *rest = NULL;
1865
1866 slen = strlen (line) + 1;
1867 memcpy (copy, line, slen);
1868 temp = strstr (copy, key);
1869 if (NULL == temp)
1870 return NULL;
1871 token = strtok_r (temp, ":", &rest);
1872 if (NULL == token)
1873 return NULL;
1874 token = strtok_r (NULL, ":", &rest);
1875 if (NULL == token)
1876 return NULL;
1877 token2 = strtok_r (token, "}", &rest);
1878 if (NULL == token2)
1879 return NULL;
1880 return GNUNET_strdup (token2);
1881}
1882
1883
1884/**
1885 * Every line in the topology configuration starts with a string indicating which
1886 * kind of information will be configured with this line. Configuration values following
1887 * this string are seperated by special sequences of characters. A value might be
1888 * a key value pair. A special key is the 'connect' key which can appear more than once.
1889 * The value is the information about a connection via some protocol to some other node.
1890 * This function returns the struct GNUNET_TESTING_NodeConnection which holds the information
1891 * of the connect value.
1892 *
1893 * @param value The value of the connect key value pair.
1894 * @return The struct GNUNET_TESTING_NodeConnection.
1895 */
1896static struct GNUNET_TESTING_NodeConnection *
1897get_connect_value (const char *line,
1898 struct GNUNET_TESTING_NetjailNode *node)
1899{
1900 struct GNUNET_TESTING_NodeConnection *node_connection;
1901 char *copy;
1902 char *token;
1903 char *token2;
1904 unsigned int node_n;
1905 unsigned int namespace_n;
1906 char *rest = NULL;
1907 char *rest2 = NULL;
1908 struct GNUNET_TESTING_AddressPrefix *prefix;
1909 unsigned int sscanf_ret;
1910
1911 node_connection = GNUNET_new (struct GNUNET_TESTING_NodeConnection);
1912 node_connection->node = node;
1913
1914 copy = GNUNET_strdup (line);
1915 token = strtok_r (copy, ":", &rest);
1916 if (0 == strcmp ("{K", token))
1917 {
1918 node_connection->node_type = GNUNET_TESTING_GLOBAL_NODE;
1919 token = strtok_r (NULL, ":", &rest);
1920 GNUNET_assert (1 == sscanf (token, "%u", &node_n));
1921 LOG (GNUNET_ERROR_TYPE_DEBUG,
1922 "node_n %u\n",
1923 node_n);
1924 node_connection->node_n = node_n;
1925 node_connection->namespace_n = 0;
1926 }
1927 else if (0 == strcmp ("{P", token))
1928 {
1929 node_connection->node_type = GNUNET_TESTING_SUBNET_NODE;
1930 token = strtok_r (NULL, ":", &rest);
1931 errno = 0;
1932 sscanf_ret = sscanf (token, "%u", &namespace_n);
1933 if (errno != 0)
1934 {
1935 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
1936 }
1937 GNUNET_assert (0 < sscanf_ret);
1938 node_connection->namespace_n = namespace_n;
1939 token = strtok_r (NULL, ":", &rest);
1940 errno = 0;
1941 sscanf_ret = sscanf (token, "%u", &node_n);
1942 if (errno != 0)
1943 {
1944 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
1945 }
1946 GNUNET_assert (0 < sscanf_ret);
1947 node_connection->node_n = node_n;
1948 LOG (GNUNET_ERROR_TYPE_DEBUG,
1949 "node_n %u namespace_n %u node->node_n %u node->namespace_n %u\n",
1950 node_n,
1951 namespace_n,
1952 node->node_n,
1953 node->namespace_n);
1954 }
1955 else
1956 {
1957 GNUNET_break (0);
1958 GNUNET_free (node_connection);
1959 GNUNET_free (copy);
1960 return NULL;
1961 }
1962
1963 while (NULL != (token = strtok_r (NULL, ":", &rest)))
1964 {
1965 prefix = GNUNET_new (struct GNUNET_TESTING_AddressPrefix);
1966 token2 = strtok_r (token, "}", &rest2);
1967 if (NULL != token2)
1968 prefix->address_prefix = GNUNET_strdup (token2);
1969 else
1970 prefix->address_prefix = GNUNET_strdup (token);
1971
1972 LOG (GNUNET_ERROR_TYPE_DEBUG,
1973 "address_prefix %s\n",
1974 prefix->address_prefix);
1975
1976 GNUNET_CONTAINER_DLL_insert (node_connection->address_prefixes_head,
1977 node_connection->address_prefixes_tail,
1978 prefix);
1979 LOG (GNUNET_ERROR_TYPE_DEBUG,
1980 "address_prefix %s\n",
1981 prefix->address_prefix);
1982 }
1983
1984 GNUNET_free (copy);
1985 return node_connection;
1986}
1987
1988
1989/**
1990 * Every line in the topology configuration starts with a string indicating which
1991 * kind of information will be configured with this line. Configuration values following
1992 * this string are seperated by special sequences of characters. A value might be
1993 * a key value pair. A special key is the 'connect' key.
1994 * The value is the information about a connections via some protocol to other nodes.
1995 * Each connection itself is a key value pair separated by the character '|' and
1996 * surrounded by the characters '{' and '}'.
1997 * The struct GNUNET_TESTING_NodeConnection holds the information of each connection value.
1998 * This function extracts the values of each connection into a DLL of
1999 * struct GNUNET_TESTING_NodeConnection which will be added to a node.
2000 *
2001 * @param line The line of configuration.
2002 * @param node The struct GNUNET_TESTING_NetjailNode to which the DLL of
2003 * struct GNUNET_TESTING_NodeConnection will be added.
2004 */
2005static void
2006node_connections (const char *line, struct GNUNET_TESTING_NetjailNode *node)
2007{
2008 char *value, *value2;
2009 char *temp;
2010 char *copy;
2011 char *rest = NULL;
2012 char *rest2 = NULL;
2013 struct GNUNET_TESTING_NodeConnection *node_connection;
2014
2015
2016 temp = strstr (line, "connect");
2017 if (NULL != temp)
2018 {
2019 copy = GNUNET_strdup (temp);
2020 strtok_r (copy, ":", &rest);
2021 value = strtok_r (rest, "|", &rest2);
2022
2023 while (NULL != value)
2024 {
2025 LOG (GNUNET_ERROR_TYPE_DEBUG,
2026 "node_connections value %s\n",
2027 value);
2028 node_connection = get_connect_value (value, node);
2029 if (NULL == node_connection)
2030 {
2031 LOG (GNUNET_ERROR_TYPE_WARNING,
2032 "connect key was not expected in this configuration line: %s\n",
2033 line);
2034 break;
2035 }
2036 GNUNET_CONTAINER_DLL_insert (node->node_connections_head,
2037 node->node_connections_tail,
2038 node_connection);
2039 value2 = strstr (value, "}}");
2040 if (NULL != value2)
2041 break;
2042 value = strtok_r (NULL, "|", &rest2);
2043
2044 }
2045 GNUNET_free (copy);
2046 }
2047}
2048
2049
2050/**
2051 * A helper function to log information about individual nodes.
2052 *
2053 * @param cls This is not used actually.
2054 * @param id The key of this value in the map.
2055 * @param value A struct GNUNET_TESTING_NetjailNode which holds information about a node.
2056 * return GNUNET_YES to continue with iterating, GNUNET_NO otherwise.
2057 */
2058static int
2059log_nodes (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
2060{
2061 struct GNUNET_TESTING_NetjailNode *node = value;
2062 struct GNUNET_TESTING_NodeConnection *pos_connection;
2063 struct GNUNET_TESTING_AddressPrefix *pos_prefix;
2064
2065 LOG (GNUNET_ERROR_TYPE_DEBUG,
2066 "plugin: %s space: %u node: %u global: %u\n",
2067 node->plugin,
2068 node->namespace_n,
2069 node->node_n,
2070 node->is_global);
2071
2072 for (pos_connection = node->node_connections_head; NULL != pos_connection;
2073 pos_connection = pos_connection->next)
2074 {
2075
2076 LOG (GNUNET_ERROR_TYPE_DEBUG,
2077 "namespace_n: %u node_n: %u node_type: %u\n",
2078 pos_connection->namespace_n,
2079 pos_connection->node_n,
2080 pos_connection->node_type);
2081
2082 for (pos_prefix = pos_connection->address_prefixes_head; NULL != pos_prefix;
2083 pos_prefix =
2084 pos_prefix->next)
2085 {
2086 LOG (GNUNET_ERROR_TYPE_DEBUG,
2087 "prefix: %s\n",
2088 pos_prefix->address_prefix);
2089 }
2090 }
2091 return GNUNET_YES;
2092}
2093
2094
2095/**
2096 * Helper function to log information about namespaces.
2097 *
2098 * @param cls This is not used actually.
2099 * @param id The key of this value in the map.
2100 * @param value A struct GNUNET_TESTING_NetjailNamespace which holds information about a subnet.
2101 * return GNUNET_YES to continue with iterating, GNUNET_NO otherwise.
2102 */
2103static int
2104log_namespaces (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
2105{
2106 struct GNUNET_TESTING_NetjailNamespace *namespace = value;
2107
2108 GNUNET_CONTAINER_multishortmap_iterate (namespace->nodes, &log_nodes, NULL);
2109 return GNUNET_YES;
2110}
2111
2112
2113/**
2114 * Helper function to log the configuration in case of a problem with configuration.
2115 *
2116 * @param topology The struct GNUNET_TESTING_NetjailTopology holding the configuration information.
2117 */
2118static int
2119log_topo (const struct GNUNET_TESTING_NetjailTopology *topology)
2120{
2121 LOG (GNUNET_ERROR_TYPE_DEBUG,
2122 "plugin: %s spaces: %u nodes: %u known: %u\n",
2123 topology->plugin,
2124 topology->namespaces_n,
2125 topology->nodes_m,
2126 topology->nodes_x);
2127
2128 GNUNET_CONTAINER_multishortmap_iterate (topology->map_namespaces,
2129 log_namespaces, NULL);
2130 GNUNET_CONTAINER_multishortmap_iterate (topology->map_globals, &log_nodes,
2131 NULL);
2132 return GNUNET_YES;
2133}
2134
2135
2136/**
2137 * This function extracts information about a specific node from the topology.
2138 *
2139 * @param num The global index number of the node.
2140 * @param[out] node_ex A struct GNUNET_TESTING_NetjailNode with information about the node.
2141 * @param[out] namespace_ex A struct GNUNET_TESTING_NetjailNamespace with information about the namespace
2142 the node is in or NULL, if the node is a global node.
2143 * @param[out] node_connections_ex A struct GNUNET_TESTING_NodeConnection with information about the connection
2144 of this node to other nodes.
2145*/
2146static void
2147get_node_info (unsigned int num,
2148 const struct GNUNET_TESTING_NetjailTopology *topology,
2149 struct GNUNET_TESTING_NetjailNode **node_ex,
2150 struct GNUNET_TESTING_NetjailNamespace **namespace_ex,
2151 struct GNUNET_TESTING_NodeConnection **node_connections_ex)
2152{
2153 struct GNUNET_ShortHashCode hkey;
2154 struct GNUNET_HashCode hc;
2155 unsigned int namespace_n;
2156 unsigned int node_m;
2157 struct GNUNET_TESTING_NetjailNode *node;
2158 struct GNUNET_TESTING_NetjailNamespace *namespace;
2159 struct GNUNET_TESTING_NodeConnection *node_connections = NULL;
2160
2161 log_topo (topology);
2162 LOG (GNUNET_ERROR_TYPE_DEBUG,
2163 "num: %u \n",
2164 num);
2165 if (topology->nodes_x >= num)
2166 {
2167
2168 GNUNET_CRYPTO_hash (&num, sizeof(num), &hc);
2169 memcpy (&hkey,
2170 &hc,
2171 sizeof (hkey));
2172 node = GNUNET_CONTAINER_multishortmap_get (topology->map_globals,
2173 &hkey);
2174 if (NULL != node)
2175 {
2176 *node_ex = node;
2177 *node_connections_ex = node->node_connections_head;
2178 }
2179 }
2180 else
2181 {
2182 namespace_n = (unsigned int) ceil ((double) (num - topology->nodes_x)
2183 / topology->nodes_m);
2184 LOG (GNUNET_ERROR_TYPE_DEBUG,
2185 "ceil num: %u nodes_x: %u nodes_m: %u namespace_n: %u\n",
2186 num,
2187 topology->nodes_x,
2188 topology->nodes_m,
2189 namespace_n);
2190 GNUNET_CRYPTO_hash (&namespace_n, sizeof(namespace_n), &hc);
2191 memcpy (&hkey,
2192 &hc,
2193 sizeof (hkey));
2194 namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces,
2195 &hkey);
2196 if (NULL != namespace)
2197 {
2198 node_m = num - topology->nodes_x - topology->nodes_m * (namespace_n - 1);
2199 GNUNET_CRYPTO_hash (&node_m, sizeof(node_m), &hc);
2200 memcpy (&hkey,
2201 &hc,
2202 sizeof (hkey));
2203 node = GNUNET_CONTAINER_multishortmap_get (namespace->nodes,
2204 &hkey);
2205 if (NULL != node)
2206 {
2207 LOG (GNUNET_ERROR_TYPE_DEBUG,
2208 "node additional_connects: %u %p\n",
2209 node->additional_connects,
2210 node);
2211 node_connections = node->node_connections_head;
2212 }
2213 *node_ex = node;
2214 *namespace_ex = namespace;
2215 *node_connections_ex = node_connections;
2216 }
2217 }
2218}
2219
2220
2221/**
2222 * Get a node from the topology.
2223 *
2224 * @param num The specific node we want the connections for.
2225 * @param topology The topology we get the connections from.
2226 * @return The connections of the node.
2227 */
2228struct GNUNET_TESTING_NetjailNode *
2229GNUNET_TESTING_get_node (unsigned int num,
2230 struct GNUNET_TESTING_NetjailTopology *topology)
2231{
2232 struct GNUNET_TESTING_NetjailNode *node;
2233 struct GNUNET_TESTING_NetjailNamespace *namespace;
2234 struct GNUNET_TESTING_NodeConnection *node_connections;
2235
2236 get_node_info (num, topology, &node, &namespace, &node_connections);
2237
2238 return node;
2239
2240}
2241
2242
2243/**
2244 * Get the connections to other nodes for a specific node.
2245 *
2246 * @param num The specific node we want the connections for.
2247 * @param topology The topology we get the connections from.
2248 * @return The connections of the node.
2249 */
2250struct GNUNET_TESTING_NodeConnection *
2251GNUNET_TESTING_get_connections (unsigned int num,
2252 const struct
2253 GNUNET_TESTING_NetjailTopology *topology)
2254{
2255 struct GNUNET_TESTING_NetjailNode *node;
2256 struct GNUNET_TESTING_NetjailNamespace *namespace;
2257 struct GNUNET_TESTING_NodeConnection *node_connections;
2258
2259 LOG (GNUNET_ERROR_TYPE_DEBUG,
2260 "get_connections\n");
2261
2262 get_node_info (num, topology, &node, &namespace, &node_connections);
2263
2264 return node_connections;
2265}
2266
2267
2268/**
2269 * Retrieve the peer identity from the test system with the unique node id.
2270 *
2271 * @param num The unique node id.
2272 * @param tl_system The test system.
2273 * @return The peer identity wrapping the public key.
2274 */
2275struct GNUNET_PeerIdentity *
2276GNUNET_TESTING_get_peer (unsigned int num,
2277 const struct GNUNET_TESTING_System *tl_system)
2278{
2279 struct GNUNET_PeerIdentity *peer = GNUNET_new (struct GNUNET_PeerIdentity);
2280 struct GNUNET_CRYPTO_EddsaPrivateKey *priv_key;
2281
2282 priv_key = GNUNET_TESTING_hostkey_get (tl_system,
2283 num,
2284 peer);
2285
2286 GNUNET_CRYPTO_eddsa_key_get_public (priv_key,
2287 &peer->public_key);
2288 GNUNET_free (priv_key);
2289 return peer;
2290}
2291
2292
2293int
2294free_nodes_cb (void *cls,
2295 const struct GNUNET_ShortHashCode *key,
2296 void *value)
2297{
2298 (void) cls;
2299 struct GNUNET_TESTING_NetjailNode *node = value;
2300 struct GNUNET_TESTING_NodeConnection *pos_connection;
2301 struct GNUNET_TESTING_AddressPrefix *pos_prefix;
2302
2303 while (NULL != (pos_connection = node->node_connections_head))
2304 {
2305 while (NULL != (pos_prefix = pos_connection->address_prefixes_head))
2306 {
2307 GNUNET_CONTAINER_DLL_remove (pos_connection->address_prefixes_head,
2308 pos_connection->address_prefixes_tail,
2309 pos_prefix);
2310 GNUNET_free (pos_prefix->address_prefix);
2311 GNUNET_free (pos_prefix);
2312 }
2313 GNUNET_CONTAINER_DLL_remove (node->node_connections_head,
2314 node->node_connections_tail,
2315 pos_connection);
2316 GNUNET_free (pos_connection);
2317 }
2318
2319 GNUNET_free (node->plugin);
2320 GNUNET_free (node);
2321 return GNUNET_OK;
2322}
2323
2324
2325int
2326free_namespaces_cb (void *cls,
2327 const struct GNUNET_ShortHashCode *key,
2328 void *value)
2329{
2330 (void) cls;
2331 struct GNUNET_TESTING_NetjailNamespace *namespace = value;
2332
2333 GNUNET_free (namespace->router);
2334 GNUNET_CONTAINER_multishortmap_iterate (namespace->nodes, free_nodes_cb,
2335 namespace->nodes);
2336 return GNUNET_OK;
2337
2338}
2339
2340
2341/**
2342 * Deallocate memory of the struct GNUNET_TESTING_NetjailTopology.
2343 *
2344 * @param topology The GNUNET_TESTING_NetjailTopology to be deallocated.
2345 */
2346void
2347GNUNET_TESTING_free_topology (struct GNUNET_TESTING_NetjailTopology *topology)
2348{
2349 GNUNET_CONTAINER_multishortmap_iterate (topology->map_namespaces,
2350 free_namespaces_cb, NULL);
2351 GNUNET_CONTAINER_multishortmap_destroy (topology->map_namespaces);
2352 GNUNET_CONTAINER_multishortmap_iterate (topology->map_globals, free_nodes_cb,
2353 NULL);
2354 GNUNET_CONTAINER_multishortmap_destroy (topology->map_globals);
2355 GNUNET_free (topology->plugin);
2356 GNUNET_free (topology);
2357}
2358
2359
2360unsigned int
2361GNUNET_TESTING_calculate_num (
2362 struct GNUNET_TESTING_NodeConnection *node_connection,
2363 struct GNUNET_TESTING_NetjailTopology *topology)
2364{
2365 unsigned int n, m, num;
2366
2367 n = node_connection->namespace_n;
2368 m = node_connection->node_n;
2369
2370 if (0 == n)
2371 num = m;
2372 else
2373 num = (n - 1) * topology->nodes_m + m + topology->nodes_x;
2374
2375 return num;
2376}
2377
2378
2379/**
2380 * Get the address for a specific communicator from a connection.
2381 *
2382 * @param connection The connection we like to have the address from.
2383 * @param prefix The communicator protocol prefix.
2384 * @return The address of the communicator.
2385 */
2386char *
2387GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection,
2388 const char *prefix)
2389{
2390 struct GNUNET_TESTING_NetjailNode *node;
2391 char *addr;
2392 char *template;
2393 unsigned int node_n;
2394
2395 LOG (GNUNET_ERROR_TYPE_DEBUG,
2396 "get address prefix: %s node_n: %u\n",
2397 prefix,
2398 connection->node_n);
2399
2400 node = connection->node;
2401 if (connection->namespace_n == node->namespace_n)
2402 {
2403 template = CONNECT_ADDRESS_TEMPLATE;
2404 node_n = connection->node_n;
2405 }
2406 else if (0 == connection->namespace_n)
2407 {
2408 template = KNOWN_CONNECT_ADDRESS_TEMPLATE;
2409 node_n = connection->node_n;
2410 }
2411 else if (1 == connection->node_n)
2412 {
2413 template = ROUTER_CONNECT_ADDRESS_TEMPLATE;
2414 node_n = connection->namespace_n;
2415 }
2416 else
2417 {
2418 return NULL;
2419 }
2420
2421 if (0 == strcmp (PREFIX_TCP, prefix) ||
2422 0 == strcmp (PREFIX_UDP, prefix) ||
2423 0 == strcmp (PREFIX_UDP_NATTED, prefix) ||
2424 0 == strcmp (PREFIX_TCP_NATTED, prefix))
2425 {
2426 GNUNET_asprintf (&addr,
2427 template,
2428 prefix,
2429 node_n);
2430 }
2431 else
2432 {
2433 GNUNET_assert (0);
2434 }
2435
2436 return addr;
2437}
2438
2439
2440/**
2441 * Get the number of unintentional additional connections the node waits for.
2442 *
2443 * @param num The specific node we want the additional connects for.
2444 * @return The number of additional connects
2445 */
2446unsigned int
2447GNUNET_TESTING_get_additional_connects (unsigned int num,
2448 struct GNUNET_TESTING_NetjailTopology *
2449 topology)
2450{
2451 struct GNUNET_TESTING_NetjailNode *node;
2452 struct GNUNET_TESTING_NetjailNamespace *namespace;
2453 struct GNUNET_TESTING_NodeConnection *node_connections;
2454
2455 LOG (GNUNET_ERROR_TYPE_DEBUG,
2456 "get_additional_connects\n");
2457
2458 get_node_info (num, topology, &node, &namespace, &node_connections);
2459
2460 if (NULL == node)
2461 {
2462 LOG (GNUNET_ERROR_TYPE_WARNING,
2463 "No info found for node %d\n", num);
2464 return 0;
2465 }
2466 LOG (GNUNET_ERROR_TYPE_DEBUG,
2467 "node additional_connects for node %p\n",
2468 node);
2469 LOG (GNUNET_ERROR_TYPE_DEBUG,
2470 "node additional_connects: %u\n",
2471 node->additional_connects);
2472
2473 return node->additional_connects;
2474}
2475
2476
2477static void
2478parse_ac (struct GNUNET_TESTING_NetjailNode *p_node, const char *token)
2479{
2480 char *ac_value;
2481 int ret;
2482
2483 ac_value = get_value ("AC", token);
2484 if (NULL != ac_value)
2485 {
2486 LOG (GNUNET_ERROR_TYPE_DEBUG,
2487 "ac value: %s\n",
2488 ac_value);
2489 errno = 0;
2490 ret = sscanf (ac_value, "%u", &p_node->additional_connects);
2491 if (errno != 0)
2492 {
2493 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
2494 }
2495 GNUNET_assert (0 < ret);
2496 LOG (GNUNET_ERROR_TYPE_DEBUG,
2497 "AC %u\n",
2498 p_node->additional_connects);
2499 }
2500 else
2501 {
2502 p_node->additional_connects = 0;
2503 }
2504 GNUNET_free (ac_value);
2505}
2506
2507
2508/**
2509 * Parse the topology data.
2510 *
2511 * @param data The topology data.
2512 * @return The GNUNET_TESTING_NetjailTopology
2513 */
2514struct GNUNET_TESTING_NetjailTopology *
2515GNUNET_TESTING_get_topo_from_string (const char *input)
2516{
2517 char *token;
2518 char *key = NULL;
2519 unsigned int out;
2520 char *rest = NULL;
2521 char *value = NULL;
2522 char *value2;
2523 char *data;
2524 int ret;
2525 struct GNUNET_TESTING_NetjailTopology *topo;
2526 struct GNUNET_TESTING_NetjailRouter *router;
2527 struct GNUNET_TESTING_NetjailNamespace *namespace;
2528 struct GNUNET_HashCode hc;
2529
2530 data = GNUNET_strdup (input);
2531 token = strtok_r (data, "\n", &rest);
2532 topo = GNUNET_new (struct GNUNET_TESTING_NetjailTopology);
2533 topo->map_namespaces =
2534 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2535 topo->map_globals =
2536 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2537
2538 while (NULL != token)
2539 {
2540 if (NULL != key)
2541 GNUNET_free (key);
2542 key = get_key (token);
2543 LOG (GNUNET_ERROR_TYPE_DEBUG,
2544 "In the loop with token: %s beginning with %s\n",
2545 token,
2546 key);
2547 if (0 == strcmp (key, "M"))
2548 {
2549 LOG (GNUNET_ERROR_TYPE_DEBUG,
2550 "Get first Value for M.\n");
2551 out = get_first_value (token);
2552 LOG (GNUNET_ERROR_TYPE_DEBUG,
2553 "M: %u\n",
2554 out);
2555 topo->nodes_m = out;
2556 }
2557 else if (0 == strcmp (key, "N"))
2558 {
2559 LOG (GNUNET_ERROR_TYPE_DEBUG,
2560 "Get first Value for N.\n");
2561 out = get_first_value (token);
2562 LOG (GNUNET_ERROR_TYPE_DEBUG,
2563 "N: %u\n",
2564 out);
2565 topo->namespaces_n = out;
2566 }
2567 else if (0 == strcmp (key, "X"))
2568 {
2569 LOG (GNUNET_ERROR_TYPE_DEBUG,
2570 "Get first Value for X.\n");
2571 out = get_first_value (token);
2572 LOG (GNUNET_ERROR_TYPE_DEBUG,
2573 "X: %u\n",
2574 out);
2575 topo->nodes_x = out;
2576 }
2577 else if (0 == strcmp (key, "AC"))
2578 {
2579 LOG (GNUNET_ERROR_TYPE_DEBUG,
2580 "Get first Value for AC.\n");
2581 out = get_first_value (token);
2582 LOG (GNUNET_ERROR_TYPE_DEBUG,
2583 "AC: %u\n",
2584 out);
2585 topo->additional_connects = out;
2586 }
2587 else if (0 == strcmp (key, "T"))
2588 {
2589 LOG (GNUNET_ERROR_TYPE_DEBUG,
2590 "Get first string value for T.\n");
2591 value = get_first_string_value (token);
2592 LOG (GNUNET_ERROR_TYPE_DEBUG,
2593 "value: %s\n",
2594 value);
2595 topo->plugin = value;
2596 }
2597 else if (0 == strcmp (key, "K"))
2598 {
2599 struct GNUNET_ShortHashCode hkey_k;
2600 struct GNUNET_TESTING_NetjailNode *k_node = GNUNET_new (struct
2601 GNUNET_TESTING_NetjailNode);
2602
2603 LOG (GNUNET_ERROR_TYPE_DEBUG,
2604 "Get first Value for K.\n");
2605 out = get_first_value (token);
2606 LOG (GNUNET_ERROR_TYPE_DEBUG,
2607 "K: %u\n",
2608 out);
2609 k_node->node_n = out;
2610 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2611 memcpy (&hkey_k,
2612 &hc,
2613 sizeof (hkey_k));
2614 k_node->is_global = GNUNET_YES;
2615
2616 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2617 topo->map_globals,
2618 &hkey_k))
2619 GNUNET_break (0);
2620 else
2621 GNUNET_CONTAINER_multishortmap_put (topo->map_globals,
2622 &hkey_k,
2623 k_node,
2624 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2625 LOG (GNUNET_ERROR_TYPE_DEBUG,
2626 "Get value for key value on K.\n");
2627 value = get_value ("plugin", token);
2628 LOG (GNUNET_ERROR_TYPE_DEBUG,
2629 "value: %s\n",
2630 value);
2631 k_node->plugin = value;
2632 parse_ac (k_node, token);
2633 node_connections (token, k_node);
2634 GNUNET_free (value);
2635 }
2636 else if (0 == strcmp (key, "R"))
2637 {
2638 struct GNUNET_ShortHashCode hkey_r;
2639 router = GNUNET_new (struct GNUNET_TESTING_NetjailRouter);
2640
2641 LOG (GNUNET_ERROR_TYPE_DEBUG,
2642 "Get first Value for R.\n");
2643 out = get_first_value (token);
2644 LOG (GNUNET_ERROR_TYPE_DEBUG,
2645 "R: %u\n",
2646 out);
2647 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2648 memcpy (&hkey_r,
2649 &hc,
2650 sizeof (hkey_r));
2651 LOG (GNUNET_ERROR_TYPE_DEBUG,
2652 "Get value for key tcp_port on R.\n");
2653 value = get_value ("tcp_port", token);
2654 LOG (GNUNET_ERROR_TYPE_DEBUG,
2655 "tcp_port: %s\n",
2656 value);
2657 ret = sscanf (value, "%u", &(router->tcp_port));
2658 GNUNET_free (value);
2659 GNUNET_break (0 != ret && 1 >= router->tcp_port);
2660
2661 LOG (GNUNET_ERROR_TYPE_DEBUG,
2662 "Get value for key udp_port on R.\n");
2663 value2 = get_value ("udp_port", token);
2664 ret = sscanf (value2, "%u", &(router->udp_port));
2665 GNUNET_free (value2);
2666 GNUNET_break (0 != ret && 1 >= router->udp_port);
2667 LOG (GNUNET_ERROR_TYPE_DEBUG,
2668 "udp_port: %s\n",
2669 value2);
2670 GNUNET_free (value2);
2671 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2672 topo->map_namespaces,
2673 &hkey_r))
2674 {
2675 namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
2676 &hkey_r);
2677 }
2678 else
2679 {
2680 namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
2681 namespace->namespace_n = out;
2682 namespace->nodes = GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2683 GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
2684 &hkey_r,
2685 namespace,
2686 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2687 }
2688 namespace->router = router;
2689
2690 }
2691 else if (0 == strcmp (key, "P"))
2692 {
2693 struct GNUNET_TESTING_NetjailNode *p_node = GNUNET_new (struct
2694 GNUNET_TESTING_NetjailNode);
2695 struct GNUNET_ShortHashCode hkey_p;
2696
2697 LOG (GNUNET_ERROR_TYPE_DEBUG,
2698 "Get first Value for P.\n");
2699 out = get_first_value (token);
2700 LOG (GNUNET_ERROR_TYPE_DEBUG,
2701 "P: %u\n",
2702 out);
2703 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2704 memcpy (&hkey_p,
2705 &hc,
2706 sizeof (hkey_p));
2707
2708 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2709 topo->map_namespaces,
2710 &hkey_p))
2711 {
2712 namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
2713 &hkey_p);
2714 }
2715 else
2716 {
2717 namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
2718 namespace->nodes = GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2719 namespace->namespace_n = out;
2720 GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
2721 &hkey_p,
2722 namespace,
2723 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2724 }
2725 LOG (GNUNET_ERROR_TYPE_DEBUG,
2726 "Get second Value for P.\n");
2727 out = get_second_value (token);
2728 LOG (GNUNET_ERROR_TYPE_DEBUG,
2729 "P: %u\n",
2730 out);
2731 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2732 memcpy (&hkey_p,
2733 &hc,
2734 sizeof (hkey_p));
2735 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2736 namespace->nodes,
2737 &hkey_p))
2738 {
2739 GNUNET_break (0);
2740 }
2741 else
2742 {
2743
2744 GNUNET_CONTAINER_multishortmap_put (namespace->nodes,
2745 &hkey_p,
2746 p_node,
2747 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2748 LOG (GNUNET_ERROR_TYPE_DEBUG,
2749 "Get value for key plugin on P.\n");
2750 value = get_value ("plugin", token);
2751 if (NULL != value)
2752 {
2753 LOG (GNUNET_ERROR_TYPE_DEBUG,
2754 "plugin: %s\n",
2755 value);
2756 p_node->plugin = value;
2757 }
2758 p_node->node_n = out;
2759 p_node->namespace_n = namespace->namespace_n;
2760 }
2761 LOG (GNUNET_ERROR_TYPE_DEBUG,
2762 "Get AC Value for P.\n");
2763 parse_ac (p_node, token);
2764 node_connections (token, p_node);
2765 }
2766 token = strtok_r (NULL, "\n", &rest);
2767 if (NULL != token)
2768 LOG (GNUNET_ERROR_TYPE_DEBUG,
2769 "Next token %s\n",
2770 token);
2771 }
2772 if (NULL != key)
2773 GNUNET_free (key);
2774 GNUNET_free (data);
2775 return topo;
2776}
2777
2778
2779/**
2780 * Getting the topology from file.
2781 *
2782 * @param filename The name of the topology file.
2783 * @return The GNUNET_TESTING_NetjailTopology
2784 */
2785struct GNUNET_TESTING_NetjailTopology *
2786GNUNET_TESTING_get_topo_from_file (const char *filename)
2787{
2788 uint64_t fs;
2789 char *data;
2790 struct GNUNET_TESTING_NetjailTopology *topo;
2791
2792 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
2793 {
2794 LOG (GNUNET_ERROR_TYPE_ERROR,
2795 _ ("Topology file %s not found\n"),
2796 filename);
2797 return NULL;
2798 }
2799 if (GNUNET_OK !=
2800 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
2801 {
2802 LOG (GNUNET_ERROR_TYPE_ERROR,
2803 _ ("Topology file %s has no data\n"),
2804 filename);
2805 return NULL;
2806 }
2807 data = GNUNET_malloc (fs + 1);
2808 if (fs != GNUNET_DISK_fn_read (filename, data, fs))
2809 {
2810 LOG (GNUNET_ERROR_TYPE_ERROR,
2811 _ ("Topology file %s cannot be read\n"),
2812 filename);
2813 GNUNET_free (data);
2814 return NULL;
2815 }
2816
2817 LOG (GNUNET_ERROR_TYPE_DEBUG,
2818 "file length %" PRIu64 "\n",
2819 fs);
2820 data[fs] = '\0';
2821
2822 topo = GNUNET_TESTING_get_topo_from_string (data);
2823
2824 GNUNET_free (data);
2825
2826 return topo;
2827}
2828
2829
2830/* end of testing.c */
diff --git a/src/lib/testing/testing.conf b/src/lib/testing/testing.conf
deleted file mode 100644
index 7e25f8c13..000000000
--- a/src/lib/testing/testing.conf
+++ /dev/null
@@ -1,11 +0,0 @@
1[TESTING]
2# How long before failing a connection?
3CONNECT_TIMEOUT = 30 s
4# How many connect attempts should we make?
5CONNECT_ATTEMPTS = 3
6# How many connections can happen simultaneously?
7MAX_OUTSTANDING_CONNECTIONS = 50
8
9# Should we clean up the files on peer group shutdown?
10DELETE_FILES = YES
11
diff --git a/src/lib/testing/testing.h b/src/lib/testing/testing.h
deleted file mode 100644
index fbd7d0d34..000000000
--- a/src/lib/testing/testing.h
+++ /dev/null
@@ -1,352 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @author t3sserakt
23 */
24#ifndef TESTING_H
25#define TESTING_H
26#include "gnunet_util_lib.h"
27#include "gnunet_testing_plugin.h"
28
29GNUNET_NETWORK_STRUCT_BEGIN
30
31/**
32 * Message send to a child loop to inform the child loop about a barrier being advanced.
33 */
34struct CommandBarrierCrossable
35{
36 /**
37 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_CROSSABLE
38 */
39 struct GNUNET_MessageHeader header;
40
41 /* followed by 0-terminated barrier name */
42};
43
44/**
45 * Message send by a child loop to inform the master loop how much
46 * GNUNET_CMDS_BARRIER_REACHED messages the child will send.
47 */
48struct CommandBarrierAttached
49{
50 /**
51 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_ATTACHED
52 */
53 struct GNUNET_MessageHeader header;
54
55 /**
56 * How often the child loop will reach the barrier.
57 */
58 uint32_t expected_reaches GNUNET_PACKED;
59
60 /**
61 * The number of the node the barrier is running on.
62 */
63 uint32_t node_number GNUNET_PACKED;
64
65 /* followed by 0-terminated barrier name */
66};
67
68struct GNUNET_TESTING_CommandBarrierReached
69{
70 /**
71 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_REACHED
72 */
73 struct GNUNET_MessageHeader header;
74
75 /**
76 * The number of the node the barrier is reached.
77 */
78 uint32_t node_number GNUNET_PACKED;
79
80 /**
81 * The number of reach messages which most likely will send.
82 */
83 uint32_t expected_number_of_reached_messages GNUNET_PACKED;
84
85 /* followed by 0-terminated barrier name */
86};
87
88GNUNET_NETWORK_STRUCT_END
89
90/**
91 * Handle for a plugin.
92 */
93struct TestcasePlugin
94{
95 /**
96 * Name of the shared library.
97 */
98 char *library_name;
99
100 /**
101 * Plugin API.
102 */
103 struct GNUNET_TESTING_PluginFunctions *api;
104
105 /**
106 * IP address of the specific node the helper is running for.
107 *
108 */
109 char *node_ip;
110
111 /**
112 * Name of the test case plugin.
113 *
114 */
115 char *plugin_name;
116
117 /**
118 * The number of namespaces
119 *
120 */
121 char *global_n;
122
123 /**
124 * The number of local nodes per namespace.
125 *
126 */
127 char *local_m;
128
129 /**
130 * The number of the namespace this node is in.
131 *
132 */
133 char *n;
134
135 /**
136 * The number of the node in the namespace.
137 *
138 */
139 char *m;
140};
141
142struct CommandListEntry
143{
144 struct CommandListEntry *next;
145
146 struct CommandListEntry *prev;
147
148 struct GNUNET_TESTING_Command *command;
149};
150
151
152struct GNUNET_TESTING_Barrier
153{
154 /**
155 * Pointer to the previous prefix in the DLL.
156 */
157 struct GNUNET_TESTING_Barrier *prev;
158
159 /**
160 * Pointer to the next prefix in the DLL.
161 */
162 struct GNUNET_TESTING_Barrier *next;
163
164 /**
165 * Head of the DLL with local commands the barrier is attached too.
166 */
167 struct CommandListEntry *cmds_head;
168
169 /**
170 * Tail of the DLL with local commands the barrier is attached too.
171 */
172 struct CommandListEntry *cmds_tail;
173
174 /**
175 * Hash map containing the global known nodes which are not natted.
176 */
177 struct GNUNET_CONTAINER_MultiShortmap *nodes;
178
179 /**
180 * Name of the barrier.
181 */
182 const char *name;
183
184 /**
185 * Is this barrier running on the master.
186 */
187 unsigned int running_on_master;
188
189 /**
190 * Number of commands attached to this barrier.
191 */
192 unsigned int expected_reaches;
193
194 /**
195 * Number of commands which reached this barrier.
196 */
197 unsigned int reached;
198
199 /**
200 * Percentage of of commands which need to reach the barrier to change state.
201 * Can not be used together with to_be_reached;
202 */
203 double percentage_to_be_reached;
204
205 /**
206 * Number of commands which need to reach the barrier to change state.
207 * Can not be used together with percentage_to_be_reached;
208 */
209 unsigned int number_to_be_reached;
210
211 /*
212 * No barrier locally. Shadow created. Real barrier created elsewhere.
213 */
214 unsigned int shadow;
215};
216
217
218/**
219 * Advance internal pointer to next command.
220 *
221 * @param cls batch internal state
222 * @return true if we could advance, false if the batch
223 * has completed and cannot advance anymore
224 */
225bool
226GNUNET_TESTING_cmd_batch_next_ (void *cls);
227
228
229/**
230 * Test if this command is a batch command.
231 *
232 * @return false if not, true if it is a batch command
233 */
234bool
235GNUNET_TESTING_cmd_is_batch_ (const struct GNUNET_TESTING_Command *cmd);
236
237
238/**
239 * Obtain what command the batch is at.
240 *
241 * @return cmd current batch command
242 */
243struct GNUNET_TESTING_Command *
244GNUNET_TESTING_cmd_batch_get_current_ (const struct GNUNET_TESTING_Command *cmd);
245
246
247/**
248 * Set what command the batch should be at. Needed for
249 * loops. We may want to change this to take a label
250 * and/or expose it in the public API in the future.
251 * Not used for now.
252 *
253 * @param cmd current batch command
254 * @param new_ip where to move the IP
255 */
256void
257GNUNET_TESTING_cmd_batch_set_current_ (const struct GNUNET_TESTING_Command *cmd,
258 unsigned int new_ip);
259
260
261/**
262 * This function checks, if a barrier can be crossed, which actually means that
263 * the cmd representing the barrier is finished.
264 *
265 * @param barrier The barrier in question.
266 * @return GNUNET_YES if we can cross the barrier, GNUNET_NO if not.
267 */
268unsigned int
269GNUNET_TESTING_barrier_crossable (struct GNUNET_TESTING_Barrier *barrier);
270
271
272/**
273 * Send Message to a netjail node that a barrier can be crossed.
274 *
275 * @param is The interpreter loop.
276 * @param barrier_name The name of the barrier to cross.
277 * @param global_node_number The global number of the node to inform.
278 */
279void
280TST_interpreter_send_barrier_crossable (struct GNUNET_TESTING_Interpreter *is,
281 const char *barrier_name,
282 unsigned int global_node_number);
283
284
285/**
286 * Finish all "barrier reached" comands attached to this barrier.
287 *
288 * @param barrier The barrier in question.
289 */
290void
291TST_interpreter_finish_attached_cmds (struct GNUNET_TESTING_Interpreter *is,
292 const char *barrier_name);
293
294
295/**
296 * Send Message to master loop that cmds being attached to a barrier.
297 * FIXME: Unused function
298 *
299 * @param is The interpreter loop.
300 * @param barrier_name The name of the barrier to attach to.
301 * @param subnet_number The number of the subnet.
302 * @param node_number The node to inform.
303 * @param write_message Callback to write messages to the master loop.
304 */
305void
306GNUNET_TESTING_send_barrier_attach (struct GNUNET_TESTING_Interpreter *is,
307 char *barrier_name,
308 unsigned int global_node_number,
309 unsigned int expected_reaches,
310 GNUNET_TESTING_cmd_helper_write_cb write_message);
311
312
313/**
314 * Getting a node from a map by global node number.
315 * FIXME: This is a barrier helper function not related to a command but it is
316 * implemented in the *_cmd_barrier.c file.
317 * Maybe move into a separate file like testing_barrier.c; see also can
318 * barrier advance above
319 *
320 * @param nodes The map.
321 * @param node_number The global node number.
322 * @return The node.
323 */
324struct GNUNET_TESTING_NetjailNode *
325GNUNET_TESTING_barrier_get_node (struct GNUNET_TESTING_Barrier *barrier,
326 unsigned int node_number);
327
328
329/**
330 * Getting a barrier from the interpreter.
331 *
332 * @param is The interpreter.
333 * @param barrier_name The name of the barrier.
334 * @return The barrier.
335 */
336struct GNUNET_TESTING_Barrier *
337TST_interpreter_get_barrier (struct GNUNET_TESTING_Interpreter *is,
338 const char *barrier_name);
339
340
341/**
342 * Add a barrier to the loop.
343 *
344 * @param is The interpreter.
345 * @param barrier The barrier to add.
346 */
347void
348TST_interpreter_add_barrier (struct GNUNET_TESTING_Interpreter *is,
349 struct GNUNET_TESTING_Barrier *barrier);
350
351
352#endif
diff --git a/src/lib/testing/testing_api_cmd_barrier.c b/src/lib/testing/testing_api_cmd_barrier.c
deleted file mode 100644
index c9c43b178..000000000
--- a/src/lib/testing/testing_api_cmd_barrier.c
+++ /dev/null
@@ -1,202 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_barrier.c
23 * @brief Barrier functionality.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "testing.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_netjail_lib.h"
31#include "gnunet_testing_barrier.h"
32
33/**
34 * Generic logging shortcut
35 */
36#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
37
38struct BarrierState
39{
40 /*
41 * Our barrier.
42 */
43 struct GNUNET_TESTING_Barrier *barrier;
44
45 /*
46 * Our label.
47 */
48 const char *label;
49};
50
51// FIXME Unused function
52void
53GNUNET_TESTING_send_barrier_attach (struct GNUNET_TESTING_Interpreter *is,
54 char *barrier_name,
55 unsigned int global_node_number,
56 unsigned int expected_reaches,
57 GNUNET_TESTING_cmd_helper_write_cb
58 write_message)
59{
60 struct CommandBarrierAttached *atm = GNUNET_new (struct
61 CommandBarrierAttached);
62 size_t msg_length = sizeof(struct CommandBarrierAttached);
63 size_t name_len;
64
65 name_len = strlen (barrier_name) + 1;
66 atm->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_ATTACHED);
67 atm->header.size = htons ((uint16_t) msg_length);
68 atm->expected_reaches = expected_reaches;
69 atm->node_number = global_node_number;
70 memcpy (&atm[1], barrier_name, name_len);
71 write_message ((struct GNUNET_MessageHeader *) atm, msg_length);
72
73 GNUNET_free (atm);
74}
75
76
77unsigned int
78GNUNET_TESTING_barrier_crossable (struct GNUNET_TESTING_Barrier *barrier)
79{
80 unsigned int expected_reaches = barrier->expected_reaches;
81 unsigned int reached = barrier->reached;
82 double percentage_to_be_reached = barrier->percentage_to_be_reached;
83 unsigned int number_to_be_reached = barrier->number_to_be_reached;
84 double percentage_reached = (double) reached / expected_reaches * 100;
85
86 LOG (GNUNET_ERROR_TYPE_DEBUG,
87 "%u %f %f %u %u\n",
88 expected_reaches,
89 percentage_to_be_reached,
90 percentage_reached,
91 number_to_be_reached,
92 reached);
93
94 if (((0 < percentage_to_be_reached) &&
95 (percentage_reached >= percentage_to_be_reached)) ||
96 ((0 < number_to_be_reached) && (reached >= number_to_be_reached)))
97 {
98 return GNUNET_YES;
99 }
100 else
101 {
102 return GNUNET_NO;
103 }
104}
105
106
107/**
108 * Offer internal data from a "barrier" CMD, to other commands.
109 *
110 * @param cls closure.
111 * @param[out] ret result.
112 * @param trait name of the trait.
113 * @param index index number of the object to offer.
114 * @return #GNUNET_OK on success.
115 */
116static enum GNUNET_GenericReturnValue
117barrier_traits (void *cls,
118 const void **ret,
119 const char *trait,
120 unsigned int index)
121{
122 struct GNUNET_TESTING_Trait traits[] = {
123 GNUNET_TESTING_trait_end ()
124 };
125
126 /* Always return current command. */
127 return GNUNET_TESTING_get_trait (traits,
128 ret,
129 trait,
130 index);
131}
132
133
134/**
135 * Cleanup the state from a "barrier" CMD, and possibly
136 * cancel a pending operation thereof.
137 *
138 * @param cls closure.
139 */
140static void
141barrier_cleanup (void *cls)
142{
143 struct BarrierState *brs = cls;
144
145 GNUNET_free (brs);
146}
147
148
149/**
150 * Run the command.
151 *
152 * @param cls closure.
153 * @param is the interpreter state.
154 */
155static void
156barrier_run (void *cls,
157 struct GNUNET_TESTING_Interpreter *is)
158{
159 struct BarrierState *brs = cls;
160
161 TST_interpreter_add_barrier (is, brs->barrier);
162}
163
164
165struct GNUNET_TESTING_NetjailNode *
166GNUNET_TESTING_barrier_get_node (struct GNUNET_TESTING_Barrier *barrier,
167 unsigned int node_number)
168{
169 struct GNUNET_HashCode hc;
170 struct GNUNET_ShortHashCode key;
171
172 GNUNET_CRYPTO_hash (&(node_number), sizeof(node_number), &hc);
173 memcpy (&key,
174 &hc,
175 sizeof (key));
176 return GNUNET_CONTAINER_multishortmap_get (barrier->nodes, &key);
177}
178
179
180struct GNUNET_TESTING_Command
181GNUNET_TESTING_cmd_barrier_create (const char *label,
182 double percentage_to_be_reached,
183 unsigned int number_to_be_reached)
184{
185 struct GNUNET_TESTING_Barrier *barrier;
186 struct BarrierState *bs;
187
188 bs = GNUNET_new (struct BarrierState);
189 bs->label = label;
190 barrier = GNUNET_new (struct GNUNET_TESTING_Barrier);
191 barrier->name = label;
192 barrier->percentage_to_be_reached = percentage_to_be_reached;
193 barrier->number_to_be_reached = number_to_be_reached;
194 GNUNET_assert ((0 < percentage_to_be_reached && 0 == number_to_be_reached) ||
195 (0 == percentage_to_be_reached && 0 < number_to_be_reached));
196 bs->barrier = barrier;
197 return GNUNET_TESTING_command_new (bs, label,
198 &barrier_run,
199 &barrier_cleanup,
200 &barrier_traits,
201 NULL);
202}
diff --git a/src/lib/testing/testing_api_cmd_barrier_reached.c b/src/lib/testing/testing_api_cmd_barrier_reached.c
deleted file mode 100644
index 161240d4d..000000000
--- a/src/lib/testing/testing_api_cmd_barrier_reached.c
+++ /dev/null
@@ -1,229 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_barrier_reached.c
23 * @brief Command to signal barrier was reached.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_lib.h"
28#include "testing_cmds.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_barrier.h"
31#include "gnunet_testing_netjail_lib.h"
32#include "testing.h"
33
34/**
35 * Generic logging shortcut
36 */
37#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
38
39/**
40 * Struct with information for callbacks.
41 *
42 */
43struct BarrierReachedState
44{
45 /**
46 * Callback to write messages to the master loop.
47 *
48 */
49 GNUNET_TESTING_cmd_helper_write_cb write_message;
50
51 /**
52 * Context for our asynchronous completion.
53 */
54 struct GNUNET_TESTING_AsyncContext ac;
55
56 /**
57 * The label of this command.
58 */
59 const char *label;
60
61 /**
62 * The name of the barrier this commands wait (if finishing asynchronous) for or/and reaches.
63 */
64 const char *barrier_name;
65
66 /*
67 * The global numer of the node the cmd runs on.
68 */
69 unsigned int node_number;
70
71 /**
72 * If this command will block.
73 */
74 unsigned int asynchronous_finish;
75
76 /**
77 * Is this cmd running on the master loop.
78 */
79 unsigned int running_on_master;
80};
81
82
83/**
84 * Run the command.
85 *
86 * @param cls closure.
87 * @param is the interpreter state.
88 */
89static void
90barrier_reached_run (void *cls,
91 struct GNUNET_TESTING_Interpreter *is)
92{
93 struct BarrierReachedState *brs = cls;
94 struct GNUNET_TESTING_Barrier *barrier;
95 struct GNUNET_TESTING_Command *cmd =
96 GNUNET_TESTING_interpreter_get_current_command (is);
97 struct CommandListEntry *cle;
98 size_t msg_length;
99 struct GNUNET_TESTING_CommandBarrierReached *msg;
100 size_t name_len;
101
102 barrier = TST_interpreter_get_barrier (is, brs->barrier_name);
103 if (NULL == barrier)
104 {
105 barrier = GNUNET_new (struct GNUNET_TESTING_Barrier);
106 barrier->name = brs->barrier_name;
107 TST_interpreter_add_barrier (is, barrier);
108 LOG (GNUNET_ERROR_TYPE_DEBUG,
109 "barrier %s added locally\n",
110 brs->barrier_name);
111 }
112 barrier->reached++;
113 if (GNUNET_TESTING_barrier_crossable (barrier))
114 {
115 GNUNET_assert (NULL != cmd);
116 cmd->asynchronous_finish = GNUNET_YES;
117 TST_interpreter_finish_attached_cmds (is, barrier->name);
118 }
119 else if (GNUNET_NO == brs->asynchronous_finish)
120 {
121 cle = GNUNET_new (struct CommandListEntry);
122 cle->command = cmd;
123 GNUNET_CONTAINER_DLL_insert (barrier->cmds_head,
124 barrier->cmds_tail,
125 cle);
126 LOG (GNUNET_ERROR_TYPE_DEBUG,
127 "added cle for %p %s\n",
128 barrier,
129 barrier->name);
130 }
131
132 if (GNUNET_NO == brs->running_on_master)
133 {
134 char *terminator = "\0";
135
136 name_len = strlen (barrier->name);
137 msg_length = sizeof(struct GNUNET_TESTING_CommandBarrierReached)
138 + name_len + 1;
139 msg = GNUNET_malloc (msg_length);
140 msg->header.size = htons ((uint16_t) msg_length);
141 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_REACHED);
142 msg->node_number = brs->node_number;
143 memcpy (&msg[1], barrier->name, name_len + 1);
144 memcpy (&msg[name_len + 1],terminator,1);
145 brs->write_message ((struct GNUNET_MessageHeader *) msg, msg_length);
146 }
147}
148
149
150/**
151 * Cleanup the state from a "barrier reached" CMD, and possibly
152 * cancel a pending operation thereof.
153 *
154 * @param cls closure.
155 */
156static void
157barrier_reached_cleanup (void *cls)
158{
159 struct BarrierReachedState *brs = cls;
160
161 GNUNET_free (brs);
162}
163
164
165/**
166 * Offer internal data from a "batch" CMD, to other commands.
167 *
168 * @param cls closure.
169 * @param[out] ret result.
170 * @param trait name of the trait.
171 * @param index index number of the object to offer.
172 * @return #GNUNET_OK on success.
173 */
174static enum GNUNET_GenericReturnValue
175barrier_reached_traits (void *cls,
176 const void **ret,
177 const char *trait,
178 unsigned int index)
179{
180 struct BarrierReachedState *brs = cls;
181 struct GNUNET_TESTING_AsyncContext *ac = &brs->ac;
182
183 struct GNUNET_TESTING_Trait traits[] = {
184 GNUNET_TESTING_make_trait_async_context (ac),
185 GNUNET_TESTING_trait_end ()
186 };
187
188 return GNUNET_TESTING_get_trait (traits,
189 ret,
190 trait,
191 index);
192}
193
194
195/**
196 * Create command.
197 *
198 * @param label name for command.
199 * @param barrier_label The name of the barrier we wait for (if finishing asynchronous) and which will be reached.
200 * @param asynchronous_finish If GNUNET_YES this command will not block.
201 * @param node_number The global numer of the node the cmd runs on.
202 * @param running_on_master Is this cmd running on the master loop.
203 * @param write_message Callback to write messages to the master loop.
204 * @return command.
205 */
206struct GNUNET_TESTING_Command
207GNUNET_TESTING_cmd_barrier_reached (
208 const char *label,
209 const char *barrier_label,
210 unsigned int asynchronous_finish,
211 unsigned int node_number,
212 unsigned int running_on_master,
213 GNUNET_TESTING_cmd_helper_write_cb write_message)
214{
215 struct BarrierReachedState *brs;
216
217 brs = GNUNET_new (struct BarrierReachedState);
218 brs->label = label;
219 brs->barrier_name = barrier_label;
220 brs->asynchronous_finish = asynchronous_finish;
221 brs->node_number = node_number;
222 brs->running_on_master = running_on_master;
223 brs->write_message = write_message;
224 return GNUNET_TESTING_command_new (brs, label,
225 &barrier_reached_run,
226 &barrier_reached_cleanup,
227 &barrier_reached_traits,
228 &brs->ac);
229}
diff --git a/src/lib/testing/testing_api_cmd_batch.c b/src/lib/testing/testing_api_cmd_batch.c
deleted file mode 100644
index 7dc990855..000000000
--- a/src/lib/testing/testing_api_cmd_batch.c
+++ /dev/null
@@ -1,223 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_batch.c
23 * @brief Implement batch-execution of CMDs.
24 * @author Marcello Stanisci (GNU Taler testing)
25 * @author t3sserakt
26 */
27#include "platform.h"
28#include "gnunet_testing_ng_lib.h"
29#include "testing.h"
30
31/**
32 * State for a "batch" CMD.
33 */
34struct BatchState
35{
36 /**
37 * CMDs batch.
38 */
39 struct GNUNET_TESTING_Command *batch;
40
41 /**
42 * Our label.
43 */
44 const char *label;
45
46 /**
47 * Internal command pointer.
48 */
49 unsigned int batch_ip;
50};
51
52
53/**
54 * Run the command.
55 *
56 * @param cls closure.
57 * @param is the interpreter state.
58 */
59static void
60batch_run (void *cls,
61 struct GNUNET_TESTING_Interpreter *is)
62{
63 struct BatchState *bs = cls;
64
65 if (NULL != bs->batch[bs->batch_ip].run)
66 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
67 "Running batched command: %s\n",
68 bs->batch[bs->batch_ip].label);
69
70 /* hit end command, leap to next top-level command. */
71 if (NULL == bs->batch[bs->batch_ip].run)
72 {
73 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
74 "Exiting from batch: %s\n",
75 bs->label);
76 return;
77 }
78 bs->batch[bs->batch_ip].start_time
79 = bs->batch[bs->batch_ip].last_req_time
80 = GNUNET_TIME_absolute_get ();
81 bs->batch[bs->batch_ip].num_tries = 1;
82 bs->batch[bs->batch_ip].run (bs->batch[bs->batch_ip].cls,
83 is);
84}
85
86
87/**
88 * Cleanup the state from a "reserve status" CMD, and possibly
89 * cancel a pending operation thereof.
90 *
91 * @param cls closure.
92 */
93static void
94batch_cleanup (void *cls)
95{
96 struct BatchState *bs = cls;
97
98 for (unsigned int i = 0;
99 NULL != bs->batch[i].run;
100 i++)
101 bs->batch[i].cleanup (bs->batch[i].cls);
102 GNUNET_free (bs->batch);
103 GNUNET_free (bs);
104}
105
106
107/**
108 * Offer internal data from a "batch" CMD, to other commands.
109 *
110 * @param cls closure.
111 * @param[out] ret result.
112 * @param trait name of the trait.
113 * @param index index number of the object to offer.
114 * @return #GNUNET_OK on success.
115 */
116static enum GNUNET_GenericReturnValue
117batch_traits (void *cls,
118 const void **ret,
119 const char *trait,
120 unsigned int index)
121{
122 struct BatchState *bs = cls;
123 // FIXME: these constants should be more global!
124#define CURRENT_CMD_INDEX 0
125#define BATCH_INDEX 1
126 struct GNUNET_TESTING_Trait traits[] = {
127 GNUNET_TESTING_make_trait_cmd (CURRENT_CMD_INDEX,
128 &bs->batch[bs->batch_ip]),
129 GNUNET_TESTING_make_trait_cmd (BATCH_INDEX,
130 bs->batch),
131 GNUNET_TESTING_trait_end ()
132 };
133
134 /* Always return current command. */
135 return GNUNET_TESTING_get_trait (traits,
136 ret,
137 trait,
138 index);
139}
140
141
142/**
143 * Create a "batch" command. Such command takes a
144 * end_CMD-terminated array of CMDs and executed them.
145 * Once it hits the end CMD, it passes the control
146 * to the next top-level CMD, regardless of it being
147 * another batch or ordinary CMD.
148 *
149 * @param label the command label.
150 * @param batch array of CMDs to execute.
151 *
152 * @return the command.
153 */
154struct GNUNET_TESTING_Command
155GNUNET_TESTING_cmd_batch (const char *label,
156 struct GNUNET_TESTING_Command *batch)
157{
158 struct BatchState *bs;
159 unsigned int i;
160
161 bs = GNUNET_new (struct BatchState);
162 bs->label = label;
163 /* Get number of commands. */
164 for (i = 0; NULL != batch[i].run; i++)
165 /* noop */
166 ;
167
168 bs->batch = GNUNET_new_array (i + 1,
169 struct GNUNET_TESTING_Command);
170 memcpy (bs->batch,
171 batch,
172 sizeof (struct GNUNET_TESTING_Command) * i);
173 return GNUNET_TESTING_command_new (bs, label,
174 &batch_run,
175 &batch_cleanup,
176 &batch_traits, NULL);
177}
178
179
180bool
181GNUNET_TESTING_cmd_batch_next_ (void *cls)
182{
183 struct BatchState *bs = cls;
184
185 if (NULL == bs->batch[bs->batch_ip].run)
186 return false;
187 bs->batch[bs->batch_ip].finish_time
188 = GNUNET_TIME_absolute_get ();
189 bs->batch_ip++;
190 return true;
191}
192
193
194bool
195GNUNET_TESTING_cmd_is_batch_ (const struct GNUNET_TESTING_Command *cmd)
196{
197 return cmd->run == &batch_run;
198}
199
200
201struct GNUNET_TESTING_Command *
202GNUNET_TESTING_cmd_batch_get_current_ (const struct GNUNET_TESTING_Command *cmd)
203{
204 struct BatchState *bs = cmd->cls;
205
206 GNUNET_assert (GNUNET_TESTING_cmd_is_batch_ (cmd));
207 return &bs->batch[bs->batch_ip];
208}
209
210
211void
212GNUNET_TESTING_cmd_batch_set_current_ (const struct GNUNET_TESTING_Command *cmd,
213 unsigned int new_ip)
214{
215 struct BatchState *bs = cmd->cls;
216
217 /* sanity checks */
218 GNUNET_assert (GNUNET_TESTING_cmd_is_batch_ (cmd));
219 for (unsigned int i = 0; i < new_ip; i++)
220 GNUNET_assert (NULL != bs->batch[i].label);
221 /* actual logic */
222 bs->batch_ip = new_ip;
223}
diff --git a/src/lib/testing/testing_api_cmd_block_until_external_trigger.c b/src/lib/testing/testing_api_cmd_block_until_external_trigger.c
deleted file mode 100644
index 6a3b00e51..000000000
--- a/src/lib/testing/testing_api_cmd_block_until_external_trigger.c
+++ /dev/null
@@ -1,119 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing_api_cmd_block_until_all_peers_started.c
23 * @brief cmd to block the interpreter loop until all peers started.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "testing_cmds.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_barrier.h"
31#include "gnunet_testing_netjail_lib.h"
32
33/**
34 * Generic logging shortcut
35 */
36#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
37
38
39/**
40 * The cleanup function of this cmd frees resources the cmd allocated.
41 *
42 */
43static void
44block_until_all_peers_started_cleanup (void *cls)
45{
46 struct BlockState *bs = cls;
47
48 GNUNET_free (bs);
49}
50
51
52static int
53block_until_external_trigger_traits (void *cls,
54 const void **ret,
55 const char *trait,
56 unsigned int index)
57{
58 struct GNUNET_TESTING_BlockState *bs = cls;
59 struct GNUNET_TESTING_AsyncContext *ac = &bs->ac;
60 struct GNUNET_TESTING_Trait traits[] = {
61 GNUNET_TESTING_make_trait_async_context (ac),
62 GNUNET_TESTING_make_trait_block_state (bs),
63 GNUNET_TESTING_trait_end ()
64 };
65
66 return GNUNET_TESTING_get_trait (traits,
67 ret,
68 trait,
69 index);
70}
71
72
73/**
74 * This function does nothing but to start the cmd.
75 *
76 */
77static void
78block_until_all_peers_started_run (void *cls,
79 struct GNUNET_TESTING_Interpreter *is)
80{
81 struct GNUNET_TESTING_BlockState *bs = cls;
82 struct GNUNET_TESTING_Command *cmd =
83 GNUNET_TESTING_interpreter_get_current_command (is);
84
85 LOG (GNUNET_ERROR_TYPE_DEBUG,
86 "block %s running %u!\n",
87 bs->label,
88 bs->asynchronous_finish);
89 if (GNUNET_YES == bs->asynchronous_finish)
90 {
91 LOG (GNUNET_ERROR_TYPE_DEBUG,
92 "block %s running asynchronous!\n",
93 bs->label);
94 cmd->asynchronous_finish = bs->asynchronous_finish;
95 }
96}
97
98
99/**
100 * Create command.
101 *
102 * @param label name for command.
103 * @return command.
104 */
105struct GNUNET_TESTING_Command
106GNUNET_TESTING_cmd_block_until_external_trigger (
107 const char *label)
108{
109 struct GNUNET_TESTING_BlockState *bs;
110
111 bs = GNUNET_new (struct GNUNET_TESTING_BlockState);
112 bs->label = label;
113 bs->asynchronous_finish = GNUNET_NO;
114 return GNUNET_TESTING_command_new (bs, label,
115 &block_until_all_peers_started_run,
116 &block_until_all_peers_started_cleanup,
117 &block_until_external_trigger_traits,
118 &bs->ac);
119}
diff --git a/src/lib/testing/testing_api_cmd_exec_bash_script.c b/src/lib/testing/testing_api_cmd_exec_bash_script.c
deleted file mode 100644
index 7e7aafb69..000000000
--- a/src/lib/testing/testing_api_cmd_exec_bash_script.c
+++ /dev/null
@@ -1,216 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2023 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing_api_cmd_local_test_prepared.c
23 * @brief cmd to block the interpreter loop until all peers started.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29
30#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
31
32struct BashScriptState
33{
34 /**
35 * Context for our asynchronous completion.
36 */
37 struct GNUNET_TESTING_AsyncContext ac;
38
39 /**
40 * Callback handed over to the command, which should
41 * be called upon death or completion of the script.
42 */
43 GNUNET_ChildCompletedCallback cb;
44
45 // Child Wait handle
46 struct GNUNET_ChildWaitHandle *cwh;
47
48 /**
49 * The process id of the script.
50 */
51 struct GNUNET_OS_Process *start_proc;
52
53 /**
54 * Script this cmd will execute.
55 */
56 const char *script;
57
58
59 /**
60 * Arguments for the script
61 */
62 char **script_argv;
63
64 /**
65 * Size of script_argv.
66 */
67 int argc;
68};
69
70/**
71 * The cleanup function of this cmd frees resources the cmd allocated.
72 *
73 */
74static void
75exec_bash_script_cleanup (void *cls)
76{
77 struct BashScriptState *bss = cls;
78
79 if (NULL != bss->cwh)
80 {
81 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
82 "Cancel child\n");
83 GNUNET_wait_child_cancel (bss->cwh);
84 bss->cwh = NULL;
85 }
86 if (NULL != bss->start_proc)
87 {
88 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
89 "Kill process\n");
90 GNUNET_assert (0 ==
91 GNUNET_OS_process_kill (bss->start_proc,
92 SIGKILL));
93 GNUNET_assert (GNUNET_OK ==
94 GNUNET_OS_process_wait (bss->start_proc));
95 GNUNET_OS_process_destroy (bss->start_proc);
96 bss->start_proc = NULL;
97 }
98 GNUNET_free (bss);
99}
100
101/**
102 * Callback which will be called if the setup script finished.
103 *
104 */
105static void
106child_completed_callback (void *cls,
107 enum GNUNET_OS_ProcessStatusType type,
108 long unsigned int exit_code)
109{
110 struct BashScriptState *bss = cls;
111
112 GNUNET_OS_process_destroy (bss->start_proc);
113 bss->start_proc = NULL;
114 bss->cwh = NULL;
115 if (0 == exit_code)
116 {
117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118 "Child succeeded!\n");
119 GNUNET_TESTING_async_finish (&bss->ac);
120 }
121 else
122 {
123 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
124 "Child failed with error %lu!\n",
125 exit_code);
126 GNUNET_TESTING_async_fail (&bss->ac);
127 }
128 bss->cb (cls, type, exit_code);
129}
130
131/**
132 * Run method of the command created by the interpreter to wait for another
133 * command to finish.
134 *
135 */
136static void
137exec_bash_script_run (void *cls,
138 struct GNUNET_TESTING_Interpreter *is)
139{
140 struct BashScriptState *bss = cls;
141 enum GNUNET_GenericReturnValue helper_check;
142 char *argv[bss->argc + 2];
143
144 char *data_dir;
145 char *script_name;
146
147 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
148 GNUNET_asprintf (&script_name, "%s%s", data_dir, bss->script);
149
150 helper_check = GNUNET_OS_check_helper_binary (
151 script_name,
152 GNUNET_YES,
153 NULL);
154
155 LOG (GNUNET_ERROR_TYPE_DEBUG,
156 "script_name %s\n",
157 script_name);
158
159 if (GNUNET_NO == helper_check)
160 {
161 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
162 "No SUID for %s!\n",
163 script_name);
164 GNUNET_TESTING_interpreter_fail (is);
165 return;
166 }
167 if (GNUNET_SYSERR == helper_check)
168 {
169 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
170 "%s not found!\n",
171 script_name);
172 GNUNET_TESTING_interpreter_fail (is);
173 return;
174 }
175 argv[0] = script_name;
176 if (NULL != bss->script_argv)
177 {
178 for (int i = 0; i < bss->argc;i++)
179 argv[i + 1] = bss->script_argv[i];
180 }
181 argv[bss->argc] = NULL;
182
183 bss->start_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
184 NULL,
185 NULL,
186 NULL,
187 script_name,
188 argv);
189 bss->cwh = GNUNET_wait_child (bss->start_proc,
190 &child_completed_callback,
191 bss);
192 GNUNET_break (NULL != bss->cwh);
193}
194
195const struct GNUNET_TESTING_Command
196GNUNET_TESTING_cmd_exec_bash_script (const char *label,
197 const char *script,
198 char *const script_argv[],
199 int argc,
200 GNUNET_ChildCompletedCallback cb)
201{
202 struct BashScriptState *bss;
203
204 bss = GNUNET_new (struct BashScriptState);
205 bss->script = script;
206 bss->script_argv = script_argv; // FIXME this is not just a cast to fix
207 bss->argc = argc;
208 bss->cb = cb;
209
210 return GNUNET_TESTING_command_new (bss,
211 label,
212 &exec_bash_script_run,
213 &exec_bash_script_cleanup,
214 NULL,
215 &bss->ac);
216}
diff --git a/src/lib/testing/testing_api_cmd_finish.c b/src/lib/testing/testing_api_cmd_finish.c
deleted file mode 100644
index e1fc69a09..000000000
--- a/src/lib/testing/testing_api_cmd_finish.c
+++ /dev/null
@@ -1,195 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file testing/testing_api_cmd_finish.c
22 * @brief command to wait for completion of async command
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_testing_ng_lib.h"
28#include "gnunet_testing_plugin.h"
29#include "gnunet_testing_barrier.h"
30#include "gnunet_testing_netjail_lib.h"
31
32
33/**
34 * Struct to use for command-specific context information closure of a command waiting
35 * for another command.
36 */
37struct FinishState
38{
39 /**
40 * Closure for all commands with command-specific context information.
41 */
42 void *cls;
43
44 /**
45 * Label of the asynchronous command the synchronous command of this closure waits for.
46 */
47 const char *async_label;
48
49 /**
50 * Task for running the finish method of the asynchronous task the command is waiting for.
51 */
52 struct GNUNET_SCHEDULER_Task *finish_task;
53
54 /**
55 * Function to call when done.
56 */
57 struct GNUNET_TESTING_AsyncContext ac;
58
59 /**
60 * How long to wait until finish fails hard?
61 */
62 struct GNUNET_TIME_Relative timeout;
63
64};
65
66
67/**
68 * Function called when the command we are waiting on
69 * is finished. Hence we are finished, too.
70 *
71 * @param cls a `struct FinishState` being notified
72 */
73static void
74done_finish (void *cls)
75{
76 struct FinishState *finish_state = cls;
77
78 GNUNET_SCHEDULER_cancel (finish_state->finish_task);
79 finish_state->finish_task = NULL;
80 GNUNET_TESTING_async_finish (&finish_state->ac);
81}
82
83
84/**
85 * Function triggered if the command we are waiting
86 * for did not complete on time.
87 *
88 * @param cls our `struct FinishState`
89 */
90static void
91timeout_finish (void *cls)
92{
93 struct FinishState *finish_state = cls;
94
95 finish_state->finish_task = NULL;
96 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
97 "Timeout waiting for command `%s' to finish\n",
98 finish_state->async_label);
99 GNUNET_TESTING_async_fail (&finish_state->ac);
100}
101
102
103/**
104 * Run method of the command created by the interpreter to wait for another
105 * command to finish.
106 *
107 */
108static void
109run_finish (void *cls,
110 struct GNUNET_TESTING_Interpreter *is)
111{
112 struct FinishState *finish_state = cls;
113 const struct GNUNET_TESTING_Command *async_cmd;
114 struct GNUNET_TESTING_AsyncContext *aac;
115
116 async_cmd
117 = GNUNET_TESTING_interpreter_lookup_command (is,
118 finish_state->async_label);
119 if (NULL == async_cmd)
120 {
121 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
122 "Did not find command `%s'\n",
123 finish_state->async_label);
124 GNUNET_TESTING_interpreter_fail (is);
125 return;
126 }
127 if ( (NULL == (aac = async_cmd->ac)) ||
128 (! async_cmd->asynchronous_finish) )
129 {
130 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
131 "Cannot finish `%s': not asynchronous\n",
132 finish_state->async_label);
133 GNUNET_TESTING_interpreter_fail (is);
134 return;
135 }
136 if (GNUNET_NO != aac->finished)
137 {
138 /* Command is already finished, so are we! */
139 GNUNET_TESTING_async_finish (&finish_state->ac);
140 return;
141 }
142 finish_state->finish_task
143 = GNUNET_SCHEDULER_add_delayed (finish_state->timeout,
144 &timeout_finish,
145 finish_state);
146 aac->cont = &done_finish;
147 aac->cont_cls = finish_state;
148}
149
150
151/**
152 * Cleanup state of a finish command.
153 *
154 * @param cls a `struct FinishState` to clean up
155 */
156static void
157cleanup_finish (void *cls)
158{
159 struct FinishState *finish_state = cls;
160
161 if (NULL != finish_state->finish_task)
162 {
163 GNUNET_SCHEDULER_cancel (finish_state->finish_task);
164 finish_state->finish_task = NULL;
165 }
166 GNUNET_free (finish_state);
167}
168
169
170const struct GNUNET_TESTING_Command
171GNUNET_TESTING_cmd_finish (const char *finish_label,
172 const char *cmd_ref,
173 struct GNUNET_TIME_Relative timeout)
174{
175 struct FinishState *finish_state;
176
177 finish_state = GNUNET_new (struct FinishState);
178 finish_state->async_label = cmd_ref;
179 finish_state->timeout = timeout;
180 return GNUNET_TESTING_command_new (finish_state, finish_label,
181 &run_finish,
182 &cleanup_finish,
183 NULL, &finish_state->ac);
184}
185
186
187struct GNUNET_TESTING_Command
188GNUNET_TESTING_cmd_make_unblocking (struct GNUNET_TESTING_Command cmd)
189{
190 /* do not permit this function to be used on
191 a finish command! */
192 GNUNET_assert (cmd.run != &run_finish);
193 cmd.asynchronous_finish = true;
194 return cmd;
195}
diff --git a/src/lib/testing/testing_api_cmd_local_test_prepared.c b/src/lib/testing/testing_api_cmd_local_test_prepared.c
deleted file mode 100644
index 2b1525077..000000000
--- a/src/lib/testing/testing_api_cmd_local_test_prepared.c
+++ /dev/null
@@ -1,112 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing_api_cmd_local_test_prepared.c
23 * @brief cmd to block the interpreter loop until all peers started.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_barrier.h"
31#include "gnunet_testing_netjail_lib.h"
32#include "testing_cmds.h"
33
34/**
35 * Generic logging shortcut
36 */
37#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
38
39
40/**
41 * This function prepares an array with traits.
42 *
43 */
44enum GNUNET_GenericReturnValue
45local_test_prepared_traits (void *cls,
46 const void **ret,
47 const char *trait,
48 unsigned int index)
49{
50 struct LocalPreparedState *lfs = cls;
51 struct GNUNET_TESTING_Trait traits[] = {
52 GNUNET_TESTING_make_trait_local_prepared_state ((const void *) lfs),
53 GNUNET_TESTING_trait_end ()
54 };
55 return GNUNET_TESTING_get_trait (traits,
56 ret,
57 trait,
58 index);
59}
60
61
62/**
63 * The cleanup function of this cmd frees resources the cmd allocated.
64 *
65 */
66static void
67local_test_prepared_cleanup (void *cls)
68{
69 struct LocalPreparedState *lfs = cls;
70
71 GNUNET_free (lfs);
72}
73
74
75/**
76 * This function sends a GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TESTS_PREPARED message to the master loop.
77 *
78 */
79static void
80local_test_prepared_run (void *cls,
81 struct GNUNET_TESTING_Interpreter *is)
82{
83 struct GNUNET_TESTING_LocalPreparedState *lfs = cls;
84
85 struct GNUNET_TESTING_CommandLocalTestPrepared *reply;
86 size_t msg_length;
87
88 msg_length = sizeof(struct GNUNET_TESTING_CommandLocalTestPrepared);
89 reply = GNUNET_new (struct GNUNET_TESTING_CommandLocalTestPrepared);
90 reply->header.type = htons (
91 GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED);
92 reply->header.size = htons ((uint16_t) msg_length);
93 lfs->write_message ((struct GNUNET_MessageHeader *) reply, msg_length);
94}
95
96
97struct GNUNET_TESTING_Command
98GNUNET_TESTING_cmd_local_test_prepared (const char *label,
99 GNUNET_TESTING_cmd_helper_write_cb
100 write_message)
101{
102 struct GNUNET_TESTING_LocalPreparedState *lfs;
103
104 lfs = GNUNET_new (struct GNUNET_TESTING_LocalPreparedState);
105 lfs->write_message = write_message;
106
107 return GNUNET_TESTING_command_new (lfs, label,
108 &local_test_prepared_run,
109 &local_test_prepared_cleanup,
110 &local_test_prepared_traits,
111 &lfs->ac);
112}
diff --git a/src/lib/testing/testing_api_cmd_netjail_start.c b/src/lib/testing/testing_api_cmd_netjail_start.c
deleted file mode 100644
index f45ab939b..000000000
--- a/src/lib/testing/testing_api_cmd_netjail_start.c
+++ /dev/null
@@ -1,231 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_netjail_start.c
23 * @brief Command to start the netjail script.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_barrier.h"
31#include "gnunet_testing_netjail_lib.h"
32
33#define NETJAIL_START_SCRIPT "netjail_start.sh"
34
35#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
36
37/**
38 * Struct to hold information for callbacks.
39 *
40 */
41struct NetJailState
42{
43 /**
44 * Context for our asynchronous completion.
45 */
46 struct GNUNET_TESTING_AsyncContext ac;
47
48 // Child Wait handle
49 struct GNUNET_ChildWaitHandle *cwh;
50
51 /**
52 * The process id of the start script.
53 */
54 struct GNUNET_OS_Process *start_proc;
55
56 /**
57 * Configuration file for the test topology.
58 */
59 char *topology_config;
60
61 /**
62 * Shall we read the topology from file, or from a string.
63 */
64 unsigned int *read_file;
65};
66
67
68/**
69 * The cleanup function of this cmd frees resources the cmd allocated.
70 *
71 */
72static void
73netjail_start_cleanup (void *cls)
74{
75 struct NetJailState *ns = cls;
76
77 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
78 "netjail_start_cleanup!\n");
79
80 if (NULL != ns->cwh)
81 {
82 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
83 "Cancel child\n");
84 GNUNET_wait_child_cancel (ns->cwh);
85 ns->cwh = NULL;
86 }
87 if (NULL != ns->start_proc)
88 {
89 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
90 "Kill process\n");
91 GNUNET_assert (0 ==
92 GNUNET_OS_process_kill (ns->start_proc,
93 SIGKILL));
94 GNUNET_assert (GNUNET_OK ==
95 GNUNET_OS_process_wait (ns->start_proc));
96 GNUNET_OS_process_destroy (ns->start_proc);
97 ns->start_proc = NULL;
98 }
99 GNUNET_free (ns);
100}
101
102
103/**
104 * Callback which will be called if the setup script finished.
105 *
106 */
107static void
108child_completed_callback (void *cls,
109 enum GNUNET_OS_ProcessStatusType type,
110 long unsigned int exit_code)
111{
112 struct NetJailState *ns = cls;
113
114 GNUNET_OS_process_destroy (ns->start_proc);
115 ns->start_proc = NULL;
116 ns->cwh = NULL;
117 if (0 == exit_code)
118 {
119 GNUNET_TESTING_async_finish (&ns->ac);
120 }
121 else
122 {
123 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
124 "Child failed with error %lu!\n",
125 exit_code);
126 GNUNET_TESTING_async_fail (&ns->ac);
127 }
128}
129
130
131/**
132* The run method starts the script which setup the network namespaces.
133*
134* @param cls closure.
135* @param is interpreter state.
136*/
137static void
138netjail_start_run (void *cls,
139 struct GNUNET_TESTING_Interpreter *is)
140{
141 struct NetJailState *ns = cls;
142 char pid[15];
143 enum GNUNET_GenericReturnValue helper_check;
144 char *data_dir;
145 char *script_name;
146 char *read_file;
147
148 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
149 GNUNET_asprintf (&script_name, "%s%s", data_dir, NETJAIL_START_SCRIPT);
150 GNUNET_asprintf (&read_file, "%u", *(ns->read_file));
151
152 helper_check = GNUNET_OS_check_helper_binary (
153 script_name,
154 GNUNET_YES,
155 NULL);
156
157 LOG (GNUNET_ERROR_TYPE_DEBUG,
158 "script_name %s\n",
159 script_name);
160
161 if (GNUNET_NO == helper_check)
162 {
163 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
164 "No SUID for %s!\n",
165 script_name);
166 GNUNET_TESTING_interpreter_fail (is);
167 return;
168 }
169 if (GNUNET_SYSERR == helper_check)
170 {
171 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
172 "%s not found!\n",
173 script_name);
174 GNUNET_TESTING_interpreter_fail (is);
175 return;
176 }
177
178 GNUNET_snprintf (pid,
179 sizeof (pid),
180 "%u",
181 getpid ());
182 {
183 char *const script_argv[] = {
184 script_name,
185 ns->topology_config,
186 pid,
187 read_file,
188 NULL
189 };
190
191 ns->start_proc
192 = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
193 NULL,
194 NULL,
195 NULL,
196 script_name,
197 script_argv);
198
199 }
200 ns->cwh = GNUNET_wait_child (ns->start_proc,
201 &child_completed_callback,
202 ns);
203 GNUNET_break (NULL != ns->cwh);
204 GNUNET_free (read_file);
205 GNUNET_free (script_name);
206 GNUNET_free (data_dir);
207}
208
209
210/**
211 * Create command.
212 *
213 * @param label name for command.
214 * @param topology_config Configuration file for the test topology.
215 * @return command.
216 */
217struct GNUNET_TESTING_Command
218GNUNET_TESTING_cmd_netjail_start (const char *label,
219 char *topology_config,
220 unsigned int *read_file)
221{
222 struct NetJailState *ns;
223
224 ns = GNUNET_new (struct NetJailState);
225 ns->topology_config = topology_config;
226 ns->read_file = read_file;
227 return GNUNET_TESTING_command_new (ns, label,
228 &netjail_start_run,
229 &netjail_start_cleanup,
230 NULL, &ns->ac);
231}
diff --git a/src/lib/testing/testing_api_cmd_netjail_start_cmds_helper.c b/src/lib/testing/testing_api_cmd_netjail_start_cmds_helper.c
deleted file mode 100644
index 51a20dd9b..000000000
--- a/src/lib/testing/testing_api_cmd_netjail_start_cmds_helper.c
+++ /dev/null
@@ -1,913 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_hello_world.c
23 * @brief Command to start the netjail peers.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28#include "gnunet_testing_plugin.h"
29#include "gnunet_testing_barrier.h"
30#include "gnunet_testing_netjail_lib.h"
31#include "testing.h"
32#include "testing_cmds.h"
33
34#define NETJAIL_EXEC_SCRIPT "netjail_exec.sh"
35
36#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
37
38/**
39 * Generic logging shortcut
40 */
41#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
42
43/**
44 * Struct to store messages send/received by the helper into a DLL
45 *
46 */
47struct HelperMessage
48{
49
50 /**
51 * Kept in a DLL.
52 */
53 struct HelperMessage *next;
54
55 /**
56 * Kept in a DLL.
57 */
58 struct HelperMessage *prev;
59
60 /**
61 * Size of the original message.
62 */
63 uint16_t bytes_msg;
64
65 /* Followed by @e bytes_msg of msg.*/
66};
67
68
69/**
70 * Struct to store information handed over to callbacks.
71 *
72 */
73struct NetJailState
74{
75 /**
76 * Global state of the interpreter, used by a command
77 * to access information about other commands.
78 */
79 struct GNUNET_TESTING_Interpreter *is;
80
81 /**
82 * Context for our asynchronous completion.
83 */
84 struct GNUNET_TESTING_AsyncContext ac;
85
86 /**
87 * The complete topology information.
88 */
89 struct GNUNET_TESTING_NetjailTopology *topology;
90
91 /**
92 * Array with handles of helper processes.
93 */
94 const struct GNUNET_HELPER_Handle **helper;
95
96 /**
97 * Size of the array NetJailState#helper.
98 *
99 */
100 unsigned int n_helper;
101
102 /**
103 * Number of nodes in a natted subnet.
104 *
105 */
106 unsigned int local_m;
107
108 /**
109 * Number of natted subnets.
110 *
111 */
112 unsigned int global_n;
113
114 /**
115 * Number of global known nodes.
116 *
117 */
118 unsigned int known;
119
120
121 /**
122 * Number of test environments started.
123 *
124 */
125 unsigned int number_of_testsystems_started;
126
127 /**
128 * Number of peers started.
129 *
130 */
131 unsigned int number_of_peers_started;
132
133 /**
134 * Number of local tests finished.
135 *
136 */
137 unsigned int number_of_local_tests_finished;
138
139 /**
140 * Number of local tests prepared to finish.
141 *
142 */
143 unsigned int number_of_local_tests_prepared;
144
145 /**
146 * Name of the test case plugin the helper will load.
147 *
148 */
149 char *plugin_name;
150
151 /**
152 * Shall we read the topology from file, or from a string.
153 */
154 unsigned int *read_file;
155
156 /**
157 * String with topology data or name of topology file.
158 */
159 char *topology_data;
160
161 /**
162 * Time after this cmd has to finish.
163 */
164 struct GNUNET_TIME_Relative timeout;
165
166 /**
167 * Timeout task.
168 */
169 struct GNUNET_SCHEDULER_Task *timeout_task;
170};
171
172/**
173 * Struct containing the number of the netjail node and the NetJailState which
174 * will be handed to callbacks specific to a test environment.
175 */
176struct TestingSystemCount
177{
178 /**
179 * The plugin correlated to this netjail node.
180 */
181 struct TestcasePlugin *plugin;
182
183 /**
184 * Kept in a DLL.
185 */
186 struct TestingSystemCount *next;
187
188 /**
189 * Kept in a DLL.
190 */
191 struct TestingSystemCount *prev;
192
193 /**
194 * The send handle for the helper
195 */
196 struct GNUNET_HELPER_SendHandle *shandle;
197
198 /**
199 * Struct to store information handed over to callbacks.
200 *
201 */
202 struct NetJailState *ns;
203
204 /**
205 * The messages send to the helper.
206 */
207 struct GNUNET_MessageHeader *msg;
208};
209
210
211/**
212* Code to clean up resource this cmd used.
213*
214* @param cls closure
215*/
216static void
217netjail_exec_cleanup (void *cls)
218{
219 struct NetJailState *ns = cls;
220 GNUNET_free (ns);
221}
222
223
224/**
225 * This function prepares an array with traits.
226 *
227 */
228static enum GNUNET_GenericReturnValue
229netjail_exec_traits (void *cls,
230 const void **ret,
231 const char *trait,
232 unsigned int index)
233{
234 struct NetJailState *ns = cls;
235 const struct GNUNET_HELPER_Handle **helper = ns->helper;
236
237
238 struct GNUNET_TESTING_Trait traits[] = {
239 GNUNET_TESTING_make_trait_helper_handles (helper),
240 GNUNET_TESTING_trait_end ()
241 };
242
243 return GNUNET_TESTING_get_trait (traits,
244 ret,
245 trait,
246 index);
247}
248
249
250/**
251 * Continuation function from GNUNET_HELPER_send()
252 *
253 * @param cls closure
254 * @param result GNUNET_OK on success,
255 * GNUNET_NO if helper process died
256 * GNUNET_SYSERR during GNUNET_HELPER_stop
257 */
258static void
259clear_msg (void *cls, int result)
260{
261 struct TestingSystemCount *tbc = cls;
262
263 GNUNET_assert (NULL != tbc->shandle);
264 // GNUNET_free (tbc->shandle);
265 GNUNET_free (tbc->plugin);
266 tbc->shandle = NULL;
267 GNUNET_free (tbc);
268}
269
270
271static void
272send_message_to_locals (
273 unsigned int i,
274 unsigned int j,
275 struct NetJailState *ns,
276 struct GNUNET_MessageHeader *header
277 )
278{
279 const struct GNUNET_HELPER_Handle *helper;
280 struct TestingSystemCount *tbc;
281 unsigned int count;
282
283 LOG (GNUNET_ERROR_TYPE_DEBUG,
284 "send message of type %u to locals\n",
285 header->type);
286 tbc = GNUNET_new (struct TestingSystemCount);
287 tbc->ns = ns;
288 if (0 == i)
289 count = j;
290 else
291 count = (i - 1) * ns->local_m + j + ns->known;
292
293 helper = ns->helper[count - 1];
294
295
296 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
297 (struct GNUNET_HELPER_Handle *) helper,
298 header,
299 GNUNET_NO,
300 &clear_msg,
301 tbc);
302
303 tbc->shandle = sh;
304}
305
306
307static void
308send_all_local_tests_prepared (unsigned int i, unsigned int j, struct
309 NetJailState *ns)
310{
311 struct GNUNET_TESTING_CommandAllLocalTestsPrepared *reply;
312 size_t msg_length;
313
314
315 msg_length = sizeof(struct GNUNET_TESTING_CommandAllLocalTestsPrepared);
316 reply = GNUNET_new (struct GNUNET_TESTING_CommandAllLocalTestsPrepared);
317 reply->header.type = htons (
318 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_LOCAL_TESTS_PREPARED);
319 reply->header.size = htons ((uint16_t) msg_length);
320
321 send_message_to_locals (i, j, ns, &reply->header);
322 GNUNET_free (reply);
323}
324
325
326static void
327send_all_peers_started (unsigned int i, unsigned int j, struct NetJailState *ns)
328{
329 struct GNUNET_TESTING_CommandAllPeersStarted *reply;
330 size_t msg_length;
331
332 msg_length = sizeof(struct GNUNET_TESTING_CommandAllPeersStarted);
333 reply = GNUNET_new (struct GNUNET_TESTING_CommandAllPeersStarted);
334 reply->header.type = htons (
335 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
336 reply->header.size = htons ((uint16_t) msg_length);
337
338 send_message_to_locals (i, j, ns, &reply->header);
339 GNUNET_free (reply);
340}
341
342
343void
344barrier_attached (struct NetJailState *ns, const struct
345 GNUNET_MessageHeader *message)
346{
347 struct CommandBarrierAttached *am;
348 struct GNUNET_TESTING_NetjailNode *node;
349 struct GNUNET_TESTING_Barrier *barrier;
350 struct GNUNET_ShortHashCode key;
351 struct GNUNET_HashCode hc;
352 const char *barrier_name;
353
354 am = (struct CommandBarrierAttached *) message;
355 barrier_name = (const char *) &am[1];
356 barrier = TST_interpreter_get_barrier (ns->is, barrier_name);
357 GNUNET_assert (NULL != barrier);
358 node = GNUNET_TESTING_barrier_get_node (barrier, am->node_number);
359 if (NULL == node)
360 {
361 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
362 node->node_number = am->node_number;
363
364 GNUNET_CRYPTO_hash (&(node->node_number), sizeof(node->node_number), &hc);
365 memcpy (&key, &hc, sizeof (key));
366 GNUNET_CONTAINER_multishortmap_put (barrier->nodes,
367 &key,
368 node,
369 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
370 }
371 node->expected_reaches = node->expected_reaches + am->expected_reaches;
372 barrier->expected_reaches = barrier->expected_reaches + am->expected_reaches;
373}
374
375
376void
377barrier_reached (struct NetJailState *ns, const struct
378 GNUNET_MessageHeader *message)
379{
380 struct GNUNET_TESTING_Barrier *barrier;
381 const char *barrier_name;
382 struct GNUNET_TESTING_CommandBarrierReached *rm = (struct
383 GNUNET_TESTING_CommandBarrierReached
384 *) message;
385
386 barrier_name = (const char *) &rm[1];
387
388 barrier = TST_interpreter_get_barrier (ns->is, barrier_name);
389 GNUNET_assert (NULL != barrier);
390 LOG (GNUNET_ERROR_TYPE_DEBUG,
391 "barrier %s reached %p %u\n",
392 barrier_name,
393 barrier,
394 barrier->reached);
395 barrier->reached++;
396 LOG (GNUNET_ERROR_TYPE_DEBUG,
397 "%u %p\n",
398 barrier->reached,
399 barrier);
400 if (GNUNET_TESTING_barrier_crossable (barrier))
401 {
402 LOG (GNUNET_ERROR_TYPE_DEBUG,
403 "%s can be crossed\n",
404 barrier_name);
405 TST_interpreter_finish_attached_cmds (ns->is, barrier->name);
406 }
407 LOG (GNUNET_ERROR_TYPE_DEBUG,
408 "barrier %s reached finished\n",
409 barrier_name);
410}
411
412
413/**
414 * Functions with this signature are called whenever a
415 * complete message is received by the tokenizer.
416 *
417 * Do not call GNUNET_SERVER_mst_destroy in callback
418 *
419 * @param cls closure
420 * @param client identification of the client
421 * @param message the actual message
422 *
423 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
424 */
425static int
426helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
427{
428 struct NetJailState *ns = cls;
429 unsigned int total_number = ns->local_m * ns->global_n + ns->known;
430 uint16_t message_type = ntohs (message->type);
431 struct GNUNET_TESTING_CommandLocalFinished *lf;
432
433 switch (message_type)
434 {
435 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_ATTACHED:
436 barrier_attached (ns, message);
437 break;
438 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_REACHED:
439 barrier_reached (ns, message);
440 break;
441 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY:
442 ns->number_of_testsystems_started++;
443 break;
444 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED:
445 ns->number_of_peers_started++;
446 if (ns->number_of_peers_started == total_number)
447 {
448 for (int i = 1; i <= ns->known; i++)
449 {
450 send_all_peers_started (0,i, ns);
451 }
452 for (int i = 1; i <= ns->global_n; i++)
453 {
454 for (int j = 1; j <= ns->local_m; j++)
455 {
456 send_all_peers_started (i,j, ns);
457 }
458 }
459 ns->number_of_peers_started = 0;
460 }
461 break;
462 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED:
463 ns->number_of_local_tests_prepared++;
464 if (ns->number_of_local_tests_prepared == total_number)
465 {
466 for (int i = 1; i <= ns->known; i++)
467 {
468 send_all_local_tests_prepared (0,i, ns);
469 }
470
471 for (int i = 1; i <= ns->global_n; i++)
472 {
473 for (int j = 1; j <= ns->local_m; j++)
474 {
475 send_all_local_tests_prepared (i,j, ns);
476 }
477 }
478 }
479 break;
480 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED:
481 lf = (struct GNUNET_TESTING_CommandLocalFinished *) message;
482
483 ns->number_of_local_tests_finished++;
484 if (GNUNET_OK != lf->rv)
485 {
486 GNUNET_TESTING_async_fail (&(ns->ac));
487 }
488 else if (ns->number_of_local_tests_finished == total_number)
489 {
490 GNUNET_SCHEDULER_cancel (ns->timeout_task);
491 ns->timeout_task = NULL;
492 GNUNET_TESTING_async_finish (&ns->ac);
493 }
494 break;
495 default:
496 // We received a message we can not handle.
497 GNUNET_assert (0);
498 }
499
500 LOG (GNUNET_ERROR_TYPE_DEBUG,
501 "total %u sysstarted %u peersstarted %u prep %u finished %u %u %u %u\n",
502 total_number,
503 ns->number_of_testsystems_started,
504 ns->number_of_peers_started,
505 ns->number_of_local_tests_prepared,
506 ns->number_of_local_tests_finished,
507 ns->local_m,
508 ns->global_n,
509 ns->known);
510
511
512 return GNUNET_OK;
513}
514
515
516/**
517 * Callback called if there was an exception during execution of the helper.
518 *
519 */
520static void
521exp_cb (void *cls)
522{
523 struct NetJailState *ns = cls;
524
525 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
526 if (NULL != ns->timeout_task)
527 GNUNET_SCHEDULER_cancel (ns->timeout_task);
528 GNUNET_TESTING_async_fail (&(ns->ac));
529}
530
531
532/**
533 * Function to initialize a init message for the helper.
534 *
535 * @param plugin_name Name of the test case plugin the helper will load.
536 *
537 */
538static struct GNUNET_TESTING_CommandHelperInit *
539create_helper_init_msg_ (const char *plugin_name)
540{
541 struct GNUNET_TESTING_CommandHelperInit *msg;
542 uint16_t plugin_name_len;
543 uint16_t msg_size;
544
545 GNUNET_assert (NULL != plugin_name);
546 plugin_name_len = strlen (plugin_name);
547 msg_size = sizeof(struct GNUNET_TESTING_CommandHelperInit) + plugin_name_len;
548 msg = GNUNET_malloc (msg_size);
549 msg->header.size = htons (msg_size);
550 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT);
551 msg->plugin_name_size = htons (plugin_name_len);
552 GNUNET_memcpy ((char *) &msg[1],
553 plugin_name,
554 plugin_name_len);
555 return msg;
556}
557
558
559/**
560 * Function which start a single helper process.
561 *
562 */
563static void
564start_helper (struct NetJailState *ns,
565 unsigned int m,
566 unsigned int n)
567{
568 struct TestcasePlugin *plugin;
569 struct GNUNET_HELPER_Handle *helper;
570 struct GNUNET_TESTING_CommandHelperInit *msg;
571 struct TestingSystemCount *tbc;
572 char *m_char;
573 char *n_char;
574 char *global_n_char;
575 char *local_m_char;
576 char *known_char;
577 char *node_id;
578 char *plugin_name;
579 char *read_file;
580 pid_t pid;
581 unsigned int script_num;
582 struct GNUNET_ShortHashCode *hkey;
583 struct GNUNET_ShortHashCode key;
584 struct GNUNET_HashCode hc;
585 struct GNUNET_TESTING_NetjailTopology *topology = ns->topology;
586 struct GNUNET_TESTING_NetjailNode *node;
587 struct GNUNET_TESTING_NetjailNode *barrier_node;
588 struct GNUNET_TESTING_NetjailNamespace *namespace;
589 char *data_dir;
590 char *script_name;
591 struct GNUNET_TESTING_BarrierListEntry *pos;
592 struct GNUNET_TESTING_Barrier *barrier;
593 struct GNUNET_TESTING_BarrierList *barriers;
594 unsigned int node_num;
595 char *binary_path;
596
597 if (0 == n)
598 {
599 node_num = m;
600 script_num = m - 1;
601 }
602 else
603 {
604 node_num = (n - 1) * ns->local_m + m + ns->known;
605 script_num = n - 1 + (n - 1) * ns->local_m + m + ns->known;
606 }
607 pid = getpid ();
608
609 GNUNET_asprintf (&m_char, "%u", m);
610 GNUNET_asprintf (&n_char, "%u", n);
611 GNUNET_asprintf (&local_m_char, "%u", ns->local_m);
612 GNUNET_asprintf (&global_n_char, "%u",ns->global_n);
613 GNUNET_asprintf (&known_char, "%u",ns->known);
614 GNUNET_asprintf (&node_id, "%s%06x-%06x\n",
615 "if",
616 pid,
617 script_num);
618 // GNUNET_asprintf (&topology_data, "'%s'", ns->topology_data);
619 GNUNET_asprintf (&read_file, "%u", *(ns->read_file));
620
621 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
622 GNUNET_asprintf (&script_name, "%s%s", data_dir, NETJAIL_EXEC_SCRIPT);
623 unsigned int helper_check = GNUNET_OS_check_helper_binary (
624 script_name,
625 GNUNET_YES,
626 NULL);
627
628 tbc = GNUNET_new (struct TestingSystemCount);
629 tbc->ns = ns;
630
631 if (GNUNET_NO == helper_check)
632 {
633 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
634 "No SUID for %s!\n",
635 script_name);
636 GNUNET_TESTING_interpreter_fail (ns->is);
637 }
638 else if (GNUNET_NO == helper_check)
639 {
640 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
641 "%s not found!\n",
642 script_name);
643 GNUNET_TESTING_interpreter_fail (ns->is);
644 }
645
646 binary_path = GNUNET_OS_get_libexec_binary_path (HELPER_CMDS_BINARY);
647
648 LOG (GNUNET_ERROR_TYPE_DEBUG,
649 "sysstarted %u peersstarted %u prep %u finished %u %u %u %u\n",
650 ns->number_of_testsystems_started,
651 ns->number_of_peers_started,
652 ns->number_of_local_tests_prepared,
653 ns->number_of_local_tests_finished,
654 ns->local_m,
655 ns->global_n,
656 ns->known);
657 {
658 char *const script_argv[] = {script_name,
659 m_char,
660 n_char,
661 binary_path,
662 global_n_char,
663 local_m_char,
664 node_id,
665 read_file,
666 ns->topology_data,
667 NULL};
668 helper = GNUNET_HELPER_start (
669 GNUNET_YES,
670 script_name,
671 script_argv,
672 &helper_mst,
673 &exp_cb,
674 ns);
675 GNUNET_array_append (ns->helper, ns->n_helper, helper);
676 }
677 GNUNET_TESTING_add_netjail_helper (ns->is,
678 helper);
679 plugin_name = topology->plugin;
680
681 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
682 if (0 == n)
683 {
684 GNUNET_CRYPTO_hash (&m, sizeof(m), &hc);
685 memcpy (hkey,
686 &hc,
687 sizeof (*hkey));
688 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_globals,
689 hkey))
690 {
691 node = GNUNET_CONTAINER_multishortmap_get (topology->map_globals,
692 hkey);
693 if (NULL != node->plugin)
694 plugin_name = node->plugin;
695 }
696 }
697 else
698 {
699 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
700 memcpy (hkey,
701 &hc,
702 sizeof (*hkey));
703 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_namespaces,
704 hkey))
705 {
706 namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces,
707 hkey);
708 GNUNET_CRYPTO_hash (&m, sizeof(m), &hc);
709 memcpy (hkey,
710 &hc,
711 sizeof (*hkey));
712 if (1 == GNUNET_CONTAINER_multishortmap_contains (namespace->nodes,
713 hkey))
714 {
715 node = GNUNET_CONTAINER_multishortmap_get (namespace->nodes,
716 hkey);
717 if (NULL != node->plugin)
718 plugin_name = node->plugin;
719 }
720 }
721
722
723 }
724 GNUNET_assert (NULL != node);
725 node->node_number = node_num;
726 plugin = GNUNET_new (struct TestcasePlugin);
727 plugin->api = GNUNET_PLUGIN_load (plugin_name,
728 NULL);
729 barriers = plugin->api->get_waiting_for_barriers ();
730
731
732 for (pos = barriers->head; NULL != pos; pos = pos->next)
733 {
734 barrier = TST_interpreter_get_barrier (ns->is, pos->barrier_name);
735 if (NULL == barrier)
736 {
737 LOG (GNUNET_ERROR_TYPE_DEBUG,
738 "barrier %s added\n",
739 pos->barrier_name);
740 barrier = GNUNET_new (struct GNUNET_TESTING_Barrier);
741 barrier->name = pos->barrier_name;
742 barrier->shadow = GNUNET_YES;
743 TST_interpreter_add_barrier (ns->is, barrier);
744
745 LOG (GNUNET_ERROR_TYPE_DEBUG,
746 "%u %p\n",
747 barrier->reached,
748 barrier);
749
750 barrier->nodes = GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
751 }
752 LOG (GNUNET_ERROR_TYPE_DEBUG,
753 "barrier %p %s node %u added \n",
754 barrier,
755 pos->barrier_name,
756 node->node_number);
757 barrier_node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
758 barrier_node->node_number = node->node_number;
759 barrier_node->expected_reaches = pos->expected_reaches;
760 barrier->expected_reaches = barrier->expected_reaches
761 + pos->expected_reaches;
762 LOG (GNUNET_ERROR_TYPE_DEBUG,
763 "number_to_be_reached %u\n",
764 barrier->number_to_be_reached);
765 if (GNUNET_YES == barrier->shadow)
766 barrier->number_to_be_reached++;
767 LOG (GNUNET_ERROR_TYPE_DEBUG,
768 "number_to_be_reached %u\n",
769 barrier->number_to_be_reached);
770 GNUNET_CRYPTO_hash (&(node->node_number), sizeof(node->node_number), &hc);
771 memcpy (&key, &hc, sizeof (key));
772 GNUNET_CONTAINER_multishortmap_put (barrier->nodes,
773 &key,
774 barrier_node,
775 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
776 }
777
778 tbc->plugin = plugin;
779
780 msg = create_helper_init_msg_ (plugin_name);
781
782 tbc->shandle = GNUNET_HELPER_send (
783 helper,
784 &msg->header,
785 GNUNET_NO,
786 &clear_msg,
787 tbc);
788
789 if (NULL == tbc->shandle)
790 {
791 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
792 "Send handle is NULL!\n");
793 GNUNET_TESTING_interpreter_fail (ns->is);
794 }
795 GNUNET_free (pos);
796 GNUNET_free (binary_path);
797 GNUNET_free (hkey);
798 GNUNET_free (msg);
799 GNUNET_free (m_char);
800 GNUNET_free (n_char);
801 GNUNET_free (local_m_char);
802 GNUNET_free (global_n_char);
803 GNUNET_free (known_char);
804 GNUNET_free (node_id);
805 GNUNET_free (read_file);
806 GNUNET_free (data_dir);
807 GNUNET_free (script_name);
808 GNUNET_free (barriers);
809}
810
811
812/**
813 * Function run when the cmd terminates (good or bad) with timeout.
814 *
815 * @param cls the interpreter state
816 */
817static void
818do_timeout (void *cls)
819{
820 struct NetJailState *ns = cls;
821 struct GNUNET_TESTING_Command *cmd;
822
823 ns->timeout_task = NULL;
824 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
825 "Terminating cmd due to global timeout\n");
826 cmd = GNUNET_TESTING_interpreter_get_current_command (ns->is);
827 GNUNET_TESTING_async_finish (cmd->ac);
828}
829
830
831/**
832* This function starts a helper process for each node.
833*
834* @param cls closure.
835* @param cmd CMD being run.
836* @param is interpreter state.
837*/
838static void
839netjail_exec_run (void *cls,
840 struct GNUNET_TESTING_Interpreter *is)
841{
842 struct NetJailState *ns = cls;
843
844 ns->is = is;
845 for (int i = 1; i <= ns->known; i++)
846 {
847 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
848 "i %u\n",
849 i);
850 start_helper (ns,
851 i,
852 0);
853 }
854
855 for (int i = 1; i <= ns->global_n; i++)
856 {
857 for (int j = 1; j <= ns->local_m; j++)
858 {
859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
860 "i %u j %u\n",
861 i,
862 j);
863 start_helper (ns,
864 j,
865 i);
866 }
867 }
868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
869 "Adding timeout %s\n",
870 GNUNET_STRINGS_relative_time_to_string (ns->timeout, GNUNET_NO));
871 ns->timeout_task
872 = GNUNET_SCHEDULER_add_delayed (ns->timeout,
873 &do_timeout,
874 ns);
875}
876
877
878/**
879 * Create command.
880 *
881 * @param label Name for the command.
882 * @param topology The complete topology information.
883 * @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.
884 * @param topology_data If read_file is GNUNET_NO, topology_data holds the string with the topology.
885 * @param timeout Before this timeout is reached this cmd MUST finish.
886 * @return command.
887 */
888struct GNUNET_TESTING_Command
889GNUNET_TESTING_cmd_netjail_start_cmds_helper (
890 const char *label,
891 struct GNUNET_TESTING_NetjailTopology *topology,
892 unsigned int *read_file,
893 char *topology_data,
894 struct GNUNET_TIME_Relative timeout)
895{
896 struct NetJailState *ns;
897
898 ns = GNUNET_new (struct NetJailState);
899 ns->local_m = topology->nodes_m;
900 ns->global_n = topology->namespaces_n;
901 ns->known = topology->nodes_x;
902 ns->plugin_name = topology->plugin;
903 ns->topology = topology;
904 ns->read_file = read_file;
905 ns->topology_data = topology_data;
906 ns->timeout = GNUNET_TIME_relative_subtract (timeout, TIMEOUT);
907
908 return GNUNET_TESTING_command_new (ns, label,
909 &netjail_exec_run,
910 &netjail_exec_cleanup,
911 &netjail_exec_traits,
912 &ns->ac);
913}
diff --git a/src/lib/testing/testing_api_cmd_netjail_stop.c b/src/lib/testing/testing_api_cmd_netjail_stop.c
deleted file mode 100644
index cc05617f7..000000000
--- a/src/lib/testing/testing_api_cmd_netjail_stop.c
+++ /dev/null
@@ -1,200 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_netjail_stop.c
23 * @brief Command to stop the netjail script.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_barrier.h"
31#include "gnunet_testing_netjail_lib.h"
32
33
34#define NETJAIL_STOP_SCRIPT "netjail_stop.sh"
35
36/**
37 * Struct to hold information for callbacks.
38 *
39 */
40struct NetJailState
41{
42 /**
43 * Context for our asynchronous completion.
44 */
45 struct GNUNET_TESTING_AsyncContext ac;
46
47 // Child Wait handle
48 struct GNUNET_ChildWaitHandle *cwh;
49
50 /**
51 * Configuration file for the test topology.
52 */
53 char *topology_config;
54
55 /**
56 * The process id of the start script.
57 */
58 struct GNUNET_OS_Process *stop_proc;
59
60 /**
61 * Shall we read the topology from file, or from a string.
62 */
63 unsigned int *read_file;
64
65};
66
67
68/**
69 * The cleanup function of this cmd frees resources the cmd allocated.
70 *
71 */
72static void
73netjail_stop_cleanup (void *cls)
74{
75 struct NetJailState *ns = cls;
76
77 if (NULL != ns->cwh)
78 {
79 GNUNET_wait_child_cancel (ns->cwh);
80 ns->cwh = NULL;
81 }
82 if (NULL != ns->stop_proc)
83 {
84 GNUNET_assert (0 ==
85 GNUNET_OS_process_kill (ns->stop_proc,
86 SIGKILL));
87 GNUNET_assert (GNUNET_OK ==
88 GNUNET_OS_process_wait (ns->stop_proc));
89 GNUNET_OS_process_destroy (ns->stop_proc);
90 ns->stop_proc = NULL;
91 }
92 GNUNET_free (ns);
93}
94
95
96/**
97 * Callback which will be called if the setup script finished.
98 *
99 */
100static void
101child_completed_callback (void *cls,
102 enum GNUNET_OS_ProcessStatusType type,
103 long unsigned int exit_code)
104{
105 struct NetJailState *ns = cls;
106
107 ns->cwh = NULL;
108 GNUNET_OS_process_destroy (ns->stop_proc);
109 ns->stop_proc = NULL;
110 if (0 == exit_code)
111 {
112 GNUNET_TESTING_async_finish (&ns->ac);
113 }
114 else
115 {
116 GNUNET_TESTING_async_fail (&ns->ac);
117 }
118}
119
120
121/**
122* The run method starts the script which deletes the network namespaces.
123*
124* @param cls closure.
125* @param is interpreter state.
126*/
127static void
128netjail_stop_run (void *cls,
129 struct GNUNET_TESTING_Interpreter *is)
130{
131 struct NetJailState *ns = cls;
132 char *pid;
133 char *data_dir;
134 char *script_name;
135 char *read_file;
136
137
138 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
139 GNUNET_asprintf (&script_name, "%s%s", data_dir, NETJAIL_STOP_SCRIPT);
140 GNUNET_asprintf (&read_file, "%u", *(ns->read_file));
141 unsigned int helper_check = GNUNET_OS_check_helper_binary (
142 script_name,
143 GNUNET_YES,
144 NULL);
145
146 if (GNUNET_NO == helper_check)
147 {
148 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
149 "No SUID for %s!\n",
150 script_name);
151 GNUNET_TESTING_interpreter_fail (is);
152 }
153 else if (GNUNET_NO == helper_check)
154 {
155 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
156 "%s not found!\n",
157 script_name);
158 GNUNET_TESTING_interpreter_fail (is);
159 }
160
161 GNUNET_asprintf (&pid,
162 "%u",
163 getpid ());
164 {
165 char *const script_argv[] = {script_name,
166 ns->topology_config,
167 pid,
168 read_file,
169 NULL};
170 ns->stop_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
171 NULL,
172 NULL,
173 NULL,
174 script_name,
175 script_argv);
176 }
177 ns->cwh = GNUNET_wait_child (ns->stop_proc,
178 &child_completed_callback,
179 ns);
180 GNUNET_break (NULL != ns->cwh);
181 GNUNET_free (read_file);
182 GNUNET_free (pid);
183}
184
185
186struct GNUNET_TESTING_Command
187GNUNET_TESTING_cmd_netjail_stop (const char *label,
188 char *topology_config,
189 unsigned int *read_file)
190{
191 struct NetJailState *ns;
192
193 ns = GNUNET_new (struct NetJailState);
194 ns->topology_config = topology_config;
195 ns->read_file = read_file;
196 return GNUNET_TESTING_command_new (ns, label,
197 &netjail_stop_run,
198 &netjail_stop_cleanup,
199 NULL, &ns->ac);
200}
diff --git a/src/lib/testing/testing_api_cmd_netjail_stop_cmds_helper.c b/src/lib/testing/testing_api_cmd_netjail_stop_cmds_helper.c
deleted file mode 100644
index c6bb0ab52..000000000
--- a/src/lib/testing/testing_api_cmd_netjail_stop_cmds_helper.c
+++ /dev/null
@@ -1,157 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_hello_world.c
23 * @brief Command to start the netjail peers.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28#include "gnunet_testing_plugin.h"
29#include "gnunet_testing_barrier.h"
30#include "gnunet_testing_netjail_lib.h"
31#include "testing_cmds.h"
32
33
34/**
35 * Struct to store information handed over to callbacks.
36 *
37 */
38struct StopHelperState
39{
40
41 /**
42 * The complete topology information.
43 */
44 struct GNUNET_TESTING_NetjailTopology *topology;
45
46 const char *helper_start_label;
47
48 /**
49 * The process handle
50 */
51 struct GNUNET_HELPER_Handle **helper;
52
53 unsigned int local_m;
54
55 unsigned int global_n;
56
57 /**
58 * Number of global known nodes.
59 *
60 */
61 unsigned int known;
62};
63
64
65/**
66* Code to clean up resource this cmd used.
67*
68* @param cls closure
69* @param cmd current CMD being cleaned up.
70*/
71static void
72stop_testing_system_cleanup (void *cls)
73{
74 struct StopHelperState *shs = cls;
75
76 GNUNET_free (shs);
77}
78
79
80/**
81* This function stops the helper process for each node.
82*
83* @param cls closure.
84* @param is interpreter state.
85*/
86static void
87stop_testing_system_run (void *cls,
88 struct GNUNET_TESTING_Interpreter *is)
89{
90 struct StopHelperState *shs = cls;
91 const struct GNUNET_HELPER_Handle **helper;
92 const struct GNUNET_TESTING_Command *start_helper_cmd;
93
94 start_helper_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
95 shs->
96 helper_start_label);
97 GNUNET_TESTING_get_trait_helper_handles (start_helper_cmd,
98 &helper);
99
100 for (int i = 1; i <= shs->known; i++)
101 {
102 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
103 "i: %u\n",
104 i);
105 GNUNET_HELPER_stop (
106 (struct GNUNET_HELPER_Handle *) helper[i - 1],
107 GNUNET_YES);
108 }
109
110 for (int i = 1; i <= shs->global_n; i++)
111 {
112 for (int j = 1; j <= shs->local_m; j++)
113 {
114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
115 "i: %u j: %u\n",
116 i,
117 j);
118 GNUNET_HELPER_stop ((struct GNUNET_HELPER_Handle *) helper[(i - 1)
119 * shs->local_m
120 + j
121 + shs->known
122 - 1],
123 GNUNET_YES);
124 }
125 }
126 GNUNET_free (helper);
127}
128
129
130/**
131 * Create command.
132 *
133 * @param label name for command.
134 * @param helper_start_label label of the cmd to start the test system.
135 * @param topology The complete topology information.
136 * @return command.
137 */
138struct GNUNET_TESTING_Command
139GNUNET_TESTING_cmd_stop_cmds_helper (
140 const char *label,
141 const char *helper_start_label,
142 struct GNUNET_TESTING_NetjailTopology *topology)
143{
144 struct StopHelperState *shs;
145
146 shs = GNUNET_new (struct StopHelperState);
147 shs->helper_start_label = helper_start_label;
148 shs->local_m = topology->nodes_m;
149 shs->global_n = topology->namespaces_n;
150 shs->known = topology->nodes_x;
151 shs->topology = topology;
152
153 return GNUNET_TESTING_command_new (shs, label,
154 &stop_testing_system_run,
155 &stop_testing_system_cleanup,
156 NULL, NULL);
157}
diff --git a/src/lib/testing/testing_api_cmd_send_peer_ready.c b/src/lib/testing/testing_api_cmd_send_peer_ready.c
deleted file mode 100644
index f615a1cee..000000000
--- a/src/lib/testing/testing_api_cmd_send_peer_ready.c
+++ /dev/null
@@ -1,123 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing_api_cmd_send_peer_ready.c
23 * @brief cmd to send a helper message if peer is ready.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_barrier.h"
31#include "gnunet_testing_netjail_lib.h"
32#include "testing_cmds.h"
33
34
35/**
36 * Struct to hold information for callbacks.
37 *
38 */
39struct SendPeerReadyState
40{
41 /**
42 * Callback to write messages to the master loop.
43 *
44 */
45 GNUNET_TESTING_cmd_helper_write_cb write_message;
46
47 /**
48 * The message send back to the master loop.
49 *
50 */
51 struct GNUNET_TESTING_CommandPeerStarted *reply;
52};
53
54
55/**
56 * Trait function of this cmd does nothing.
57 *
58 */
59static enum GNUNET_GenericReturnValue
60send_peer_ready_traits (void *cls,
61 const void **ret,
62 const char *trait,
63 unsigned int index)
64{
65 return GNUNET_NO;
66}
67
68
69/**
70 * The cleanup function of this cmd frees resources the cmd allocated.
71 *
72 */
73static void
74send_peer_ready_cleanup (void *cls)
75{
76 struct SendPeerReadyState *sprs = cls;
77
78 GNUNET_free (sprs);
79}
80
81
82/**
83 * This function sends a GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED message to the master loop.
84 *
85 */
86static void
87send_peer_ready_run (void *cls,
88 struct GNUNET_TESTING_Interpreter *is)
89{
90 struct SendPeerReadyState *sprs = cls;
91 struct GNUNET_TESTING_CommandPeerStarted *reply;
92 size_t msg_length;
93
94 msg_length = sizeof(struct GNUNET_TESTING_CommandPeerStarted);
95 reply = GNUNET_new (struct GNUNET_TESTING_CommandPeerStarted);
96 reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED);
97 reply->header.size = htons ((uint16_t) msg_length);
98 sprs->reply = reply;
99 sprs->write_message ((struct GNUNET_MessageHeader *) reply, msg_length);
100}
101
102
103/**
104 * Create command.
105 *
106 * @param label name for command.
107 * @param write_message Callback to write messages to the master loop.
108 * @return command.
109 */
110struct GNUNET_TESTING_Command
111GNUNET_TESTING_cmd_send_peer_ready (const char *label,
112 GNUNET_TESTING_cmd_helper_write_cb
113 write_message)
114{
115 struct SendPeerReadyState *sprs;
116
117 sprs = GNUNET_new (struct SendPeerReadyState);
118 sprs->write_message = write_message;
119 return GNUNET_TESTING_command_new (sprs, label,
120 &send_peer_ready_run,
121 &send_peer_ready_cleanup,
122 &send_peer_ready_traits, NULL);
123}
diff --git a/src/lib/testing/testing_api_cmd_start_peer.c b/src/lib/testing/testing_api_cmd_start_peer.c
deleted file mode 100644
index e2a2c0fbf..000000000
--- a/src/lib/testing/testing_api_cmd_start_peer.c
+++ /dev/null
@@ -1,298 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing_api_cmd_start_peer.c
23 * @brief cmd to start a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "testing_cmds.h"
29#include "gnunet_testing_ng_lib.h"
30#include "gnunet_testing_netjail_lib.h"
31
32/**
33 * Generic logging shortcut
34 */
35#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
36
37
38/**
39 * The run method of this cmd will start all services of a peer to test the transport service.
40 *
41 */
42static void
43start_peer_run (void *cls,
44 struct GNUNET_TESTING_Interpreter *is)
45{
46 struct GNUNET_TESTING_StartPeerState *sps = cls;
47 char *emsg = NULL;
48 struct GNUNET_PeerIdentity dummy;
49 const struct GNUNET_TESTING_Command *system_cmd;
50 const struct GNUNET_TESTING_System *tl_system;
51 char *home;
52 char *transport_unix_path;
53 char *tcp_communicator_unix_path;
54 char *udp_communicator_unix_path;
55 char *bindto;
56 char *bindto_udp;
57
58 if (GNUNET_NO == GNUNET_DISK_file_test (sps->cfgname))
59 {
60 LOG (GNUNET_ERROR_TYPE_ERROR,
61 "File not found: `%s'\n",
62 sps->cfgname);
63 GNUNET_TESTING_interpreter_fail (is);
64 return;
65 }
66
67
68 sps->cfg = GNUNET_CONFIGURATION_create ();
69 GNUNET_assert (GNUNET_OK ==
70 GNUNET_CONFIGURATION_load (sps->cfg, sps->cfgname));
71
72 GNUNET_asprintf (&home,
73 "$GNUNET_TMP/test-transport/api-tcp-p%u",
74 sps->no);
75
76 GNUNET_asprintf (&transport_unix_path,
77 "$GNUNET_RUNTIME_DIR/tng-p%u.sock",
78 sps->no);
79
80 GNUNET_asprintf (&tcp_communicator_unix_path,
81 "$GNUNET_RUNTIME_DIR/tcp-comm-p%u.sock",
82 sps->no);
83
84 GNUNET_asprintf (&udp_communicator_unix_path,
85 "$GNUNET_RUNTIME_DIR/tcp-comm-p%u.sock",
86 sps->no);
87
88 GNUNET_asprintf (&bindto,
89 "%s:60002",
90 sps->node_ip);
91
92 GNUNET_asprintf (&bindto_udp,
93 "2086");
94
95 LOG (GNUNET_ERROR_TYPE_DEBUG,
96 "node_ip %s\n",
97 bindto);
98
99 LOG (GNUNET_ERROR_TYPE_DEBUG,
100 "bind_udp %s\n",
101 GNUNET_YES == sps->broadcast ?
102 bindto_udp : bindto);
103
104 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "PATHS", "GNUNET_TEST_HOME",
105 home);
106 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "transport", "UNIXPATH",
107 transport_unix_path);
108 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "communicator-tcp",
109 "BINDTO",
110 bindto);
111 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "communicator-udp",
112 "BINDTO",
113 GNUNET_YES == sps->broadcast ?
114 bindto_udp : bindto);
115 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "communicator-tcp",
116 "UNIXPATH",
117 tcp_communicator_unix_path);
118 GNUNET_CONFIGURATION_set_value_string (sps->cfg, "communicator-udp",
119 "UNIXPATH",
120 udp_communicator_unix_path);
121
122
123 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
124 sps->system_label);
125 GNUNET_TESTING_get_trait_test_system (system_cmd,
126 &tl_system);
127
128 sps->tl_system = tl_system;
129
130 LOG (GNUNET_ERROR_TYPE_DEBUG,
131 "Creating testing library with key number %u\n",
132 sps->no);
133
134 if (GNUNET_SYSERR ==
135 GNUNET_TESTING_configuration_create ((struct
136 GNUNET_TESTING_System *) tl_system,
137 sps->cfg))
138 {
139 LOG (GNUNET_ERROR_TYPE_DEBUG,
140 "Testing library failed to create unique configuration based on `%s'\n",
141 sps->cfgname);
142 GNUNET_CONFIGURATION_destroy (sps->cfg);
143 GNUNET_TESTING_interpreter_fail (is);
144 return;
145 }
146
147 sps->peer = GNUNET_TESTING_peer_configure ((struct
148 GNUNET_TESTING_System *) sps->
149 tl_system,
150 sps->cfg,
151 sps->no,
152 NULL,
153 &emsg);
154 if (NULL == sps->peer)
155 {
156 LOG (GNUNET_ERROR_TYPE_ERROR,
157 "Testing library failed to create unique configuration based on `%s': `%s' with key number %u\n",
158 sps->cfgname,
159 emsg,
160 sps->no);
161 GNUNET_free (emsg);
162 GNUNET_TESTING_interpreter_fail (is);
163 return;
164 }
165
166 if (GNUNET_OK != GNUNET_TESTING_peer_start (sps->peer))
167 {
168 LOG (GNUNET_ERROR_TYPE_ERROR,
169 "Testing library failed to create unique configuration based on `%s'\n",
170 sps->cfgname);
171 GNUNET_free (emsg);
172 GNUNET_TESTING_interpreter_fail (is);
173 return;
174 }
175
176 memset (&dummy,
177 '\0',
178 sizeof(dummy));
179
180 GNUNET_TESTING_peer_get_identity (sps->peer,
181 &sps->id);
182
183 if (0 == memcmp (&dummy,
184 &sps->id,
185 sizeof(struct GNUNET_PeerIdentity)))
186 {
187 LOG (GNUNET_ERROR_TYPE_ERROR,
188 "Testing library failed to obtain peer identity for peer %u\n",
189 sps->no);
190 GNUNET_free (emsg);
191 GNUNET_TESTING_interpreter_fail (is);
192 return;
193 }
194 LOG (GNUNET_ERROR_TYPE_DEBUG,
195 "Peer %u configured with identity `%s'\n",
196 sps->no,
197 GNUNET_i2s_full (&sps->id));
198
199 GNUNET_free (home);
200 GNUNET_free (transport_unix_path);
201 GNUNET_free (tcp_communicator_unix_path);
202 GNUNET_free (udp_communicator_unix_path);
203 GNUNET_free (bindto);
204 GNUNET_free (bindto_udp);
205}
206
207
208/**
209 * The cleanup function of this cmd frees resources the cmd allocated.
210 *
211 */
212static void
213start_peer_cleanup (void *cls)
214{
215 struct GNUNET_TESTING_StartPeerState *sps = cls;
216
217 //TODO Investigate why this caused problems during shutdown.
218 /*if (NULL != sps->cfg)
219 {
220 GNUNET_CONFIGURATION_destroy (sps->cfg);
221 sps->cfg = NULL;
222 }*/
223 GNUNET_free (sps->cfgname);
224 GNUNET_free (sps->node_ip);
225 GNUNET_free (sps->system_label);
226 GNUNET_free (sps->hello);
227 GNUNET_free (sps->connected_peers_map);
228 GNUNET_free (sps);
229}
230
231
232/**
233 * This function prepares an array with traits.
234 *
235 */
236static int
237start_peer_traits (void *cls,
238 const void **ret,
239 const char *trait,
240 unsigned int index)
241{
242 struct GNUNET_TESTING_StartPeerState *sps = cls;
243 struct GNUNET_TRANSPORT_ApplicationHandle *ah = sps->ah;
244 struct GNUNET_PeerIdentity *id = &sps->id;
245 struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map =
246 sps->connected_peers_map;
247 char *hello = sps->hello;
248 size_t hello_size = sps->hello_size;
249
250
251 struct GNUNET_TESTING_Trait traits[] = {
252 GNUNET_TESTING_make_trait_application_handle ((const void *) ah),
253 GNUNET_TESTING_make_trait_peer_id ((const void *) id),
254 GNUNET_TESTING_make_trait_connected_peers_map ((const
255 void *)
256 connected_peers_map),
257 GNUNET_TESTING_make_trait_hello ((const void *) hello),
258 GNUNET_TESTING_make_trait_hello_size ((const void *) hello_size),
259 GNUNET_TESTING_make_trait_state ((const void *) sps),
260 GNUNET_TESTING_make_trait_broadcast ((const void *) &sps->broadcast),
261 GNUNET_TESTING_trait_end ()
262 };
263
264 return GNUNET_TESTING_get_trait (traits,
265 ret,
266 trait,
267 index);
268}
269
270
271struct GNUNET_TESTING_Command
272GNUNET_TESTING_cmd_start_peer (const char *label,
273 const char *system_label,
274 uint32_t no,
275 const char *node_ip,
276 const char *cfgname,
277 unsigned int broadcast)
278{
279 struct GNUNET_TESTING_StartPeerState *sps;
280 struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map =
281 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
282 unsigned int i;
283
284 sps = GNUNET_new (struct GNUNET_TESTING_StartPeerState);
285 sps->no = no;
286 sps->system_label = GNUNET_strdup (system_label);
287 sps->connected_peers_map = connected_peers_map;
288 sps->cfgname = GNUNET_strdup (cfgname);
289 sps->node_ip = GNUNET_strdup (node_ip);
290 sps->broadcast = broadcast;
291
292 return GNUNET_TESTING_command_new (sps,
293 label,
294 &start_peer_run,
295 &start_peer_cleanup,
296 &start_peer_traits,
297 NULL);
298}
diff --git a/src/lib/testing/testing_api_cmd_stop_peer.c b/src/lib/testing/testing_api_cmd_stop_peer.c
deleted file mode 100644
index 2cbf978c6..000000000
--- a/src/lib/testing/testing_api_cmd_stop_peer.c
+++ /dev/null
@@ -1,130 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing_api_cmd_stop_peer.c
23 * @brief cmd to stop a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_netjail_lib.h"
30
31/**
32 * Generic logging shortcut
33 */
34#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
35
36
37/**
38 * Struct to hold information for callbacks.
39 *
40 */
41struct StopPeerState
42{
43 // Label of the cmd to start the peer.
44 const char *start_label;
45};
46
47
48/**
49 * The run method of this cmd will stop all services of a peer which were used to test the transport service.
50 *
51 */
52static void
53stop_peer_run (void *cls,
54 struct GNUNET_TESTING_Interpreter *is)
55{
56 struct StopPeerState *stop_ps = cls;
57 const struct GNUNET_TESTING_StartPeerState *sps;
58 const struct GNUNET_TESTING_Command *start_cmd;
59
60 start_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
61 stop_ps->start_label);
62 GNUNET_TESTING_get_trait_state (start_cmd,
63 &sps);
64
65 if (NULL != sps->peer)
66 {
67 if (GNUNET_OK !=
68 GNUNET_TESTING_peer_stop (sps->peer))
69 {
70 LOG (GNUNET_ERROR_TYPE_ERROR,
71 "Testing lib failed to stop peer %u (`%s')\n",
72 sps->no,
73 GNUNET_i2s (&sps->id));
74 }
75 GNUNET_TESTING_peer_destroy (sps->peer);
76 }
77 if (NULL != sps->rh_task)
78 GNUNET_SCHEDULER_cancel (sps->rh_task);
79}
80
81
82/**
83 * The cleanup function of this cmd frees resources the cmd allocated.
84 *
85 */
86static void
87stop_peer_cleanup (void *cls)
88{
89 struct StopPeerState *sps = cls;
90
91 GNUNET_free (sps);
92}
93
94
95/**
96 * Trait function of this cmd does nothing.
97 *
98 */
99static int
100stop_peer_traits (void *cls,
101 const void **ret,
102 const char *trait,
103 unsigned int index)
104{
105 return GNUNET_OK;
106}
107
108
109/**
110 * Create command.
111 *
112 * @param label name for command.
113 * @param start_label Label of the cmd to start the peer.
114 * @return command.
115 */
116struct GNUNET_TESTING_Command
117GNUNET_TESTING_cmd_stop_peer (const char *label,
118 const char *start_label)
119{
120 struct StopPeerState *sps;
121
122 sps = GNUNET_new (struct StopPeerState);
123 sps->start_label = start_label;
124 return GNUNET_TESTING_command_new (sps,
125 label,
126 &stop_peer_run,
127 &stop_peer_cleanup,
128 &stop_peer_traits,
129 NULL);
130}
diff --git a/src/lib/testing/testing_api_cmd_system_create.c b/src/lib/testing/testing_api_cmd_system_create.c
deleted file mode 100644
index 46fbd706e..000000000
--- a/src/lib/testing/testing_api_cmd_system_create.c
+++ /dev/null
@@ -1,124 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing_api_cmd_system_create.c
23 * @brief cmd to create a testing system handle.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_netjail_lib.h"
31#include "gnunet_testing_lib.h"
32
33/**
34 * Struct to hold information for callbacks.
35 *
36 */
37struct TestSystemState
38{
39 struct GNUNET_TESTING_System *test_system;
40
41 const char *testdir;
42};
43
44
45/**
46 * The run method of this cmd will setup a test environment for a node.
47 *
48 */
49static void
50system_create_run (void *cls,
51 struct GNUNET_TESTING_Interpreter *is)
52{
53 struct TestSystemState *tss = cls;
54
55 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
56 "system create\n");
57
58 tss->test_system = GNUNET_TESTING_system_create (tss->testdir,
59 NULL,
60 NULL,
61 NULL);
62 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
63 "system created\n");
64}
65
66
67/**
68 * This function prepares an array with traits.
69 *
70 */
71static int
72system_create_traits (void *cls,
73 const void **ret,
74 const char *trait,
75 unsigned int index)
76{
77 struct TestSystemState *tss = cls;
78 struct GNUNET_TESTING_System *test_system = tss->test_system;
79
80 struct GNUNET_TESTING_Trait traits[] = {
81 GNUNET_TESTING_make_trait_test_system ((const void *) test_system),
82 GNUNET_TESTING_trait_end ()
83 };
84
85 return GNUNET_TESTING_get_trait (traits,
86 ret,
87 trait,
88 index);
89}
90
91
92/**
93 * The cleanup function of this cmd frees resources the cmd allocated.
94 *
95 */
96static void
97system_create_cleanup (void *cls)
98{
99 struct TestSystemState *tss = cls;
100
101 GNUNET_free (tss);
102}
103
104
105/**
106 * Create command.
107 *
108 * @param label name for command.
109 * @param label name for the test environment directory.
110 * @return command.
111 */
112struct GNUNET_TESTING_Command
113GNUNET_TESTING_cmd_system_create (const char *label,
114 const char *testdir)
115{
116 struct TestSystemState *tss;
117
118 tss = GNUNET_new (struct TestSystemState);
119 tss->testdir = testdir;
120
121 return GNUNET_TESTING_command_new (tss, label, &system_create_run,
122 &system_create_cleanup,
123 &system_create_traits, NULL);
124}
diff --git a/src/lib/testing/testing_api_cmd_system_destroy.c b/src/lib/testing/testing_api_cmd_system_destroy.c
deleted file mode 100644
index 45adfd0da..000000000
--- a/src/lib/testing/testing_api_cmd_system_destroy.c
+++ /dev/null
@@ -1,111 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing_api_cmd_system_destroy.c
23 * @brief cmd to destroy a testing system handle.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_netjail_lib.h"
31#include "gnunet_testing_lib.h"
32
33
34/**
35 * Struct to hold information for callbacks.
36 *
37 */
38struct TestSystemState
39{
40 // Label of the cmd which started the test system.
41 const char *create_label;
42};
43
44
45/**
46 * The run method of this cmd will remove the test environment for a node.
47 *
48 */
49static void
50system_destroy_run (void *cls,
51 struct GNUNET_TESTING_Interpreter *is)
52{
53 struct TestSystemState *tss = cls;
54 const struct GNUNET_TESTING_Command *system_cmd;
55 const struct GNUNET_TESTING_System *tl_system;
56
57 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
58 tss->create_label);
59 GNUNET_TESTING_get_trait_test_system (system_cmd,
60 &tl_system);
61 GNUNET_TESTING_system_destroy ((struct GNUNET_TESTING_System *) tl_system,
62 GNUNET_YES);
63}
64
65
66/**
67 * The cleanup function of this cmd frees resources the cmd allocated.
68 *
69 */
70static void
71system_destroy_cleanup (void *cls)
72{
73 struct TestSystemState *tss = cls;
74
75 GNUNET_free (tss);
76}
77
78
79/**
80 * Trait function of this cmd does nothing.
81 *
82 */
83static enum GNUNET_GenericReturnValue
84system_destroy_traits (void *cls,
85 const void **ret,
86 const char *trait,
87 unsigned int index)
88{
89 return GNUNET_OK;
90}
91
92
93/**
94 * Create command.
95 *
96 * @param label name for command.
97 * @param create_label Label of the cmd which started the test system.
98 * @return command.
99 */
100struct GNUNET_TESTING_Command
101GNUNET_TESTING_cmd_system_destroy (const char *label,
102 const char *create_label)
103{
104 struct TestSystemState *tss;
105
106 tss = GNUNET_new (struct TestSystemState);
107 tss->create_label = create_label;
108 return GNUNET_TESTING_command_new (tss, label, &system_destroy_run,
109 &system_destroy_cleanup,
110 &system_destroy_traits, NULL);
111}
diff --git a/src/lib/testing/testing_api_loop.c b/src/lib/testing/testing_api_loop.c
deleted file mode 100644
index db0a00c22..000000000
--- a/src/lib/testing/testing_api_loop.c
+++ /dev/null
@@ -1,937 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_loop.c
23 * @brief main interpreter loop for testcases
24 * @author Christian Grothoff (GNU Taler testing)
25 * @author Marcello Stanisci (GNU Taler testing)
26 * @author t3sserakt
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testing_ng_lib.h"
31#include "gnunet_testing_plugin.h"
32#include "gnunet_testing_barrier.h"
33#include "gnunet_testing_netjail_lib.h"
34#include "testing.h"
35
36/**
37 * Global state of the interpreter, used by a command
38 * to access information about other commands.
39 */
40struct GNUNET_TESTING_Interpreter
41{
42 /**
43 * Array with handles of helper processes for communication with netjails.
44 */
45 const struct GNUNET_HELPER_Handle **helper;
46
47 /**
48 * Size of the array helper.
49 *
50 */
51 unsigned int n_helper;
52
53 /**
54 * Function to call with the test result.
55 */
56 GNUNET_TESTING_ResultCallback rc;
57
58 /**
59 * Closure for @e rc.
60 */
61 void *rc_cls;
62
63 /**
64 * Commands the interpreter will run.
65 */
66 struct GNUNET_TESTING_Command *commands;
67
68 /**
69 * Map with barriers for this loop.
70 */
71 struct GNUNET_CONTAINER_MultiShortmap *barriers;
72
73 /**
74 * Number of GNUNET_TESTING_Command in commands.
75 */
76 unsigned int cmds_n;
77
78 /**
79 * Interpreter task (if one is scheduled).
80 */
81 struct GNUNET_SCHEDULER_Task *task;
82
83 /**
84 * Final task that returns the result.
85 */
86 struct GNUNET_SCHEDULER_Task *final_task;
87
88 /**
89 * Task run on timeout.
90 */
91 struct GNUNET_SCHEDULER_Task *timeout_task;
92
93 /**
94 * Instruction pointer. Tells #interpreter_run() which instruction to run
95 * next. Need (signed) int because it gets -1 when rewinding the
96 * interpreter to the first CMD.
97 */
98 int ip;
99
100 /**
101 * Result of the testcases, #GNUNET_OK on success
102 */
103 enum GNUNET_GenericReturnValue result;
104
105 /**
106 * Is the interpreter finishing?
107 */
108 unsigned int finishing;
109
110};
111
112struct FreeBarrierNodeCbCls
113{
114 /**
115 * The interpreter.
116 */
117 struct GNUNET_TESTING_Interpreter *is;
118
119 /**
120 * The barrier from which the nodes are freed..
121 */
122 struct GNUNET_TESTING_Barrier *barrier;
123};
124
125
126static const struct GNUNET_TESTING_Command *
127get_command (struct GNUNET_TESTING_Interpreter *is,
128 const char *label,
129 unsigned int future)
130{
131 int start_i = GNUNET_NO == future ? is->ip : is->cmds_n - 1;
132 int end_i = GNUNET_NO == future ? 0 : is->ip + 1;
133
134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
135 "start_i: %u end_i: %u\n",
136 start_i,
137 end_i);
138 if (NULL == label)
139 {
140 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
141 "Attempt to lookup command for empty label\n");
142 return NULL;
143 }
144
145 for (int i = start_i; i >= end_i; i--)
146 {
147 const struct GNUNET_TESTING_Command *cmd = &is->commands[i];
148
149 if (NULL != cmd->run)
150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
151 "label to compare %s\n",
152 cmd->label);
153 /* Give precedence to top-level commands. */
154 if ( (NULL != cmd->run) &&
155 (0 == strcmp (cmd->label,
156 label)) )
157 return cmd;
158
159 if (GNUNET_TESTING_cmd_is_batch_ (cmd))
160 {
161 struct GNUNET_TESTING_Command **batch;
162 struct GNUNET_TESTING_Command *current;
163 const struct GNUNET_TESTING_Command *icmd;
164 const struct GNUNET_TESTING_Command *match;
165
166 current = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
167 GNUNET_assert (GNUNET_OK ==
168 GNUNET_TESTING_get_trait_batch_cmds (cmd,
169 &batch));
170 /* We must do the loop forward, but we can find the last match */
171 match = NULL;
172 for (unsigned int j = 0;
173 NULL != (icmd = &(*batch)[j])->run;
174 j++)
175 {
176 if (current == icmd)
177 break; /* do not go past current command */
178 if ( (NULL != icmd->run) &&
179 (0 == strcmp (icmd->label,
180 label)) )
181 match = icmd;
182 }
183 if (NULL != match)
184 return match;
185 }
186 }
187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
188 "Command `%s' not found\n",
189 label);
190 return NULL;
191}
192
193
194/**
195 * Lookup command by label.
196 * Only future commands are looked up.
197 *
198 * @param is interpreter to lookup command in
199 * @param label label of the command to lookup.
200 * @return the command, if it is found, or NULL.
201 */
202const struct GNUNET_TESTING_Command *
203GNUNET_TESTING_interpreter_lookup_future_command (
204 struct GNUNET_TESTING_Interpreter *is,
205 const char *label)
206{
207 return get_command (is, label, GNUNET_YES);
208}
209
210
211/**
212 * Lookup command by label.
213 * Only commands from current command to commands in the past are looked up.
214 *
215 * @param is interpreter to lookup command in
216 * @param label label of the command to lookup.
217 * @return the command, if it is found, or NULL.
218 */
219const struct GNUNET_TESTING_Command *
220GNUNET_TESTING_interpreter_lookup_command (
221 struct GNUNET_TESTING_Interpreter *is,
222 const char *label)
223{
224 return get_command (is, label, GNUNET_NO);
225}
226
227
228const struct GNUNET_TESTING_Command *
229GNUNET_TESTING_interpreter_lookup_command_all (
230 struct GNUNET_TESTING_Interpreter *is,
231 const char *label)
232{
233 const struct GNUNET_TESTING_Command *cmd;
234
235 cmd = get_command (is, label, GNUNET_NO);
236 if (NULL == cmd)
237 cmd = get_command (is, label, GNUNET_YES);
238 return cmd;
239}
240
241
242int
243free_barrier_node_cb (void *cls,
244 const struct GNUNET_ShortHashCode *key,
245 void *value)
246{
247 struct FreeBarrierNodeCbCls *free_barrier_node_cb_cls = cls;
248 struct GNUNET_TESTING_NetjailNode *node = value;
249 struct GNUNET_TESTING_Barrier *barrier = free_barrier_node_cb_cls->barrier;
250 struct GNUNET_TESTING_Interpreter *is = free_barrier_node_cb_cls->is;
251
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "free_barrier_node_cb\n");
254 if (GNUNET_NO == is->finishing)
255 {
256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
257 "TST_interpreter_send_barrier_crossable\n");
258 TST_interpreter_send_barrier_crossable (is,
259 barrier->name,
260 node->node_number);
261 }
262 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (
263 barrier->nodes, key, node));
264 return GNUNET_YES;
265}
266
267
268static int
269free_barriers_cb (void *cls,
270 const struct GNUNET_ShortHashCode *key,
271 void *value)
272{
273 struct GNUNET_TESTING_Interpreter *is = cls;
274 struct GNUNET_TESTING_Barrier *barrier = value;
275 struct CommandListEntry *pos;
276 struct FreeBarrierNodeCbCls *free_barrier_node_cb_cls;
277
278 if (NULL != barrier->nodes)
279 {
280 free_barrier_node_cb_cls = GNUNET_new (struct FreeBarrierNodeCbCls);
281 free_barrier_node_cb_cls->barrier = barrier;
282 free_barrier_node_cb_cls->is = is;
283 GNUNET_CONTAINER_multishortmap_iterate (barrier->nodes,
284 free_barrier_node_cb,
285 free_barrier_node_cb_cls);
286 GNUNET_CONTAINER_multishortmap_destroy (barrier->nodes);
287 barrier->nodes = NULL;
288 }
289
290 while (NULL != (pos = barrier->cmds_head))
291 {
292 GNUNET_CONTAINER_DLL_remove (barrier->cmds_head,
293 barrier->cmds_tail,
294 pos);
295 GNUNET_free (pos);
296 }
297 GNUNET_free (barrier);
298 return GNUNET_YES;
299}
300
301
302/**
303 * Deleting all barriers create in the context of this interpreter.
304 *
305 * @param is The interpreter.
306 */
307static void
308interpreter_delete_barriers (struct GNUNET_TESTING_Interpreter *is)
309{
310 GNUNET_CONTAINER_multishortmap_iterate (is->barriers,
311 free_barriers_cb,
312 is);
313 GNUNET_CONTAINER_multishortmap_destroy (is->barriers);
314}
315
316
317/**
318 * Finish the test run, return the final result.
319 *
320 * @param cls the `struct GNUNET_TESTING_Interpreter`
321 */
322static void
323finish_test (void *cls)
324{
325 struct GNUNET_TESTING_Interpreter *is = cls;
326 struct GNUNET_TESTING_Command *cmd;
327 const char *label;
328
329 is->finishing = GNUNET_YES;
330 is->final_task = NULL;
331 label = is->commands[is->ip].label;
332 if (NULL == is->commands[is->ip].run)
333 label = "END";
334 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
335 "Interpreter finishes at `%s' with status %d\n",
336 label,
337 is->result);
338 for (unsigned int j = 0;
339 NULL != (cmd = &is->commands[j])->run;
340 j++)
341 {
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 "Cleaning up cmd %s\n",
344 cmd->label);
345 cmd->cleanup (cmd->cls);
346 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
347 "Cleaned up cmd %s\n",
348 cmd->label);
349 }
350 if (NULL != is->task)
351 {
352 GNUNET_SCHEDULER_cancel (is->task);
353 is->task = NULL;
354 }
355 if (NULL != is->timeout_task)
356 {
357 GNUNET_SCHEDULER_cancel (is->timeout_task);
358 is->timeout_task = NULL;
359 }
360 GNUNET_free (is->commands);
361 is->rc (is->rc_cls,
362 is->result);
363 interpreter_delete_barriers (is);
364 GNUNET_free (is->helper);
365 GNUNET_free (is);
366}
367
368
369/**
370 * Run the main interpreter loop that performs exchange operations.
371 *
372 * @param cls contains the `struct InterpreterState`
373 */
374static void
375interpreter_run (void *cls);
376
377
378/**
379 * Current command is done, run the next one.
380 */
381static void
382interpreter_next (void *cls)
383{
384 struct GNUNET_TESTING_Interpreter *is = cls;
385 static unsigned long long ipc;
386 static struct GNUNET_TIME_Absolute last_report;
387 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
388
389 if (GNUNET_SYSERR == is->result)
390 return; /* ignore, we already failed! */
391 cmd->finish_time = GNUNET_TIME_absolute_get ();
392 if ( (! GNUNET_TESTING_cmd_is_batch_ (cmd)) ||
393 (! GNUNET_TESTING_cmd_batch_next_ (cmd->cls)) )
394 is->ip++;
395 if (0 == (ipc % 1000))
396 {
397 if (0 != ipc)
398 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
399 "Interpreter executed 1000 instructions in %s\n",
400 GNUNET_STRINGS_relative_time_to_string (
401 GNUNET_TIME_absolute_get_duration (last_report),
402 GNUNET_YES));
403 last_report = GNUNET_TIME_absolute_get ();
404 }
405 ipc++;
406 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
407 is);
408}
409
410
411void
412GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is)
413{
414 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
415
416 if (GNUNET_SYSERR == is->result)
417 {
418 GNUNET_break (0);
419 return; /* ignore, we already failed! */
420 }
421 if (NULL != cmd)
422 {
423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
424 "Failed at command `%s'\n",
425 cmd->label);
426 while (GNUNET_TESTING_cmd_is_batch_ (cmd))
427 {
428 cmd = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
429 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
430 "Failed in batch at command `%s'\n",
431 cmd->label);
432 }
433 }
434 else
435 {
436 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
437 "Failed with CMD being NULL!\n");
438 }
439 is->result = GNUNET_SYSERR;
440 GNUNET_assert (NULL == is->final_task);
441 is->final_task = GNUNET_SCHEDULER_add_now (&finish_test,
442 is);
443}
444
445
446/**
447 * Returns the actual running command.
448 *
449 * @param is Global state of the interpreter, used by a command
450 * to access information about other commands.
451 * @return The actual running command.
452 */
453struct GNUNET_TESTING_Command *
454GNUNET_TESTING_interpreter_get_current_command (
455 struct GNUNET_TESTING_Interpreter *is)
456{
457 return &is->commands[is->ip];
458}
459
460
461const char *
462GNUNET_TESTING_interpreter_get_current_label (
463 struct GNUNET_TESTING_Interpreter *is)
464{
465 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
466
467 return cmd->label;
468}
469
470
471/**
472 * Run the main interpreter loop.
473 *
474 * @param cls contains the `struct GNUNET_TESTING_Interpreter`
475 */
476static void
477interpreter_run (void *cls)
478{
479 struct GNUNET_TESTING_Interpreter *is = cls;
480 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
481
482 is->task = NULL;
483 if (NULL == cmd->run)
484 {
485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
486 "Running command END\n");
487 is->result = GNUNET_OK;
488 finish_test (is);
489 return;
490 }
491 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
492 "Running command `%s'\n",
493 cmd->label);
494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
495 "start time of %p expected 0 is `%" PRIu64 "'\n",
496 cmd,
497 cmd->start_time.abs_value_us);
498 cmd->start_time
499 = cmd->last_req_time
500 = GNUNET_TIME_absolute_get ();
501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
502 "start time of %p expected something is `%" PRIu64 "'\n",
503 cmd,
504 cmd->start_time.abs_value_us);
505 cmd->num_tries = 1;
506 if (NULL != cmd->ac)
507 {
508 cmd->ac->is = is;
509 cmd->ac->cont = &interpreter_next;
510 cmd->ac->cont_cls = is;
511 cmd->ac->finished = GNUNET_NO;
512 }
513 cmd->run (cmd->cls,
514 is);
515 if (NULL == cmd->ac)
516 {
517 interpreter_next (is);
518 }
519 else if ( (cmd->asynchronous_finish) &&
520 (NULL != cmd->ac->cont) )
521 {
522 cmd->ac->cont = NULL;
523 interpreter_next (is);
524 }
525}
526
527
528/**
529 * Function run when the test terminates (good or bad) with timeout.
530 *
531 * @param cls the interpreter state
532 */
533static void
534do_timeout (void *cls)
535{
536 struct GNUNET_TESTING_Interpreter *is = cls;
537
538 is->timeout_task = NULL;
539 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
540 "Terminating test due to global timeout\n");
541 is->result = GNUNET_SYSERR;
542 finish_test (is);
543}
544
545
546enum GNUNET_GenericReturnValue
547GNUNET_TESTING_running (const struct GNUNET_TESTING_Command *command)
548{
549 return 0 != command->start_time.abs_value_us && 0 ==
550 command->finish_time.abs_value_us;
551}
552
553
554enum GNUNET_GenericReturnValue
555GNUNET_TESTING_finished (const struct GNUNET_TESTING_Command *command)
556{
557 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
558 struct GNUNET_TIME_Relative diff = GNUNET_TIME_absolute_get_difference (
559 command->finish_time,
560 now);
561 return 0 < diff.rel_value_us;
562}
563
564
565struct GNUNET_TESTING_Interpreter *
566GNUNET_TESTING_run (const struct GNUNET_TESTING_Command *commands,
567 struct GNUNET_TIME_Relative timeout,
568 GNUNET_TESTING_ResultCallback rc,
569 void *rc_cls)
570{
571 struct GNUNET_TESTING_Interpreter *is;
572 unsigned int i;
573
574 is = GNUNET_new (struct GNUNET_TESTING_Interpreter);
575 is->rc = rc;
576 is->rc_cls = rc_cls;
577 is->barriers = GNUNET_CONTAINER_multishortmap_create (1,
578 false);
579 /* get the number of commands */
580 for (i = 0; NULL != commands[i].run; i++)
581 ;
582 is->cmds_n = i + 1;
583 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
584 "Got %u commands\n",
585 i);
586 is->commands = GNUNET_malloc_large ( (i + 1)
587 * sizeof (struct
588 GNUNET_TESTING_Command));
589 GNUNET_assert (NULL != is->commands);
590 memcpy (is->commands,
591 commands,
592 sizeof (struct GNUNET_TESTING_Command) * i);
593 is->timeout_task
594 = GNUNET_SCHEDULER_add_delayed (timeout,
595 &do_timeout,
596 is);
597 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
598 is);
599
600 return is;
601}
602
603
604struct GNUNET_TESTING_Command
605GNUNET_TESTING_command_new (void *cls,
606 const char *label,
607 GNUNET_TESTING_CommandRunRoutine run,
608 GNUNET_TESTING_CommandCleanupRoutine cleanup,
609 GNUNET_TESTING_CommandGetTraits traits,
610 struct GNUNET_TESTING_AsyncContext *ac)
611{
612 struct GNUNET_TESTING_Command cmd = {
613 .cls = cls,
614 .run = run,
615 .ac = ac,
616 .cleanup = cleanup,
617 .traits = traits
618 };
619
620 GNUNET_assert (NULL != run);
621 if (NULL != label)
622 {
623 GNUNET_assert (strlen (label) <=
624 GNUNET_TESTING_CMD_MAX_LABEL_LENGTH);
625 strncpy (cmd.label,
626 label,
627 GNUNET_TESTING_CMD_MAX_LABEL_LENGTH);
628 }
629 return cmd;
630}
631
632
633struct GNUNET_TESTING_Command
634GNUNET_TESTING_cmd_end (void)
635{
636 struct GNUNET_TESTING_Command cmd = {
637 .run = NULL
638 };
639
640 return cmd;
641}
642
643
644/**
645 * Closure for #loop_run().
646 */
647struct MainParams
648{
649
650 /**
651 * NULL-label terminated array of commands.
652 */
653 struct GNUNET_TESTING_Command *commands;
654
655 /**
656 * Global timeout for the test.
657 */
658 struct GNUNET_TIME_Relative timeout;
659
660 /**
661 * Set to #EXIT_FAILURE on error.
662 */
663 int rv;
664};
665
666
667/**
668 * Function called with the final result of the test.
669 *
670 * @param cls the `struct MainParams`
671 * @param rv #GNUNET_OK if the test passed
672 */
673static void
674handle_result (void *cls,
675 enum GNUNET_GenericReturnValue rv)
676{
677 struct MainParams *mp = cls;
678
679 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
680 "Test exits with status %d\n",
681 rv);
682 if (GNUNET_OK != rv)
683 mp->rv = EXIT_FAILURE;
684 GNUNET_SCHEDULER_shutdown ();
685}
686
687
688/**
689 * Main function to run the test cases.
690 *
691 * @param cls a `struct MainParams *`
692 */
693static void
694loop_run (void *cls)
695{
696 struct MainParams *mp = cls;
697
698 GNUNET_TESTING_run (mp->commands,
699 mp->timeout,
700 &handle_result,
701 mp);
702}
703
704
705/**
706 * Continuation function from GNUNET_HELPER_send()
707 *
708 * @param cls closure
709 * @param result #GNUNET_OK on success,
710 * #GNUNET_NO if helper process died
711 * #GNUNET_SYSERR during GNUNET_HELPER_stop()
712 */
713static void
714clear_msg (void *cls, int result)
715{
716 GNUNET_assert (GNUNET_YES == result);
717}
718
719
720/**
721 * Adding a helper handle to the interpreter.
722 *
723 * @param is The interpreter.
724 * @param helper The helper handle.
725 */
726void
727GNUNET_TESTING_add_netjail_helper (struct GNUNET_TESTING_Interpreter *is,
728 const struct GNUNET_HELPER_Handle *helper)
729{
730 GNUNET_array_append (is->helper, is->n_helper, helper);
731}
732
733
734/**
735 * Send Message to netjail nodes.
736 *
737 * @param is The interpreter.
738 * @param global_node_number The netjail node to inform.
739 * @param header The message to send.
740 */
741void
742send_message_to_netjail (struct GNUNET_TESTING_Interpreter *is,
743 unsigned int global_node_number,
744 struct GNUNET_MessageHeader *header)
745{
746 const struct GNUNET_HELPER_Handle *helper;
747
748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
749 "send message of type %u to locals\n",
750 ntohs (header->type));
751 helper = is->helper[global_node_number - 1];
752 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
753 (struct GNUNET_HELPER_Handle *) helper,
754 header,
755 GNUNET_NO,
756 &clear_msg,
757 NULL);
758}
759
760
761void
762TST_interpreter_send_barrier_crossable (struct GNUNET_TESTING_Interpreter *is,
763 const char *barrier_name,
764 unsigned int global_node_number)
765{
766 struct CommandBarrierCrossable *adm;
767 size_t msg_length;
768 size_t name_len;
769
770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
771 "send barrier name %s barrier_name\n",
772 barrier_name);
773 name_len = strlen (barrier_name);
774 msg_length = sizeof(struct CommandBarrierCrossable) + name_len + 1;
775 adm = GNUNET_malloc (msg_length);
776 adm->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_CROSSABLE);
777 adm->header.size = htons ((uint16_t) msg_length);
778 memcpy (&adm[1], barrier_name, name_len);
779 send_message_to_netjail (is,
780 global_node_number,
781 &adm->header);
782 GNUNET_free (adm);
783}
784
785
786/**
787 * Getting a barrier from the interpreter.
788 *
789 * @param is The interpreter.
790 * @param barrier_name The name of the barrier.
791 * @return The barrier.
792 */
793struct GNUNET_TESTING_Barrier *
794TST_interpreter_get_barrier (struct GNUNET_TESTING_Interpreter *is,
795 const char *barrier_name)
796{
797 struct GNUNET_HashCode hc;
798 struct GNUNET_ShortHashCode create_key;
799 struct GNUNET_TESTING_Barrier *barrier;
800
801 GNUNET_CRYPTO_hash (barrier_name, strlen (barrier_name), &hc);
802 memcpy (&create_key,
803 &hc,
804 sizeof (create_key));
805 barrier = GNUNET_CONTAINER_multishortmap_get (is->barriers, &create_key);
806 return barrier;
807}
808
809
810/**
811 * Finish all "barrier reached" comands attached to this barrier.
812 *
813 * @param barrier The barrier in question.
814 */
815void
816TST_interpreter_finish_attached_cmds (struct GNUNET_TESTING_Interpreter *is,
817 const char *barrier_name)
818{
819 struct CommandListEntry *pos;
820 struct GNUNET_TESTING_Barrier *barrier = TST_interpreter_get_barrier (is,
821 barrier_name);
822
823 while (NULL != barrier && NULL != (pos = barrier->cmds_head))
824 {
825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
826 "command label %s\n",
827 pos->command->label);
828 if (GNUNET_NO == pos->command->ac->finished &&
829 GNUNET_NO == pos->command->asynchronous_finish)
830 {
831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
832 "command label %s finish\n",
833 pos->command->label);
834 GNUNET_TESTING_async_finish (pos->command->ac);
835 }
836 else if (GNUNET_NO == pos->command->ac->finished)
837 {
838 pos->command->asynchronous_finish = GNUNET_YES;
839 }
840 GNUNET_CONTAINER_DLL_remove (barrier->cmds_head,
841 barrier->cmds_tail,
842 pos);
843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
844 "command entry label %s removed\n",
845 pos->command->label);
846 GNUNET_free (pos);
847 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
848 "command entry freed\n");
849 }
850 if (NULL != barrier->nodes)
851 {
852 struct FreeBarrierNodeCbCls free_barrier_node_cb_cls = {
853 .barrier = barrier,
854 .is = is
855 };
856
857 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
858 "freeing nodes\n");
859 GNUNET_CONTAINER_multishortmap_iterate (barrier->nodes,
860 &free_barrier_node_cb,
861 &free_barrier_node_cb_cls);
862 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
863 "nodes freed\n");
864 GNUNET_CONTAINER_multishortmap_destroy (barrier->nodes);
865 barrier->nodes = NULL;
866 }
867}
868
869
870/**
871 * Add a barrier to the loop.
872 *
873 * @param is The interpreter.
874 * @param barrier The barrier to add.
875 */
876void
877TST_interpreter_add_barrier (struct GNUNET_TESTING_Interpreter *is,
878 struct GNUNET_TESTING_Barrier *barrier)
879{
880 struct GNUNET_HashCode hc;
881 struct GNUNET_ShortHashCode create_key;
882
883 GNUNET_CRYPTO_hash (barrier->name, strlen (barrier->name), &hc);
884 memcpy (&create_key,
885 &hc,
886 sizeof (create_key));
887 GNUNET_CONTAINER_multishortmap_put (is->barriers,
888 &create_key,
889 barrier,
890 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
891}
892
893
894int
895GNUNET_TESTING_main (struct GNUNET_TESTING_Command *commands,
896 struct GNUNET_TIME_Relative timeout)
897{
898 struct MainParams mp = {
899 .commands = commands,
900 .timeout = timeout,
901 .rv = EXIT_SUCCESS
902 };
903
904 GNUNET_SCHEDULER_run (&loop_run,
905 &mp);
906 return mp.rv;
907}
908
909
910void
911GNUNET_TESTING_async_fail (struct GNUNET_TESTING_AsyncContext *ac)
912{
913 GNUNET_assert (GNUNET_NO == ac->finished);
914 ac->finished = GNUNET_SYSERR;
915 GNUNET_TESTING_interpreter_fail (ac->is);
916 if (NULL != ac->cont)
917 {
918 ac->cont (ac->cont_cls);
919 ac->cont = NULL;
920 }
921}
922
923
924void
925GNUNET_TESTING_async_finish (struct GNUNET_TESTING_AsyncContext *ac)
926{
927 GNUNET_assert (GNUNET_NO == ac->finished);
928 ac->finished = GNUNET_OK;
929 if (NULL != ac->cont)
930 {
931 ac->cont (ac->cont_cls);
932 ac->cont = NULL;
933 }
934}
935
936
937/* end of testing_api_loop.c */
diff --git a/src/lib/testing/testing_api_traits.c b/src/lib/testing/testing_api_traits.c
deleted file mode 100644
index ee3edbed0..000000000
--- a/src/lib/testing/testing_api_traits.c
+++ /dev/null
@@ -1,90 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_traits.c
23 * @brief loop for trait resolution
24 * @author Christian Grothoff (GNU Taler testing)
25 * @author Marcello Stanisci (GNU Taler testing)
26 * @author t3sserakt
27 */
28#include "platform.h"
29#include "gnunet_testing_ng_lib.h"
30#include "gnunet_testing_plugin.h"
31#include "gnunet_testing_barrier.h"
32#include "gnunet_testing_netjail_lib.h"
33
34
35GNUNET_TESTING_SIMPLE_TRAITS (GNUNET_TESTING_MAKE_IMPL_SIMPLE_TRAIT)
36
37GNUNET_TESTING_INDEXED_TRAITS (GNUNET_TESTING_MAKE_IMPL_INDEXED_TRAIT)
38
39GNUNET_TESTING_SIMPLE_NETJAIL_TRAITS (GNUNET_TESTING_MAKE_IMPL_SIMPLE_TRAIT)
40
41/**
42 * End a trait array. Usually, commands offer several traits,
43 * and put them in arrays.
44 */
45struct GNUNET_TESTING_Trait
46GNUNET_TESTING_trait_end ()
47{
48 struct GNUNET_TESTING_Trait end = {
49 .index = 0,
50 .trait_name = NULL,
51 .ptr = NULL
52 };
53
54 return end;
55}
56
57
58/**
59 * Pick the chosen trait from the traits array.
60 *
61 * @param traits the traits array.
62 * @param ret where to store the result.
63 * @param trait type of the trait to extract.
64 * @param index index number of the object to extract.
65 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
66 */
67enum GNUNET_GenericReturnValue
68GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits,
69 const void **ret,
70 const char *trait,
71 unsigned int index)
72{
73 for (unsigned int i = 0; NULL != traits[i].trait_name; i++)
74 {
75 if ( (0 == strcmp (trait, traits[i].trait_name)) &&
76 (index == traits[i].index) )
77 {
78 *ret = (void *) traits[i].ptr;
79 return GNUNET_OK;
80 }
81 }
82 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
83 "Trait %s/%u not found.\n",
84 trait, index);
85
86 return GNUNET_SYSERR;
87}
88
89
90/* end of testing_api_traits.c */
diff --git a/src/lib/testing/testing_cmds.h b/src/lib/testing/testing_cmds.h
deleted file mode 100644
index 9c261aab5..000000000
--- a/src/lib/testing/testing_cmds.h
+++ /dev/null
@@ -1,143 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_cmds.h
23 * @brief Message formats for communication between testing cmds helper and testcase plugins.
24 * @author t3sserakt
25 */
26
27#ifndef TESTING_CMDS_H
28#define TESTING_CMDS_H
29
30#define HELPER_CMDS_BINARY "gnunet-cmds-helper"
31#include "gnunet_common.h"
32
33GNUNET_NETWORK_STRUCT_BEGIN
34
35/**
36 * Initialization message for gnunet-cmds-testbed to start cmd binary.
37 */
38struct GNUNET_TESTING_CommandHelperInit
39{
40 /**
41 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT
42 */
43 struct GNUNET_MessageHeader header;
44
45 /**
46 *
47 */
48 uint16_t plugin_name_size GNUNET_PACKED;
49
50 /* Followed by plugin name of the plugin running the test case. This is not NULL
51 * terminated */
52};
53
54/**
55 * Reply message from cmds helper process
56 */
57struct GNUNET_TESTING_CommandHelperReply
58{
59 /**
60 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY
61 */
62 struct GNUNET_MessageHeader header;
63};
64
65struct GNUNET_TESTING_CommandPeerStarted
66{
67 /**
68 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED
69 */
70 struct GNUNET_MessageHeader header;
71};
72
73struct GNUNET_TESTING_CommandAllPeersStarted
74{
75 /**
76 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED
77 */
78 struct GNUNET_MessageHeader header;
79};
80
81struct GNUNET_TESTING_CommandLocalFinished
82{
83 /**
84 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED
85 */
86 struct GNUNET_MessageHeader header;
87
88 /**
89 * The exit status local test return with.
90 */
91 enum GNUNET_GenericReturnValue rv;
92};
93
94
95struct GNUNET_TESTING_CommandLocalTestPrepared
96{
97 /**
98 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED
99 */
100 struct GNUNET_MessageHeader header;
101};
102
103struct GNUNET_TESTING_CommandAllLocalTestsPrepared
104{
105 /**
106 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_LOCAL_TESTS_PREPARED
107 */
108 struct GNUNET_MessageHeader header;
109};
110
111GNUNET_NETWORK_STRUCT_END
112
113/**
114 * Global state of the interpreter, used by a command
115 * to access information about other commands.
116 */
117struct GNUNET_TESTING_Interpreter;
118
119
120/**
121 * Returns the actual running command.
122 *
123 * @param is Global state of the interpreter, used by a command
124 * to access information about other commands.
125 * @return The actual running command.
126 */
127struct GNUNET_TESTING_Command *
128GNUNET_TESTING_interpreter_get_current_command (
129 struct GNUNET_TESTING_Interpreter *is);
130
131
132/**
133 * Adding a helper handle to the interpreter.
134 *
135 * @param is The interpreter.
136 * @param helper The helper handle.
137 */
138void
139GNUNET_TESTING_add_netjail_helper (struct GNUNET_TESTING_Interpreter *is,
140 const struct GNUNET_HELPER_Handle *helper);
141
142#endif
143/* end of testing_cmds.h */
diff --git a/src/lib/testing/topo.sh b/src/lib/testing/topo.sh
deleted file mode 100755
index 0046622b6..000000000
--- a/src/lib/testing/topo.sh
+++ /dev/null
@@ -1,99 +0,0 @@
1#!/bin/bash
2
3declare -A K_PLUGIN
4declare -A R_TCP
5declare -A R_UDP
6declare -A P_PLUGIN
7
8extract_attributes()
9{
10 line_key=$1
11 line=$2
12
13 if [ "$line_key" = "P" ]
14 then
15 n=$(echo $line|cut -d \| -f 1|awk -F: '{print $2}')
16 echo $n
17 m=$(echo $line|cut -d \| -f 1|awk -F: '{print $3}')
18 echo $m
19 else
20 number=$(echo $line|cut -d \| -f 1| cut -c 2-|cut -d : -f 2 )
21 echo $number
22 fi
23
24 nf=$(echo $line|awk -F: '{print NF}')
25 for ((i=2;i<=$nf;i++))
26 do
27 entry=$(echo $line |awk -v i=$i -F\| '{print $i}')
28 key=$(echo $entry|cut -d { -f 2|cut -d } -f 1|cut -d : -f 1)
29 value=$(echo $entry|cut -d { -f 2|cut -d } -f 1|cut -d : -f 2)
30 if [ "$key" = "tcp_port" ]
31 then
32 echo tcp port: $value
33 R_TCP[$number]=$value
34 elif [ "$key" = "udp_port" ]
35 then
36 echo udp port: $value
37 R_UDP[$number]=$value
38 elif [ "$key" = "plugin" ]
39 then
40 echo plugin: $value
41 echo $line_key
42 if [ "$line_key" = "P" ]
43 then
44 P_PLUGIN[$n,$m]=$value
45 echo $n $m ${P_PLUGIN[$n,$m]}
46 elif [ "$line_key" = "K" ]
47 then
48 K_PLUGIN[$number]=$value
49 fi
50 fi
51 done
52}
53
54read_topology(){
55
56local filename=$1
57while read line; do
58# reading each line
59 echo $line
60 key=$(cut -c -1 <<< $line)
61 if [ "$key" = "M" ]
62 then
63 LOCAL_M=$(cut -d : -f 2 <<< $line)
64 echo $LOCAL_M
65 elif [ "$key" = "N" ]
66 then
67 GLOBAL_N=$(cut -d : -f 2 <<< $line)
68 echo $GLOBAL_N
69 for ((i=1;i<=$GLOBAL_N;i++))
70 do
71 R_TCP[$i]=0
72 R_UDP[$i]=0
73 done
74 elif [ "$key" = "X" ]
75 then
76 KNOWN=$(cut -d : -f 2 <<< $line)
77 echo $KNOWN
78 elif [ "$key" = "T" ]
79 then
80 PLUGIN=$(cut -d : -f 2 <<< $line)
81 echo $PLUGIN
82 elif [ "$key" = "K" ]
83 then
84 echo know node
85 extract_attributes $key $line
86 elif [ "$key" = "R" ]
87 then
88 echo router
89 extract_attributes $key $line
90 elif [ "$key" = "P" ]
91 then
92 echo node
93 extract_attributes $key $line
94 fi
95done < $filename
96}
97
98
99