aboutsummaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing')
-rw-r--r--src/testing/.gitignore7
-rw-r--r--src/testing/Makefile.am127
-rw-r--r--src/testing/gnunet-cmds-helper.c640
-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.c2678
-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.c169
-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.c146
-rw-r--r--src/testing/testing_api_cmd_netjail_start.c236
-rw-r--r--src/testing/testing_api_cmd_netjail_start_testsystem.c793
-rw-r--r--src/testing/testing_api_cmd_netjail_stop.c203
-rw-r--r--src/testing/testing_api_cmd_netjail_stop_testsystem.c153
-rw-r--r--src/testing/testing_api_cmd_send_peer_ready.c127
-rw-r--r--src/testing/testing_api_cmd_system_create.c151
-rw-r--r--src/testing/testing_api_cmd_system_destroy.c118
-rw-r--r--src/testing/testing_api_loop.c606
-rw-r--r--src/testing/testing_api_trait_cmd.c79
-rw-r--r--src/testing/testing_api_trait_process.c81
-rw-r--r--src/testing/testing_api_traits.c81
-rw-r--r--src/testing/testing_cmds.h109
-rwxr-xr-xsrc/testing/topo.sh99
38 files changed, 0 insertions, 9007 deletions
diff --git a/src/testing/.gitignore b/src/testing/.gitignore
deleted file mode 100644
index f350da1f2..000000000
--- a/src/testing/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
1list-keys
2gnunet-testing
3test_testing_peerstartup
4test_testing_peerstartup2
5test_testing_portreservation
6test_testing_servicestartup
7test_testing_sharedservices
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
deleted file mode 100644
index a9a1b5a02..000000000
--- a/src/testing/Makefile.am
+++ /dev/null
@@ -1,127 +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_trait_cmd.c \
48 testing_api_trait_process.c \
49 testing_api_traits.c
50libgnunettesting_la_LIBADD = \
51 $(top_builddir)/src/arm/libgnunetarm.la \
52 $(top_builddir)/src/util/libgnunetutil.la \
53 $(LTLIBINTL)
54libgnunettesting_la_LDFLAGS = \
55 $(GN_LIB_LDFLAGS) \
56 -version-info 2:0:1
57
58bin_PROGRAMS = \
59 gnunet-testing
60
61noinst_PROGRAMS = \
62 list-keys
63
64gnunet_testing_SOURCES = \
65 gnunet-testing.c
66gnunet_testing_LDADD = \
67 libgnunettesting.la \
68 $(top_builddir)/src/util/libgnunetutil.la \
69 $(GN_LIBINTL)
70
71list_keys_SOURCES = \
72 list-keys.c
73list_keys_LDADD = \
74 $(top_builddir)/src/util/libgnunetutil.la \
75 $(GN_LIBINTL)
76
77
78check_PROGRAMS = \
79 test_testing_portreservation \
80 test_testing_servicestartup \
81 test_testing_peerstartup \
82 test_testing_peerstartup2 \
83 test_testing_sharedservices
84
85if ENABLE_TEST_RUN
86AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
87TESTS = \
88 test_testing_portreservation \
89 test_testing_peerstartup \
90 test_testing_peerstartup2 \
91 test_testing_servicestartup
92endif
93
94test_testing_portreservation_SOURCES = \
95 test_testing_portreservation.c
96test_testing_portreservation_LDADD = \
97 libgnunettesting.la \
98 $(top_builddir)/src/util/libgnunetutil.la
99
100test_testing_peerstartup_SOURCES = \
101 test_testing_peerstartup.c
102test_testing_peerstartup_LDADD = \
103 libgnunettesting.la \
104 $(top_builddir)/src/util/libgnunetutil.la
105
106test_testing_peerstartup2_SOURCES = \
107 test_testing_peerstartup2.c
108test_testing_peerstartup2_LDADD = \
109 libgnunettesting.la \
110 $(top_builddir)/src/util/libgnunetutil.la
111
112test_testing_servicestartup_SOURCES = \
113 test_testing_servicestartup.c
114test_testing_servicestartup_LDADD = \
115 libgnunettesting.la \
116 $(top_builddir)/src/util/libgnunetutil.la
117
118test_testing_sharedservices_SOURCES = \
119 test_testing_sharedservices.c
120test_testing_sharedservices_LDADD = \
121 libgnunettesting.la \
122 $(top_builddir)/src/util/libgnunetutil.la
123
124EXTRA_DIST = \
125 test_testing_defaults.conf \
126 test_testing_sharedservices.conf \
127 testing_cmds.h
diff --git a/src/testing/gnunet-cmds-helper.c b/src/testing/gnunet-cmds-helper.c
deleted file mode 100644
index 5ff7c04ea..000000000
--- a/src/testing/gnunet-cmds-helper.c
+++ /dev/null
@@ -1,640 +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 * Handle to the testing system
190 */
191static struct GNUNET_TESTING_System *test_system;
192
193/**
194 * Our message stream tokenizer
195 */
196struct GNUNET_MessageStreamTokenizer *tokenizer;
197
198/**
199 * Disk handle from stdin
200 */
201static struct GNUNET_DISK_FileHandle *stdin_fd;
202
203/**
204 * Disk handle for stdout
205 */
206static struct GNUNET_DISK_FileHandle *stdout_fd;
207
208/**
209 * Pipe used to communicate shutdown via signal.
210 */
211static struct GNUNET_DISK_PipeHandle *sigpipe;
212
213/**
214 * Task identifier for the read task
215 */
216static struct GNUNET_SCHEDULER_Task *read_task_id;
217
218/**
219 * Task identifier for the write task
220 */
221static struct GNUNET_SCHEDULER_Task *write_task_id;
222
223/**
224 * Are we done reading messages from stdin?
225 */
226static int done_reading;
227
228/**
229 * Result to return in case we fail
230 */
231static int status;
232
233
234/**
235 * Task to shut down cleanly
236 *
237 * @param cls NULL
238 */
239static void
240shutdown_task (void *cls)
241{
242
243 LOG_DEBUG ("Shutting down.\n");
244
245 if (NULL != read_task_id)
246 {
247 GNUNET_SCHEDULER_cancel (read_task_id);
248 read_task_id = NULL;
249 }
250 if (NULL != write_task_id)
251 {
252 struct WriteContext *wc;
253
254 wc = GNUNET_SCHEDULER_cancel (write_task_id);
255 write_task_id = NULL;
256 GNUNET_free (wc->data);
257 GNUNET_free (wc);
258 }
259 if (NULL != stdin_fd)
260 (void) GNUNET_DISK_file_close (stdin_fd);
261 if (NULL != stdout_fd)
262 (void) GNUNET_DISK_file_close (stdout_fd);
263 GNUNET_MST_destroy (tokenizer);
264 tokenizer = NULL;
265
266 if (NULL != test_system)
267 {
268 GNUNET_TESTING_system_destroy (test_system, GNUNET_YES);
269 test_system = NULL;
270 }
271}
272
273
274/**
275 * Task to write to the standard out
276 *
277 * @param cls the WriteContext
278 */
279static void
280write_task (void *cls)
281{
282 struct WriteContext *wc = cls;
283 ssize_t bytes_wrote;
284
285 GNUNET_assert (NULL != wc);
286 write_task_id = NULL;
287 bytes_wrote = GNUNET_DISK_file_write (stdout_fd,
288 wc->data + wc->pos,
289 wc->length - wc->pos);
290 if (GNUNET_SYSERR == bytes_wrote)
291 {
292 LOG (GNUNET_ERROR_TYPE_WARNING,
293 "Cannot reply back successful initialization\n");
294 GNUNET_free (wc->data);
295 GNUNET_free (wc);
296 return;
297 }
298 wc->pos += bytes_wrote;
299 if (wc->pos == wc->length)
300 {
301 GNUNET_free (wc->data);
302 GNUNET_free (wc);
303 return;
304 }
305 write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
306 stdout_fd,
307 &write_task,
308 wc);
309}
310
311
312/**
313 * Callback to write a message to the master loop.
314 *
315 */
316static void
317write_message (struct GNUNET_MessageHeader *message, size_t msg_length)
318{
319 struct WriteContext *wc;
320
321 wc = GNUNET_new (struct WriteContext);
322 wc->length = msg_length;
323 wc->data = message;
324 write_task_id = GNUNET_SCHEDULER_add_write_file (
325 GNUNET_TIME_UNIT_FOREVER_REL,
326 stdout_fd,
327 &write_task,
328 wc);
329}
330
331
332/**
333 * Functions with this signature are called whenever a
334 * complete message is received by the tokenizer.
335 *
336 * Do not call #GNUNET_mst_destroy() in this callback
337 *
338 * @param cls identification of the client
339 * @param message the actual message
340 * @return #GNUNET_OK on success,
341 * #GNUNET_NO to stop further processing (no error)
342 * #GNUNET_SYSERR to stop further processing with error
343 */
344static int
345tokenizer_cb (void *cls, const struct GNUNET_MessageHeader *message)
346{
347
348 struct NodeIdentifier *ni = cls;
349 const struct GNUNET_CMDS_HelperInit *msg;
350 struct GNUNET_CMDS_HelperReply *reply;
351 char *binary;
352 char *plugin_name;
353 size_t plugin_name_size;
354 uint16_t msize;
355 size_t msg_length;
356 char *router_ip;
357 char *node_ip;
358 unsigned int namespace_n;
359
360 msize = ntohs (message->size);
361 if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT == ntohs (message->type))
362 {
363 msg = (const struct GNUNET_CMDS_HelperInit *) message;
364 plugin_name_size = ntohs (msg->plugin_name_size);
365 if ((sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_size) > msize)
366 {
367 GNUNET_break (0);
368 LOG (GNUNET_ERROR_TYPE_WARNING,
369 "Received unexpected message -- exiting\n");
370 goto error;
371 }
372 plugin_name = GNUNET_malloc (plugin_name_size + 1);
373 GNUNET_strlcpy (plugin_name,
374 ((char *) &msg[1]),
375 plugin_name_size + 1);
376
377 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-cmd");
378
379 plugin = GNUNET_new (struct Plugin);
380 plugin->api = GNUNET_PLUGIN_load (plugin_name,
381 NULL);
382 plugin->library_name = GNUNET_strdup (basename (plugin_name));
383
384 plugin->global_n = ni->global_n;
385 plugin->local_m = ni->local_m;
386 plugin->n = ni->n;
387 plugin->m = ni->m;
388
389 router_ip = GNUNET_malloc (strlen (ROUTER_BASE_IP) + strlen (plugin->n)
390 + 1);
391 strcpy (router_ip, ROUTER_BASE_IP);
392 strcat (router_ip, plugin->n);
393
394 sscanf (plugin->n, "%u", &namespace_n);
395
396 if (0 == namespace_n)
397 {
398 LOG (GNUNET_ERROR_TYPE_ERROR,
399 "known node n: %s\n",
400 plugin->n);
401 node_ip = GNUNET_malloc (strlen (KNOWN_BASE_IP) + strlen (plugin->m) + 1);
402 strcat (node_ip, KNOWN_BASE_IP);
403 }
404 else
405 {
406 LOG (GNUNET_ERROR_TYPE_ERROR,
407 "subnet node n: %s\n",
408 plugin->n);
409 node_ip = GNUNET_malloc (strlen (NODE_BASE_IP) + strlen (plugin->m) + 1);
410 strcat (node_ip, NODE_BASE_IP);
411 }
412 strcat (node_ip, plugin->m);
413
414 plugin->api->start_testcase (&write_message, router_ip, node_ip, plugin->m,
415 plugin->n, plugin->local_m, ni->topology_data,
416 ni->read_file);
417
418 msg_length = sizeof(struct GNUNET_CMDS_HelperReply);
419 reply = GNUNET_new (struct GNUNET_CMDS_HelperReply);
420 reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY);
421 reply->header.size = htons ((uint16_t) msg_length);
422
423 write_message ((struct GNUNET_MessageHeader *) reply, msg_length);
424
425 GNUNET_free (binary);
426 GNUNET_free (router_ip);
427 GNUNET_free (plugin_name);
428
429 return GNUNET_OK;
430 }
431 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED == ntohs (
432 message->type))
433 {
434 LOG (GNUNET_ERROR_TYPE_DEBUG,
435 "all peers started\n");
436 plugin->api->all_peers_started ();
437 return GNUNET_OK;
438 }
439 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_LOCAL_TESTS_PREPARED == ntohs (
440 message->type))
441 {
442 LOG (GNUNET_ERROR_TYPE_DEBUG,
443 "all local tests prepared\n");
444 plugin->api->all_local_tests_prepared ();
445 return GNUNET_OK;
446 }
447 else
448 {
449 LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n");
450 goto error;
451 }
452
453
454 error:
455 status = GNUNET_SYSERR;
456 LOG (GNUNET_ERROR_TYPE_ERROR,
457 "tokenizer shutting down!\n");
458 GNUNET_SCHEDULER_shutdown ();
459 return GNUNET_SYSERR;
460}
461
462
463/**
464 * Task to read from stdin
465 *
466 * @param cls NULL
467 */
468static void
469read_task (void *cls)
470{
471 char buf[GNUNET_MAX_MESSAGE_SIZE];
472 ssize_t sread;
473
474 read_task_id = NULL;
475 sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof(buf));
476 if ((GNUNET_SYSERR == sread) || (0 == sread))
477 {
478 LOG_DEBUG ("STDIN closed\n");
479 GNUNET_SCHEDULER_shutdown ();
480 return;
481 }
482 if (GNUNET_YES == done_reading)
483 {
484 /* didn't expect any more data! */
485 GNUNET_break_op (0);
486 LOG (GNUNET_ERROR_TYPE_ERROR,
487 "tokenizer shutting down during reading, didn't expect any more data!\n");
488 GNUNET_SCHEDULER_shutdown ();
489 return;
490 }
491 LOG_DEBUG ("Read %u bytes\n", (unsigned int) sread);
492 /* FIXME: could introduce a GNUNET_MST_read2 to read
493 directly from 'stdin_fd' and save a memcpy() here */
494 if (GNUNET_OK !=
495 GNUNET_MST_from_buffer (tokenizer, buf, sread, GNUNET_NO, GNUNET_NO))
496 {
497 GNUNET_break (0);
498 LOG (GNUNET_ERROR_TYPE_ERROR,
499 "tokenizer shutting down during reading, writing to buffer failed!\n");
500 GNUNET_SCHEDULER_shutdown ();
501 return;
502 }
503 read_task_id /* No timeout while reading */
504 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
505 stdin_fd,
506 &read_task,
507 NULL);
508}
509
510
511/**
512 * Main function that will be run.
513 *
514 * @param cls closure
515 * @param args remaining command-line arguments
516 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
517 * @param cfg configuration
518 */
519static void
520run (void *cls,
521 char *const *args,
522 const char *cfgfile,
523 const struct GNUNET_CONFIGURATION_Handle *cfg)
524{
525 struct NodeIdentifier *ni = cls;
526
527 LOG_DEBUG ("Starting interpreter loop helper...\n");
528
529 tokenizer = GNUNET_MST_create (&tokenizer_cb, ni);
530 stdin_fd = GNUNET_DISK_get_handle_from_native (stdin);
531 stdout_fd = GNUNET_DISK_get_handle_from_native (stdout);
532 read_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
533 stdin_fd,
534 &read_task,
535 NULL);
536 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
537}
538
539
540/**
541 * Signal handler called for SIGCHLD.
542 */
543static void
544sighandler_child_death ()
545{
546 static char c;
547 int old_errno; /* back-up errno */
548
549 old_errno = errno;
550 GNUNET_break (
551 1 ==
552 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe,
553 GNUNET_DISK_PIPE_END_WRITE),
554 &c,
555 sizeof(c)));
556 errno = old_errno;
557}
558
559
560/**
561 * Main function
562 *
563 * @param argc the number of command line arguments
564 * @param argv command line arg array
565 * @return return code
566 */
567int
568main (int argc, char **argv)
569{
570 struct NodeIdentifier *ni;
571 struct GNUNET_SIGNAL_Context *shc_chld;
572 struct GNUNET_GETOPT_CommandLineOption options[] =
573 { GNUNET_GETOPT_OPTION_END };
574 int ret;
575 int i;
576 size_t topology_data_length = 0;
577 unsigned int read_file;
578 char cr[1] = "\n";
579
580 GNUNET_log_setup ("gnunet-cmds-helper",
581 "DEBUG",
582 NULL);
583 ni = GNUNET_new (struct NodeIdentifier);
584 ni->global_n = argv[1];
585 ni->local_m = argv[2];
586 ni->m = argv[3];
587 ni->n = argv[4];
588
589 sscanf (argv[5], "%u", &read_file);
590
591 if (1 == read_file)
592 ni->topology_data = argv[6];
593 else
594 {
595 for (i = 6; i<argc; i++)
596 topology_data_length += strlen (argv[i]) + 1;
597 LOG (GNUNET_ERROR_TYPE_DEBUG,
598 "topo data length %lu\n",
599 topology_data_length);
600 ni->topology_data = GNUNET_malloc (topology_data_length);
601 for (i = 6; i<argc; i++)
602 {
603 strcat (ni->topology_data, argv[i]);
604 strcat (ni->topology_data, cr);
605 }
606 }
607 ni->read_file = &read_file;
608 ni->topology_data[topology_data_length - 1] = '\0';
609 LOG (GNUNET_ERROR_TYPE_DEBUG,
610 "topo data %s\n",
611 ni->topology_data);
612
613 status = GNUNET_OK;
614 if (NULL ==
615 (sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE)))
616 {
617 GNUNET_break (0);
618 return 1;
619 }
620 shc_chld =
621 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
622 ret = GNUNET_PROGRAM_run (argc,
623 argv,
624 "gnunet-cmds-helper",
625 "Helper for starting a local interpreter loop",
626 options,
627 &run,
628 ni);
629
630 GNUNET_SIGNAL_handler_uninstall (shc_chld);
631 shc_chld = NULL;
632 GNUNET_DISK_pipe_close (sigpipe);
633 GNUNET_free (ni);
634 if (GNUNET_OK != ret)
635 return 1;
636 return (GNUNET_OK == status) ? 0 : 1;
637}
638
639
640/* 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 7474d9b5f..000000000
--- a/src/testing/testing.c
+++ /dev/null
@@ -1,2678 +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:60002"
42
43#define ROUTER_CONNECT_ADDRESS_TEMPLATE "%s-92.68.150.%u:60002"
44
45#define KNOWN_CONNECT_ADDRESS_TEMPLATE "%s-92.68.151.%u:60002"
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
1322 err_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, struct
2173 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/**
2262 * Calculate the unique id identifying a node from a given connction.
2263 *
2264 * @param node_connection The connection we calculate the id from.
2265 * @param topology The topology we get all needed information from.
2266 * @return The unique id of the node from the connection.
2267 */
2268unsigned int
2269GNUNET_TESTING_calculate_num (struct
2270 GNUNET_TESTING_NodeConnection *node_connection,
2271 struct GNUNET_TESTING_NetjailTopology *topology)
2272{
2273 unsigned int n, m, num;
2274
2275 n = node_connection->namespace_n;
2276 m = node_connection->node_n;
2277
2278 if (0 == n)
2279 num = m;
2280 else
2281 num = (n - 1) * topology->nodes_m + m + topology->nodes_x;
2282
2283 return num;
2284}
2285
2286
2287/**
2288 * Get the address for a specific communicator from a connection.
2289 *
2290 * @param connection The connection we like to have the address from.
2291 * @param prefix The communicator protocol prefix.
2292 * @return The address of the communicator.
2293 */
2294char *
2295GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection,
2296 char *prefix)
2297{
2298 struct GNUNET_TESTING_NetjailNode *node;
2299 char *addr;
2300 char *template;
2301
2302 LOG (GNUNET_ERROR_TYPE_DEBUG,
2303 "node_n: %u\n",
2304 connection->node_n);
2305
2306 node = connection->node;
2307 if (connection->namespace_n == node->namespace_n)
2308 {
2309 template = CONNECT_ADDRESS_TEMPLATE;
2310 }
2311 else if (0 == connection->namespace_n)
2312 {
2313 template = KNOWN_CONNECT_ADDRESS_TEMPLATE;
2314 }
2315 else if (1 == connection->node_n)
2316 {
2317 template = ROUTER_CONNECT_ADDRESS_TEMPLATE;
2318 }
2319 else
2320 {
2321 return NULL;
2322 }
2323
2324 if (0 == strcmp (PREFIX_TCP, prefix))
2325 {
2326
2327 GNUNET_asprintf (&addr,
2328 template,
2329 prefix,
2330 connection->node_n);
2331 }
2332 else if (0 == strcmp (PREFIX_UDP, prefix))
2333 {
2334 GNUNET_asprintf (&addr,
2335 template,
2336 prefix,
2337 connection->node_n);
2338 }
2339 else
2340 {
2341 GNUNET_assert (0);
2342 }
2343
2344 return addr;
2345}
2346
2347
2348/**
2349 * Create a GNUNET_CMDS_LOCAL_FINISHED message.
2350 *
2351 * @param rv The result of the local test as GNUNET_GenericReturnValue.
2352 * @return The GNUNET_CMDS_LOCAL_FINISHED message.
2353*/
2354struct GNUNET_MessageHeader *
2355GNUNET_TESTING_send_local_test_finished_msg (enum GNUNET_GenericReturnValue rv)
2356{
2357 struct GNUNET_CMDS_LOCAL_FINISHED *reply;
2358 size_t msg_length;
2359
2360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2361 "Local test exits with status %d\n",
2362 rv);
2363 msg_length = sizeof(struct GNUNET_CMDS_LOCAL_FINISHED);
2364 reply = GNUNET_new (struct GNUNET_CMDS_LOCAL_FINISHED);
2365 reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED);
2366 reply->header.size = htons ((uint16_t) msg_length);
2367 reply->result = htons (rv);
2368
2369 return (struct GNUNET_MessageHeader *) reply;
2370}
2371
2372
2373/**
2374 * Parse the topology data.
2375 *
2376 * @param data The topology data.
2377 * @return The GNUNET_TESTING_NetjailTopology
2378 */
2379struct GNUNET_TESTING_NetjailTopology *
2380GNUNET_TESTING_get_topo_from_string (char *data)
2381{
2382 char *token;
2383 char *key = NULL;
2384 unsigned int out;
2385 char *rest = NULL;
2386 char *value = NULL;
2387 char *value2;
2388 int ret;
2389 struct GNUNET_TESTING_NetjailTopology *topo;
2390 struct GNUNET_TESTING_NetjailNode *node;
2391 struct GNUNET_TESTING_NetjailRouter *router;
2392 struct GNUNET_TESTING_NetjailNamespace *namespace;
2393 struct GNUNET_ShortHashCode *hkey;
2394 struct GNUNET_HashCode hc;
2395
2396 token = strtok_r (data, "\n", &rest);
2397 topo = GNUNET_new (struct GNUNET_TESTING_NetjailTopology);
2398 topo->map_namespaces =
2399 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2400 topo->map_globals =
2401 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2402
2403 while (NULL != token)
2404 {
2405 if (NULL != key)
2406 free (key);
2407 key = get_key (token);
2408 LOG (GNUNET_ERROR_TYPE_DEBUG,
2409 "In the loop with token: %s beginning with %s\n",
2410 token,
2411 key);
2412 if (0 == strcmp (key, "M"))
2413 {
2414 LOG (GNUNET_ERROR_TYPE_DEBUG,
2415 "Get first Value for M.\n");
2416 out = get_first_value (token);
2417 LOG (GNUNET_ERROR_TYPE_DEBUG,
2418 "M: %u\n",
2419 out);
2420 topo->nodes_m = out;
2421 }
2422 else if (0 == strcmp (key, "N"))
2423 {
2424 LOG (GNUNET_ERROR_TYPE_DEBUG,
2425 "Get first Value for N.\n");
2426 out = get_first_value (token);
2427 LOG (GNUNET_ERROR_TYPE_DEBUG,
2428 "N: %u\n",
2429 out);
2430 topo->namespaces_n = out;
2431 }
2432 else if (0 == strcmp (key, "X"))
2433 {
2434 LOG (GNUNET_ERROR_TYPE_DEBUG,
2435 "Get first Value for X.\n");
2436 out = get_first_value (token);
2437 LOG (GNUNET_ERROR_TYPE_DEBUG,
2438 "X: %u\n",
2439 out);
2440 topo->nodes_x = out;
2441 }
2442 else if (0 == strcmp (key, "T"))
2443 {
2444 LOG (GNUNET_ERROR_TYPE_DEBUG,
2445 "Get first string value for T.\n");
2446 value = get_first_string_value (token);
2447 LOG (GNUNET_ERROR_TYPE_DEBUG,
2448 "value: %s\n",
2449 value);
2450 topo->plugin = value;
2451 }
2452 else if (0 == strcmp (key, "K"))
2453 {
2454 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
2455 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
2456
2457 LOG (GNUNET_ERROR_TYPE_DEBUG,
2458 "Get first Value for K.\n");
2459 out = get_first_value (token);
2460 LOG (GNUNET_ERROR_TYPE_DEBUG,
2461 "K: %u\n",
2462 out);
2463 node->node_n = out;
2464 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2465 memcpy (hkey,
2466 &hc,
2467 sizeof (*hkey));
2468 node->is_global = GNUNET_YES;
2469
2470 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2471 topo->map_globals,
2472 hkey))
2473 GNUNET_break (0);
2474 else
2475 GNUNET_CONTAINER_multishortmap_put (topo->map_globals,
2476 hkey,
2477 node,
2478 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2479 LOG (GNUNET_ERROR_TYPE_DEBUG,
2480 "Get value for key value on K.\n");
2481 value = get_value ("plugin", token);
2482 LOG (GNUNET_ERROR_TYPE_DEBUG,
2483 "value: %s\n",
2484 value);
2485 node->plugin = value;
2486 node_connections (token, node);
2487 }
2488 else if (0 == strcmp (key, "R"))
2489 {
2490 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
2491 router = GNUNET_new (struct GNUNET_TESTING_NetjailRouter);
2492 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
2493
2494 LOG (GNUNET_ERROR_TYPE_DEBUG,
2495 "Get first Value for R.\n");
2496 out = get_first_value (token);
2497 LOG (GNUNET_ERROR_TYPE_DEBUG,
2498 "R: %u\n",
2499 out);
2500 node->node_n = out;
2501 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2502 memcpy (hkey,
2503 &hc,
2504 sizeof (*hkey));
2505 LOG (GNUNET_ERROR_TYPE_DEBUG,
2506 "Get value for key tcp_port on R.\n");
2507 value = get_value ("tcp_port", token);
2508 LOG (GNUNET_ERROR_TYPE_DEBUG,
2509 "tcp_port: %s\n",
2510 value);
2511 ret = sscanf (value, "%u", &(router->tcp_port));
2512
2513 GNUNET_break (0 != ret && 1 >= router->tcp_port);
2514
2515 LOG (GNUNET_ERROR_TYPE_DEBUG,
2516 "Get value for key udp_port on R.\n");
2517 value2 = get_value ("udp_port", token);
2518 ret = sscanf (value2, "%u", &(router->udp_port));
2519 GNUNET_break (0 != ret && 1 >= router->udp_port);
2520 LOG (GNUNET_ERROR_TYPE_DEBUG,
2521 "udp_port: %s\n",
2522 value2);
2523
2524 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2525 topo->map_namespaces,
2526 hkey))
2527 {
2528 namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
2529 hkey);
2530 }
2531 else
2532 {
2533 namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
2534 namespace->namespace_n = out;
2535 namespace->nodes = GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2536 GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
2537 hkey,
2538 namespace,
2539 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2540 }
2541 namespace->router = router;
2542
2543 }
2544 else if (0 == strcmp (key, "P"))
2545 {
2546 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
2547 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
2548
2549 LOG (GNUNET_ERROR_TYPE_DEBUG,
2550 "Get first Value for P.\n");
2551 out = get_first_value (token);
2552 LOG (GNUNET_ERROR_TYPE_DEBUG,
2553 "P: %u\n",
2554 out);
2555 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2556 memcpy (hkey,
2557 &hc,
2558 sizeof (*hkey));
2559
2560 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2561 topo->map_namespaces,
2562 hkey))
2563 {
2564 namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
2565 hkey);
2566 }
2567 else
2568 {
2569 namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
2570 namespace->nodes = GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
2571 namespace->namespace_n = out;
2572 GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
2573 hkey,
2574 namespace,
2575 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2576 }
2577 LOG (GNUNET_ERROR_TYPE_DEBUG,
2578 "Get second Value for P.\n");
2579 out = get_second_value (token);
2580 LOG (GNUNET_ERROR_TYPE_DEBUG,
2581 "P: %u\n",
2582 out);
2583 GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
2584 memcpy (hkey,
2585 &hc,
2586 sizeof (*hkey));
2587 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (
2588 namespace->nodes,
2589 hkey))
2590 {
2591 GNUNET_break (0);
2592 }
2593 else
2594 {
2595 node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
2596 GNUNET_CONTAINER_multishortmap_put (namespace->nodes,
2597 hkey,
2598 node,
2599 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2600 LOG (GNUNET_ERROR_TYPE_DEBUG,
2601 "Get value for key plugin on P.\n");
2602 value = get_value ("plugin", token);
2603 LOG (GNUNET_ERROR_TYPE_DEBUG,
2604 "plugin: %s\n",
2605 value);
2606 node->plugin = value;
2607 node->node_n = out;
2608 node->namespace_n = namespace->namespace_n;
2609 }
2610 node_connections (token, node);
2611 }
2612 token = strtok_r (NULL, "\n", &rest);
2613 if (NULL != token)
2614 LOG (GNUNET_ERROR_TYPE_DEBUG,
2615 "Next token %s\n",
2616 token);
2617 }
2618 if (NULL != key)
2619 GNUNET_free (key);
2620 /*if (NULL != value)
2621 GNUNET_free (value);*/
2622
2623 return topo;
2624}
2625
2626
2627/**
2628 * Getting the topology from file.
2629 *
2630 * @param filename The name of the topology file.
2631 * @return The GNUNET_TESTING_NetjailTopology
2632 */
2633struct GNUNET_TESTING_NetjailTopology *
2634GNUNET_TESTING_get_topo_from_file (const char *filename)
2635{
2636 uint64_t fs;
2637 char *data;
2638 struct GNUNET_TESTING_NetjailTopology *topo;
2639
2640 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
2641 {
2642 LOG (GNUNET_ERROR_TYPE_ERROR,
2643 _ ("Topology file %s not found\n"),
2644 filename);
2645 return NULL;
2646 }
2647 if (GNUNET_OK !=
2648 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
2649 {
2650 LOG (GNUNET_ERROR_TYPE_ERROR,
2651 _ ("Topology file %s has no data\n"),
2652 filename);
2653 return NULL;
2654 }
2655 data = GNUNET_malloc (fs + 1);
2656 if (fs != GNUNET_DISK_fn_read (filename, data, fs))
2657 {
2658 LOG (GNUNET_ERROR_TYPE_ERROR,
2659 _ ("Topology file %s cannot be read\n"),
2660 filename);
2661 GNUNET_free (data);
2662 return NULL;
2663 }
2664
2665 LOG (GNUNET_ERROR_TYPE_DEBUG,
2666 "file lenght %lu\n",
2667 fs);
2668 data[fs] = '\0';
2669
2670 topo = GNUNET_TESTING_get_topo_from_string (data);
2671
2672 GNUNET_free (data);
2673
2674 return topo;
2675}
2676
2677
2678/* 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 9360dd02e..000000000
--- a/src/testing/testing_api_cmd_block_until_external_trigger.c
+++ /dev/null
@@ -1,169 +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 {
59 .index = 0,
60 .trait_name = "async_context",
61 .ptr = (const void *) ac,
62 },
63 {
64 .index = 1,
65 .trait_name = "block_state",
66 .ptr = (const void *) bs,
67 },
68 GNUNET_TESTING_trait_end ()
69 };
70
71 return GNUNET_TESTING_get_trait (traits,
72 ret,
73 trait,
74 index);
75}
76
77
78/**
79 * Function to get the trait with the internal command state BlockState.
80 *
81 * * @param[out] ac struct BlockState.
82* @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
83 */
84int
85GNUNET_TESTING_get_trait_block_state (
86 const struct GNUNET_TESTING_Command *cmd,
87 struct BlockState **bs)
88{
89 return cmd->traits (cmd->cls,
90 (const void **) bs,
91 "block_state",
92 (unsigned int) 1);
93}
94
95
96/**
97 * Function to get the trait with the async context.
98 *
99 * @param[out] ac struct GNUNET_TESTING_AsyncContext.
100 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
101 */
102int
103GNUNET_TESTING_get_trait_async_context (
104 const struct GNUNET_TESTING_Command *cmd,
105 struct GNUNET_TESTING_AsyncContext **ac)
106{
107 return cmd->traits (cmd->cls,
108 (const void **) ac,
109 "async_context",
110 (unsigned int) 0);
111}
112
113
114/**
115 * This function does nothing but to start the cmd.
116 *
117 */
118static void
119block_until_all_peers_started_run (void *cls,
120 struct GNUNET_TESTING_Interpreter *is)
121{
122 struct BlockState *bs = cls;
123 struct GNUNET_TESTING_Command *cmd =
124 GNUNET_TESTING_interpreter_get_current_command (is);
125
126 LOG (GNUNET_ERROR_TYPE_DEBUG,
127 "block %s running %u!\n",
128 bs->label,
129 bs->asynchronous_finish);
130 if (GNUNET_YES == bs->asynchronous_finish)
131 {
132 LOG (GNUNET_ERROR_TYPE_DEBUG,
133 "block %s running asynchronous!\n",
134 bs->label);
135 cmd->asynchronous_finish = bs->asynchronous_finish;
136 }
137}
138
139
140/**
141 * Create command.
142 *
143 * @param label name for command.
144 * @param all_peers_started Flag which will be set from outside.
145 * @param asynchronous_finish If GNUNET_YES this command will not block. Can be NULL.
146 * @return command.
147 */
148struct GNUNET_TESTING_Command
149GNUNET_TESTING_cmd_block_until_external_trigger (
150 const char *label)
151{
152 struct BlockState *bs;
153
154 bs = GNUNET_new (struct BlockState);
155 bs->label = label;
156 bs->asynchronous_finish = GNUNET_NO;
157 {
158 struct GNUNET_TESTING_Command cmd = {
159 .cls = bs,
160 .label = label,
161 .run = &block_until_all_peers_started_run,
162 .ac = &bs->ac,
163 .cleanup = &block_until_all_peers_started_cleanup,
164 .traits = block_until_external_trigger_traits
165 };
166
167 return cmd;
168 }
169}
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 9dc7dfa9a..000000000
--- a/src/testing/testing_api_cmd_local_test_prepared.c
+++ /dev/null
@@ -1,146 +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 {
51 .index = 0,
52 .trait_name = "state",
53 .ptr = (const void *) lfs,
54 },
55 GNUNET_TESTING_trait_end ()
56 };
57 return GNUNET_TESTING_get_trait (traits,
58 ret,
59 trait,
60 index);
61}
62
63
64/**
65 * Function to get the trait with the struct LocalPreparedState.
66 *
67 * @param[out] lfs struct LocalPreparedState.
68 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
69 *
70 */
71enum GNUNET_GenericReturnValue
72GNUNET_TESTING_get_trait_local_prepared_state (
73 const struct GNUNET_TESTING_Command *cmd,
74 struct LocalPreparedState **lfs)
75{
76 return cmd->traits (cmd->cls,
77 (const void **) lfs,
78 "state",
79 (unsigned int) 0);
80}
81
82
83/**
84 * The cleanup function of this cmd frees resources the cmd allocated.
85 *
86 */
87static void
88local_test_prepared_cleanup (void *cls)
89{
90 struct LocalPreparedState *lfs = cls;
91
92 GNUNET_free (lfs);
93}
94
95
96/**
97 * This function sends a GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TESTS_PREPARED message to the master loop.
98 *
99 */
100static void
101local_test_prepared_run (void *cls,
102 struct GNUNET_TESTING_Interpreter *is)
103{
104 struct LocalPreparedState *lfs = cls;
105
106 struct GNUNET_CMDS_LOCAL_TEST_PREPARED *reply;
107 size_t msg_length;
108
109 msg_length = sizeof(struct GNUNET_CMDS_LOCAL_TEST_PREPARED);
110 reply = GNUNET_new (struct GNUNET_CMDS_LOCAL_TEST_PREPARED);
111 reply->header.type = htons (
112 GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED);
113 reply->header.size = htons ((uint16_t) msg_length);
114 lfs->write_message ((struct GNUNET_MessageHeader *) reply, msg_length);
115}
116
117
118/**
119 * Create command.
120 *
121 * @param label name for command.
122 * @param write_message Callback to write messages to the master loop.
123 * @param all_local_tests_prepared Flag which will be set from outside.
124 * @return command.
125 */
126struct GNUNET_TESTING_Command
127GNUNET_TESTING_cmd_local_test_prepared (const char *label,
128 TESTING_CMD_HELPER_write_cb
129 write_message)
130{
131 struct LocalPreparedState *lfs;
132
133 lfs = GNUNET_new (struct LocalPreparedState);
134 lfs->write_message = write_message;
135
136 struct GNUNET_TESTING_Command cmd = {
137 .cls = lfs,
138 .label = label,
139 .run = &local_test_prepared_run,
140 .ac = &lfs->ac,
141 .cleanup = &local_test_prepared_cleanup,
142 .traits = &local_test_prepared_traits
143 };
144
145 return cmd;
146}
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 1709a58d2..000000000
--- a/src/testing/testing_api_cmd_netjail_start_testsystem.c
+++ /dev/null
@@ -1,793 +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/**
34 * Generic logging shortcut
35 */
36#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
37
38/**
39 * Struct to store messages send/received by the helper into a DLL
40 *
41 */
42struct HelperMessage
43{
44
45 /**
46 * Kept in a DLL.
47 */
48 struct HelperMessage *next;
49
50 /**
51 * Kept in a DLL.
52 */
53 struct HelperMessage *prev;
54
55 /**
56 * Size of the original message.
57 */
58 uint16_t bytes_msg;
59
60 /* Followed by @e bytes_msg of msg.*/
61};
62
63
64/**
65 * Struct to store information handed over to callbacks.
66 *
67 */
68struct NetJailState
69{
70 /**
71 * Global state of the interpreter, used by a command
72 * to access information about other commands.
73 */
74 struct GNUNET_TESTING_Interpreter *is;
75
76 /**
77 * Context for our asynchronous completion.
78 */
79 struct GNUNET_TESTING_AsyncContext ac;
80
81 /**
82 * The complete topology information.
83 */
84 struct GNUNET_TESTING_NetjailTopology *topology;
85
86 /**
87 * Array with handles of helper processes.
88 */
89 struct GNUNET_HELPER_Handle **helper;
90
91 /**
92 * Size of the array NetJailState#helper.
93 *
94 */
95 unsigned int n_helper;
96
97 /**
98 * Number of nodes in a natted subnet.
99 *
100 */
101 unsigned int local_m;
102
103 /**
104 * Number of natted subnets.
105 *
106 */
107 unsigned int global_n;
108
109 /**
110 * Number of global known nodes.
111 *
112 */
113 unsigned int known;
114
115
116 /**
117 * Number of test environments started.
118 *
119 */
120 unsigned int number_of_testsystems_started;
121
122 /**
123 * Number of peers started.
124 *
125 */
126 unsigned int number_of_peers_started;
127
128 /**
129 * Number of local tests finished.
130 *
131 */
132 unsigned int number_of_local_tests_finished;
133
134 /**
135 * Number of local tests prepared to finish.
136 *
137 */
138 unsigned int number_of_local_tests_prepared;
139
140 /**
141 * Name of the test case plugin the helper will load.
142 *
143 */
144 char *plugin_name;
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 * Struct containing the number of the test environment and the NetJailState which
159 * will be handed to callbacks specific to a test environment.
160 */
161struct TestingSystemCount
162{
163 /**
164 * Kept in a DLL.
165 */
166 struct TestingSystemCount *next;
167
168 /**
169 * Kept in a DLL.
170 */
171 struct TestingSystemCount *prev;
172
173 /**
174 * The send handle for the helper
175 */
176 struct GNUNET_HELPER_SendHandle *shandle;
177
178 /**
179 * The number of the test environment.
180 *
181 */
182 unsigned int count;
183
184 /**
185 * Struct to store information handed over to callbacks.
186 *
187 */
188 struct NetJailState *ns;
189
190 /**
191 * The messages send to the helper.
192 */
193 struct GNUNET_MessageHeader *msg;
194};
195
196/**
197* Code to clean up resource this cmd used.
198*
199* @param cls closure
200*/
201static void
202netjail_exec_cleanup (void *cls)
203{
204 struct NetJailState *ns = cls;
205
206 GNUNET_free (ns);
207}
208
209
210/**
211 * This function prepares an array with traits.
212 *
213 */
214static int
215netjail_exec_traits (void *cls,
216 const void **ret,
217 const char *trait,
218 unsigned int index)
219{
220 struct NetJailState *ns = cls;
221 struct GNUNET_HELPER_Handle **helper = ns->helper;
222
223
224 struct GNUNET_TESTING_Trait traits[] = {
225 {
226 .index = 0,
227 .trait_name = "helper_handles",
228 .ptr = (const void *) helper,
229 },
230 GNUNET_TESTING_trait_end ()
231 };
232
233 return GNUNET_TESTING_get_trait (traits,
234 ret,
235 trait,
236 index);
237}
238
239
240/**
241 * Offer handles to testing cmd helper from trait
242 *
243 * @param cmd command to extract the message from.
244 * @param pt pointer to message.
245 * @return #GNUNET_OK on success.
246 */
247int
248GNUNET_TESTING_get_trait_helper_handles (const struct
249 GNUNET_TESTING_Command *cmd,
250 struct GNUNET_HELPER_Handle ***
251 helper)
252{
253 return cmd->traits (cmd->cls,
254 (const void **) helper,
255 "helper_handles",
256 (unsigned int) 0);
257}
258
259
260/**
261 * Continuation function from GNUNET_HELPER_send()
262 *
263 * @param cls closure
264 * @param result GNUNET_OK on success,
265 * GNUNET_NO if helper process died
266 * GNUNET_SYSERR during GNUNET_HELPER_stop
267 */
268static void
269clear_msg (void *cls, int result)
270{
271 struct TestingSystemCount *tbc = cls;
272
273 GNUNET_assert (NULL != tbc->shandle);
274 /*GNUNET_free (tbc->shandle);
275 tbc->shandle = NULL;*/
276 GNUNET_free (tbc->msg);
277 tbc->msg = NULL;
278}
279
280
281static void
282send_message_to_locals (
283 unsigned int i,
284 unsigned int j,
285 struct NetJailState *ns,
286 struct GNUNET_MessageHeader *header
287 )
288{
289 // unsigned int total_number = ns->local_m * ns->global_n + ns->known;
290 struct GNUNET_HELPER_Handle *helper;
291 struct TestingSystemCount *tbc;
292
293 LOG (GNUNET_ERROR_TYPE_DEBUG,
294 "send message of type %u to locals\n",
295 header->type);
296 tbc = GNUNET_new (struct TestingSystemCount);
297 tbc->ns = ns;
298 // 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.
299 if (0 == i)
300 tbc->count = j; // + total_number;
301 else
302 tbc->count = (i - 1) * ns->local_m + j + ns->known; // + total_number ;
303
304 helper = ns->helper[tbc->count - 1];// - total_number];
305
306
307
308 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
309 helper,
310 header,
311 GNUNET_NO,
312 &clear_msg,
313 tbc);
314
315 tbc->shandle = sh;
316 // GNUNET_array_append (tbc->shandle, tbc->n_shandle, sh);
317}
318
319
320static void
321send_all_local_tests_prepared (unsigned int i, unsigned int j, struct
322 NetJailState *ns)
323{
324 struct GNUNET_CMDS_ALL_LOCAL_TESTS_PREPARED *reply;
325 size_t msg_length;
326
327
328 msg_length = sizeof(struct GNUNET_CMDS_ALL_LOCAL_TESTS_PREPARED);
329 reply = GNUNET_new (struct GNUNET_CMDS_ALL_LOCAL_TESTS_PREPARED);
330 reply->header.type = htons (
331 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_LOCAL_TESTS_PREPARED);
332 reply->header.size = htons ((uint16_t) msg_length);
333
334 send_message_to_locals (i, j, ns, &reply->header);
335}
336
337
338static void
339send_all_peers_started (unsigned int i, unsigned int j, struct NetJailState *ns)
340{
341
342 struct GNUNET_CMDS_ALL_PEERS_STARTED *reply;
343 size_t msg_length;
344
345
346 msg_length = sizeof(struct GNUNET_CMDS_ALL_PEERS_STARTED);
347 reply = GNUNET_new (struct GNUNET_CMDS_ALL_PEERS_STARTED);
348 reply->header.type = htons (
349 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
350 reply->header.size = htons ((uint16_t) msg_length);
351
352 send_message_to_locals (i, j, ns, &reply->header);
353}
354
355
356/**
357 * Functions with this signature are called whenever a
358 * complete message is received by the tokenizer.
359 *
360 * Do not call GNUNET_SERVER_mst_destroy in callback
361 *
362 * @param cls closure
363 * @param client identification of the client
364 * @param message the actual message
365 *
366 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
367 */
368static int
369helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
370{
371 // struct TestingSystemCount *tbc = cls;
372 struct NetJailState *ns = cls;
373 unsigned int total_number = ns->local_m * ns->global_n + ns->known;
374 uint16_t message_type = ntohs (message->type);
375
376 switch (message_type)
377 {
378 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY:
379 ns->number_of_testsystems_started++;
380 break;
381 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED:
382 ns->number_of_peers_started++;
383 if (ns->number_of_peers_started == total_number)
384 {
385 for (int i = 1; i <= ns->known; i++)
386 {
387 send_all_peers_started (0,i, ns);
388 }
389 for (int i = 1; i <= ns->global_n; i++)
390 {
391 for (int j = 1; j <= ns->local_m; j++)
392 {
393 send_all_peers_started (i,j, ns);
394 }
395 }
396 ns->number_of_peers_started = 0;
397 }
398 break;
399 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED:
400 ns->number_of_local_tests_prepared++;
401 if (ns->number_of_local_tests_prepared == total_number)
402 {
403 for (int i = 1; i <= ns->known; i++)
404 {
405 send_all_local_tests_prepared (0,i, ns);
406 }
407
408 for (int i = 1; i <= ns->global_n; i++)
409 {
410 for (int j = 1; j <= ns->local_m; j++)
411 {
412 send_all_local_tests_prepared (i,j, ns);
413 }
414 }
415 }
416 break;
417 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED:
418 ns->number_of_local_tests_finished++;
419 if (ns->number_of_local_tests_finished == total_number)
420 {
421 GNUNET_TESTING_async_finish (&ns->ac);
422 }
423 break;
424 default:
425 // We received a message we can not handle.
426 GNUNET_assert (0);
427 }
428 /*if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY == ntohs (message->type))
429 {
430 ns->number_of_testsystems_started++;
431 }
432 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED == ntohs (
433 message->type))
434 {
435 ns->number_of_peers_started++;
436 if (ns->number_of_peers_started == total_number)
437 {
438 for (int i = 1; i <= ns->known; i++)
439 {
440 send_all_peers_started (0,i, ns);
441 }
442
443 for (int i = 1; i <= ns->global_n; i++)
444 {
445 for (int j = 1; j <= ns->local_m; j++)
446 {
447 send_all_peers_started (i,j, ns);
448 }
449 }
450 ns->number_of_peers_started = 0;
451 }
452 }
453 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED == ntohs (
454 message->type))
455 {
456 ns->number_of_local_tests_prepared++;
457 if (ns->number_of_local_tests_prepared == total_number)
458 {
459 for (int i = 1; i <= ns->known; i++)
460 {
461 send_all_local_tests_prepared (0,i, ns);
462 }
463
464 for (int i = 1; i <= ns->global_n; i++)
465 {
466 for (int j = 1; j <= ns->local_m; j++)
467 {
468 send_all_local_tests_prepared (i,j, ns);
469 }
470 }
471 }
472 }
473 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED == ntohs (
474 message->type))
475 {
476 ns->number_of_local_tests_finished++;
477 if (ns->number_of_local_tests_finished == total_number)
478 {
479 GNUNET_TESTING_async_finish (&ns->ac);
480 }
481 }
482 else
483 {
484 // We received a message we can not handle.
485 GNUNET_assert (0);
486 }*/
487
488
489 LOG (GNUNET_ERROR_TYPE_DEBUG,
490 "total %u sysstarted %u peersstarted %u prep %u finished %u %u %u %u\n",
491 total_number,
492 ns->number_of_testsystems_started,
493 ns->number_of_peers_started,
494 ns->number_of_local_tests_prepared,
495 ns->number_of_local_tests_finished,
496 ns->local_m,
497 ns->global_n,
498 ns->known);
499
500
501
502
503 return GNUNET_OK;
504}
505
506
507/**
508 * Callback called if there was an exception during execution of the helper.
509 *
510 */
511static void
512exp_cb (void *cls)
513{
514 struct TestingSystemCount *tbc = cls;
515
516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
517 GNUNET_TESTING_async_fail (&(tbc->ns->ac));
518}
519
520
521/**
522 * Function to initialize a init message for the helper.
523 *
524 * @param plugin_name Name of the test case plugin the helper will load.
525 *
526 */
527static struct GNUNET_CMDS_HelperInit *
528create_helper_init_msg_ (const char *plugin_name)
529{
530 struct GNUNET_CMDS_HelperInit *msg;
531 uint16_t plugin_name_len;
532 uint16_t msg_size;
533
534 GNUNET_assert (NULL != plugin_name);
535 plugin_name_len = strlen (plugin_name);
536 msg_size = sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_len;
537 msg = GNUNET_malloc (msg_size);
538 msg->header.size = htons (msg_size);
539 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT);
540 msg->plugin_name_size = htons (plugin_name_len);
541 GNUNET_memcpy ((char *) &msg[1],
542 plugin_name,
543 plugin_name_len);
544 return msg;
545}
546
547
548/**
549 * Function which start a single helper process.
550 *
551 */
552static void
553start_helper (struct NetJailState *ns,
554 unsigned int m,
555 unsigned int n)
556{
557 struct GNUNET_HELPER_Handle *helper;
558 struct GNUNET_CMDS_HelperInit *msg;
559 struct TestingSystemCount *tbc;
560 char *m_char;
561 char *n_char;
562 char *global_n_char;
563 char *local_m_char;
564 char *known_char;
565 char *node_id;
566 char *plugin;
567 char *read_file;
568 pid_t pid;
569 unsigned int script_num;
570 struct GNUNET_ShortHashCode *hkey;
571 struct GNUNET_HashCode hc;
572 struct GNUNET_TESTING_NetjailTopology *topology = ns->topology;
573 struct GNUNET_TESTING_NetjailNode *node;
574 struct GNUNET_TESTING_NetjailNamespace *namespace;
575 char *data_dir;
576 char *script_name;
577
578
579 if (0 == n)
580 script_num = m - 1;
581 else
582 script_num = n - 1 + (n - 1) * ns->local_m + m + ns->known;
583 pid = getpid ();
584
585 GNUNET_asprintf (&m_char, "%u", m);
586 GNUNET_asprintf (&n_char, "%u", n);
587 GNUNET_asprintf (&local_m_char, "%u", ns->local_m);
588 GNUNET_asprintf (&global_n_char, "%u",ns->global_n);
589 GNUNET_asprintf (&known_char, "%u",ns->known);
590 GNUNET_asprintf (&node_id, "%06x-%08x\n",
591 pid,
592 script_num);
593 // GNUNET_asprintf (&topology_data, "'%s'", ns->topology_data);
594 GNUNET_asprintf (&read_file, "%u", *(ns->read_file));
595
596 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
597 GNUNET_asprintf (&script_name, "%s%s", data_dir, NETJAIL_EXEC_SCRIPT);
598 unsigned int helper_check = GNUNET_OS_check_helper_binary (
599 script_name,
600 GNUNET_YES,
601 NULL);
602
603 tbc = GNUNET_new (struct TestingSystemCount);
604 tbc->ns = ns;
605
606 if (GNUNET_NO == helper_check)
607 {
608 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
609 "No SUID for %s!\n",
610 script_name);
611 GNUNET_TESTING_interpreter_fail (ns->is);
612 }
613 else if (GNUNET_NO == helper_check)
614 {
615 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
616 "%s not found!\n",
617 script_name);
618 GNUNET_TESTING_interpreter_fail (ns->is);
619 }
620
621 LOG (GNUNET_ERROR_TYPE_DEBUG,
622 "sysstarted %u peersstarted %u prep %u finished %u %u %u %u\n",
623 ns->number_of_testsystems_started,
624 ns->number_of_peers_started,
625 ns->number_of_local_tests_prepared,
626 ns->number_of_local_tests_finished,
627 ns->local_m,
628 ns->global_n,
629 ns->known);
630 {
631 char *const script_argv[] = {script_name,
632 m_char,
633 n_char,
634 GNUNET_OS_get_libexec_binary_path (
635 HELPER_CMDS_BINARY),
636 global_n_char,
637 local_m_char,
638 node_id,
639 read_file,
640 ns->topology_data,
641 NULL};
642 helper = GNUNET_HELPER_start (
643 GNUNET_YES,
644 script_name,
645 script_argv,
646 &helper_mst,
647 &exp_cb,
648 ns);
649 GNUNET_array_append (ns->helper, ns->n_helper, helper);
650 }
651
652 tbc->count = ns->n_helper;
653 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
654
655 plugin = topology->plugin;
656
657 if (0 == m)
658 {
659
660 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
661 memcpy (hkey,
662 &hc,
663 sizeof (*hkey));
664 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_globals,
665 hkey))
666 {
667 node = GNUNET_CONTAINER_multishortmap_get (topology->map_globals,
668 hkey);
669 if (NULL != node->plugin)
670 plugin = node->plugin;
671 }
672
673 }
674 else
675 {
676 GNUNET_CRYPTO_hash (&m, sizeof(m), &hc);
677 memcpy (hkey,
678 &hc,
679 sizeof (*hkey));
680 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_namespaces,
681 hkey))
682 {
683 namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces,
684 hkey);
685 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
686 memcpy (hkey,
687 &hc,
688 sizeof (*hkey));
689 if (1 == GNUNET_CONTAINER_multishortmap_contains (namespace->nodes,
690 hkey))
691 {
692 node = GNUNET_CONTAINER_multishortmap_get (namespace->nodes,
693 hkey);
694 if (NULL != node->plugin)
695 plugin = node->plugin;
696 }
697 }
698
699
700 }
701
702 msg = create_helper_init_msg_ (plugin);
703
704 // GNUNET_array_append (tbc->shandle, tbc->n_shandle,
705 tbc->shandle = GNUNET_HELPER_send (
706 helper,
707 &msg->header,
708 GNUNET_NO,
709 &clear_msg,
710 tbc); // );
711
712 if (NULL == tbc->shandle)// [tbc->count - 1])
713 {
714 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
715 "Send handle is NULL!\n");
716 GNUNET_free (msg);
717 GNUNET_TESTING_interpreter_fail (ns->is);
718 }
719 GNUNET_free (hkey);
720}
721
722
723/**
724* This function starts a helper process for each node.
725*
726* @param cls closure.
727* @param cmd CMD being run.
728* @param is interpreter state.
729*/
730static void
731netjail_exec_run (void *cls,
732 struct GNUNET_TESTING_Interpreter *is)
733{
734 struct NetJailState *ns = cls;
735
736 ns->is = is;
737 for (int i = 1; i <= ns->known; i++)
738 {
739 start_helper (ns,
740 i,
741 0);
742 }
743
744 for (int i = 1; i <= ns->global_n; i++)
745 {
746 for (int j = 1; j <= ns->local_m; j++)
747 {
748 start_helper (ns,
749 j,
750 i);
751 }
752 }
753}
754
755
756/**
757 * Create command.
758 *
759 * @param label Name for the command.
760 * @param topology The complete topology information.
761 * @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.
762 * @param topology_data If read_file is GNUNET_NO, topology_data holds the string with the topology.
763 * @return command.
764 */
765struct GNUNET_TESTING_Command
766GNUNET_TESTING_cmd_netjail_start_testing_system (
767 const char *label,
768 struct GNUNET_TESTING_NetjailTopology *topology,
769 unsigned int *read_file,
770 char *topology_data)
771{
772 struct NetJailState *ns;
773
774 ns = GNUNET_new (struct NetJailState);
775 ns->local_m = topology->nodes_m;
776 ns->global_n = topology->namespaces_n;
777 ns->known = topology->nodes_x;
778 ns->plugin_name = topology->plugin;
779 ns->topology = topology;
780 ns->read_file = read_file;
781 ns->topology_data = topology_data;
782
783 struct GNUNET_TESTING_Command cmd = {
784 .cls = ns,
785 .label = label,
786 .run = &netjail_exec_run,
787 .ac = &ns->ac,
788 .cleanup = &netjail_exec_cleanup,
789 .traits = &netjail_exec_traits
790 };
791
792 return cmd;
793}
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 4b52878c4..000000000
--- a/src/testing/testing_api_cmd_netjail_stop_testsystem.c
+++ /dev/null
@@ -1,153 +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 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 (helper[i - 1],
104 GNUNET_YES);
105 }
106
107 for (int i = 1; i <= shs->global_n; i++)
108 {
109 for (int j = 1; j <= shs->local_m; j++)
110 {
111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
112 "i: %u j: %u\n",
113 i,
114 j);
115 GNUNET_HELPER_stop (helper[(i - 1) * shs->local_m + j + shs->known - 1],
116 GNUNET_YES);
117 }
118 }
119}
120
121
122/**
123 * Create command.
124 *
125 * @param label name for command.
126 * @param helper_start_label label of the cmd to start the test system.
127 * @param topology The complete topology information.
128 * @return command.
129 */
130struct GNUNET_TESTING_Command
131GNUNET_TESTING_cmd_stop_testing_system (
132 const char *label,
133 const char *helper_start_label,
134 struct GNUNET_TESTING_NetjailTopology *topology)
135{
136 struct StopHelperState *shs;
137
138 shs = GNUNET_new (struct StopHelperState);
139 shs->helper_start_label = helper_start_label;
140 shs->local_m = topology->nodes_m;
141 shs->global_n = topology->namespaces_n;
142 shs->known = topology->nodes_x;
143 shs->topology = topology;
144
145 struct GNUNET_TESTING_Command cmd = {
146 .cls = shs,
147 .label = label,
148 .run = &stop_testing_system_run,
149 .cleanup = &stop_testing_system_cleanup,
150 };
151
152 return cmd;
153}
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 275132684..000000000
--- a/src/testing/testing_api_cmd_system_create.c
+++ /dev/null
@@ -1,151 +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 {
81 .index = 0,
82 .trait_name = "test_system",
83 .ptr = (const void *) test_system,
84 },
85 GNUNET_TESTING_trait_end ()
86 };
87
88 return GNUNET_TESTING_get_trait (traits,
89 ret,
90 trait,
91 index);
92}
93
94
95/**
96 * Function to get the trait with struct GNUNET_TESTING_System
97 *
98 * @param[out] test_system The struct GNUNET_TESTING_System.
99 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
100 */
101int
102GNUNET_TESTING_get_trait_test_system (const struct
103 GNUNET_TESTING_Command *cmd,
104 struct GNUNET_TESTING_System **test_system)
105{
106 return cmd->traits (cmd->cls,
107 (const void **) test_system,
108 "test_system",
109 (unsigned int) 0);
110}
111
112
113/**
114 * The cleanup function of this cmd frees resources the cmd allocated.
115 *
116 */
117static void
118system_create_cleanup (void *cls)
119{
120 struct TestSystemState *tss = cls;
121
122 GNUNET_free (tss);
123}
124
125
126/**
127 * Create command.
128 *
129 * @param label name for command.
130 * @param label name for the test environment directory.
131 * @return command.
132 */
133struct GNUNET_TESTING_Command
134GNUNET_TESTING_cmd_system_create (const char *label,
135 const char *testdir)
136{
137 struct TestSystemState *tss;
138
139 tss = GNUNET_new (struct TestSystemState);
140 tss->testdir = testdir;
141
142 struct GNUNET_TESTING_Command cmd = {
143 .cls = tss,
144 .label = label,
145 .run = &system_create_run,
146 .cleanup = &system_create_cleanup,
147 .traits = &system_create_traits
148 };
149
150 return cmd;
151}
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 cdfc65d53..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 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 (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 290311c59..000000000
--- a/src/testing/testing_api_loop.c
+++ /dev/null
@@ -1,606 +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#define BATCH_INDEX 1
126 struct GNUNET_TESTING_Command *batch;
127 struct GNUNET_TESTING_Command *current;
128 struct GNUNET_TESTING_Command *icmd;
129 const struct GNUNET_TESTING_Command *match;
130
131 current = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
132 GNUNET_assert (GNUNET_OK ==
133 GNUNET_TESTING_get_trait_cmd (cmd,
134 BATCH_INDEX,
135 &batch));
136 /* We must do the loop forward, but we can find the last match */
137 match = NULL;
138 for (unsigned int j = 0;
139 NULL != (icmd = &batch[j])->label;
140 j++)
141 {
142 if (current == icmd)
143 break; /* do not go past current command */
144 if ( (NULL != icmd->label) &&
145 (0 == strcmp (icmd->label,
146 label)) )
147 match = icmd;
148 }
149 if (NULL != match)
150 return match;
151 }
152 }
153 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
154 "Command `%s' not found\n",
155 label);
156 return NULL;
157}
158
159
160/**
161 * Lookup command by label.
162 * Only future commands are looked up.
163 *
164 * @param is interpreter to lookup command in
165 * @param label label of the command to lookup.
166 * @return the command, if it is found, or NULL.
167 */
168const struct GNUNET_TESTING_Command *
169GNUNET_TESTING_interpreter_lookup_future_command (
170 struct GNUNET_TESTING_Interpreter *is,
171 const char *label)
172{
173 return get_command (is, label, GNUNET_YES);
174}
175
176
177/**
178 * Lookup command by label.
179 * Only commands from current command to commands in the past are looked up.
180 *
181 * @param is interpreter to lookup command in
182 * @param label label of the command to lookup.
183 * @return the command, if it is found, or NULL.
184 */
185const struct GNUNET_TESTING_Command *
186GNUNET_TESTING_interpreter_lookup_command (
187 struct GNUNET_TESTING_Interpreter *is,
188 const char *label)
189{
190 return get_command (is, label, GNUNET_NO);
191}
192
193
194/**
195 * Lookup command by label.
196 * All commands, first into the past, then into the furture are looked up.
197 *
198 * @param is interpreter to lookup command in
199 * @param label label of the command to lookup.
200 * @return the command, if it is found, or NULL.
201 */
202const struct GNUNET_TESTING_Command *
203GNUNET_TESTING_interpreter_lookup_command_all (
204 struct GNUNET_TESTING_Interpreter *is,
205 const char *label)
206{
207 const struct GNUNET_TESTING_Command *cmd;
208
209 cmd = get_command (is, label, GNUNET_NO);
210 if (NULL == cmd)
211 cmd = get_command (is, label, GNUNET_YES);
212 return cmd;
213}
214
215
216/**
217 * Finish the test run, return the final result.
218 *
219 * @param cls the `struct GNUNET_TESTING_Interpreter`
220 */
221static void
222finish_test (void *cls)
223{
224 struct GNUNET_TESTING_Interpreter *is = cls;
225 struct GNUNET_TESTING_Command *cmd;
226 const char *label;
227
228 is->final_task = NULL;
229 label = is->commands[is->ip].label;
230 if (NULL == label)
231 label = "END";
232 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
233 "Interpreter finishes at `%s' with status %d\n",
234 label,
235 is->result);
236 for (unsigned int j = 0;
237 NULL != (cmd = &is->commands[j])->label;
238 j++)
239 {
240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
241 "Cleaning up cmd %s\n",
242 cmd->label);
243 cmd->cleanup (cmd->cls);
244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
245 "Cleaned up cmd %s\n",
246 cmd->label);
247 }
248 if (NULL != is->task)
249 {
250 GNUNET_SCHEDULER_cancel (is->task);
251 is->task = NULL;
252 }
253 if (NULL != is->timeout_task)
254 {
255 GNUNET_SCHEDULER_cancel (is->timeout_task);
256 is->timeout_task = NULL;
257 }
258 GNUNET_free (is->commands);
259 is->rc (is->rc_cls,
260 is->result);
261 GNUNET_free (is);
262}
263
264
265/**
266 * Run the main interpreter loop that performs exchange operations.
267 *
268 * @param cls contains the `struct InterpreterState`
269 */
270static void
271interpreter_run (void *cls);
272
273
274/**
275 * Current command is done, run the next one.
276 */
277static void
278interpreter_next (void *cls)
279{
280 struct GNUNET_TESTING_Interpreter *is = cls;
281 static unsigned long long ipc;
282 static struct GNUNET_TIME_Absolute last_report;
283 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
284
285 if (GNUNET_SYSERR == is->result)
286 return; /* ignore, we already failed! */
287 cmd->finish_time = GNUNET_TIME_absolute_get ();
288 if ( (! GNUNET_TESTING_cmd_is_batch_ (cmd)) ||
289 (! GNUNET_TESTING_cmd_batch_next_ (cmd->cls)) )
290 is->ip++;
291 if (0 == (ipc % 1000))
292 {
293 if (0 != ipc)
294 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
295 "Interpreter executed 1000 instructions in %s\n",
296 GNUNET_STRINGS_relative_time_to_string (
297 GNUNET_TIME_absolute_get_duration (last_report),
298 GNUNET_YES));
299 last_report = GNUNET_TIME_absolute_get ();
300 }
301 ipc++;
302 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
303 is);
304}
305
306
307void
308GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is)
309{
310 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
311
312 if (GNUNET_SYSERR == is->result)
313 {
314 GNUNET_break (0);
315 return; /* ignore, we already failed! */
316 }
317 if (NULL != cmd)
318 {
319 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
320 "Failed at command `%s'\n",
321 cmd->label);
322 while (GNUNET_TESTING_cmd_is_batch_ (cmd))
323 {
324 cmd = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
325 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
326 "Failed in batch at command `%s'\n",
327 cmd->label);
328 }
329 }
330 else
331 {
332 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
333 "Failed with CMD being NULL!\n");
334 }
335 is->result = GNUNET_SYSERR;
336 GNUNET_assert (NULL == is->final_task);
337 is->final_task = GNUNET_SCHEDULER_add_now (&finish_test,
338 is);
339}
340
341
342/**
343 * Returns the actual running command.
344 *
345 * @param is Global state of the interpreter, used by a command
346 * to access information about other commands.
347 * @return The actual running command.
348 */
349struct GNUNET_TESTING_Command *
350GNUNET_TESTING_interpreter_get_current_command (
351 struct GNUNET_TESTING_Interpreter *is)
352{
353 return &is->commands[is->ip];
354}
355
356const char *
357GNUNET_TESTING_interpreter_get_current_label (
358 struct GNUNET_TESTING_Interpreter *is)
359{
360 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
361
362 return cmd->label;
363}
364
365
366/**
367 * Run the main interpreter loop.
368 *
369 * @param cls contains the `struct GNUNET_TESTING_Interpreter`
370 */
371static void
372interpreter_run (void *cls)
373{
374 struct GNUNET_TESTING_Interpreter *is = cls;
375 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
376
377 is->task = NULL;
378 if (NULL == cmd->label)
379 {
380 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
381 "Running command END\n");
382 is->result = GNUNET_OK;
383 finish_test (is);
384 return;
385 }
386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
387 "Running command `%s'\n",
388 cmd->label);
389 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
390 "start time of %p expected 0 is `%lu'\n",
391 cmd,
392 cmd->start_time.abs_value_us);
393 cmd->start_time
394 = cmd->last_req_time
395 = GNUNET_TIME_absolute_get ();
396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
397 "start time of %p expected something is `%lu'\n",
398 cmd,
399 cmd->start_time.abs_value_us);
400 cmd->num_tries = 1;
401 if (NULL != cmd->ac)
402 {
403 cmd->ac->is = is;
404 cmd->ac->cont = &interpreter_next;
405 cmd->ac->cont_cls = is;
406 cmd->ac->finished = GNUNET_NO;
407 }
408 cmd->run (cmd->cls,
409 is);
410 if (NULL == cmd->ac)
411 {
412 interpreter_next (is);
413 }
414 else if ( (cmd->asynchronous_finish) &&
415 (NULL != cmd->ac->cont) )
416 {
417 cmd->ac->cont = NULL;
418 interpreter_next (is);
419 }
420}
421
422
423/**
424 * Function run when the test terminates (good or bad) with timeout.
425 *
426 * @param cls the interpreter state
427 */
428static void
429do_timeout (void *cls)
430{
431 struct GNUNET_TESTING_Interpreter *is = cls;
432
433 is->timeout_task = NULL;
434 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
435 "Terminating test due to global timeout\n");
436 is->result = GNUNET_SYSERR;
437 finish_test (is);
438}
439
440
441/**
442 * Check if the command is running.
443 *
444 * @param cmd The command to check.
445 * @return GNUNET_NO if the command is not running, GNUNET_YES if it is running.
446 */
447enum GNUNET_GenericReturnValue
448GNUNET_TESTING_running (const struct GNUNET_TESTING_Command *command)
449{
450 return 0 != command->start_time.abs_value_us && 0 ==
451 command->finish_time.abs_value_us;
452}
453
454
455/**
456 * Check if a command is finished.
457 *
458 * @param cmd The command to check.
459 * @return GNUNET_NO if the command is not finished, GNUNET_YES if it is finished.
460 */
461enum GNUNET_GenericReturnValue
462GNUNET_TESTING_finished (struct GNUNET_TESTING_Command *command)
463{
464 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
465 struct GNUNET_TIME_Relative diff = GNUNET_TIME_absolute_get_difference (
466 command->finish_time,
467 now);
468 return 0 < diff.rel_value_us;
469}
470
471
472void
473GNUNET_TESTING_run (struct GNUNET_TESTING_Command *commands,
474 struct GNUNET_TIME_Relative timeout,
475 GNUNET_TESTING_ResultCallback rc,
476 void *rc_cls)
477{
478 struct GNUNET_TESTING_Interpreter *is;
479 unsigned int i;
480
481 is = GNUNET_new (struct GNUNET_TESTING_Interpreter);
482 is->rc = rc;
483 is->rc_cls = rc_cls;
484 /* get the number of commands */
485 for (i = 0; NULL != commands[i].label; i++)
486 ;
487 is->cmds_n = i + 1;
488 is->commands = GNUNET_new_array (is->cmds_n,
489 struct GNUNET_TESTING_Command);
490 memcpy (is->commands,
491 commands,
492 sizeof (struct GNUNET_TESTING_Command) * i);
493 is->timeout_task
494 = GNUNET_SCHEDULER_add_delayed (timeout,
495 &do_timeout,
496 is);
497 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
498 is);
499}
500
501
502/**
503 * Closure for #loop_run().
504 */
505struct MainParams
506{
507
508 /**
509 * NULL-label terminated array of commands.
510 */
511 struct GNUNET_TESTING_Command *commands;
512
513 /**
514 * Global timeout for the test.
515 */
516 struct GNUNET_TIME_Relative timeout;
517
518 /**
519 * Set to #EXIT_FAILURE on error.
520 */
521 int rv;
522};
523
524
525/**
526 * Function called with the final result of the test.
527 *
528 * @param cls the `struct MainParams`
529 * @param rv #GNUNET_OK if the test passed
530 */
531static void
532handle_result (void *cls,
533 enum GNUNET_GenericReturnValue rv)
534{
535 struct MainParams *mp = cls;
536
537 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
538 "Test exits with status %d\n",
539 rv);
540 if (GNUNET_OK != rv)
541 mp->rv = EXIT_FAILURE;
542 GNUNET_SCHEDULER_shutdown ();
543}
544
545
546/**
547 * Main function to run the test cases.
548 *
549 * @param cls a `struct MainParams *`
550 */
551static void
552loop_run (void *cls)
553{
554 struct MainParams *mp = cls;
555
556 GNUNET_TESTING_run (mp->commands,
557 mp->timeout,
558 &handle_result,
559 mp);
560}
561
562
563int
564GNUNET_TESTING_main (struct GNUNET_TESTING_Command *commands,
565 struct GNUNET_TIME_Relative timeout)
566{
567 struct MainParams mp = {
568 .commands = commands,
569 .timeout = timeout,
570 .rv = EXIT_SUCCESS
571 };
572
573 GNUNET_SCHEDULER_run (&loop_run,
574 &mp);
575 return mp.rv;
576}
577
578
579void
580GNUNET_TESTING_async_fail (struct GNUNET_TESTING_AsyncContext *ac)
581{
582 GNUNET_assert (GNUNET_NO == ac->finished);
583 ac->finished = GNUNET_SYSERR;
584 GNUNET_TESTING_interpreter_fail (ac->is);
585 if (NULL != ac->cont)
586 {
587 ac->cont (ac->cont_cls);
588 ac->cont = NULL;
589 }
590}
591
592
593void
594GNUNET_TESTING_async_finish (struct GNUNET_TESTING_AsyncContext *ac)
595{
596 GNUNET_assert (GNUNET_NO == ac->finished);
597 ac->finished = GNUNET_OK;
598 if (NULL != ac->cont)
599 {
600 ac->cont (ac->cont_cls);
601 ac->cont = NULL;
602 }
603}
604
605
606/* end of testing_api_loop.c */
diff --git a/src/testing/testing_api_trait_cmd.c b/src/testing/testing_api_trait_cmd.c
deleted file mode 100644
index 7afa8b264..000000000
--- a/src/testing/testing_api_trait_cmd.c
+++ /dev/null
@@ -1,79 +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_trait_cmd.c
23 * @brief offers CMDs as traits.
24 * @author Marcello Stanisci (GNU Taler testing)
25 * @author t3sserakt
26 */
27#include "platform.h"
28#include "gnunet_testing_ng_lib.h"
29
30#define GNUNET_TESTING_TRAIT_CMD "cmd"
31
32
33/**
34 * Obtain a command from @a cmd.
35 *
36 * @param cmd command to extract the command from.
37 * @param index always zero. Commands offering this
38 * kind of traits do not need this index. For
39 * example, a "batch" CMD returns always the
40 * CMD currently being executed.
41 * @param[out] _cmd where to write the wire details.
42 * @return #GNUNET_OK on success.
43 */
44enum GNUNET_GenericReturnValue
45GNUNET_TESTING_get_trait_cmd (const struct GNUNET_TESTING_Command *cmd,
46 unsigned int index,
47 struct GNUNET_TESTING_Command **_cmd)
48{
49 return cmd->traits (cmd->cls,
50 (const void **) _cmd,
51 GNUNET_TESTING_TRAIT_CMD,
52 index);
53}
54
55
56/**
57 * Offer a command in a trait.
58 *
59 * @param index always zero. Commands offering this
60 * kind of traits do not need this index. For
61 * example, a "meta" CMD returns always the
62 * CMD currently being executed.
63 * @param cmd wire details to offer.
64 * @return the trait.
65 */
66struct GNUNET_TESTING_Trait
67GNUNET_TESTING_make_trait_cmd (unsigned int index,
68 const struct GNUNET_TESTING_Command *cmd)
69{
70 struct GNUNET_TESTING_Trait ret = {
71 .index = index,
72 .trait_name = GNUNET_TESTING_TRAIT_CMD,
73 .ptr = (const struct GNUNET_TESTING_Command *) cmd
74 };
75 return ret;
76}
77
78
79/* end of testing_api_trait_cmd.c */
diff --git a/src/testing/testing_api_trait_process.c b/src/testing/testing_api_trait_process.c
deleted file mode 100644
index 31cdb01df..000000000
--- a/src/testing/testing_api_trait_process.c
+++ /dev/null
@@ -1,81 +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_trait_process.c
23 * @brief trait offering process handles.
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
31#define GNUNET_TESTING_TRAIT_PROCESS "process"
32
33
34/**
35 * Obtain location where a command stores a pointer to a process.
36 *
37 * @param cmd command to extract trait from.
38 * @param index which process to pick if @a cmd
39 * has multiple on offer.
40 * @param[out] processp set to the address of the pointer to the
41 * process.
42 * @return #GNUNET_OK on success.
43 */
44int
45GNUNET_TESTING_get_trait_process
46 (const struct GNUNET_TESTING_Command *cmd,
47 unsigned int index,
48 struct GNUNET_OS_Process ***processp)
49{
50 return cmd->traits (cmd->cls,
51 (const void **) processp,
52 GNUNET_TESTING_TRAIT_PROCESS,
53 index);
54}
55
56
57/**
58 * Offer location where a command stores a pointer to a process.
59 *
60 * @param index offered location index number, in case there are
61 * multiple on offer.
62 * @param processp process location to offer.
63 *
64 * @return the trait.
65 */
66struct GNUNET_TESTING_Trait
67GNUNET_TESTING_make_trait_process
68 (unsigned int index,
69 struct GNUNET_OS_Process **processp)
70{
71 struct GNUNET_TESTING_Trait ret = {
72 .index = index,
73 .trait_name = GNUNET_TESTING_TRAIT_PROCESS,
74 .ptr = (const void *) processp
75 };
76
77 return ret;
78}
79
80
81/* end of testing_api_trait_process.c */
diff --git a/src/testing/testing_api_traits.c b/src/testing/testing_api_traits.c
deleted file mode 100644
index 2f836ddfa..000000000
--- a/src/testing/testing_api_traits.c
+++ /dev/null
@@ -1,81 +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
31
32/**
33 * End a trait array. Usually, commands offer several traits,
34 * and put them in arrays.
35 */
36struct GNUNET_TESTING_Trait
37GNUNET_TESTING_trait_end ()
38{
39 struct GNUNET_TESTING_Trait end = {
40 .index = 0,
41 .trait_name = NULL,
42 .ptr = NULL
43 };
44
45 return end;
46}
47
48
49/**
50 * Pick the chosen trait from the traits array.
51 *
52 * @param traits the traits array.
53 * @param ret where to store the result.
54 * @param trait type of the trait to extract.
55 * @param index index number of the object to extract.
56 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
57 */
58enum GNUNET_GenericReturnValue
59GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits,
60 const void **ret,
61 const char *trait,
62 unsigned int index)
63{
64 for (unsigned int i = 0; NULL != traits[i].trait_name; i++)
65 {
66 if ( (0 == strcmp (trait, traits[i].trait_name)) &&
67 (index == traits[i].index) )
68 {
69 *ret = (void *) traits[i].ptr;
70 return GNUNET_OK;
71 }
72 }
73 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
74 "Trait %s/%u not found.\n",
75 trait, index);
76
77 return GNUNET_SYSERR;
78}
79
80
81/* 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