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