aboutsummaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing')
-rw-r--r--src/testing/Makefile.am19
-rwxr-xr-xsrc/testing/netjail_core.sh190
-rwxr-xr-xsrc/testing/netjail_core_v2.sh260
-rwxr-xr-xsrc/testing/netjail_exec.sh6
-rwxr-xr-xsrc/testing/netjail_exec_v2.sh14
-rwxr-xr-xsrc/testing/netjail_start.sh70
-rwxr-xr-xsrc/testing/netjail_start_v2.sh74
-rwxr-xr-xsrc/testing/netjail_stop.sh49
-rwxr-xr-xsrc/testing/netjail_stop_v2.sh59
-rw-r--r--src/testing/test_testing_plugin_testcmd.c19
-rw-r--r--src/testing/testing.c26
-rw-r--r--src/testing/testing.h94
-rw-r--r--src/testing/testing_api_cmd_batch.c86
-rw-r--r--src/testing/testing_api_cmd_block_until_all_peers_started.c66
-rw-r--r--src/testing/testing_api_cmd_block_until_external_trigger.c116
-rw-r--r--src/testing/testing_api_cmd_end.c39
-rw-r--r--src/testing/testing_api_cmd_finish.c198
-rw-r--r--src/testing/testing_api_cmd_hello_world.c65
-rw-r--r--src/testing/testing_api_cmd_hello_world_birth.c10
-rw-r--r--src/testing/testing_api_cmd_local_test_finished.c67
-rw-r--r--src/testing/testing_api_cmd_netjail_start.c148
-rw-r--r--src/testing/testing_api_cmd_netjail_start_testsystem.c319
-rw-r--r--src/testing/testing_api_cmd_netjail_start_testsystem_v2.c809
-rw-r--r--src/testing/testing_api_cmd_netjail_start_v2.c229
-rw-r--r--src/testing/testing_api_cmd_netjail_stop.c116
-rw-r--r--src/testing/testing_api_cmd_netjail_stop_testsystem.c58
-rw-r--r--src/testing/testing_api_cmd_netjail_stop_testsystem_v2.c163
-rw-r--r--src/testing/testing_api_cmd_netjail_stop_v2.c225
-rw-r--r--src/testing/testing_api_cmd_send_peer_ready.c29
-rw-r--r--src/testing/testing_api_cmd_system_create.c4
-rw-r--r--src/testing/testing_api_cmd_system_destroy.c33
-rw-r--r--src/testing/testing_api_loop.c629
-rw-r--r--src/testing/testing_api_trait_cmd.c2
-rw-r--r--src/testing/testing_api_traits.c2
-rw-r--r--src/testing/testing_cmds.h2
35 files changed, 1369 insertions, 2926 deletions
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 07caeb44e..3daa29e1e 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -42,20 +42,19 @@ libgnunet_test_testing_plugin_testcmd_la_LIBADD = \
42libgnunet_test_testing_plugin_testcmd_la_LDFLAGS = \ 42libgnunet_test_testing_plugin_testcmd_la_LDFLAGS = \
43 $(GN_PLUGIN_LDFLAGS) 43 $(GN_PLUGIN_LDFLAGS)
44 44
45
45libgnunettesting_la_SOURCES = \ 46libgnunettesting_la_SOURCES = \
47 testing_api_cmd_end.c \
48 testing_api_cmd_finish.c \
46 testing_api_cmd_local_test_finished.c \ 49 testing_api_cmd_local_test_finished.c \
47 testing_api_cmd_local_test_prepared.c \ 50 testing_api_cmd_local_test_prepared.c \
48 testing_api_cmd_send_peer_ready.c \ 51 testing_api_cmd_send_peer_ready.c \
49 testing_api_cmd_block_until_all_peers_started.c \ 52 testing_api_cmd_block_until_all_peers_started.c \
50 testing_api_cmd_block_until_external_trigger.c \ 53 testing_api_cmd_block_until_external_trigger.c \
51 testing_api_cmd_netjail_start.c \ 54 testing_api_cmd_netjail_start.c \
52 testing_api_cmd_netjail_start_v2.c \
53 testing_api_cmd_netjail_start_testsystem.c \ 55 testing_api_cmd_netjail_start_testsystem.c \
54 testing_api_cmd_netjail_start_testsystem_v2.c \
55 testing_api_cmd_netjail_stop_testsystem.c \ 56 testing_api_cmd_netjail_stop_testsystem.c \
56 testing_api_cmd_netjail_stop_testsystem_v2.c \
57 testing_api_cmd_netjail_stop.c \ 57 testing_api_cmd_netjail_stop.c \
58 testing_api_cmd_netjail_stop_v2.c \
59 testing.c testing.h \ 58 testing.c testing.h \
60 testing_api_cmd_system_create.c \ 59 testing_api_cmd_system_create.c \
61 testing_api_cmd_system_destroy.c \ 60 testing_api_cmd_system_destroy.c \
@@ -95,7 +94,6 @@ list_keys_LDADD = \
95 94
96 95
97check_PROGRAMS = \ 96check_PROGRAMS = \
98 test_testing_topology \
99 test_testing_api_cmd_netjail \ 97 test_testing_api_cmd_netjail \
100 test_testing_hello_world \ 98 test_testing_hello_world \
101 test_testing_portreservation \ 99 test_testing_portreservation \
@@ -107,7 +105,6 @@ check_PROGRAMS = \
107if ENABLE_TEST_RUN 105if ENABLE_TEST_RUN
108AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 106AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
109TESTS = \ 107TESTS = \
110 test_testing_topology \
111 test_testing_api_cmd_netjail \ 108 test_testing_api_cmd_netjail \
112 test_testing_hello_world \ 109 test_testing_hello_world \
113 test_testing_portreservation \ 110 test_testing_portreservation \
@@ -116,11 +113,11 @@ TESTS = \
116 test_testing_servicestartup 113 test_testing_servicestartup
117endif 114endif
118 115
119test_testing_topology_SOURCES = \ 116#test_testing_topology_SOURCES = \
120 test_testing_topology.c 117# test_testing_topology.c
121test_testing_topology_LDADD = \ 118#test_testing_topology_LDADD = \
122 libgnunettesting.la \ 119# libgnunettesting.la \
123 $(top_builddir)/src/util/libgnunetutil.la 120# $(top_builddir)/src/util/libgnunetutil.la
124 121
125test_testing_api_cmd_netjail_SOURCES = \ 122test_testing_api_cmd_netjail_SOURCES = \
126 test_testing_api_cmd_netjail.c 123 test_testing_api_cmd_netjail.c
diff --git a/src/testing/netjail_core.sh b/src/testing/netjail_core.sh
index cf350d3fa..ef0a54a5e 100755
--- a/src/testing/netjail_core.sh
+++ b/src/testing/netjail_core.sh
@@ -2,6 +2,7 @@
2# 2#
3 3
4 4
5PREFIX=${PPID:?must run from a parent process}
5 6
6# running with `sudo` is required to be 7# running with `sudo` is required to be
7# able running the actual commands as the 8# able running the actual commands as the
@@ -9,10 +10,61 @@
9 10
10export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 11export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
11 12
12netjail_check() { 13export RESULT=
13 NODE_COUNT=$1 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}
14 64
15 FD_COUNT=$(($(ls /proc/self/fd | wc -w) - 4)) 65netjail_check() {
66 local NODE_COUNT=$1
67 local FD_COUNT=$(($(ls /proc/self/fd | wc -w) - 4))
16 68
17 # quit if `$FD_COUNT < ($LOCAL_M * $GLOBAL_N * 2)`: 69 # quit if `$FD_COUNT < ($LOCAL_M * $GLOBAL_N * 2)`:
18 # the script also requires `sudo -C ($FD_COUNT + 4)` 70 # the script also requires `sudo -C ($FD_COUNT + 4)`
@@ -25,43 +77,81 @@ netjail_check() {
25 fi 77 fi
26} 78}
27 79
28netjail_print_name() { 80netjail_check_bin() {
29 printf "%s%02x%02x" $1 $2 ${3:-0} 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
30} 91}
31 92
32netjail_bridge() { 93netjail_bridge() {
33 BRIDGE=$1 94 netjail_next_interface
95 local NUM=$RESULT
96 local BRIDGE=$(printf "%06x-%08x" $PREFIX $NUM)
34 97
35 ip link add $BRIDGE type bridge 98 ip link add $BRIDGE type bridge
36 ip link set dev $BRIDGE up 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
37} 110}
38 111
39netjail_bridge_clear() { 112netjail_bridge_clear() {
40 BRIDGE=$1 113 local BRIDGE=$1
41 114
42 ip link delete $BRIDGE 115 ip link delete $BRIDGE
43} 116}
44 117
45netjail_node() { 118netjail_node() {
46 NODE=$1 119 netjail_next_namespace
120 local NUM=$RESULT
121 local NODE=$(printf "%06x-%08x" $PREFIX $NUM)
47 122
48 ip netns add $NODE 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
49} 134}
50 135
51netjail_node_clear() { 136netjail_node_clear() {
52 NODE=$1 137 local NODE=$1
53 138
54 ip netns delete $NODE 139 ip netns delete $NODE
55} 140}
56 141
57netjail_node_link_bridge() { 142netjail_node_link_bridge() {
58 NODE=$1 143 local NODE=$1
59 BRIDGE=$2 144 local BRIDGE=$2
60 ADDRESS=$3 145 local ADDRESS=$3
61 MASK=$4 146 local MASK=$4
62 147
63 LINK_IF="$NODE-$BRIDGE-0" 148 netjail_next_interface
64 LINK_BR="$NODE-$BRIDGE-1" 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)
65 155
66 ip link add $LINK_IF type veth peer name $LINK_BR 156 ip link add $LINK_IF type veth peer name $LINK_BR
67 ip link set $LINK_IF netns $NODE 157 ip link set $LINK_IF netns $NODE
@@ -72,28 +162,47 @@ netjail_node_link_bridge() {
72 ip -n $NODE link set up dev lo 162 ip -n $NODE link set up dev lo
73 163
74 ip link set $LINK_BR up 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
75} 184}
76 185
77netjail_node_add_nat() { 186netjail_node_add_nat() {
78 NODE=$1 187 local NODE=$1
79 ADDRESS=$2 188 local ADDRESS=$2
80 MASK=$3 189 local MASK=$3
81 190
82 ip netns exec $NODE iptables -t nat -A POSTROUTING -s "$ADDRESS/$MASK" -j MASQUERADE 191 ip netns exec $NODE iptables -t nat -A POSTROUTING -s "$ADDRESS/$MASK" -j MASQUERADE
83} 192}
84 193
85netjail_node_add_default() { 194netjail_node_add_default() {
86 NODE=$1 195 local NODE=$1
87 ADDRESS=$2 196 local ADDRESS=$2
88 197
89 ip -n $NODE route add default via $ADDRESS 198 ip -n $NODE route add default via $ADDRESS
90} 199}
91 200
92netjail_node_exec() { 201netjail_node_exec() {
93 JAILOR=${SUDO_USER:?must run in sudo} 202 JAILOR=${SUDO_USER:?must run in sudo}
94 NODE=$1 203 local NODE=$1
95 FD_IN=$2 204 local FD_IN=$2
96 FD_OUT=$3 205 local FD_OUT=$3
97 shift 3 206 shift 3
98 207
99 ip netns exec $NODE sudo -u $JAILOR -- $@ 1>& $FD_OUT 0<& $FD_IN 208 ip netns exec $NODE sudo -u $JAILOR -- $@ 1>& $FD_OUT 0<& $FD_IN
@@ -114,3 +223,38 @@ netjail_node_exec_without_fds_and_sudo() {
114 ip netns exec $NODE $@ 223 ip netns exec $NODE $@
115} 224}
116 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_core_v2.sh b/src/testing/netjail_core_v2.sh
deleted file mode 100755
index ef0a54a5e..000000000
--- a/src/testing/netjail_core_v2.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
index 17a7caaac..cd993a39b 100755
--- a/src/testing/netjail_exec.sh
+++ b/src/testing/netjail_exec.sh
@@ -9,8 +9,6 @@ export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
9M=$1 9M=$1
10N=$2 10N=$2
11 11
12NODE=$(netjail_print_name "N" $N $M) 12NODE=$6
13 13
14 14netjail_node_exec_without_fds_and_sudo $NODE $3 $4 $5 $1 $2
15
16netjail_node_exec_without_fds_and_sudo $NODE $3 $4 $5 $1 $2
diff --git a/src/testing/netjail_exec_v2.sh b/src/testing/netjail_exec_v2.sh
deleted file mode 100755
index 597baad20..000000000
--- a/src/testing/netjail_exec_v2.sh
+++ /dev/null
@@ -1,14 +0,0 @@
1#!/bin/sh
2. "./../testing/netjail_core_v2.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
index 0984a3c42..1dfe1dfdf 100755
--- a/src/testing/netjail_start.sh
+++ b/src/testing/netjail_start.sh
@@ -1,52 +1,74 @@
1#!/bin/sh 1#!/bin/bash
2. "./../testing/netjail_core.sh" 2. "./../testing/netjail_core.sh"
3. "./../testing/topo.sh"
3 4
4set -eu 5set -eu
5set -x 6set -x
6 7
7export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 8export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
8 9
9LOCAL_M=$1 10filename=$1
10GLOBAL_N=$2 11PREFIX=$2
11 12
12# TODO: stunserver? ..and globally known peer? 13read_topology $filename
13 14
14shift 2 15shift 2
15 16
16LOCAL_GROUP="192.168.15" 17LOCAL_GROUP="192.168.15"
17GLOBAL_GROUP="92.68.150" 18GLOBAL_GROUP="92.68.150"
19KNOWN_GROUP="92.68.151"
18 20
19NETWORK_NET=$(netjail_print_name "n" $GLOBAL_N $LOCAL_M)
20 21
21netjail_bridge $NETWORK_NET 22echo "Start [local: $LOCAL_GROUP.0/24, global: $GLOBAL_GROUP.0/16]"
22 23
23for N in $(seq $GLOBAL_N); do 24netjail_bridge
24 ROUTER=$(netjail_print_name "R" $N) 25NETWORK_NET=$RESULT
25 26
26 netjail_node $ROUTER 27for X in $(seq $KNOWN); do
27 netjail_node_link_bridge $ROUTER $NETWORK_NET "$GLOBAL_GROUP.$N" 24 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
28 33
29 ROUTER_NET=$(netjail_print_name "r" $N) 34declare -A NODES
35declare -A NODE_LINKS
30 36
31 netjail_bridge $ROUTER_NET 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
32 44
33 for M in $(seq $LOCAL_M); do 45 for M in $(seq $LOCAL_M); do
34 NODE=$(netjail_print_name "N" $N $M) 46 netjail_node
35 47 NODES[$N,$M]=$RESULT
36 netjail_node $NODE 48 netjail_node_link_bridge ${NODES[$N,$M]} ${ROUTER_NETS[$N]} "$LOCAL_GROUP.$M" 24
37 netjail_node_link_bridge $NODE $ROUTER_NET "$LOCAL_GROUP.$M" 24 49 NODE_LINKS[$N,$M]=$RESULT
38 done 50 done
39 51
40 ROUTER_ADDR="$LOCAL_GROUP.$(($LOCAL_M+1))" 52 ROUTER_ADDR="$LOCAL_GROUP.$(($LOCAL_M+1))"
41 53 netjail_node_link_bridge ${ROUTERS[$N]} ${ROUTER_NETS[$N]} $ROUTER_ADDR 24
42 netjail_node_link_bridge $ROUTER $ROUTER_NET $ROUTER_ADDR 24 54 ROUTER_LINKS[$N]=$RESULT
43 netjail_node_add_nat $ROUTER $ROUTER_ADDR 24 55
56 netjail_node_add_nat ${ROUTERS[$N]} $ROUTER_ADDR 24
44 57
45 for M in $(seq $LOCAL_M); do 58 for M in $(seq $LOCAL_M); do
46 NODE=$(netjail_print_name "N" $N $M) 59 netjail_node_add_default ${NODES[$N,$M]} $ROUTER_ADDR
47
48 netjail_node_add_default $NODE $ROUTER_ADDR
49 done 60 done
50done
51
52 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_start_v2.sh b/src/testing/netjail_start_v2.sh
deleted file mode 100755
index 81196d53d..000000000
--- a/src/testing/netjail_start_v2.sh
+++ /dev/null
@@ -1,74 +0,0 @@
1#!/bin/bash
2. "./../testing/netjail_core_v2.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 [ -z "${R_TCP[$N]}" -a "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 [ -z "${R_UDP[$N]}" -a "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
index 08f68cf7f..abfaf3acf 100755
--- a/src/testing/netjail_stop.sh
+++ b/src/testing/netjail_stop.sh
@@ -1,24 +1,57 @@
1#!/bin/sh 1#!/bin/bash
2. "./../testing/netjail_core.sh" 2. "./../testing/netjail_core.sh"
3. "./../testing/topo.sh"
3 4
4set -eu 5set -eu
5set -x 6set -x
6 7
7export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 8export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
8 9
9LOCAL_M=$1 10filename=$1
10GLOBAL_N=$2 11PREFIX=$2
11NETWORK_NET=$(netjail_print_name "n" $GLOBAL_N $LOCAL_M)
12 12
13shift 2 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
14 29
15for N in $(seq $GLOBAL_N); do 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
16 for M in $(seq $LOCAL_M); do 42 for M in $(seq $LOCAL_M); do
17 netjail_node_clear $(netjail_print_name "N" $N $M) 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]}
18 done 49 done
50
19 51
20 netjail_bridge_clear $(netjail_print_name "r" $N) 52 netjail_bridge_clear ${ROUTER_NETS[$N]}
21 netjail_node_clear $(netjail_print_name "R" $N) 53 netjail_node_unlink_bridge ${NETWORK_LINKS[$N]}
54 netjail_node_clear ${ROUTERS[$N]}
22done 55done
23 56
24netjail_bridge_clear $NETWORK_NET 57netjail_bridge_clear $NETWORK_NET
diff --git a/src/testing/netjail_stop_v2.sh b/src/testing/netjail_stop_v2.sh
deleted file mode 100755
index 6e9fd1ccc..000000000
--- a/src/testing/netjail_stop_v2.sh
+++ /dev/null
@@ -1,59 +0,0 @@
1#!/bin/bash
2. "./../testing/netjail_core_v2.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_plugin_testcmd.c b/src/testing/test_testing_plugin_testcmd.c
index 444272fcd..32e2b38a7 100644
--- a/src/testing/test_testing_plugin_testcmd.c
+++ b/src/testing/test_testing_plugin_testcmd.c
@@ -17,11 +17,12 @@
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19 */ 19 */
20
21/** 20/**
22 * @file testbed/plugin_testcmd.c 21 * @file testbed/plugin_testcmd.c
23 * @brief a plugin to provide the API for running test cases. 22 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt 23 * @author t3sserakt
24 *
25 * // FIXME: too verbose, no logic to return final status, will segv!
25 */ 26 */
26#include "platform.h" 27#include "platform.h"
27#include "gnunet_testing_ng_lib.h" 28#include "gnunet_testing_ng_lib.h"
@@ -33,8 +34,11 @@
33 */ 34 */
34#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) 35#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
35 36
37
38// FIXME: bad global!
36unsigned int are_all_peers_started; 39unsigned int are_all_peers_started;
37 40
41
38static void 42static void
39all_peers_started () 43all_peers_started ()
40{ 44{
@@ -44,8 +48,10 @@ all_peers_started ()
44 are_all_peers_started); 48 are_all_peers_started);
45} 49}
46 50
51
47static void 52static void
48start_testcase (TESTING_CMD_HELPER_write_cb write_message, char *router_ip, 53start_testcase (TESTING_CMD_HELPER_write_cb write_message,
54 char *router_ip,
49 char *node_ip, 55 char *node_ip,
50 char *n, 56 char *n,
51 char *m, 57 char *m,
@@ -70,9 +76,10 @@ start_testcase (TESTING_CMD_HELPER_write_cb write_message, char *router_ip,
70 write_message) 76 write_message)
71 }; 77 };
72 78
73 GNUNET_TESTING_run (NULL, 79 GNUNET_TESTING_run (commands,
74 commands, 80 GNUNET_TIME_UNIT_FOREVER_REL,
75 GNUNET_TIME_UNIT_FOREVER_REL); 81 NULL, /* FIXME: pass continuation! */
82 NULL);
76 LOG (GNUNET_ERROR_TYPE_ERROR, 83 LOG (GNUNET_ERROR_TYPE_ERROR,
77 "We got here 7!\n"); 84 "We got here 7!\n");
78 85
@@ -113,4 +120,4 @@ libgnunet_plugin_testcmd_done (void *cls)
113} 120}
114 121
115 122
116/* end of plugin_testcmd.c */ 123
diff --git a/src/testing/testing.c b/src/testing/testing.c
index d3acd4689..4d9b7c0cb 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -34,6 +34,7 @@
34#include "gnunet_arm_service.h" 34#include "gnunet_arm_service.h"
35#include "gnunet_testing_lib.h" 35#include "gnunet_testing_lib.h"
36#include "gnunet_testing_ng_lib.h" 36#include "gnunet_testing_ng_lib.h"
37#include "testing_cmds.h"
37 38
38#define LOG(kind, ...) GNUNET_log_from (kind, "testing-api", __VA_ARGS__) 39#define LOG(kind, ...) GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
39 40
@@ -2259,6 +2260,31 @@ GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection,
2259 2260
2260 2261
2261/** 2262/**
2263 * Create a GNUNET_CMDS_LOCAL_FINISHED message.
2264 *
2265 * @param rv The result of the local test as GNUNET_GenericReturnValue.
2266 * @return The GNUNET_CMDS_LOCAL_FINISHED message.
2267*/
2268struct GNUNET_MessageHeader *
2269GNUNET_TESTING_send_local_test_finished_msg (enum GNUNET_GenericReturnValue rv)
2270{
2271 struct GNUNET_CMDS_LOCAL_FINISHED *reply;
2272 size_t msg_length;
2273
2274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2275 "Local test exits with status %d\n",
2276 rv);
2277 msg_length = sizeof(struct GNUNET_CMDS_LOCAL_FINISHED);
2278 reply = GNUNET_new (struct GNUNET_CMDS_LOCAL_FINISHED);
2279 reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED);
2280 reply->header.size = htons ((uint16_t) msg_length);
2281 reply->result = htons (rv);
2282
2283 return (struct GNUNET_MessageHeader *) reply;
2284}
2285
2286
2287/**
2262 * Getting the topology from file. 2288 * Getting the topology from file.
2263 * 2289 *
2264 * @param filename The name of the topology file. 2290 * @param filename The name of the topology file.
diff --git a/src/testing/testing.h b/src/testing/testing.h
index b12466530..8aba09e4b 100644
--- a/src/testing/testing.h
+++ b/src/testing/testing.h
@@ -21,54 +21,54 @@
21/** 21/**
22 * @author t3sserakt 22 * @author t3sserakt
23 */ 23 */
24 24#ifndef TESTING_H
25#define TESTING_H
25#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
26 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
27/** 58/**
28 * Global state of the interpreter, used by a command 59 * Set what command the batch should be at. Needed for
29 * to access information about other commands. 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
30 */ 66 */
31// SUGGESTION: consider making this struct opaque (only known inside of libgnunettesting, 67void
32// say main loop and a few select commands, like next/fail/batch); + helper 68GNUNET_TESTING_cmd_batch_set_current_ (const struct GNUNET_TESTING_Command *cmd,
33// function to access 'cfg'? 69 unsigned int new_ip);
34struct GNUNET_TESTING_Interpreter 70
35{ 71
36 72
37 /** 73
38 * Commands the interpreter will run. 74#endif
39 */
40 struct GNUNET_TESTING_Command *commands;
41
42 /**
43 * Interpreter task (if one is scheduled).
44 */
45 struct GNUNET_SCHEDULER_Task *task;
46
47 /**
48 * Finish task of a blocking call to a commands finish method.
49 */
50 struct GNUNET_SCHEDULER_Task *finish_task;
51
52 /**
53 * Our configuration.
54 */
55 const struct GNUNET_CONFIGURATION_Handle *cfg;
56
57 /**
58 * Task run on timeout.
59 */
60 struct GNUNET_SCHEDULER_Task *timeout_task;
61
62 /**
63 * Instruction pointer. Tells #interpreter_run() which instruction to run
64 * next. Need (signed) int because it gets -1 when rewinding the
65 * interpreter to the first CMD.
66 */
67 int ip;
68
69 /**
70 * Result of the testcases, #GNUNET_OK on success
71 */
72 int result;
73
74};
diff --git a/src/testing/testing_api_cmd_batch.c b/src/testing/testing_api_cmd_batch.c
index af260f80d..080a4880d 100644
--- a/src/testing/testing_api_cmd_batch.c
+++ b/src/testing/testing_api_cmd_batch.c
@@ -39,6 +39,11 @@ struct BatchState
39 struct GNUNET_TESTING_Command *batch; 39 struct GNUNET_TESTING_Command *batch;
40 40
41 /** 41 /**
42 * Our label.
43 */
44 const char *label;
45
46 /**
42 * Internal command pointer. 47 * Internal command pointer.
43 */ 48 */
44 unsigned int batch_ip; 49 unsigned int batch_ip;
@@ -49,12 +54,10 @@ struct BatchState
49 * Run the command. 54 * Run the command.
50 * 55 *
51 * @param cls closure. 56 * @param cls closure.
52 * @param cmd the command being executed.
53 * @param is the interpreter state. 57 * @param is the interpreter state.
54 */ 58 */
55static void 59static void
56batch_run (void *cls, 60batch_run (void *cls,
57 const struct GNUNET_TESTING_Command *cmd,
58 struct GNUNET_TESTING_Interpreter *is) 61 struct GNUNET_TESTING_Interpreter *is)
59{ 62{
60 struct BatchState *bs = cls; 63 struct BatchState *bs = cls;
@@ -69,7 +72,7 @@ batch_run (void *cls,
69 { 72 {
70 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 73 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
71 "Exiting from batch: %s\n", 74 "Exiting from batch: %s\n",
72 cmd->label); 75 bs->label);
73 return; 76 return;
74 } 77 }
75 bs->batch[bs->batch_ip].start_time 78 bs->batch[bs->batch_ip].start_time
@@ -77,7 +80,6 @@ batch_run (void *cls,
77 = GNUNET_TIME_absolute_get (); 80 = GNUNET_TIME_absolute_get ();
78 bs->batch[bs->batch_ip].num_tries = 1; 81 bs->batch[bs->batch_ip].num_tries = 1;
79 bs->batch[bs->batch_ip].run (bs->batch[bs->batch_ip].cls, 82 bs->batch[bs->batch_ip].run (bs->batch[bs->batch_ip].cls,
80 &bs->batch[bs->batch_ip],
81 is); 83 is);
82} 84}
83 85
@@ -87,20 +89,16 @@ batch_run (void *cls,
87 * cancel a pending operation thereof. 89 * cancel a pending operation thereof.
88 * 90 *
89 * @param cls closure. 91 * @param cls closure.
90 * @param cmd the command which is being cleaned up.
91 */ 92 */
92static void 93static void
93batch_cleanup (void *cls, 94batch_cleanup (void *cls)
94 const struct GNUNET_TESTING_Command *cmd)
95{ 95{
96 struct BatchState *bs = cls; 96 struct BatchState *bs = cls;
97 97
98 (void) cmd;
99 for (unsigned int i = 0; 98 for (unsigned int i = 0;
100 NULL != bs->batch[i].label; 99 NULL != bs->batch[i].label;
101 i++) 100 i++)
102 bs->batch[i].cleanup (bs->batch[i].cls, 101 bs->batch[i].cleanup (bs->batch[i].cls);
103 &bs->batch[i]);
104 GNUNET_free (bs->batch); 102 GNUNET_free (bs->batch);
105 GNUNET_free (bs); 103 GNUNET_free (bs);
106} 104}
@@ -115,22 +113,21 @@ batch_cleanup (void *cls,
115 * @param index index number of the object to offer. 113 * @param index index number of the object to offer.
116 * @return #GNUNET_OK on success. 114 * @return #GNUNET_OK on success.
117 */ 115 */
118static int 116static enum GNUNET_GenericReturnValue
119batch_traits (void *cls, 117batch_traits (void *cls,
120 const void **ret, 118 const void **ret,
121 const char *trait, 119 const char *trait,
122 unsigned int index) 120 unsigned int index)
123{ 121{
122 struct BatchState *bs = cls;
123 // FIXME: these constants should be more global!
124#define CURRENT_CMD_INDEX 0 124#define CURRENT_CMD_INDEX 0
125#define BATCH_INDEX 1 125#define BATCH_INDEX 1
126
127 struct BatchState *bs = cls;
128
129 struct GNUNET_TESTING_Trait traits[] = { 126 struct GNUNET_TESTING_Trait traits[] = {
130 GNUNET_TESTING_make_trait_cmd 127 GNUNET_TESTING_make_trait_cmd (CURRENT_CMD_INDEX,
131 (CURRENT_CMD_INDEX, &bs->batch[bs->batch_ip]), 128 &bs->batch[bs->batch_ip]),
132 GNUNET_TESTING_make_trait_cmd 129 GNUNET_TESTING_make_trait_cmd (BATCH_INDEX,
133 (BATCH_INDEX, bs->batch), 130 bs->batch),
134 GNUNET_TESTING_trait_end () 131 GNUNET_TESTING_trait_end ()
135 }; 132 };
136 133
@@ -162,7 +159,7 @@ GNUNET_TESTING_cmd_batch (const char *label,
162 unsigned int i; 159 unsigned int i;
163 160
164 bs = GNUNET_new (struct BatchState); 161 bs = GNUNET_new (struct BatchState);
165 162 bs->label = label;
166 /* Get number of commands. */ 163 /* Get number of commands. */
167 for (i = 0; NULL != batch[i].label; i++) 164 for (i = 0; NULL != batch[i].label; i++)
168 /* noop */ 165 /* noop */
@@ -187,68 +184,45 @@ GNUNET_TESTING_cmd_batch (const char *label,
187} 184}
188 185
189 186
190/** 187bool
191 * Advance internal pointer to next command. 188GNUNET_TESTING_cmd_batch_next_ (void *cls)
192 *
193 * @param is interpreter state.
194 */
195void
196GNUNET_TESTING_cmd_batch_next (struct GNUNET_TESTING_Interpreter *is)
197{ 189{
198 struct BatchState *bs = is->commands[is->ip].cls; 190 struct BatchState *bs = cls;
199 191
200 if (NULL == bs->batch[bs->batch_ip].label) 192 if (NULL == bs->batch[bs->batch_ip].label)
201 { 193 return false;
202 is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get (); 194 bs->batch[bs->batch_ip].finish_time
203 is->ip++; 195 = GNUNET_TIME_absolute_get ();
204 return;
205 }
206 bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get ();
207 bs->batch_ip++; 196 bs->batch_ip++;
197 return true;
208} 198}
209 199
210 200
211/** 201bool
212 * Test if this command is a batch command. 202GNUNET_TESTING_cmd_is_batch_ (const struct GNUNET_TESTING_Command *cmd)
213 *
214 * @return false if not, true if it is a batch command
215 */
216int
217GNUNET_TESTING_cmd_is_batch (const struct GNUNET_TESTING_Command *cmd)
218{ 203{
219 return cmd->run == &batch_run; 204 return cmd->run == &batch_run;
220} 205}
221 206
222 207
223/**
224 * Obtain what command the batch is at.
225 *
226 * @return cmd current batch command
227 */
228struct GNUNET_TESTING_Command * 208struct GNUNET_TESTING_Command *
229GNUNET_TESTING_cmd_batch_get_current (const struct GNUNET_TESTING_Command *cmd) 209GNUNET_TESTING_cmd_batch_get_current_ (const struct GNUNET_TESTING_Command *cmd)
230{ 210{
231 struct BatchState *bs = cmd->cls; 211 struct BatchState *bs = cmd->cls;
232 212
233 GNUNET_assert (cmd->run == &batch_run); 213 GNUNET_assert (GNUNET_TESTING_cmd_is_batch_ (cmd));
234 return &bs->batch[bs->batch_ip]; 214 return &bs->batch[bs->batch_ip];
235} 215}
236 216
237 217
238/**
239 * Set what command the batch should be at.
240 *
241 * @param cmd current batch command
242 * @param new_ip where to move the IP
243 */
244void 218void
245GNUNET_TESTING_cmd_batch_set_current (const struct GNUNET_TESTING_Command *cmd, 219GNUNET_TESTING_cmd_batch_set_current_ (const struct GNUNET_TESTING_Command *cmd,
246 unsigned int new_ip) 220 unsigned int new_ip)
247{ 221{
248 struct BatchState *bs = cmd->cls; 222 struct BatchState *bs = cmd->cls;
249 223
250 /* sanity checks */ 224 /* sanity checks */
251 GNUNET_assert (cmd->run == &batch_run); 225 GNUNET_assert (GNUNET_TESTING_cmd_is_batch_ (cmd));
252 for (unsigned int i = 0; i < new_ip; i++) 226 for (unsigned int i = 0; i < new_ip; i++)
253 GNUNET_assert (NULL != bs->batch[i].label); 227 GNUNET_assert (NULL != bs->batch[i].label);
254 /* actual logic */ 228 /* actual logic */
diff --git a/src/testing/testing_api_cmd_block_until_all_peers_started.c b/src/testing/testing_api_cmd_block_until_all_peers_started.c
index e9d3f0ed3..763713e15 100644
--- a/src/testing/testing_api_cmd_block_until_all_peers_started.c
+++ b/src/testing/testing_api_cmd_block_until_all_peers_started.c
@@ -39,6 +39,11 @@
39struct BlockState 39struct BlockState
40{ 40{
41 /** 41 /**
42 * Context for our asynchronous completion.
43 */
44 struct GNUNET_TESTING_AsyncContext ac;
45
46 /**
42 * Flag to indicate if all peers have started. 47 * Flag to indicate if all peers have started.
43 * 48 *
44 */ 49 */
@@ -47,26 +52,11 @@ struct BlockState
47 52
48 53
49/** 54/**
50 * Trait function of this cmd does nothing.
51 *
52 */
53static int
54block_until_all_peers_started_traits (void *cls,
55 const void **ret,
56 const char *trait,
57 unsigned int index)
58{
59 return GNUNET_OK;
60}
61
62
63/**
64 * The cleanup function of this cmd frees resources the cmd allocated. 55 * The cleanup function of this cmd frees resources the cmd allocated.
65 * 56 *
66 */ 57 */
67static void 58static void
68block_until_all_peers_started_cleanup (void *cls, 59block_until_all_peers_started_cleanup (void *cls)
69 const struct GNUNET_TESTING_Command *cmd)
70{ 60{
71 struct BlockState *bs = cls; 61 struct BlockState *bs = cls;
72 62
@@ -80,7 +70,6 @@ block_until_all_peers_started_cleanup (void *cls,
80 */ 70 */
81static void 71static void
82block_until_all_peers_started_run (void *cls, 72block_until_all_peers_started_run (void *cls,
83 const struct GNUNET_TESTING_Command *cmd,
84 struct GNUNET_TESTING_Interpreter *is) 73 struct GNUNET_TESTING_Interpreter *is)
85{ 74{
86 LOG (GNUNET_ERROR_TYPE_DEBUG, 75 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -89,27 +78,6 @@ block_until_all_peers_started_run (void *cls,
89 78
90 79
91/** 80/**
92 * Function to check if BlockState#all_peers_started is GNUNET_YES. In that case interpreter_next will be called.
93 *
94 */
95static int
96block_until_all_peers_started_finish (void *cls,
97 GNUNET_SCHEDULER_TaskCallback cont,
98 void *cont_cls)
99{
100 struct BlockState *bs = cls;
101 unsigned int *ret = bs->all_peers_started;
102
103 if (GNUNET_YES == *ret)
104 {
105 cont (cont_cls);
106 }
107
108 return *ret;
109}
110
111
112/**
113 * Create command. 81 * Create command.
114 * 82 *
115 * @param label name for command. 83 * @param label name for command.
@@ -125,15 +93,15 @@ GNUNET_TESTING_cmd_block_until_all_peers_started (const char *label,
125 93
126 bs = GNUNET_new (struct BlockState); 94 bs = GNUNET_new (struct BlockState);
127 bs->all_peers_started = all_peers_started; 95 bs->all_peers_started = all_peers_started;
128 96 {
129 struct GNUNET_TESTING_Command cmd = { 97 struct GNUNET_TESTING_Command cmd = {
130 .cls = bs, 98 .cls = bs,
131 .label = label, 99 .label = label,
132 .run = &block_until_all_peers_started_run, 100 .run = &block_until_all_peers_started_run,
133 .finish = &block_until_all_peers_started_finish, 101 .ac = &bs->ac,
134 .cleanup = &block_until_all_peers_started_cleanup, 102 .cleanup = &block_until_all_peers_started_cleanup
135 .traits = &block_until_all_peers_started_traits 103 };
136 }; 104
137 105 return cmd;
138 return cmd; 106 }
139} 107}
diff --git a/src/testing/testing_api_cmd_block_until_external_trigger.c b/src/testing/testing_api_cmd_block_until_external_trigger.c
index 2439afeaf..aeb9ffda3 100644
--- a/src/testing/testing_api_cmd_block_until_external_trigger.c
+++ b/src/testing/testing_api_cmd_block_until_external_trigger.c
@@ -39,25 +39,15 @@
39struct BlockState 39struct BlockState
40{ 40{
41 /** 41 /**
42 * Flag to indicate if all peers have started. 42 * Context for our asynchronous completion.
43 *
44 */ 43 */
45 unsigned int *stop_blocking; 44 struct GNUNET_TESTING_AsyncContext ac;
46};
47
48 45
49/** 46 /**
50 * Trait function of this cmd does nothing. 47 * The label of this command.
51 * 48 */
52 */ 49 const char *label;
53static int 50};
54block_until_all_peers_started_traits (void *cls,
55 const void **ret,
56 const char *trait,
57 unsigned int index)
58{
59 return GNUNET_OK;
60}
61 51
62 52
63/** 53/**
@@ -65,47 +55,68 @@ block_until_all_peers_started_traits (void *cls,
65 * 55 *
66 */ 56 */
67static void 57static void
68block_until_all_peers_started_cleanup (void *cls, 58block_until_all_peers_started_cleanup (void *cls)
69 const struct GNUNET_TESTING_Command *cmd)
70{ 59{
71 struct BlockState *bs = cls; 60 struct BlockState *bs = cls;
72 61
73 GNUNET_free (bs); 62 GNUNET_free (bs);
74} 63}
75 64
65static int
66block_until_external_trigger_traits (void *cls,
67 const void **ret,
68 const char *trait,
69 unsigned int index)
70{
71 struct BlockState *bs = cls;
72 struct GNUNET_TESTING_AsyncContext *ac = &bs->ac;
73 struct GNUNET_TESTING_Trait traits[] = {
74 {
75 .index = 0,
76 .trait_name = "async_context",
77 .ptr = (const void *) ac,
78 },
79 GNUNET_TESTING_trait_end ()
80 };
81
82 return GNUNET_TESTING_get_trait (traits,
83 ret,
84 trait,
85 index);
86}
87
76 88
77/** 89/**
78 * This function does nothing but to start the cmd. 90 * Function to get the trait with the async context.
79 * 91 *
92 * @param[out] ac GNUNET_TESTING_AsyncContext.
93 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
80 */ 94 */
81static void 95int
82block_until_all_peers_started_run (void *cls, 96GNUNET_TESTING_get_trait_async_context (
83 const struct GNUNET_TESTING_Command *cmd, 97 const struct GNUNET_TESTING_Command *cmd,
84 struct GNUNET_TESTING_Interpreter *is) 98 struct GNUNET_TESTING_AsyncContext **ac)
85{ 99{
86 LOG (GNUNET_ERROR_TYPE_DEBUG, 100 return cmd->traits (cmd->cls,
87 "block_until_all_peers_started_run!\n"); 101 (const void **) ac,
102 "async_context",
103 (unsigned int) 0);
88} 104}
89 105
90 106
91/** 107/**
92 * Function to check if BlockState#all_peers_started is GNUNET_YES. In that case interpreter_next will be called. 108 * This function does nothing but to start the cmd.
93 * 109 *
94 */ 110 */
95static int 111static void
96block_until_all_peers_started_finish (void *cls, 112block_until_all_peers_started_run (void *cls,
97 GNUNET_SCHEDULER_TaskCallback cont, 113 struct GNUNET_TESTING_Interpreter *is)
98 void *cont_cls)
99{ 114{
100 struct BlockState *bs = cls; 115 struct BlockState *bs = cls;
101 unsigned int *ret = bs->stop_blocking;
102 116
103 if (GNUNET_YES == *ret) 117 LOG (GNUNET_ERROR_TYPE_DEBUG,
104 { 118 "block %s running!\n",
105 cont (cont_cls); 119 bs->label);
106 }
107
108 return *ret;
109} 120}
110 121
111 122
@@ -117,23 +128,22 @@ block_until_all_peers_started_finish (void *cls,
117 * @return command. 128 * @return command.
118 */ 129 */
119struct GNUNET_TESTING_Command 130struct GNUNET_TESTING_Command
120GNUNET_TESTING_cmd_block_until_external_trigger (const char *label, 131GNUNET_TESTING_cmd_block_until_external_trigger (const char *label)
121 unsigned int *
122 stop_blocking)
123{ 132{
124 struct BlockState *bs; 133 struct BlockState *bs;
125 134
126 bs = GNUNET_new (struct BlockState); 135 bs = GNUNET_new (struct BlockState);
127 bs->stop_blocking = stop_blocking; 136 bs->label = label;
128 137 {
129 struct GNUNET_TESTING_Command cmd = { 138 struct GNUNET_TESTING_Command cmd = {
130 .cls = bs, 139 .cls = bs,
131 .label = label, 140 .label = label,
132 .run = &block_until_all_peers_started_run, 141 .run = &block_until_all_peers_started_run,
133 .finish = &block_until_all_peers_started_finish, 142 .ac = &bs->ac,
134 .cleanup = &block_until_all_peers_started_cleanup, 143 .cleanup = &block_until_all_peers_started_cleanup,
135 .traits = &block_until_all_peers_started_traits 144 .traits = block_until_external_trigger_traits
136 }; 145 };
137 146
138 return cmd; 147 return cmd;
148 }
139} 149}
diff --git a/src/testing/testing_api_cmd_end.c b/src/testing/testing_api_cmd_end.c
new file mode 100644
index 000000000..f0f036429
--- /dev/null
+++ b/src/testing/testing_api_cmd_end.c
@@ -0,0 +1,39 @@
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
new file mode 100644
index 000000000..3ac0871a5
--- /dev/null
+++ b/src/testing/testing_api_cmd_finish.c
@@ -0,0 +1,198 @@
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
29/**
30 * Struct to use for command-specific context information closure of a command waiting
31 * for another command.
32 */
33struct FinishState
34{
35 /**
36 * Closure for all commands with command-specific context information.
37 */
38 void *cls;
39
40 /**
41 * Label of the asynchronous command the synchronous command of this closure waits for.
42 */
43 const char *async_label;
44
45 /**
46 * Task for running the finish method of the asynchronous task the command is waiting for.
47 */
48 struct GNUNET_SCHEDULER_Task *finish_task;
49
50 /**
51 * Function to call when done.
52 */
53 struct GNUNET_TESTING_AsyncContext ac;
54
55 /**
56 * How long to wait until finish fails hard?
57 */
58 struct GNUNET_TIME_Relative timeout;
59
60};
61
62
63/**
64 * Function called when the command we are waiting on
65 * is finished. Hence we are finished, too.
66 *
67 * @param cls a `struct FinishState` being notified
68 */
69static void
70done_finish (void *cls)
71{
72 struct FinishState *finish_state = cls;
73
74 GNUNET_SCHEDULER_cancel (finish_state->finish_task);
75 finish_state->finish_task = NULL;
76 GNUNET_TESTING_async_finish (&finish_state->ac);
77}
78
79
80/**
81 * Function triggered if the command we are waiting
82 * for did not complete on time.
83 *
84 * @param cls our `struct FinishState`
85 */
86static void
87timeout_finish (void *cls)
88{
89 struct FinishState *finish_state = cls;
90
91 finish_state->finish_task = NULL;
92 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
93 "Timeout waiting for command `%s' to finish\n",
94 finish_state->async_label);
95 GNUNET_TESTING_async_fail (&finish_state->ac);
96}
97
98
99/**
100 * Run method of the command created by the interpreter to wait for another
101 * command to finish.
102 *
103 */
104static void
105run_finish (void *cls,
106 struct GNUNET_TESTING_Interpreter *is)
107{
108 struct FinishState *finish_state = cls;
109 const struct GNUNET_TESTING_Command *async_cmd;
110 struct GNUNET_TESTING_AsyncContext *aac;
111
112 async_cmd
113 = GNUNET_TESTING_interpreter_lookup_command (is,
114 finish_state->async_label);
115 if (NULL == async_cmd)
116 {
117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118 "Did not find command `%s'\n",
119 finish_state->async_label);
120 GNUNET_TESTING_interpreter_fail (is);
121 return;
122 }
123 if ( (NULL == (aac = async_cmd->ac)) ||
124 (! async_cmd->asynchronous_finish) )
125 {
126 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
127 "Cannot finish `%s': not asynchronous\n",
128 finish_state->async_label);
129 GNUNET_TESTING_interpreter_fail (is);
130 return;
131 }
132 if (GNUNET_NO != aac->finished)
133 {
134 /* Command is already finished, so are we! */
135 GNUNET_TESTING_async_finish (&finish_state->ac);
136 return;
137 }
138 finish_state->finish_task
139 = GNUNET_SCHEDULER_add_delayed (finish_state->timeout,
140 &timeout_finish,
141 finish_state);
142 aac->cont = &done_finish;
143 aac->cont_cls = finish_state;
144}
145
146
147/**
148 * Cleanup state of a finish command.
149 *
150 * @param cls a `struct FinishState` to clean up
151 */
152static void
153cleanup_finish (void *cls)
154{
155 struct FinishState *finish_state = cls;
156
157 if (NULL != finish_state->finish_task)
158 {
159 GNUNET_SCHEDULER_cancel (finish_state->finish_task);
160 finish_state->finish_task = NULL;
161 }
162 GNUNET_free (finish_state);
163}
164
165
166const struct GNUNET_TESTING_Command
167GNUNET_TESTING_cmd_finish (const char *finish_label,
168 const char *cmd_ref,
169 struct GNUNET_TIME_Relative timeout)
170{
171 struct FinishState *finish_state;
172
173 finish_state = GNUNET_new (struct FinishState);
174 finish_state->async_label = cmd_ref;
175 finish_state->timeout = timeout;
176 {
177 struct GNUNET_TESTING_Command cmd = {
178 .cls = finish_state,
179 .label = finish_label,
180 .run = &run_finish,
181 .ac = &finish_state->ac,
182 .cleanup = &cleanup_finish
183 };
184
185 return cmd;
186 }
187}
188
189
190struct GNUNET_TESTING_Command
191GNUNET_TESTING_cmd_make_unblocking (struct GNUNET_TESTING_Command cmd)
192{
193 /* do not permit this function to be used on
194 a finish command! */
195 GNUNET_assert (cmd.run != &run_finish);
196 cmd.asynchronous_finish = true;
197 return cmd;
198}
diff --git a/src/testing/testing_api_cmd_hello_world.c b/src/testing/testing_api_cmd_hello_world.c
index 4347ac818..73dcd6dff 100644
--- a/src/testing/testing_api_cmd_hello_world.c
+++ b/src/testing/testing_api_cmd_hello_world.c
@@ -32,50 +32,51 @@ struct HelloWorldState
32 const char *birthLabel; 32 const char *birthLabel;
33}; 33};
34 34
35
35/** 36/**
36* 37 *
37* 38 *
38* @param cls closure 39 * @param cls closure
39* @param cmd current CMD being cleaned up. 40 */
40*/
41static void 41static void
42hello_world_cleanup (void *cls, 42hello_world_cleanup (void *cls)
43 const struct GNUNET_TESTING_Command *cmd)
44{ 43{
45 struct HelloWorldState *hs = cls; 44 struct HelloWorldState *hs = cls;
45
46 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 46 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
47 "Cleaning up message %s\n", 47 "Cleaning up message %s\n",
48 hs->message); 48 hs->message);
49 GNUNET_free (hs);
49} 50}
50 51
52
51/** 53/**
52* 54 *
53* 55 *
54* @param cls closure. 56 * @param cls closure.
55* @param[out] ret result 57 * @param[out] ret result
56* @param trait name of the trait. 58 * @param trait name of the trait.
57* @param index index number of the object to offer. 59 * @param index index number of the object to offer.
58* @return #GNUNET_OK on success. 60 * @return #GNUNET_OK on success.
59*/ 61 */
60static int 62static enum GNUNET_GenericReturnValue
61hello_world_traits (void *cls, 63hello_world_traits (void *cls,
62 const void **ret, 64 const void **ret,
63 const char *trait, 65 const char *trait,
64 unsigned int index) 66 unsigned int index)
65{ 67{
66 return GNUNET_OK; 68 return GNUNET_NO;
67} 69}
68 70
71
69/** 72/**
70* Run the "hello world" CMD. 73* Run the "hello world" CMD.
71* 74*
72* @param cls closure. 75* @param cls closure.
73* @param cmd CMD being run.
74* @param is interpreter state. 76* @param is interpreter state.
75*/ 77*/
76static void 78static void
77hello_world_run (void *cls, 79hello_world_run (void *cls,
78 const struct GNUNET_TESTING_Command *cmd,
79 struct GNUNET_TESTING_Interpreter *is) 80 struct GNUNET_TESTING_Interpreter *is)
80{ 81{
81 struct HelloWorldState *hs = cls; 82 struct HelloWorldState *hs = cls;
@@ -84,13 +85,16 @@ hello_world_run (void *cls,
84 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 85 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
85 "%s\n", 86 "%s\n",
86 hs->message); 87 hs->message);
87 birth_cmd = GNUNET_TESTING_interpreter_lookup_command (hs->birthLabel); 88 birth_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
88 GNUNET_TESTING_get_trait_what_am_i (birth_cmd, &hs->message); 89 hs->birthLabel);
90 GNUNET_TESTING_get_trait_what_am_i (birth_cmd,
91 &hs->message);
89 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 92 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
90 "Now I am a %s\n", 93 "Now I am a %s\n",
91 hs->message); 94 hs->message);
92} 95}
93 96
97
94/** 98/**
95 * Create command. 99 * Create command.
96 * 100 *
@@ -108,14 +112,15 @@ GNUNET_TESTING_cmd_hello_world (const char *label,
108 hs = GNUNET_new (struct HelloWorldState); 112 hs = GNUNET_new (struct HelloWorldState);
109 hs->message = "Hello World, I was nobody!"; 113 hs->message = "Hello World, I was nobody!";
110 hs->birthLabel = birthLabel; 114 hs->birthLabel = birthLabel;
115 {
116 struct GNUNET_TESTING_Command cmd = {
117 .cls = hs,
118 .label = label,
119 .run = &hello_world_run,
120 .cleanup = &hello_world_cleanup,
121 .traits = &hello_world_traits
122 };
111 123
112 struct GNUNET_TESTING_Command cmd = { 124 return cmd;
113 .cls = hs, 125 }
114 .label = label,
115 .run = &hello_world_run,
116 .cleanup = &hello_world_cleanup,
117 .traits = &hello_world_traits
118 };
119
120 return cmd;
121} 126}
diff --git a/src/testing/testing_api_cmd_hello_world_birth.c b/src/testing/testing_api_cmd_hello_world_birth.c
index 9d60059a5..8415b99f0 100644
--- a/src/testing/testing_api_cmd_hello_world_birth.c
+++ b/src/testing/testing_api_cmd_hello_world_birth.c
@@ -40,8 +40,7 @@ struct HelloWorldBirthState
40* @param cmd current CMD being cleaned up. 40* @param cmd current CMD being cleaned up.
41*/ 41*/
42static void 42static void
43hello_world_birth_cleanup (void *cls, 43hello_world_birth_cleanup (void *cls)
44 const struct GNUNET_TESTING_Command *cmd)
45{ 44{
46 struct HelloWorldBirthState *hbs = cls; 45 struct HelloWorldBirthState *hbs = cls;
47 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 46 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -49,6 +48,7 @@ hello_world_birth_cleanup (void *cls,
49 hbs->what_am_i); 48 hbs->what_am_i);
50} 49}
51 50
51
52/** 52/**
53* 53*
54* 54*
@@ -82,6 +82,7 @@ hello_world_birth_traits (void *cls,
82 index); 82 index);
83} 83}
84 84
85
85/** 86/**
86* Run the "hello world" CMD. 87* Run the "hello world" CMD.
87* 88*
@@ -91,14 +92,13 @@ hello_world_birth_traits (void *cls,
91*/ 92*/
92static void 93static void
93hello_world_birth_run (void *cls, 94hello_world_birth_run (void *cls,
94 const struct GNUNET_TESTING_Command *cmd,
95 struct GNUNET_TESTING_Interpreter *is) 95 struct GNUNET_TESTING_Interpreter *is)
96{ 96{
97 struct HelloWorldBirthState *hbs = cls; 97 struct HelloWorldBirthState *hbs = cls;
98 struct GNUNET_TIME_Relative relative; 98 struct GNUNET_TIME_Relative relative;
99 99
100 relative = GNUNET_TIME_absolute_get_difference (*hbs->date, 100 relative = GNUNET_TIME_absolute_get_difference (*hbs->date,
101 GNUNET_TIME_absolute_get ()); 101 GNUNET_TIME_absolute_get ());
102 102
103 if (0 == relative.rel_value_us % 10) 103 if (0 == relative.rel_value_us % 10)
104 { 104 {
@@ -114,6 +114,7 @@ hello_world_birth_run (void *cls,
114 } 114 }
115} 115}
116 116
117
117/** 118/**
118 * Offer data from trait 119 * Offer data from trait
119 * 120 *
@@ -131,6 +132,7 @@ GNUNET_TESTING_get_trait_what_am_i (const struct GNUNET_TESTING_Command *cmd,
131 (unsigned int) 0); 132 (unsigned int) 0);
132} 133}
133 134
135
134/** 136/**
135 * Create command. 137 * Create command.
136 * 138 *
diff --git a/src/testing/testing_api_cmd_local_test_finished.c b/src/testing/testing_api_cmd_local_test_finished.c
index b50e471e9..0e7e214dc 100644
--- a/src/testing/testing_api_cmd_local_test_finished.c
+++ b/src/testing/testing_api_cmd_local_test_finished.c
@@ -19,7 +19,7 @@
19 */ 19 */
20 20
21/** 21/**
22 * @file testing_api_cmd_block_until_all_peers_started.c 22 * @file testing_api_cmd_local_test_finished.c
23 * @brief cmd to block the interpreter loop until all peers started. 23 * @brief cmd to block the interpreter loop until all peers started.
24 * @author t3sserakt 24 * @author t3sserakt
25 */ 25 */
@@ -40,6 +40,7 @@
40 */ 40 */
41struct LocalFinishedState 41struct LocalFinishedState
42{ 42{
43
43 /** 44 /**
44 * Callback to write messages to the master loop. 45 * Callback to write messages to the master loop.
45 * 46 *
@@ -55,26 +56,11 @@ struct LocalFinishedState
55 56
56 57
57/** 58/**
58 * Trait function of this cmd does nothing.
59 *
60 */
61static int
62local_test_finished_traits (void *cls,
63 const void **ret,
64 const char *trait,
65 unsigned int index)
66{
67 return GNUNET_OK;
68}
69
70
71/**
72 * The cleanup function of this cmd frees resources the cmd allocated. 59 * The cleanup function of this cmd frees resources the cmd allocated.
73 * 60 *
74 */ 61 */
75static void 62static void
76local_test_finished_cleanup (void *cls, 63local_test_finished_cleanup (void *cls)
77 const struct GNUNET_TESTING_Command *cmd)
78{ 64{
79 struct LocalFinishedState *lfs = cls; 65 struct LocalFinishedState *lfs = cls;
80 66
@@ -89,11 +75,9 @@ local_test_finished_cleanup (void *cls,
89 */ 75 */
90static void 76static void
91local_test_finished_run (void *cls, 77local_test_finished_run (void *cls,
92 const struct GNUNET_TESTING_Command *cmd,
93 struct GNUNET_TESTING_Interpreter *is) 78 struct GNUNET_TESTING_Interpreter *is)
94{ 79{
95 struct LocalFinishedState *lfs = cls; 80 struct LocalFinishedState *lfs = cls;
96
97 struct GNUNET_CMDS_LOCAL_FINISHED *reply; 81 struct GNUNET_CMDS_LOCAL_FINISHED *reply;
98 size_t msg_length; 82 size_t msg_length;
99 83
@@ -102,22 +86,8 @@ local_test_finished_run (void *cls,
102 reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED); 86 reply->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED);
103 reply->header.size = htons ((uint16_t) msg_length); 87 reply->header.size = htons ((uint16_t) msg_length);
104 lfs->reply = reply; 88 lfs->reply = reply;
105 lfs->write_message ((struct GNUNET_MessageHeader *) reply, msg_length); 89 lfs->write_message ((struct GNUNET_MessageHeader *) reply,
106} 90 msg_length);
107
108
109/**
110 * This finish function will stop the local loop without shutting down the scheduler, because we do not call the continuation, which is the interpreter_next method.
111 *
112 */
113static int
114local_test_finished_finish (void *cls,
115 GNUNET_SCHEDULER_TaskCallback cont,
116 void *cont_cls)
117{
118 LOG (GNUNET_ERROR_TYPE_ERROR,
119 "Stopping local loop\n");
120 return GNUNET_YES;
121} 91}
122 92
123 93
@@ -129,23 +99,22 @@ local_test_finished_finish (void *cls,
129 * @return command. 99 * @return command.
130 */ 100 */
131struct GNUNET_TESTING_Command 101struct GNUNET_TESTING_Command
132GNUNET_TESTING_cmd_local_test_finished (const char *label, 102GNUNET_TESTING_cmd_local_test_finished (
133 TESTING_CMD_HELPER_write_cb 103 const char *label,
134 write_message) 104 TESTING_CMD_HELPER_write_cb write_message)
135{ 105{
136 struct LocalFinishedState *lfs; 106 struct LocalFinishedState *lfs;
137 107
138 lfs = GNUNET_new (struct LocalFinishedState); 108 lfs = GNUNET_new (struct LocalFinishedState);
139 lfs->write_message = write_message; 109 lfs->write_message = write_message;
140 110 {
141 struct GNUNET_TESTING_Command cmd = { 111 struct GNUNET_TESTING_Command cmd = {
142 .cls = lfs, 112 .cls = lfs,
143 .label = label, 113 .label = label,
144 .run = &local_test_finished_run, 114 .run = &local_test_finished_run,
145 .finish = &local_test_finished_finish, 115 .cleanup = &local_test_finished_cleanup,
146 .cleanup = &local_test_finished_cleanup, 116 };
147 .traits = &local_test_finished_traits 117
148 }; 118 return cmd;
149 119 }
150 return cmd;
151} 120}
diff --git a/src/testing/testing_api_cmd_netjail_start.c b/src/testing/testing_api_cmd_netjail_start.c
index 536b356a6..35fb90f3c 100644
--- a/src/testing/testing_api_cmd_netjail_start.c
+++ b/src/testing/testing_api_cmd_netjail_start.c
@@ -19,7 +19,7 @@
19 */ 19 */
20 20
21/** 21/**
22 * @file testing/testing_api_cmd_hello_world.c 22 * @file testing/testing_api_cmd_netjail_start.c
23 * @brief Command to start the netjail script. 23 * @brief Command to start the netjail script.
24 * @author t3sserakt 24 * @author t3sserakt
25 */ 25 */
@@ -35,22 +35,24 @@
35 */ 35 */
36struct NetJailState 36struct NetJailState
37{ 37{
38 /**
39 * Context for our asynchronous completion.
40 */
41 struct GNUNET_TESTING_AsyncContext ac;
42
38 // Child Wait handle 43 // Child Wait handle
39 struct GNUNET_ChildWaitHandle *cwh; 44 struct GNUNET_ChildWaitHandle *cwh;
40 45
41 // Number of local nodes in each namespace.
42 char *local_m;
43
44 // The number of namespaces.
45 char *global_n;
46
47 /** 46 /**
48 * The process id of the start script. 47 * The process id of the start script.
49 */ 48 */
50 struct GNUNET_OS_Process *start_proc; 49 struct GNUNET_OS_Process *start_proc;
51 50
52 // Flag indication if the script finished. 51 /**
53 unsigned int finished; 52 * Configuration file for the test topology.
53 */
54 char *topology_config;
55
54}; 56};
55 57
56 58
@@ -59,8 +61,7 @@ struct NetJailState
59 * 61 *
60 */ 62 */
61static void 63static void
62netjail_start_cleanup (void *cls, 64netjail_start_cleanup (void *cls)
63 const struct GNUNET_TESTING_Command *cmd)
64{ 65{
65 struct NetJailState *ns = cls; 66 struct NetJailState *ns = cls;
66 67
@@ -87,20 +88,6 @@ netjail_start_cleanup (void *cls,
87 88
88 89
89/** 90/**
90 * Trait function of this cmd does nothing.
91 *
92 */
93static int
94netjail_start_traits (void *cls,
95 const void **ret,
96 const char *trait,
97 unsigned int index)
98{
99 return GNUNET_OK;
100}
101
102
103/**
104 * Callback which will be called if the setup script finished. 91 * Callback which will be called if the setup script finished.
105 * 92 *
106 */ 93 */
@@ -111,40 +98,40 @@ child_completed_callback (void *cls,
111{ 98{
112 struct NetJailState *ns = cls; 99 struct NetJailState *ns = cls;
113 100
101 GNUNET_OS_process_destroy (ns->start_proc);
102 ns->start_proc = NULL;
114 if (0 == exit_code) 103 if (0 == exit_code)
115 { 104 {
116 ns->finished = GNUNET_YES; 105 GNUNET_TESTING_async_finish (&ns->ac);
117 } 106 }
118 else 107 else
119 { 108 {
120 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 109 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
121 "Child completed with an error!\n"); 110 "Child failed with error %lu!\n",
122 ns->finished = GNUNET_SYSERR; 111 exit_code);
112 GNUNET_TESTING_async_fail (&ns->ac);
123 } 113 }
124 GNUNET_OS_process_destroy (ns->start_proc);
125 ns->start_proc = NULL;
126} 114}
127 115
128 116
129
130/** 117/**
131* The run method starts the script which setup the network namespaces. 118* The run method starts the script which setup the network namespaces.
132* 119*
133* @param cls closure. 120* @param cls closure.
134* @param cmd CMD being run.
135* @param is interpreter state. 121* @param is interpreter state.
136*/ 122*/
137static void 123static void
138netjail_start_run (void *cls, 124netjail_start_run (void *cls,
139 const struct GNUNET_TESTING_Command *cmd,
140 struct GNUNET_TESTING_Interpreter *is) 125 struct GNUNET_TESTING_Interpreter *is)
141{ 126{
142 struct NetJailState *ns = cls; 127 struct NetJailState *ns = cls;
143 char *const script_argv[] = {NETJAIL_START_SCRIPT, 128 char pid[15];
144 ns->local_m, 129 enum GNUNET_GenericReturnValue helper_check;
145 ns->global_n, 130
146 NULL}; 131 // FIXME: NETJAIL_START_SCRIPT like this is bad,
147 unsigned int helper_check = GNUNET_OS_check_helper_binary ( 132 // use location from share/gnunet/ of installed
133 // binary in case libgnunettesting is used as a lib!
134 helper_check = GNUNET_OS_check_helper_binary (
148 NETJAIL_START_SCRIPT, 135 NETJAIL_START_SCRIPT,
149 GNUNET_YES, 136 GNUNET_YES,
150 NULL); 137 NULL);
@@ -154,23 +141,38 @@ netjail_start_run (void *cls,
154 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 141 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
155 "No SUID for %s!\n", 142 "No SUID for %s!\n",
156 NETJAIL_START_SCRIPT); 143 NETJAIL_START_SCRIPT);
157 GNUNET_TESTING_interpreter_fail (); 144 GNUNET_TESTING_interpreter_fail (is);
145 return;
158 } 146 }
159 else if (GNUNET_NO == helper_check) 147 if (GNUNET_SYSERR == helper_check)
160 { 148 {
161 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 149 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
162 "%s not found!\n", 150 "%s not found!\n",
163 NETJAIL_START_SCRIPT); 151 NETJAIL_START_SCRIPT);
164 GNUNET_TESTING_interpreter_fail (); 152 GNUNET_TESTING_interpreter_fail (is);
153 return;
165 } 154 }
166 155
167 ns->start_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR, 156 GNUNET_snprintf (pid,
168 NULL, 157 sizeof (pid),
169 NULL, 158 "%u",
170 NULL, 159 getpid ());
171 NETJAIL_START_SCRIPT, 160 {
172 script_argv); 161 char *const script_argv[] = {
173 162 NETJAIL_START_SCRIPT,
163 ns->topology_config,
164 pid,
165 NULL
166 };
167
168 ns->start_proc
169 = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
170 NULL,
171 NULL,
172 NULL,
173 NETJAIL_START_SCRIPT,
174 script_argv);
175 }
174 ns->cwh = GNUNET_wait_child (ns->start_proc, 176 ns->cwh = GNUNET_wait_child (ns->start_proc,
175 &child_completed_callback, 177 &child_completed_callback,
176 ns); 178 ns);
@@ -179,51 +181,29 @@ netjail_start_run (void *cls,
179 181
180 182
181/** 183/**
182 * This function checks the flag NetJailState#finished, if this cmd finished.
183 *
184 */
185static int
186netjail_start_finish (void *cls,
187 GNUNET_SCHEDULER_TaskCallback cont,
188 void *cont_cls)
189{
190 struct NetJailState *ns = cls;
191
192 if (ns->finished)
193 {
194 cont (cont_cls);
195 }
196 return ns->finished;
197}
198
199/**
200 * Create command. 184 * Create command.
201 * 185 *
202 * @param label name for command. 186 * @param label name for command.
203 * @param local_m Number of local nodes in each namespace. 187 * @param topology_config Configuration file for the test topology.
204 * @param global_n The number of namespaces.
205 * @return command. 188 * @return command.
206 */ 189 */
207struct GNUNET_TESTING_Command 190struct GNUNET_TESTING_Command
208GNUNET_TESTING_cmd_netjail_start (const char *label, 191GNUNET_TESTING_cmd_netjail_start (const char *label,
209 char *local_m, 192 char *topology_config)
210 char *global_n)
211{ 193{
212 struct NetJailState *ns; 194 struct NetJailState *ns;
213 195
214 ns = GNUNET_new (struct NetJailState); 196 ns = GNUNET_new (struct NetJailState);
215 ns->local_m = local_m; 197 ns->topology_config = topology_config;
216 ns->global_n = global_n; 198 {
217 ns->finished = GNUNET_NO; 199 struct GNUNET_TESTING_Command cmd = {
218 200 .cls = ns,
219 struct GNUNET_TESTING_Command cmd = { 201 .label = label,
220 .cls = ns, 202 .run = &netjail_start_run,
221 .label = label, 203 .ac = &ns->ac,
222 .run = &netjail_start_run, 204 .cleanup = &netjail_start_cleanup
223 .finish = &netjail_start_finish, 205 };
224 .cleanup = &netjail_start_cleanup, 206
225 .traits = &netjail_start_traits 207 return cmd;
226 }; 208 }
227
228 return cmd;
229} 209}
diff --git a/src/testing/testing_api_cmd_netjail_start_testsystem.c b/src/testing/testing_api_cmd_netjail_start_testsystem.c
index 531621eb5..a1d71c436 100644
--- a/src/testing/testing_api_cmd_netjail_start_testsystem.c
+++ b/src/testing/testing_api_cmd_netjail_start_testsystem.c
@@ -62,6 +62,16 @@ struct HelperMessage
62struct NetJailState 62struct NetJailState
63{ 63{
64 /** 64 /**
65 * Context for our asynchronous completion.
66 */
67 struct GNUNET_TESTING_AsyncContext ac;
68
69 /**
70 * The complete topology information.
71 */
72 struct GNUNET_TESTING_NetjailTopology *topology;
73
74 /**
65 * Pointer to the return value of the test. 75 * Pointer to the return value of the test.
66 * 76 *
67 */ 77 */
@@ -91,16 +101,22 @@ struct NetJailState
91 unsigned int n_helper; 101 unsigned int n_helper;
92 102
93 /** 103 /**
94 * Number of nodes in a network namespace. //TODO make this a unsigned int 104 * Number of nodes in a natted subnet.
95 * 105 *
96 */ 106 */
97 char *local_m; 107 unsigned int local_m;
98 108
99 /** 109 /**
100 * Number of network namespaces. //TODO make this a unsigned int 110 * Number of natted subnets.
101 * 111 *
102 */ 112 */
103 char *global_n; 113 unsigned int global_n;
114
115 /**
116 * Number of global known nodes.
117 *
118 */
119 unsigned int known;
104 120
105 /** 121 /**
106 * The send handle for the helper 122 * The send handle for the helper
@@ -194,11 +210,9 @@ struct TestingSystemCount
194* Code to clean up resource this cmd used. 210* Code to clean up resource this cmd used.
195* 211*
196* @param cls closure 212* @param cls closure
197* @param cmd current CMD being cleaned up.
198*/ 213*/
199static void 214static void
200netjail_exec_cleanup (void *cls, 215netjail_exec_cleanup (void *cls)
201 const struct GNUNET_TESTING_Command *cmd)
202{ 216{
203 struct NetJailState *ns = cls; 217 struct NetJailState *ns = cls;
204 struct HelperMessage *message_pos; 218 struct HelperMessage *message_pos;
@@ -268,7 +282,8 @@ netjail_exec_traits (void *cls,
268int 282int
269GNUNET_TESTING_get_trait_helper_handles (const struct 283GNUNET_TESTING_get_trait_helper_handles (const struct
270 GNUNET_TESTING_Command *cmd, 284 GNUNET_TESTING_Command *cmd,
271 struct GNUNET_HELPER_Handle ***helper) 285 struct GNUNET_HELPER_Handle ***
286 helper)
272{ 287{
273 return cmd->traits (cmd->cls, 288 return cmd->traits (cmd->cls,
274 (const void **) helper, 289 (const void **) helper,
@@ -298,6 +313,43 @@ clear_msg (void *cls, int result)
298} 313}
299 314
300 315
316static void
317send_all_peers_started (unsigned int i, unsigned int j, struct NetJailState *ns)
318{
319 unsigned int total_number = ns->local_m * ns->global_n + ns->known;
320 struct GNUNET_CMDS_ALL_PEERS_STARTED *reply;
321 size_t msg_length;
322 struct GNUNET_HELPER_Handle *helper;
323 struct TestingSystemCount *tbc;
324
325 tbc = GNUNET_new (struct TestingSystemCount);
326 tbc->ns = ns;
327 // 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.
328 if (0 == i)
329 tbc->count = j + total_number;
330 else
331 tbc->count = (i - 1) * ns->local_m + j + total_number + ns->known;
332
333 helper = ns->helper[tbc->count - 1 - total_number];
334 msg_length = sizeof(struct GNUNET_CMDS_ALL_PEERS_STARTED);
335 reply = GNUNET_new (struct GNUNET_CMDS_ALL_PEERS_STARTED);
336 reply->header.type = htons (
337 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
338 reply->header.size = htons ((uint16_t) msg_length);
339
340 GNUNET_array_append (ns->msg, ns->n_msg, &reply->header);
341
342 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
343 helper,
344 &reply->header,
345 GNUNET_NO,
346 &clear_msg,
347 tbc);
348
349 GNUNET_array_append (ns->shandle, ns->n_shandle, sh);
350}
351
352
301/** 353/**
302 * Functions with this signature are called whenever a 354 * Functions with this signature are called whenever a
303 * complete message is received by the tokenizer. 355 * complete message is received by the tokenizer.
@@ -316,6 +368,7 @@ helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
316 struct TestingSystemCount *tbc = cls; 368 struct TestingSystemCount *tbc = cls;
317 struct NetJailState *ns = tbc->ns; 369 struct NetJailState *ns = tbc->ns;
318 struct HelperMessage *hp_msg; 370 struct HelperMessage *hp_msg;
371 unsigned int total_number = ns->local_m * ns->global_n + ns->known;
319 372
320 if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY == ntohs (message->type)) 373 if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY == ntohs (message->type))
321 { 374 {
@@ -325,11 +378,31 @@ helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
325 message->type)) 378 message->type))
326 { 379 {
327 ns->number_of_peers_started++; 380 ns->number_of_peers_started++;
381 if (ns->number_of_peers_started == total_number)
382 {
383 for (int i = 1; i <= ns->known; i++)
384 {
385 send_all_peers_started (0,i, ns);
386 }
387
388 for (int i = 1; i <= ns->global_n; i++)
389 {
390 for (int j = 1; j <= ns->local_m; j++)
391 {
392 send_all_peers_started (i,j, ns);
393 }
394 }
395 ns->number_of_peers_started = 0;
396 }
328 } 397 }
329 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED == ntohs ( 398 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED == ntohs (
330 message->type)) 399 message->type))
331 { 400 {
332 ns->number_of_local_test_finished++; 401 ns->number_of_local_test_finished++;
402 if (ns->number_of_local_test_finished == total_number)
403 {
404 GNUNET_TESTING_async_finish (&ns->ac);
405 }
333 } 406 }
334 else 407 else
335 { 408 {
@@ -340,6 +413,12 @@ helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
340 hp_msg); 413 hp_msg);
341 } 414 }
342 415
416
417
418
419
420
421
343 return GNUNET_OK; 422 return GNUNET_OK;
344} 423}
345 424
@@ -351,24 +430,21 @@ helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
351static void 430static void
352exp_cb (void *cls) 431exp_cb (void *cls)
353{ 432{
354 struct NetJailState *ns = cls; 433 struct TestingSystemCount *tbc = cls;
434
355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n"); 435 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
356 *ns->rv = 1; 436 GNUNET_TESTING_interpreter_fail (tbc->ns->ac.is);
357} 437}
358 438
359 439
360/** 440/**
361 * Function to initialize a init message for the helper. 441 * Function to initialize a init message for the helper.
362 * 442 *
363 * @param m_char The actual node in a namespace. //TODO Change this to unsigned int
364 * @param n_char The actual namespace. //TODO Change this to unsigned int
365 * @param plugin_name Name of the test case plugin the helper will load. 443 * @param plugin_name Name of the test case plugin the helper will load.
366 * 444 *
367 */ 445 */
368static struct GNUNET_CMDS_HelperInit * 446static struct GNUNET_CMDS_HelperInit *
369create_helper_init_msg_ (char *m_char, 447create_helper_init_msg_ (const char *plugin_name)
370 char *n_char,
371 const char *plugin_name)
372{ 448{
373 struct GNUNET_CMDS_HelperInit *msg; 449 struct GNUNET_CMDS_HelperInit *msg;
374 uint16_t plugin_name_len; 450 uint16_t plugin_name_len;
@@ -395,22 +471,49 @@ create_helper_init_msg_ (char *m_char,
395static void 471static void
396start_helper (struct NetJailState *ns, struct 472start_helper (struct NetJailState *ns, struct
397 GNUNET_CONFIGURATION_Handle *config, 473 GNUNET_CONFIGURATION_Handle *config,
398 char *m_char, 474 unsigned int m,
399 char *n_char) 475 unsigned int n)
400{ 476{
401 struct GNUNET_HELPER_Handle *helper; 477 struct GNUNET_HELPER_Handle *helper;
402 struct GNUNET_CMDS_HelperInit *msg; 478 struct GNUNET_CMDS_HelperInit *msg;
403 struct TestingSystemCount *tbc; 479 struct TestingSystemCount *tbc;
480 char *m_char, *n_char, *global_n_char, *local_m_char, *known_char, *node_id,
481 *plugin;
482 pid_t pid;
483 unsigned int script_num;
484 struct GNUNET_ShortHashCode *hkey;
485 struct GNUNET_HashCode hc;
486 struct GNUNET_TESTING_NetjailTopology *topology = ns->topology;
487 struct GNUNET_TESTING_NetjailNode *node;
488 struct GNUNET_TESTING_NetjailNamespace *namespace;
489
490
491 if (0 == n)
492 script_num = m - 1;
493 else
494 script_num = n - 1 + (n - 1) * ns->local_m + m + ns->known;
495 pid = getpid ();
496
497 GNUNET_asprintf (&m_char, "%u", m);
498 GNUNET_asprintf (&n_char, "%u", n);
499 GNUNET_asprintf (&local_m_char, "%u", ns->local_m);
500 GNUNET_asprintf (&global_n_char, "%u",ns->global_n);
501 GNUNET_asprintf (&known_char, "%u",ns->known);
502 GNUNET_asprintf (&node_id, "%06x-%08x\n",
503 pid,
504 script_num);
505
506
404 char *const script_argv[] = {NETJAIL_EXEC_SCRIPT, 507 char *const script_argv[] = {NETJAIL_EXEC_SCRIPT,
405 m_char, 508 m_char,
406 n_char, 509 n_char,
407 GNUNET_OS_get_libexec_binary_path ( 510 GNUNET_OS_get_libexec_binary_path (
408 HELPER_CMDS_BINARY), 511 HELPER_CMDS_BINARY),
409 ns->global_n, 512 global_n_char,
410 ns->local_m, 513 local_m_char,
514 node_id,
411 NULL}; 515 NULL};
412 unsigned int m = atoi (m_char); 516
413 unsigned int n = atoi (n_char);
414 unsigned int helper_check = GNUNET_OS_check_helper_binary ( 517 unsigned int helper_check = GNUNET_OS_check_helper_binary (
415 NETJAIL_EXEC_SCRIPT, 518 NETJAIL_EXEC_SCRIPT,
416 GNUNET_YES, 519 GNUNET_YES,
@@ -418,7 +521,10 @@ start_helper (struct NetJailState *ns, struct
418 521
419 tbc = GNUNET_new (struct TestingSystemCount); 522 tbc = GNUNET_new (struct TestingSystemCount);
420 tbc->ns = ns; 523 tbc->ns = ns;
421 tbc->count = (n - 1) * atoi (ns->local_m) + m; 524 if (0 == n)
525 tbc->count = m;
526 else
527 tbc->count = (n - 1) * ns->local_m + m + ns->known;
422 528
423 GNUNET_CONTAINER_DLL_insert (ns->tbcs_head, ns->tbcs_tail, 529 GNUNET_CONTAINER_DLL_insert (ns->tbcs_head, ns->tbcs_tail,
424 tbc); 530 tbc);
@@ -429,14 +535,14 @@ start_helper (struct NetJailState *ns, struct
429 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 535 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
430 "No SUID for %s!\n", 536 "No SUID for %s!\n",
431 NETJAIL_EXEC_SCRIPT); 537 NETJAIL_EXEC_SCRIPT);
432 *ns->rv = 1; 538 GNUNET_TESTING_interpreter_fail (ns->ac.is);
433 } 539 }
434 else if (GNUNET_NO == helper_check) 540 else if (GNUNET_NO == helper_check)
435 { 541 {
436 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 542 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
437 "%s not found!\n", 543 "%s not found!\n",
438 NETJAIL_EXEC_SCRIPT); 544 NETJAIL_EXEC_SCRIPT);
439 *ns->rv = 1; 545 GNUNET_TESTING_interpreter_fail (ns->ac.is);
440 } 546 }
441 547
442 GNUNET_array_append (ns->helper, ns->n_helper, GNUNET_HELPER_start ( 548 GNUNET_array_append (ns->helper, ns->n_helper, GNUNET_HELPER_start (
@@ -449,9 +555,57 @@ start_helper (struct NetJailState *ns, struct
449 555
450 helper = ns->helper[tbc->count - 1]; 556 helper = ns->helper[tbc->count - 1];
451 557
452 msg = create_helper_init_msg_ (m_char, 558 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
453 n_char, 559
454 ns->plugin_name); 560 plugin = topology->plugin;
561
562 if (0 == m)
563 {
564
565 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
566 memcpy (hkey,
567 &hc,
568 sizeof (*hkey));
569 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_globals,
570 hkey))
571 {
572 node = GNUNET_CONTAINER_multishortmap_get (topology->map_globals,
573 hkey);
574 if (NULL != node->plugin)
575 plugin = node->plugin;
576 }
577
578 }
579 else
580 {
581 GNUNET_CRYPTO_hash (&m, sizeof(m), &hc);
582 memcpy (hkey,
583 &hc,
584 sizeof (*hkey));
585 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_namespaces,
586 hkey))
587 {
588 namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces,
589 hkey);
590 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
591 memcpy (hkey,
592 &hc,
593 sizeof (*hkey));
594 if (1 == GNUNET_CONTAINER_multishortmap_contains (namespace->nodes,
595 hkey))
596 {
597 node = GNUNET_CONTAINER_multishortmap_get (namespace->nodes,
598 hkey);
599 if (NULL != node->plugin)
600 plugin = node->plugin;
601 }
602 }
603
604
605 }
606
607 msg = create_helper_init_msg_ (plugin);
608
455 GNUNET_array_append (ns->msg, ns->n_msg, &msg->header); 609 GNUNET_array_append (ns->msg, ns->n_msg, &msg->header);
456 610
457 GNUNET_array_append (ns->shandle, ns->n_shandle, GNUNET_HELPER_send ( 611 GNUNET_array_append (ns->shandle, ns->n_shandle, GNUNET_HELPER_send (
@@ -466,7 +620,7 @@ start_helper (struct NetJailState *ns, struct
466 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 620 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
467 "Send handle is NULL!\n"); 621 "Send handle is NULL!\n");
468 GNUNET_free (msg); 622 GNUNET_free (msg);
469 *ns->rv = 1; 623 GNUNET_TESTING_interpreter_fail (ns->ac.is);
470 } 624 }
471} 625}
472 626
@@ -480,95 +634,28 @@ start_helper (struct NetJailState *ns, struct
480*/ 634*/
481static void 635static void
482netjail_exec_run (void *cls, 636netjail_exec_run (void *cls,
483 const struct GNUNET_TESTING_Command *cmd,
484 struct GNUNET_TESTING_Interpreter *is) 637 struct GNUNET_TESTING_Interpreter *is)
485{ 638{
486 char str_m[12];
487 char str_n[12];
488 struct NetJailState *ns = cls; 639 struct NetJailState *ns = cls;
489 struct GNUNET_CONFIGURATION_Handle *config = 640 struct GNUNET_CONFIGURATION_Handle *config =
490 GNUNET_CONFIGURATION_create (); 641 GNUNET_CONFIGURATION_create ();
491 642
492 for (int i = 1; i <= atoi (ns->global_n); i++) 643 for (int i = 1; i <= ns->known; i++)
493 { 644 {
494 for (int j = 1; j <= atoi (ns->local_m); j++) 645 start_helper (ns, config,
495 { 646 i,
496 sprintf (str_n, "%d", i); 647 0);
497 sprintf (str_m, "%d", j);
498 start_helper (ns, config,
499 str_m,
500 str_n);
501 }
502 } 648 }
503}
504 649
505 650 for (int i = 1; i <= ns->global_n; i++)
506/**
507 * This function checks on three different information.
508 *
509 * 1. Did all helpers start. This is only logged.
510 * 2. Did all peer start.
511 * In this case a GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED is send to all peers.
512 * 3. Did all peers finished the test case. In this case interpreter_next will be called.
513 *
514 */
515static int
516netjail_start_finish (void *cls,
517 GNUNET_SCHEDULER_TaskCallback cont,
518 void *cont_cls)
519{
520 unsigned int ret = GNUNET_NO;
521 struct NetJailState *ns = cls;
522 unsigned int total_number = atoi (ns->local_m) * atoi (ns->global_n);
523 struct GNUNET_CMDS_ALL_PEERS_STARTED *reply;
524 size_t msg_length;
525 struct GNUNET_HELPER_Handle *helper;
526 struct TestingSystemCount *tbc;
527
528 if (ns->number_of_local_test_finished == total_number)
529 {
530 ret = GNUNET_YES;
531 cont (cont_cls);
532 }
533
534 if (ns->number_of_testsystems_started == total_number)
535 {
536 ns->number_of_testsystems_started = 0;
537 }
538
539 if (ns->number_of_peers_started == total_number)
540 { 651 {
541 for (int i = 1; i <= atoi (ns->global_n); i++) 652 for (int j = 1; j <= ns->local_m; j++)
542 { 653 {
543 for (int j = 1; j <= atoi (ns->local_m); j++) 654 start_helper (ns, config,
544 { 655 j,
545 tbc = GNUNET_new (struct TestingSystemCount); 656 i);
546 tbc->ns = ns;
547 // 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.
548 tbc->count = (i - 1) * atoi (ns->local_m) + j + total_number;
549
550 helper = ns->helper[tbc->count - 1 - total_number];
551 msg_length = sizeof(struct GNUNET_CMDS_ALL_PEERS_STARTED);
552 reply = GNUNET_new (struct GNUNET_CMDS_ALL_PEERS_STARTED);
553 reply->header.type = htons (
554 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
555 reply->header.size = htons ((uint16_t) msg_length);
556
557 GNUNET_array_append (ns->msg, ns->n_msg, &reply->header);
558
559 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
560 helper,
561 &reply->header,
562 GNUNET_NO,
563 &clear_msg,
564 tbc);
565
566 GNUNET_array_append (ns->shandle, ns->n_shandle, sh);
567 }
568 } 657 }
569 ns->number_of_peers_started = 0;
570 } 658 }
571 return ret;
572} 659}
573 660
574 661
@@ -576,32 +663,30 @@ netjail_start_finish (void *cls,
576 * Create command. 663 * Create command.
577 * 664 *
578 * @param label Name for the command. 665 * @param label Name for the command.
579 * @param local_m Number of nodes in a network namespace. //TODO make this a unsigned int 666 * @param topology_config Configuration file for the test topology.
580 * @param global_n Number of network namespaces. //TODO make this a unsigned int
581 * @param plugin_name Name of the test case plugin the helper will load.
582 * @param rv Pointer to the return value of the test.
583 * @return command. 667 * @return command.
584 */ 668 */
585struct GNUNET_TESTING_Command 669struct GNUNET_TESTING_Command
586GNUNET_TESTING_cmd_netjail_start_testing_system (const char *label, 670GNUNET_TESTING_cmd_netjail_start_testing_system (const char *label,
587 char *local_m, 671 const char *topology_config)
588 char *global_n,
589 char *plugin_name,
590 unsigned int *rv)
591{ 672{
592 struct NetJailState *ns; 673 struct NetJailState *ns;
593 674
675 struct GNUNET_TESTING_NetjailTopology *topology =
676 GNUNET_TESTING_get_topo_from_file (topology_config);
677
594 ns = GNUNET_new (struct NetJailState); 678 ns = GNUNET_new (struct NetJailState);
595 ns->local_m = local_m; 679 ns->local_m = topology->nodes_m;
596 ns->global_n = global_n; 680 ns->global_n = topology->namespaces_n;
597 ns->plugin_name = plugin_name; 681 ns->known = topology->nodes_x;
598 ns->rv = rv; 682 ns->plugin_name = topology->plugin;
683 ns->topology = topology;
599 684
600 struct GNUNET_TESTING_Command cmd = { 685 struct GNUNET_TESTING_Command cmd = {
601 .cls = ns, 686 .cls = ns,
602 .label = label, 687 .label = label,
603 .run = &netjail_exec_run, 688 .run = &netjail_exec_run,
604 .finish = &netjail_start_finish, 689 .ac = &ns->ac,
605 .cleanup = &netjail_exec_cleanup, 690 .cleanup = &netjail_exec_cleanup,
606 .traits = &netjail_exec_traits 691 .traits = &netjail_exec_traits
607 }; 692 };
diff --git a/src/testing/testing_api_cmd_netjail_start_testsystem_v2.c b/src/testing/testing_api_cmd_netjail_start_testsystem_v2.c
deleted file mode 100644
index 5e27a7a82..000000000
--- a/src/testing/testing_api_cmd_netjail_start_testsystem_v2.c
+++ /dev/null
@@ -1,809 +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 "testing_cmds.h"
29
30#define NETJAIL_EXEC_SCRIPT "./../testing/netjail_exec_v2.sh"
31
32/**
33 * Generic logging shortcut
34 */
35#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
36
37/**
38 * Struct to store messages send/received by the helper into a DLL
39 *
40 */
41struct HelperMessage
42{
43
44 /**
45 * Kept in a DLL.
46 */
47 struct HelperMessage *next;
48
49 /**
50 * Kept in a DLL.
51 */
52 struct HelperMessage *prev;
53
54 /**
55 * Size of the original message.
56 */
57 uint16_t bytes_msg;
58
59 /* Followed by @e bytes_msg of msg.*/
60};
61
62
63/**
64 * Struct to store information handed over to callbacks.
65 *
66 */
67struct NetJailState
68{
69 /**
70 * The complete topology information.
71 */
72 struct GNUNET_TESTING_NetjailTopology *topology;
73
74 /**
75 * Pointer to the return value of the test.
76 *
77 */
78 unsigned int *rv;
79
80 /**
81 * Head of the DLL which stores messages received by the helper.
82 *
83 */
84 struct HelperMessage *hp_messages_head;
85
86 /**
87 * Tail of the DLL which stores messages received by the helper.
88 *
89 */
90 struct HelperMessage *hp_messages_tail;
91
92 /**
93 * Array with handles of helper processes.
94 */
95 struct GNUNET_HELPER_Handle **helper;
96
97 /**
98 * Size of the array NetJailState#helper.
99 *
100 */
101 unsigned int n_helper;
102
103 /**
104 * Number of nodes in a natted subnet.
105 *
106 */
107 unsigned int local_m;
108
109 /**
110 * Number of natted subnets.
111 *
112 */
113 unsigned int global_n;
114
115 /**
116 * Number of global known nodes.
117 *
118 */
119 unsigned int known;
120
121 /**
122 * The send handle for the helper
123 */
124 // struct GNUNET_HELPER_SendHandle **shandle;
125
126 /**
127 * Size of the array NetJailState#shandle.
128 *
129 */
130 // unsigned int n_shandle;
131
132 /**
133 * The messages send to the helper.
134 */
135 struct GNUNET_MessageHeader **msg;
136
137 /**
138 * Size of the array NetJailState#msg.
139 *
140 */
141 unsigned int n_msg;
142
143 /**
144 * Number of test environments started.
145 *
146 */
147 unsigned int number_of_testsystems_started;
148
149 /**
150 * Number of peers started.
151 *
152 */
153 unsigned int number_of_peers_started;
154
155 /**
156 * Number of local tests finished.
157 *
158 */
159 unsigned int number_of_local_tests_finished;
160
161 /**
162 * Number of local tests prepared to finish.
163 *
164 */
165 unsigned int number_of_local_tests_prepared;
166
167 /**
168 * Name of the test case plugin the helper will load.
169 *
170 */
171 char *plugin_name;
172
173 /**
174 * HEAD of the DLL containing TestingSystemCount.
175 *
176 */
177 struct TestingSystemCount *tbcs_head;
178
179 /**
180 * TAIL of the DLL containing TestingSystemCount.
181 *
182 */
183 struct TestingSystemCount *tbcs_tail;
184};
185
186/**
187 * Struct containing the number of the test environment and the NetJailState which
188 * will be handed to callbacks specific to a test environment.
189 */
190struct TestingSystemCount
191{
192 /**
193 * Kept in a DLL.
194 */
195 struct TestingSystemCount *next;
196
197 /**
198 * Kept in a DLL.
199 */
200 struct TestingSystemCount *prev;
201
202 /**
203 * The send handle for the helper
204 */
205 struct GNUNET_HELPER_SendHandle *shandle;// **shandle;
206
207 /**
208 * Size of the array NetJailState#shandle.
209 *
210 */
211 // unsigned int n_shandle;
212
213 /**
214 * The number of the test environment.
215 *
216 */
217 unsigned int count;
218
219 /**
220 * Struct to store information handed over to callbacks.
221 *
222 */
223 struct NetJailState *ns;
224};
225
226/**
227* Code to clean up resource this cmd used.
228*
229* @param cls closure
230* @param cmd current CMD being cleaned up.
231*/
232static void
233netjail_exec_cleanup (void *cls,
234 const struct GNUNET_TESTING_Command *cmd)
235{
236 struct NetJailState *ns = cls;
237 struct HelperMessage *message_pos;
238 struct TestingSystemCount *tbc_pos;
239
240 while (NULL != (message_pos = ns->hp_messages_head))
241 {
242 GNUNET_CONTAINER_DLL_remove (ns->hp_messages_head,
243 ns->hp_messages_tail,
244 message_pos);
245 GNUNET_free (message_pos);
246 }
247 while (NULL != (tbc_pos = ns->tbcs_head))
248 {
249 GNUNET_CONTAINER_DLL_remove (ns->tbcs_head,
250 ns->tbcs_tail,
251 tbc_pos);
252 GNUNET_free (tbc_pos);
253 }
254 GNUNET_free (ns);
255}
256
257
258/**
259 * This function prepares an array with traits.
260 *
261 */
262static int
263netjail_exec_traits (void *cls,
264 const void **ret,
265 const char *trait,
266 unsigned int index)
267{
268 struct NetJailState *ns = cls;
269 struct GNUNET_HELPER_Handle **helper = ns->helper;
270 struct HelperMessage *hp_messages_head = ns->hp_messages_head;
271
272
273 struct GNUNET_TESTING_Trait traits[] = {
274 {
275 .index = 0,
276 .trait_name = "helper_handles",
277 .ptr = (const void *) helper,
278 },
279 {
280 .index = 1,
281 .trait_name = "hp_msgs_head",
282 .ptr = (const void *) hp_messages_head,
283 },
284 GNUNET_TESTING_trait_end ()
285 };
286
287 return GNUNET_TESTING_get_trait (traits,
288 ret,
289 trait,
290 index);
291}
292
293
294/**
295 * Offer handles to testing cmd helper from trait
296 *
297 * @param cmd command to extract the message from.
298 * @param pt pointer to message.
299 * @return #GNUNET_OK on success.
300 */
301int
302GNUNET_TESTING_get_trait_helper_handles_v2 (
303 const struct GNUNET_TESTING_Command *cmd,
304 struct GNUNET_HELPER_Handle ***helper)
305{
306 return cmd->traits (cmd->cls,
307 (const void **) helper,
308 "helper_handles",
309 (unsigned int) 0);
310}
311
312
313/**
314 * Continuation function from GNUNET_HELPER_send()
315 *
316 * @param cls closure
317 * @param result #GNUNET_OK on success,
318 * #GNUNET_NO if helper process died
319 * #GNUNET_SYSERR during GNUNET_HELPER_stop
320 */
321static void
322clear_msg (void *cls,
323 int result)
324{
325 struct TestingSystemCount *tbc = cls;
326 struct NetJailState *ns = tbc->ns;
327
328 GNUNET_assert (NULL != tbc->shandle);// [tbc->count - 1]);
329 tbc->shandle = NULL;// [tbc->count - 1] = NULL;
330 GNUNET_free (ns->msg[tbc->count - 1]);
331 ns->msg[tbc->count - 1] = NULL;
332}
333
334
335/**
336 * Functions with this signature are called whenever a
337 * complete message is received by the tokenizer.
338 *
339 * Do not call GNUNET_SERVER_mst_destroy in callback
340 *
341 * @param cls closure
342 * @param client identification of the client
343 * @param message the actual message
344 *
345 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
346 */
347static int
348helper_mst (void *cls,
349 const struct GNUNET_MessageHeader *message)
350{
351 // struct TestingSystemCount *tbc = cls;
352 struct NetJailState *ns = cls;// tbc->ns;
353 struct HelperMessage *hp_msg;
354
355 if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY == ntohs (message->type))
356 {
357 ns->number_of_testsystems_started++;
358 }
359 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED == ntohs (
360 message->type))
361 {
362 ns->number_of_peers_started++;
363 }
364 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED == ntohs (
365 message->type))
366 {
367 LOG (GNUNET_ERROR_TYPE_DEBUG,
368 "received prepare msg %u\n",
369 ns->number_of_local_tests_prepared);
370 ns->number_of_local_tests_prepared++;
371 }
372 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED == ntohs (
373 message->type))
374 {
375 ns->number_of_local_tests_finished++;
376 }
377 else
378 {
379 hp_msg = GNUNET_new (struct HelperMessage);
380 hp_msg->bytes_msg = message->size;
381 memcpy (&hp_msg[1], message, message->size);
382 GNUNET_CONTAINER_DLL_insert (ns->hp_messages_head, ns->hp_messages_tail,
383 hp_msg);
384 }
385
386 return GNUNET_OK;
387}
388
389
390/**
391 * Callback called if there was an exception during execution of the helper.
392 *
393 */
394static void
395exp_cb (void *cls)
396{
397 struct NetJailState *ns = cls;
398 unsigned int *rv = ns->rv;
399
400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
401 *rv = 1;
402}
403
404
405/**
406 * Function to initialize a init message for the helper.
407 *
408 * @param m_char The actual node in a namespace. //TODO Change this to unsigned int
409 * @param n_char The actual namespace. //TODO Change this to unsigned int
410 * @param plugin_name Name of the test case plugin the helper will load.
411 *
412 */
413static struct GNUNET_CMDS_HelperInit *
414create_helper_init_msg_ (const char *plugin_name)
415{
416 struct GNUNET_CMDS_HelperInit *msg;
417 uint16_t plugin_name_len;
418 uint16_t msg_size;
419
420 GNUNET_assert (NULL != plugin_name);
421 plugin_name_len = strlen (plugin_name);
422 msg_size = sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_len;
423 msg = GNUNET_malloc (msg_size);
424 msg->header.size = htons (msg_size);
425 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT);
426 msg->plugin_name_size = htons (plugin_name_len);
427 GNUNET_memcpy ((char *) &msg[1],
428 plugin_name,
429 plugin_name_len);
430 return msg;
431}
432
433
434/**
435 * Function which start a single helper process.
436 *
437 */
438static void
439start_helper (struct NetJailState *ns, struct
440 GNUNET_CONFIGURATION_Handle *config,
441 unsigned int m,
442 unsigned int n)
443{
444 struct GNUNET_HELPER_Handle *helper;
445 struct GNUNET_CMDS_HelperInit *msg;
446 struct TestingSystemCount *tbc;
447 char *m_char, *n_char, *global_n_char, *local_m_char, *known_char, *node_id,
448 *plugin;
449 pid_t pid;
450 unsigned int script_num;
451 struct GNUNET_ShortHashCode *hkey;
452 struct GNUNET_HashCode hc;
453 struct GNUNET_TESTING_NetjailTopology *topology = ns->topology;
454 struct GNUNET_TESTING_NetjailNode *node;
455 struct GNUNET_TESTING_NetjailNamespace *namespace;
456 unsigned int *rv = ns->rv;
457
458
459 if (0 == n)
460 script_num = m - 1;
461 else
462 script_num = n - 1 + (n - 1) * ns->local_m + m + ns->known;
463 pid = getpid ();
464
465 GNUNET_asprintf (&m_char, "%u", m);
466 GNUNET_asprintf (&n_char, "%u", n);
467 GNUNET_asprintf (&local_m_char, "%u", ns->local_m);
468 GNUNET_asprintf (&global_n_char, "%u",ns->global_n);
469 GNUNET_asprintf (&known_char, "%u",ns->known);
470 GNUNET_asprintf (&node_id, "%06x-%08x\n",
471 pid,
472 script_num);
473
474
475 char *const script_argv[] = {NETJAIL_EXEC_SCRIPT,
476 m_char,
477 n_char,
478 GNUNET_OS_get_libexec_binary_path (
479 HELPER_CMDS_BINARY),
480 global_n_char,
481 local_m_char,
482 node_id,
483 NULL};
484
485 unsigned int helper_check = GNUNET_OS_check_helper_binary (
486 NETJAIL_EXEC_SCRIPT,
487 GNUNET_YES,
488 NULL);
489
490 tbc = GNUNET_new (struct TestingSystemCount);
491 tbc->ns = ns;
492 if (0 == n)
493 tbc->count = m;
494 else
495 tbc->count = (n - 1) * ns->local_m + m + ns->known;
496
497 GNUNET_CONTAINER_DLL_insert (ns->tbcs_head,
498 ns->tbcs_tail,
499 tbc);
500
501
502 if (GNUNET_NO == helper_check)
503 {
504 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
505 "No SUID for %s!\n",
506 NETJAIL_EXEC_SCRIPT);
507 *rv = 1;
508 }
509 else if (GNUNET_NO == helper_check)
510 {
511 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
512 "%s not found!\n",
513 NETJAIL_EXEC_SCRIPT);
514 *rv = 1;
515 }
516
517 GNUNET_array_append (ns->helper, ns->n_helper, GNUNET_HELPER_start (
518 GNUNET_YES,
519 NETJAIL_EXEC_SCRIPT,
520 script_argv,
521 &helper_mst,
522 &exp_cb,
523 ns));
524
525 helper = ns->helper[tbc->count - 1];
526
527 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
528
529 plugin = topology->plugin;
530
531 if (0 == m)
532 {
533
534 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
535 memcpy (hkey,
536 &hc,
537 sizeof (*hkey));
538 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_globals,
539 hkey))
540 {
541 node = GNUNET_CONTAINER_multishortmap_get (topology->map_globals,
542 hkey);
543 if (NULL != node->plugin)
544 plugin = node->plugin;
545 }
546
547 }
548 else
549 {
550 GNUNET_CRYPTO_hash (&m, sizeof(m), &hc);
551 memcpy (hkey,
552 &hc,
553 sizeof (*hkey));
554 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_namespaces,
555 hkey))
556 {
557 namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces,
558 hkey);
559 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
560 memcpy (hkey,
561 &hc,
562 sizeof (*hkey));
563 if (1 == GNUNET_CONTAINER_multishortmap_contains (namespace->nodes,
564 hkey))
565 {
566 node = GNUNET_CONTAINER_multishortmap_get (namespace->nodes,
567 hkey);
568 if (NULL != node->plugin)
569 plugin = node->plugin;
570 }
571 }
572
573
574 }
575
576 msg = create_helper_init_msg_ (plugin);
577
578 GNUNET_array_append (ns->msg, ns->n_msg, &msg->header);
579
580 // GNUNET_array_append (tbc->shandle, tbc->n_shandle,
581 tbc->shandle = GNUNET_HELPER_send (
582 helper,
583 &msg->header,
584 GNUNET_NO,
585 &clear_msg,
586 tbc); // );
587
588 if (NULL == tbc->shandle)// [tbc->count - 1])
589 {
590 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
591 "Send handle is NULL!\n");
592 GNUNET_free (msg);
593 *rv = 1;
594 }
595}
596
597
598/**
599* This function starts a helper process for each node.
600*
601* @param cls closure.
602* @param cmd CMD being run.
603* @param is interpreter state.
604*/
605static void
606netjail_exec_run (void *cls,
607 const struct GNUNET_TESTING_Command *cmd,
608 struct GNUNET_TESTING_Interpreter *is)
609{
610 struct NetJailState *ns = cls;
611 struct GNUNET_CONFIGURATION_Handle *config =
612 GNUNET_CONFIGURATION_create ();
613
614 for (int i = 1; i <= ns->known; i++)
615 {
616 start_helper (ns, config,
617 i,
618 0);
619 }
620
621 for (int i = 1; i <= ns->global_n; i++)
622 {
623 for (int j = 1; j <= ns->local_m; j++)
624 {
625 start_helper (ns, config,
626 j,
627 i);
628 }
629 }
630}
631
632
633static void
634send_message_to_locals (
635 unsigned int i,
636 unsigned int j,
637 struct NetJailState *ns,
638 struct GNUNET_MessageHeader *header
639 )
640{
641 // unsigned int total_number = ns->local_m * ns->global_n + ns->known;
642 struct GNUNET_HELPER_Handle *helper;
643 struct TestingSystemCount *tbc;
644
645 LOG (GNUNET_ERROR_TYPE_DEBUG,
646 "send message to locals\n");
647 tbc = GNUNET_new (struct TestingSystemCount);
648 tbc->ns = ns;
649 // 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.
650 if (0 == i)
651 tbc->count = j; // + total_number;
652 else
653 tbc->count = (i - 1) * ns->local_m + j + ns->known; // + total_number ;
654
655 helper = ns->helper[tbc->count - 1];// - total_number];
656
657 GNUNET_array_append (ns->msg, ns->n_msg, header);
658
659 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
660 helper,
661 header,
662 GNUNET_NO,
663 &clear_msg,
664 tbc);
665
666 tbc->shandle = sh;
667 // GNUNET_array_append (tbc->shandle, tbc->n_shandle, sh);
668}
669
670
671static void
672send_all_local_tests_prepared (unsigned int i, unsigned int j, struct
673 NetJailState *ns)
674{
675 struct GNUNET_CMDS_ALL_LOCAL_TESTS_PREPARED *reply;
676 size_t msg_length;
677
678
679 msg_length = sizeof(struct GNUNET_CMDS_ALL_LOCAL_TESTS_PREPARED);
680 reply = GNUNET_new (struct GNUNET_CMDS_ALL_LOCAL_TESTS_PREPARED);
681 reply->header.type = htons (
682 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_LOCAL_TESTS_PREPARED);
683 reply->header.size = htons ((uint16_t) msg_length);
684
685 send_message_to_locals (i, j, ns, &reply->header);
686}
687
688
689static void
690send_all_peers_started (unsigned int i, unsigned int j, struct NetJailState *ns)
691{
692
693 struct GNUNET_CMDS_ALL_PEERS_STARTED *reply;
694 size_t msg_length;
695
696
697 msg_length = sizeof(struct GNUNET_CMDS_ALL_PEERS_STARTED);
698 reply = GNUNET_new (struct GNUNET_CMDS_ALL_PEERS_STARTED);
699 reply->header.type = htons (
700 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
701 reply->header.size = htons ((uint16_t) msg_length);
702
703 send_message_to_locals (i, j, ns, &reply->header);
704}
705
706
707/**
708 * This function checks on three different information.
709 *
710 * 1. Did all helpers start. This is only logged.
711 * 2. Did all peer start.
712 * In this case a GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED is send to all peers.
713 * 3. Did all peers finished the test case. In this case interpreter_next will be called.
714 *
715 */
716static int
717netjail_start_finish (void *cls,
718 GNUNET_SCHEDULER_TaskCallback cont,
719 void *cont_cls)
720{
721 unsigned int ret = GNUNET_NO;
722 struct NetJailState *ns = cls;
723 unsigned int total_number = ns->local_m * ns->global_n + ns->known;
724
725
726 if (ns->number_of_local_tests_finished == total_number)
727 {
728 ret = GNUNET_YES;
729 cont (cont_cls);
730 }
731
732 if (ns->number_of_local_tests_prepared == total_number)
733 {
734 for (int i = 1; i <= ns->known; i++)
735 {
736 send_all_local_tests_prepared (0,i, ns);
737 }
738
739 for (int i = 1; i <= ns->global_n; i++)
740 {
741 for (int j = 1; j <= ns->local_m; j++)
742 {
743 send_all_local_tests_prepared (i,j, ns);
744 }
745 }
746 }
747
748 if (ns->number_of_testsystems_started == total_number)
749 {
750 ns->number_of_testsystems_started = 0;
751 }
752
753 if (ns->number_of_peers_started == total_number)
754 {
755 for (int i = 1; i <= ns->known; i++)
756 {
757 send_all_peers_started (0,i, ns);
758 }
759
760 for (int i = 1; i <= ns->global_n; i++)
761 {
762 for (int j = 1; j <= ns->local_m; j++)
763 {
764 send_all_peers_started (i,j, ns);
765 }
766 }
767 ns->number_of_peers_started = 0;
768 }
769 return ret;
770}
771
772
773/**
774 * Create command.
775 *
776 * @param label Name for the command.
777 * @param topology_config Configuration file for the test topology.
778 * @param rv Pointer to the return value of the test.
779 * @return command.
780 */
781struct GNUNET_TESTING_Command
782GNUNET_TESTING_cmd_netjail_start_testing_system_v2 (const char *label,
783 const char *topology_config,
784 unsigned int *rv)
785{
786 struct NetJailState *ns;
787
788 struct GNUNET_TESTING_NetjailTopology *topology =
789 GNUNET_TESTING_get_topo_from_file (topology_config);
790
791 ns = GNUNET_new (struct NetJailState);
792 ns->rv = rv;
793 ns->local_m = topology->nodes_m;
794 ns->global_n = topology->namespaces_n;
795 ns->known = topology->nodes_x;
796 ns->plugin_name = topology->plugin;
797 ns->topology = topology;
798
799 struct GNUNET_TESTING_Command cmd = {
800 .cls = ns,
801 .label = label,
802 .run = &netjail_exec_run,
803 .finish = &netjail_start_finish,
804 .cleanup = &netjail_exec_cleanup,
805 .traits = &netjail_exec_traits
806 };
807
808 return cmd;
809}
diff --git a/src/testing/testing_api_cmd_netjail_start_v2.c b/src/testing/testing_api_cmd_netjail_start_v2.c
deleted file mode 100644
index 7d802db6a..000000000
--- a/src/testing/testing_api_cmd_netjail_start_v2.c
+++ /dev/null
@@ -1,229 +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 script.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29
30#define NETJAIL_START_SCRIPT "./../testing/netjail_start_v2.sh"
31
32/**
33 * Struct to hold information for callbacks.
34 *
35 */
36struct NetJailState
37{
38 // Child Wait handle
39 struct GNUNET_ChildWaitHandle *cwh;
40
41 /**
42 * Configuration file for the test topology.
43 */
44 char *topology_config;
45
46 /**
47 * The process id of the start script.
48 */
49 struct GNUNET_OS_Process *start_proc;
50
51 // Flag indication if the script finished.
52 unsigned int finished;
53};
54
55
56/**
57 * The cleanup function of this cmd frees resources the cmd allocated.
58 *
59 */
60static void
61netjail_start_cleanup (void *cls,
62 const struct GNUNET_TESTING_Command *cmd)
63{
64 struct NetJailState *ns = cls;
65
66 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
67 "netjail_start_cleanup!\n");
68
69 if (NULL != ns->cwh)
70 {
71 GNUNET_wait_child_cancel (ns->cwh);
72 ns->cwh = NULL;
73 }
74 if (NULL != ns->start_proc)
75 {
76 GNUNET_assert (0 ==
77 GNUNET_OS_process_kill (ns->start_proc,
78 SIGTERM));
79 GNUNET_assert (GNUNET_OK ==
80 GNUNET_OS_process_wait (ns->start_proc));
81 GNUNET_OS_process_destroy (ns->start_proc);
82 ns->start_proc = NULL;
83 }
84 GNUNET_free (ns);
85}
86
87
88/**
89 * Trait function of this cmd does nothing.
90 *
91 */
92static int
93netjail_start_traits (void *cls,
94 const void **ret,
95 const char *trait,
96 unsigned int index)
97{
98 return GNUNET_OK;
99}
100
101
102/**
103 * Callback which will be called if the setup script finished.
104 *
105 */
106static void
107child_completed_callback (void *cls,
108 enum GNUNET_OS_ProcessStatusType type,
109 long unsigned int exit_code)
110{
111 struct NetJailState *ns = cls;
112
113 if (0 == exit_code)
114 {
115 ns->finished = GNUNET_YES;
116 }
117 else
118 {
119 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
120 "Child completed with an error!\n");
121 ns->finished = GNUNET_SYSERR;
122 }
123 GNUNET_OS_process_destroy (ns->start_proc);
124 ns->start_proc = NULL;
125}
126
127
128
129/**
130* The run method starts the script which setup the network namespaces.
131*
132* @param cls closure.
133* @param cmd CMD being run.
134* @param is interpreter state.
135*/
136static void
137netjail_start_run (void *cls,
138 const struct GNUNET_TESTING_Command *cmd,
139 struct GNUNET_TESTING_Interpreter *is)
140{
141 struct NetJailState *ns = cls;
142 char *pid;
143 GNUNET_asprintf (&pid,
144 "%u",
145 getpid ());
146 char *const script_argv[] = {NETJAIL_START_SCRIPT,
147 ns->topology_config,
148 pid,
149 NULL};
150 unsigned int helper_check = GNUNET_OS_check_helper_binary (
151 NETJAIL_START_SCRIPT,
152 GNUNET_YES,
153 NULL);
154
155 if (GNUNET_NO == helper_check)
156 {
157 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
158 "No SUID for %s!\n",
159 NETJAIL_START_SCRIPT);
160 GNUNET_TESTING_interpreter_fail ();
161 }
162 else if (GNUNET_NO == helper_check)
163 {
164 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
165 "%s not found!\n",
166 NETJAIL_START_SCRIPT);
167 GNUNET_TESTING_interpreter_fail ();
168 }
169
170 ns->start_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
171 NULL,
172 NULL,
173 NULL,
174 NETJAIL_START_SCRIPT,
175 script_argv);
176
177 ns->cwh = GNUNET_wait_child (ns->start_proc,
178 &child_completed_callback,
179 ns);
180 GNUNET_break (NULL != ns->cwh);
181}
182
183
184/**
185 * This function checks the flag NetJailState#finished, if this cmd finished.
186 *
187 */
188static int
189netjail_start_finish (void *cls,
190 GNUNET_SCHEDULER_TaskCallback cont,
191 void *cont_cls)
192{
193 struct NetJailState *ns = cls;
194
195 if (ns->finished)
196 {
197 cont (cont_cls);
198 }
199 return ns->finished;
200}
201
202/**
203 * Create command.
204 *
205 * @param label name for command.
206 * @param topology_config Configuration file for the test topology.
207 * @return command.
208 */
209struct GNUNET_TESTING_Command
210GNUNET_TESTING_cmd_netjail_start_v2 (const char *label,
211 char *topology_config)
212{
213 struct NetJailState *ns;
214
215 ns = GNUNET_new (struct NetJailState);
216 ns->finished = GNUNET_NO;
217 ns->topology_config = topology_config;
218
219 struct GNUNET_TESTING_Command cmd = {
220 .cls = ns,
221 .label = label,
222 .run = &netjail_start_run,
223 .finish = &netjail_start_finish,
224 .cleanup = &netjail_start_cleanup,
225 .traits = &netjail_start_traits
226 };
227
228 return cmd;
229}
diff --git a/src/testing/testing_api_cmd_netjail_stop.c b/src/testing/testing_api_cmd_netjail_stop.c
index 99084d9af..5033272a3 100644
--- a/src/testing/testing_api_cmd_netjail_stop.c
+++ b/src/testing/testing_api_cmd_netjail_stop.c
@@ -19,7 +19,7 @@
19 */ 19 */
20 20
21/** 21/**
22 * @file testing/testing_api_cmd_hello_world.c 22 * @file testing/testing_api_cmd_netjail_stop.c
23 * @brief Command to stop the netjail script. 23 * @brief Command to stop the netjail script.
24 * @author t3sserakt 24 * @author t3sserakt
25 */ 25 */
@@ -31,7 +31,7 @@
31#define NETJAIL_STOP_SCRIPT "./../testing/netjail_stop.sh" 31#define NETJAIL_STOP_SCRIPT "./../testing/netjail_stop.sh"
32 32
33// Child Wait handle 33// Child Wait handle
34struct GNUNET_ChildWaitHandle *cwh; 34static struct GNUNET_ChildWaitHandle *cwh;
35 35
36/** 36/**
37 * Struct to hold information for callbacks. 37 * Struct to hold information for callbacks.
@@ -39,19 +39,21 @@ struct GNUNET_ChildWaitHandle *cwh;
39 */ 39 */
40struct NetJailState 40struct NetJailState
41{ 41{
42 // Number of local nodes in each namespace. 42 /**
43 char *local_m; 43 * Context for our asynchronous completion.
44 */
45 struct GNUNET_TESTING_AsyncContext ac;
44 46
45 // The number of namespaces. 47 /**
46 char *global_n; 48 * Configuration file for the test topology.
49 */
50 char *topology_config;
47 51
48 /** 52 /**
49 * The process id of the start script. 53 * The process id of the start script.
50 */ 54 */
51 struct GNUNET_OS_Process *stop_proc; 55 struct GNUNET_OS_Process *stop_proc;
52 56
53 // Flag indication if the script finished.
54 unsigned int finished;
55}; 57};
56 58
57 59
@@ -60,8 +62,7 @@ struct NetJailState
60 * 62 *
61 */ 63 */
62static void 64static void
63netjail_stop_cleanup (void *cls, 65netjail_stop_cleanup (void *cls)
64 const struct GNUNET_TESTING_Command *cmd)
65{ 66{
66 struct NetJailState *ns = cls; 67 struct NetJailState *ns = cls;
67 68
@@ -84,20 +85,6 @@ netjail_stop_cleanup (void *cls,
84 85
85 86
86/** 87/**
87 * Trait function of this cmd does nothing.
88 *
89 */
90static int
91netjail_stop_traits (void *cls,
92 const void **ret,
93 const char *trait,
94 unsigned int index)
95{
96 return GNUNET_OK;
97}
98
99
100/**
101 * Callback which will be called if the setup script finished. 88 * Callback which will be called if the setup script finished.
102 * 89 *
103 */ 90 */
@@ -108,17 +95,17 @@ child_completed_callback (void *cls,
108{ 95{
109 struct NetJailState *ns = cls; 96 struct NetJailState *ns = cls;
110 97
111 cwh = NULL; 98 cwh = NULL; // WTF? globals!?!?!
99 GNUNET_OS_process_destroy (ns->stop_proc);
100 ns->stop_proc = NULL;
112 if (0 == exit_code) 101 if (0 == exit_code)
113 { 102 {
114 ns->finished = GNUNET_YES; 103 GNUNET_TESTING_async_finish (&ns->ac);
115 } 104 }
116 else 105 else
117 { 106 {
118 ns->finished = GNUNET_SYSERR; 107 GNUNET_TESTING_async_fail (&ns->ac);
119 } 108 }
120 GNUNET_OS_process_destroy (ns->stop_proc);
121 ns->stop_proc = NULL;
122} 109}
123 110
124 111
@@ -126,18 +113,21 @@ child_completed_callback (void *cls,
126* The run method starts the script which deletes the network namespaces. 113* The run method starts the script which deletes the network namespaces.
127* 114*
128* @param cls closure. 115* @param cls closure.
129* @param cmd CMD being run.
130* @param is interpreter state. 116* @param is interpreter state.
131*/ 117*/
132static void 118static void
133netjail_stop_run (void *cls, 119netjail_stop_run (void *cls,
134 const struct GNUNET_TESTING_Command *cmd,
135 struct GNUNET_TESTING_Interpreter *is) 120 struct GNUNET_TESTING_Interpreter *is)
136{ 121{
137 struct NetJailState *ns = cls; 122 struct NetJailState *ns = cls;
123 char *pid;
124
125 GNUNET_asprintf (&pid,
126 "%u",
127 getpid ());
138 char *const script_argv[] = {NETJAIL_STOP_SCRIPT, 128 char *const script_argv[] = {NETJAIL_STOP_SCRIPT,
139 ns->local_m, 129 ns->topology_config,
140 ns->global_n, 130 pid,
141 NULL}; 131 NULL};
142 unsigned int helper_check = GNUNET_OS_check_helper_binary ( 132 unsigned int helper_check = GNUNET_OS_check_helper_binary (
143 NETJAIL_STOP_SCRIPT, 133 NETJAIL_STOP_SCRIPT,
@@ -149,14 +139,14 @@ netjail_stop_run (void *cls,
149 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 139 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
150 "No SUID for %s!\n", 140 "No SUID for %s!\n",
151 NETJAIL_STOP_SCRIPT); 141 NETJAIL_STOP_SCRIPT);
152 GNUNET_TESTING_interpreter_fail (); 142 GNUNET_TESTING_interpreter_fail (is);
153 } 143 }
154 else if (GNUNET_NO == helper_check) 144 else if (GNUNET_NO == helper_check)
155 { 145 {
156 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 146 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
157 "%s not found!\n", 147 "%s not found!\n",
158 NETJAIL_STOP_SCRIPT); 148 NETJAIL_STOP_SCRIPT);
159 GNUNET_TESTING_interpreter_fail (); 149 GNUNET_TESTING_interpreter_fail (is);
160 } 150 }
161 151
162 ns->stop_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR, 152 ns->stop_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
@@ -170,56 +160,26 @@ netjail_stop_run (void *cls,
170 &child_completed_callback, 160 &child_completed_callback,
171 ns); 161 ns);
172 GNUNET_break (NULL != cwh); 162 GNUNET_break (NULL != cwh);
173
174} 163}
175 164
176 165
177/**
178 * This function checks the flag NetJailState#finished, if this cmd finished.
179 *
180 */
181static int
182netjail_stop_finish (void *cls,
183 GNUNET_SCHEDULER_TaskCallback cont,
184 void *cont_cls)
185{
186 struct NetJailState *ns = cls;
187
188 if (ns->finished)
189 {
190 cont (cont_cls);
191 }
192 return ns->finished;
193}
194
195
196/**
197 * Create command.
198 *
199 * @param label name for command.
200 * @param local_m Number of local nodes in each namespace.
201 * @param global_n The number of namespaces.
202 * @return command.
203 */
204struct GNUNET_TESTING_Command 166struct GNUNET_TESTING_Command
205GNUNET_TESTING_cmd_netjail_stop (const char *label, 167GNUNET_TESTING_cmd_netjail_stop (const char *label,
206 char *local_m, 168 char *topology_config)
207 char *global_n)
208{ 169{
209 struct NetJailState *ns; 170 struct NetJailState *ns;
210 171
211 ns = GNUNET_new (struct NetJailState); 172 ns = GNUNET_new (struct NetJailState);
212 ns->local_m = local_m; 173 ns->topology_config = topology_config;
213 ns->global_n = global_n; 174 {
214 175 struct GNUNET_TESTING_Command cmd = {
215 struct GNUNET_TESTING_Command cmd = { 176 .cls = ns,
216 .cls = ns, 177 .label = label,
217 .label = label, 178 .run = &netjail_stop_run,
218 .run = &netjail_stop_run, 179 .ac = &ns->ac,
219 .finish = &netjail_stop_finish, 180 .cleanup = &netjail_stop_cleanup
220 .cleanup = &netjail_stop_cleanup, 181 };
221 .traits = &netjail_stop_traits 182
222 }; 183 return cmd;
223 184 }
224 return cmd;
225} 185}
diff --git a/src/testing/testing_api_cmd_netjail_stop_testsystem.c b/src/testing/testing_api_cmd_netjail_stop_testsystem.c
index 0ae82a26a..d3754153d 100644
--- a/src/testing/testing_api_cmd_netjail_stop_testsystem.c
+++ b/src/testing/testing_api_cmd_netjail_stop_testsystem.c
@@ -42,9 +42,15 @@ struct StopHelperState
42 */ 42 */
43 struct GNUNET_HELPER_Handle **helper; 43 struct GNUNET_HELPER_Handle **helper;
44 44
45 char *local_m; 45 unsigned int local_m;
46 46
47 char *global_n; 47 unsigned int global_n;
48
49 /**
50 * Number of global known nodes.
51 *
52 */
53 unsigned int known;
48}; 54};
49 55
50 56
@@ -55,8 +61,7 @@ struct StopHelperState
55* @param cmd current CMD being cleaned up. 61* @param cmd current CMD being cleaned up.
56*/ 62*/
57static void 63static void
58stop_testing_system_cleanup (void *cls, 64stop_testing_system_cleanup (void *cls)
59 const struct GNUNET_TESTING_Command *cmd)
60{ 65{
61 66
62} 67}
@@ -80,28 +85,40 @@ stop_testing_system_traits (void *cls,
80* This function stops the helper process for each node. 85* This function stops the helper process for each node.
81* 86*
82* @param cls closure. 87* @param cls closure.
83* @param cmd CMD being run.
84* @param is interpreter state. 88* @param is interpreter state.
85*/ 89*/
86static void 90static void
87stop_testing_system_run (void *cls, 91stop_testing_system_run (void *cls,
88 const struct GNUNET_TESTING_Command *cmd,
89 struct GNUNET_TESTING_Interpreter *is) 92 struct GNUNET_TESTING_Interpreter *is)
90{ 93{
91 struct StopHelperState *shs = cls; 94 struct StopHelperState *shs = cls;
92 struct GNUNET_HELPER_Handle **helper; 95 struct GNUNET_HELPER_Handle **helper;
93 const struct GNUNET_TESTING_Command *start_helper_cmd; 96 const struct GNUNET_TESTING_Command *start_helper_cmd;
94 97
95 start_helper_cmd = GNUNET_TESTING_interpreter_lookup_command ( 98 start_helper_cmd = GNUNET_TESTING_interpreter_lookup_command (NULL,
96 shs->helper_start_label); 99 shs->
100 helper_start_label);
97 GNUNET_TESTING_get_trait_helper_handles (start_helper_cmd, 101 GNUNET_TESTING_get_trait_helper_handles (start_helper_cmd,
98 &helper); 102 &helper);
99 103
100 for (int i = 1; i <= atoi (shs->global_n); i++) 104 for (int i = 1; i <= shs->known; i++)
105 {
106 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
107 "i: %u\n",
108 i);
109 GNUNET_HELPER_stop (helper[i - 1],
110 GNUNET_YES);
111 }
112
113 for (int i = 1; i <= shs->global_n; i++)
101 { 114 {
102 for (int j = 1; j <= atoi (shs->local_m); j++) 115 for (int j = 1; j <= shs->local_m; j++)
103 { 116 {
104 GNUNET_HELPER_stop (helper[(i - 1) * atoi (shs->local_m) + j - 1], 117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
118 "i: %u j: %u\n",
119 i,
120 j);
121 GNUNET_HELPER_stop (helper[(i - 1) * shs->local_m + j + shs->known - 1],
105 GNUNET_YES); 122 GNUNET_YES);
106 } 123 }
107 } 124 }
@@ -110,26 +127,27 @@ stop_testing_system_run (void *cls,
110 127
111/** 128/**
112 * Create command. 129 * Create command.
113 * @param helper_start_label label of the cmd to start the test system. 130 *
114 * @param label name for command. 131 * @param label name for command.
115 * @param . 132 * @param helper_start_label label of the cmd to start the test system.
116 * @param local_m Number of nodes in a network namespace. //TODO make this a unsigned int 133 * @param topology_config Configuration file for the test topology.
117 * @param global_n Number of network namespaces. //TODO make this a unsigned int
118 * @return command. 134 * @return command.
119 */ 135 */
120struct GNUNET_TESTING_Command 136struct GNUNET_TESTING_Command
121GNUNET_TESTING_cmd_stop_testing_system (const char *label, 137GNUNET_TESTING_cmd_stop_testing_system (const char *label,
122 const char *helper_start_label, 138 const char *helper_start_label,
123 char *local_m, 139 const char *topology_config)
124 char *global_n
125 )
126{ 140{
127 struct StopHelperState *shs; 141 struct StopHelperState *shs;
128 142
143 struct GNUNET_TESTING_NetjailTopology *topology =
144 GNUNET_TESTING_get_topo_from_file (topology_config);
145
129 shs = GNUNET_new (struct StopHelperState); 146 shs = GNUNET_new (struct StopHelperState);
130 shs->helper_start_label = helper_start_label; 147 shs->helper_start_label = helper_start_label;
131 shs->local_m = local_m; 148 shs->local_m = topology->nodes_m;
132 shs->global_n = global_n; 149 shs->global_n = topology->namespaces_n;
150 shs->known = topology->nodes_x;
133 151
134 struct GNUNET_TESTING_Command cmd = { 152 struct GNUNET_TESTING_Command cmd = {
135 .cls = shs, 153 .cls = shs,
diff --git a/src/testing/testing_api_cmd_netjail_stop_testsystem_v2.c b/src/testing/testing_api_cmd_netjail_stop_testsystem_v2.c
deleted file mode 100644
index 6ce106eaa..000000000
--- a/src/testing/testing_api_cmd_netjail_stop_testsystem_v2.c
+++ /dev/null
@@ -1,163 +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 "testing_cmds.h"
29
30
31/**
32 * Struct to store information handed over to callbacks.
33 *
34 */
35struct StopHelperState
36{
37
38 const char *helper_start_label;
39
40 /**
41 * The process handle
42 */
43 struct GNUNET_HELPER_Handle **helper;
44
45 unsigned int local_m;
46
47 unsigned int global_n;
48
49 /**
50 * Number of global known nodes.
51 *
52 */
53 unsigned int known;
54};
55
56
57/**
58* Code to clean up resource this cmd used.
59*
60* @param cls closure
61* @param cmd current CMD being cleaned up.
62*/
63static void
64stop_testing_system_cleanup (void *cls,
65 const struct GNUNET_TESTING_Command *cmd)
66{
67
68}
69
70
71/**
72 * Trait function of this cmd does nothing.
73 *
74 */
75static int
76stop_testing_system_traits (void *cls,
77 const void **ret,
78 const char *trait,
79 unsigned int index)
80{
81 return GNUNET_OK;
82}
83
84
85/**
86* This function stops the helper process for each node.
87*
88* @param cls closure.
89* @param cmd CMD being run.
90* @param is interpreter state.
91*/
92static void
93stop_testing_system_run (void *cls,
94 const struct GNUNET_TESTING_Command *cmd,
95 struct GNUNET_TESTING_Interpreter *is)
96{
97 struct StopHelperState *shs = cls;
98 struct GNUNET_HELPER_Handle **helper;
99 const struct GNUNET_TESTING_Command *start_helper_cmd;
100
101 start_helper_cmd = GNUNET_TESTING_interpreter_lookup_command (
102 shs->helper_start_label);
103 GNUNET_TESTING_get_trait_helper_handles (start_helper_cmd,
104 &helper);
105
106 for (int i = 1; i <= shs->known; i++)
107 {
108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
109 "i: %u\n",
110 i);
111 GNUNET_HELPER_stop (helper[i - 1],
112 GNUNET_YES);
113 }
114
115 for (int i = 1; i <= shs->global_n; i++)
116 {
117 for (int j = 1; j <= shs->local_m; j++)
118 {
119 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
120 "i: %u j: %u\n",
121 i,
122 j);
123 GNUNET_HELPER_stop (helper[(i - 1) * shs->local_m + j + shs->known - 1],
124 GNUNET_YES);
125 }
126 }
127}
128
129
130/**
131 * Create command.
132 *
133 * @param label name for command.
134 * @param helper_start_label label of the cmd to start the test system.
135 * @param topology_config Configuration file for the test topology.
136 * @return command.
137 */
138struct GNUNET_TESTING_Command
139GNUNET_TESTING_cmd_stop_testing_system_v2 (const char *label,
140 const char *helper_start_label,
141 const char *topology_config)
142{
143 struct StopHelperState *shs;
144
145 struct GNUNET_TESTING_NetjailTopology *topology =
146 GNUNET_TESTING_get_topo_from_file (topology_config);
147
148 shs = GNUNET_new (struct StopHelperState);
149 shs->helper_start_label = helper_start_label;
150 shs->local_m = topology->nodes_m;
151 shs->global_n = topology->namespaces_n;
152 shs->known = topology->nodes_x;
153
154 struct GNUNET_TESTING_Command cmd = {
155 .cls = shs,
156 .label = label,
157 .run = &stop_testing_system_run,
158 .cleanup = &stop_testing_system_cleanup,
159 .traits = &stop_testing_system_traits
160 };
161
162 return cmd;
163}
diff --git a/src/testing/testing_api_cmd_netjail_stop_v2.c b/src/testing/testing_api_cmd_netjail_stop_v2.c
deleted file mode 100644
index 8c1f3cedd..000000000
--- a/src/testing/testing_api_cmd_netjail_stop_v2.c
+++ /dev/null
@@ -1,225 +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 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
30
31#define NETJAIL_STOP_SCRIPT "./../testing/netjail_stop_v2.sh"
32
33// Child Wait handle
34static struct GNUNET_ChildWaitHandle *cwh;
35
36/**
37 * Struct to hold information for callbacks.
38 *
39 */
40struct NetJailState
41{
42 /**
43 * Configuration file for the test topology.
44 */
45 char *topology_config;
46
47 /**
48 * The process id of the start script.
49 */
50 struct GNUNET_OS_Process *stop_proc;
51
52 // Flag indication if the script finished.
53 unsigned int finished;
54};
55
56
57/**
58 * The cleanup function of this cmd frees resources the cmd allocated.
59 *
60 */
61static void
62netjail_stop_cleanup (void *cls,
63 const struct GNUNET_TESTING_Command *cmd)
64{
65 struct NetJailState *ns = cls;
66
67 if (NULL != cwh)
68 {
69 GNUNET_wait_child_cancel (cwh);
70 cwh = NULL;
71 }
72 if (NULL != ns->stop_proc)
73 {
74 GNUNET_assert (0 ==
75 GNUNET_OS_process_kill (ns->stop_proc,
76 SIGKILL));
77 GNUNET_assert (GNUNET_OK ==
78 GNUNET_OS_process_wait (ns->stop_proc));
79 GNUNET_OS_process_destroy (ns->stop_proc);
80 ns->stop_proc = NULL;
81 }
82}
83
84
85/**
86 * Trait function of this cmd does nothing.
87 *
88 */
89static int
90netjail_stop_traits (void *cls,
91 const void **ret,
92 const char *trait,
93 unsigned int index)
94{
95 return GNUNET_OK;
96}
97
98
99/**
100 * Callback which will be called if the setup script finished.
101 *
102 */
103static void
104child_completed_callback (void *cls,
105 enum GNUNET_OS_ProcessStatusType type,
106 long unsigned int exit_code)
107{
108 struct NetJailState *ns = cls;
109
110 cwh = NULL;
111 if (0 == exit_code)
112 {
113 ns->finished = GNUNET_YES;
114 }
115 else
116 {
117 ns->finished = GNUNET_SYSERR;
118 }
119 GNUNET_OS_process_destroy (ns->stop_proc);
120 ns->stop_proc = NULL;
121}
122
123
124/**
125* The run method starts the script which deletes the network namespaces.
126*
127* @param cls closure.
128* @param cmd CMD being run.
129* @param is interpreter state.
130*/
131static void
132netjail_stop_run (void *cls,
133 const struct GNUNET_TESTING_Command *cmd,
134 struct GNUNET_TESTING_Interpreter *is)
135{
136 struct NetJailState *ns = cls;
137 char *pid;
138 GNUNET_asprintf (&pid,
139 "%u",
140 getpid ());
141 char *const script_argv[] = {NETJAIL_STOP_SCRIPT,
142 ns->topology_config,
143 pid,
144 NULL};
145 unsigned int helper_check = GNUNET_OS_check_helper_binary (
146 NETJAIL_STOP_SCRIPT,
147 GNUNET_YES,
148 NULL);
149
150 if (GNUNET_NO == helper_check)
151 {
152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
153 "No SUID for %s!\n",
154 NETJAIL_STOP_SCRIPT);
155 GNUNET_TESTING_interpreter_fail ();
156 }
157 else if (GNUNET_NO == helper_check)
158 {
159 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
160 "%s not found!\n",
161 NETJAIL_STOP_SCRIPT);
162 GNUNET_TESTING_interpreter_fail ();
163 }
164
165 ns->stop_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
166 NULL,
167 NULL,
168 NULL,
169 NETJAIL_STOP_SCRIPT,
170 script_argv);
171
172 cwh = GNUNET_wait_child (ns->stop_proc,
173 &child_completed_callback,
174 ns);
175 GNUNET_break (NULL != cwh);
176
177}
178
179
180/**
181 * This function checks the flag NetJailState#finished, if this cmd finished.
182 *
183 */
184static int
185netjail_stop_finish (void *cls,
186 GNUNET_SCHEDULER_TaskCallback cont,
187 void *cont_cls)
188{
189 struct NetJailState *ns = cls;
190
191 if (ns->finished)
192 {
193 cont (cont_cls);
194 }
195 return ns->finished;
196}
197
198
199/**
200 * Create command.
201 *
202 * @param label name for command.
203 * @param topology_config Configuration file for the test topology.
204 * @return command.
205 */
206struct GNUNET_TESTING_Command
207GNUNET_TESTING_cmd_netjail_stop_v2 (const char *label,
208 char *topology_config)
209{
210 struct NetJailState *ns;
211
212 ns = GNUNET_new (struct NetJailState);
213 ns->topology_config = topology_config;
214
215 struct GNUNET_TESTING_Command cmd = {
216 .cls = ns,
217 .label = label,
218 .run = &netjail_stop_run,
219 .finish = &netjail_stop_finish,
220 .cleanup = &netjail_stop_cleanup,
221 .traits = &netjail_stop_traits
222 };
223
224 return cmd;
225}
diff --git a/src/testing/testing_api_cmd_send_peer_ready.c b/src/testing/testing_api_cmd_send_peer_ready.c
index 016837214..8b4c11deb 100644
--- a/src/testing/testing_api_cmd_send_peer_ready.c
+++ b/src/testing/testing_api_cmd_send_peer_ready.c
@@ -53,13 +53,13 @@ struct SendPeerReadyState
53 * Trait function of this cmd does nothing. 53 * Trait function of this cmd does nothing.
54 * 54 *
55 */ 55 */
56static int 56static enum GNUNET_GenericReturnValue
57send_peer_ready_traits (void *cls, 57send_peer_ready_traits (void *cls,
58 const void **ret, 58 const void **ret,
59 const char *trait, 59 const char *trait,
60 unsigned int index) 60 unsigned int index)
61{ 61{
62 return GNUNET_OK; 62 return GNUNET_NO;
63} 63}
64 64
65 65
@@ -68,8 +68,7 @@ send_peer_ready_traits (void *cls,
68 * 68 *
69 */ 69 */
70static void 70static void
71send_peer_ready_cleanup (void *cls, 71send_peer_ready_cleanup (void *cls)
72 const struct GNUNET_TESTING_Command *cmd)
73{ 72{
74 struct SendPeerReadyState *sprs = cls; 73 struct SendPeerReadyState *sprs = cls;
75 74
@@ -84,7 +83,6 @@ send_peer_ready_cleanup (void *cls,
84 */ 83 */
85static void 84static void
86send_peer_ready_run (void *cls, 85send_peer_ready_run (void *cls,
87 const struct GNUNET_TESTING_Command *cmd,
88 struct GNUNET_TESTING_Interpreter *is) 86 struct GNUNET_TESTING_Interpreter *is)
89{ 87{
90 struct SendPeerReadyState *sprs = cls; 88 struct SendPeerReadyState *sprs = cls;
@@ -115,14 +113,15 @@ GNUNET_TESTING_cmd_send_peer_ready (const char *label,
115 113
116 sprs = GNUNET_new (struct SendPeerReadyState); 114 sprs = GNUNET_new (struct SendPeerReadyState);
117 sprs->write_message = write_message; 115 sprs->write_message = write_message;
118 116 {
119 struct GNUNET_TESTING_Command cmd = { 117 struct GNUNET_TESTING_Command cmd = {
120 .cls = sprs, 118 .cls = sprs,
121 .label = label, 119 .label = label,
122 .run = &send_peer_ready_run, 120 .run = &send_peer_ready_run,
123 .cleanup = &send_peer_ready_cleanup, 121 .cleanup = &send_peer_ready_cleanup,
124 .traits = &send_peer_ready_traits 122 .traits = &send_peer_ready_traits
125 }; 123 };
126 124
127 return cmd; 125 return cmd;
126 }
128} 127}
diff --git a/src/testing/testing_api_cmd_system_create.c b/src/testing/testing_api_cmd_system_create.c
index f3a0b1a4c..820adf1bd 100644
--- a/src/testing/testing_api_cmd_system_create.c
+++ b/src/testing/testing_api_cmd_system_create.c
@@ -46,7 +46,6 @@ struct TestSystemState
46 */ 46 */
47static void 47static void
48system_create_run (void *cls, 48system_create_run (void *cls,
49 const struct GNUNET_TESTING_Command *cmd,
50 struct GNUNET_TESTING_Interpreter *is) 49 struct GNUNET_TESTING_Interpreter *is)
51{ 50{
52 struct TestSystemState *tss = cls; 51 struct TestSystemState *tss = cls;
@@ -115,8 +114,7 @@ GNUNET_TESTING_get_trait_test_system (const struct
115 * 114 *
116 */ 115 */
117static void 116static void
118system_create_cleanup (void *cls, 117system_create_cleanup (void *cls)
119 const struct GNUNET_TESTING_Command *cmd)
120{ 118{
121 struct TestSystemState *tss = cls; 119 struct TestSystemState *tss = cls;
122 120
diff --git a/src/testing/testing_api_cmd_system_destroy.c b/src/testing/testing_api_cmd_system_destroy.c
index 5ed0c2fd2..338123d91 100644
--- a/src/testing/testing_api_cmd_system_destroy.c
+++ b/src/testing/testing_api_cmd_system_destroy.c
@@ -46,17 +46,18 @@ struct TestSystemState
46 */ 46 */
47static void 47static void
48system_destroy_run (void *cls, 48system_destroy_run (void *cls,
49 const struct GNUNET_TESTING_Command *cmd,
50 struct GNUNET_TESTING_Interpreter *is) 49 struct GNUNET_TESTING_Interpreter *is)
51{ 50{
52 struct TestSystemState *tss = cls; 51 struct TestSystemState *tss = cls;
53 const struct GNUNET_TESTING_Command *system_cmd; 52 const struct GNUNET_TESTING_Command *system_cmd;
54 struct GNUNET_TESTING_System *tl_system; 53 struct GNUNET_TESTING_System *tl_system;
55 54
56 system_cmd = GNUNET_TESTING_interpreter_lookup_command (tss->create_label); 55 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
56 tss->create_label);
57 GNUNET_TESTING_get_trait_test_system (system_cmd, 57 GNUNET_TESTING_get_trait_test_system (system_cmd,
58 &tl_system); 58 &tl_system);
59 GNUNET_TESTING_system_destroy (tl_system, GNUNET_YES); 59 GNUNET_TESTING_system_destroy (tl_system,
60 GNUNET_YES);
60} 61}
61 62
62 63
@@ -65,8 +66,7 @@ system_destroy_run (void *cls,
65 * 66 *
66 */ 67 */
67static void 68static void
68system_destroy_cleanup (void *cls, 69system_destroy_cleanup (void *cls)
69 const struct GNUNET_TESTING_Command *cmd)
70{ 70{
71 struct TestSystemState *tss = cls; 71 struct TestSystemState *tss = cls;
72 72
@@ -78,7 +78,7 @@ system_destroy_cleanup (void *cls,
78 * Trait function of this cmd does nothing. 78 * Trait function of this cmd does nothing.
79 * 79 *
80 */ 80 */
81static int 81static enum GNUNET_GenericReturnValue
82system_destroy_traits (void *cls, 82system_destroy_traits (void *cls,
83 const void **ret, 83 const void **ret,
84 const char *trait, 84 const char *trait,
@@ -103,14 +103,15 @@ GNUNET_TESTING_cmd_system_destroy (const char *label,
103 103
104 tss = GNUNET_new (struct TestSystemState); 104 tss = GNUNET_new (struct TestSystemState);
105 tss->create_label = create_label; 105 tss->create_label = create_label;
106 106 {
107 struct GNUNET_TESTING_Command cmd = { 107 struct GNUNET_TESTING_Command cmd = {
108 .cls = tss, 108 .cls = tss,
109 .label = label, 109 .label = label,
110 .run = &system_destroy_run, 110 .run = &system_destroy_run,
111 .cleanup = &system_destroy_cleanup, 111 .cleanup = &system_destroy_cleanup,
112 .traits = &system_destroy_traits 112 .traits = &system_destroy_traits
113 }; 113 };
114 114
115 return cmd; 115 return cmd;
116 }
116} 117}
diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c
index bb04280a9..3727d2543 100644
--- a/src/testing/testing_api_loop.c
+++ b/src/testing/testing_api_loop.c
@@ -24,67 +24,68 @@
24 * @author Christian Grothoff (GNU Taler testing) 24 * @author Christian Grothoff (GNU Taler testing)
25 * @author Marcello Stanisci (GNU Taler testing) 25 * @author Marcello Stanisci (GNU Taler testing)
26 * @author t3sserakt 26 * @author t3sserakt
27*/ 27 */
28#include "platform.h" 28#include "platform.h"
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30#include "gnunet_testing_ng_lib.h" 30#include "gnunet_testing_ng_lib.h"
31#include "testing.h" 31#include "testing.h"
32 32
33#define CHECK_FINISHED_PERIOD \
34 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
35
36struct GNUNET_TESTING_Interpreter *is;
37
38
39/** 33/**
40 * Closure used to sync an asynchronous with an synchronous command. 34 * Global state of the interpreter, used by a command
35 * to access information about other commands.
41 */ 36 */
42struct SyncTaskClosure 37struct GNUNET_TESTING_Interpreter
43{ 38{
44 39
45 /** 40 /**
46 * The asynchronous command the synchronous command waits for. 41 * Function to call with the test result.
47 */ 42 */
48 const struct GNUNET_TESTING_Command *async_cmd; 43 GNUNET_TESTING_ResultCallback rc;
49 44
50 /** 45 /**
51 * The synchronous command that waits for the asynchronous command. 46 * Closure for @e rc.
52 */ 47 */
53 const struct GNUNET_TESTING_Command *sync_cmd; 48 void *rc_cls;
54 49
55 /** 50 /**
56 * The interpreter of the test. 51 * Commands the interpreter will run.
57 */ 52 */
58 struct GNUNET_TESTING_Interpreter *is; 53 struct GNUNET_TESTING_Command *commands;
59};
60 54
55 /**
56 * Interpreter task (if one is scheduled).
57 */
58 struct GNUNET_SCHEDULER_Task *task;
61 59
62/** 60 /**
63* Closure used to run the finish task. 61 * Final task that returns the result.
64*/ 62 */
65struct FinishTaskClosure 63 struct GNUNET_SCHEDULER_Task *final_task;
66{
67 64
68 /** 65 /**
69 * The asynchronous command the synchronous command waits for. 66 * Task run on timeout.
70 */ 67 */
71 const struct GNUNET_TESTING_Command *cmd; 68 struct GNUNET_SCHEDULER_Task *timeout_task;
72 69
73 /** 70 /**
74 * The interpreter of the test. 71 * Instruction pointer. Tells #interpreter_run() which instruction to run
72 * next. Need (signed) int because it gets -1 when rewinding the
73 * interpreter to the first CMD.
75 */ 74 */
76 struct GNUNET_TESTING_Interpreter *is; 75 int ip;
76
77 /**
78 * Result of the testcases, #GNUNET_OK on success
79 */
80 enum GNUNET_GenericReturnValue result;
81
77}; 82};
78 83
79 84
80/**
81 * Lookup command by label.
82 *
83 * @param label label to look for
84 * @return NULL if command was not found
85 */
86const struct GNUNET_TESTING_Command * 85const struct GNUNET_TESTING_Command *
87GNUNET_TESTING_interpreter_lookup_command (const char *label) 86GNUNET_TESTING_interpreter_lookup_command (
87 struct GNUNET_TESTING_Interpreter *is,
88 const char *label)
88{ 89{
89 if (NULL == label) 90 if (NULL == label)
90 { 91 {
@@ -103,7 +104,7 @@ GNUNET_TESTING_interpreter_lookup_command (const char *label)
103 label)) ) 104 label)) )
104 return cmd; 105 return cmd;
105 106
106 if (GNUNET_TESTING_cmd_is_batch (cmd)) 107 if (GNUNET_TESTING_cmd_is_batch_ (cmd))
107 { 108 {
108#define BATCH_INDEX 1 109#define BATCH_INDEX 1
109 struct GNUNET_TESTING_Command *batch; 110 struct GNUNET_TESTING_Command *batch;
@@ -111,7 +112,7 @@ GNUNET_TESTING_interpreter_lookup_command (const char *label)
111 struct GNUNET_TESTING_Command *icmd; 112 struct GNUNET_TESTING_Command *icmd;
112 const struct GNUNET_TESTING_Command *match; 113 const struct GNUNET_TESTING_Command *match;
113 114
114 current = GNUNET_TESTING_cmd_batch_get_current (cmd); 115 current = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
115 GNUNET_assert (GNUNET_OK == 116 GNUNET_assert (GNUNET_OK ==
116 GNUNET_TESTING_get_trait_cmd (cmd, 117 GNUNET_TESTING_get_trait_cmd (cmd,
117 BATCH_INDEX, 118 BATCH_INDEX,
@@ -134,10 +135,58 @@ GNUNET_TESTING_interpreter_lookup_command (const char *label)
134 } 135 }
135 } 136 }
136 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 137 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
137 "Command not found: %s\n", 138 "Command `%s' not found\n",
138 label); 139 label);
139 return NULL; 140 return NULL;
141}
142
143
144/**
145 * Finish the test run, return the final result.
146 *
147 * @param cls the `struct GNUNET_TESTING_Interpreter`
148 */
149static void
150finish_test (void *cls)
151{
152 struct GNUNET_TESTING_Interpreter *is = cls;
153 struct GNUNET_TESTING_Command *cmd;
154 const char *label;
140 155
156 is->final_task = NULL;
157 label = is->commands[is->ip].label;
158 if (NULL == label)
159 label = "END";
160 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
161 "Interpreter finishes at `%s' with status %d\n",
162 label,
163 is->result);
164 for (unsigned int j = 0;
165 NULL != (cmd = &is->commands[j])->label;
166 j++)
167 {
168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
169 "Cleaning up cmd %s\n",
170 cmd->label);
171 cmd->cleanup (cmd->cls);
172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
173 "Cleaned up cmd %s\n",
174 cmd->label);
175 }
176 if (NULL != is->task)
177 {
178 GNUNET_SCHEDULER_cancel (is->task);
179 is->task = NULL;
180 }
181 if (NULL != is->timeout_task)
182 {
183 GNUNET_SCHEDULER_cancel (is->timeout_task);
184 is->timeout_task = NULL;
185 }
186 GNUNET_free (is->commands);
187 is->rc (is->rc_cls,
188 is->result);
189 GNUNET_free (is);
141} 190}
142 191
143 192
@@ -163,15 +212,10 @@ interpreter_next (void *cls)
163 212
164 if (GNUNET_SYSERR == is->result) 213 if (GNUNET_SYSERR == is->result)
165 return; /* ignore, we already failed! */ 214 return; /* ignore, we already failed! */
166 if (GNUNET_TESTING_cmd_is_batch (cmd)) 215 cmd->finish_time = GNUNET_TIME_absolute_get ();
167 { 216 if ( (! GNUNET_TESTING_cmd_is_batch_ (cmd)) ||
168 GNUNET_TESTING_cmd_batch_next (is); 217 (! GNUNET_TESTING_cmd_batch_next_ (cmd->cls)) )
169 }
170 else
171 {
172 cmd->finish_time = GNUNET_TIME_absolute_get ();
173 is->ip++; 218 is->ip++;
174 }
175 if (0 == (ipc % 1000)) 219 if (0 == (ipc % 1000))
176 { 220 {
177 if (0 != ipc) 221 if (0 != ipc)
@@ -188,253 +232,44 @@ interpreter_next (void *cls)
188} 232}
189 233
190 234
191/**
192 * This function checks if the finish function of a command returns GNUNET_YES, when the command is finished. In this case the finish function might have called interpreter_next. IF GNUNET_NO was returned this function is added to the scheduler again. In case of an error interpreter_fail is called.
193 *
194 */
195static void
196run_finish_task_next (void *cls)
197{
198 struct FinishTaskClosure *ftc = cls;
199 const struct GNUNET_TESTING_Command *cmd = ftc->cmd;
200 struct GNUNET_TESTING_Interpreter *is = ftc->is;
201 unsigned int finished = cmd->finish (cmd->cls, &interpreter_next, is);
202
203 if (GNUNET_YES == finished)
204 {
205 is->finish_task = NULL;
206 }
207 else if (GNUNET_NO == finished)
208 {
209 is->finish_task = GNUNET_SCHEDULER_add_delayed (CHECK_FINISHED_PERIOD,
210 &run_finish_task_next, ftc);
211 }
212 else
213 {
214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
215 "Next task finished with an error.\n");
216 GNUNET_TESTING_interpreter_fail ();
217 }
218
219}
220
221
222/**
223 * This function checks if the finish function of an asynchronous command returns GNUNET_YES, when the command is finished. In this case the finish function might have called interpreter_next. IF GNUNET_NO was returned this function is added to the scheduler again. In case of an error interpreter_fail is called.
224 *
225 * //TODO run_finish_task_next and this function can be merged.
226 *
227 */
228static void
229run_finish_task_sync (void *cls)
230{
231 struct SyncTaskClosure *stc = cls;
232 const struct GNUNET_TESTING_Command *cmd = stc->async_cmd;
233 const struct GNUNET_TESTING_Command *sync_cmd = stc->sync_cmd;
234 struct FinishTaskClosure *ftc;
235 struct SyncState *sync_state = sync_cmd->cls;
236 struct GNUNET_SCHEDULER_Task *finish_task = sync_state->finish_task;
237 unsigned int finished = cmd->finish (cmd->cls, &interpreter_next, is);
238
239 GNUNET_assert (NULL != finish_task);
240 ftc = GNUNET_new (struct FinishTaskClosure);
241 ftc->cmd = stc->sync_cmd;
242 ftc->is = stc->is;
243 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
244 if (cmd->default_timeout.rel_value_us < now.abs_value_us
245 - sync_state->start_finish_time.abs_value_us)
246 {
247 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
248 "The command with label %s did not finish its asynchronous task in time.\n",
249 cmd->label);
250 GNUNET_TESTING_interpreter_fail ();
251 }
252
253 if (GNUNET_YES == finished)
254 {
255 finish_task = NULL;
256 }
257 else if (GNUNET_NO == finished)
258 {
259 finish_task = GNUNET_SCHEDULER_add_delayed (CHECK_FINISHED_PERIOD,
260 &run_finish_task_sync, stc);
261 }
262 else
263 {
264 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
265 "Sync task finished with an error.\n");
266 GNUNET_TESTING_interpreter_fail ();
267 }
268}
269
270
271/**
272 * run method of the command created by the interpreter to wait for another command to finish.
273 *
274 */
275static void
276start_finish_on_ref (void *cls,
277 const struct GNUNET_TESTING_Command *cmd,
278 struct GNUNET_TESTING_Interpreter *is)
279{
280 struct SyncState *sync_state = cls;
281 struct SyncTaskClosure *stc;
282 const struct GNUNET_TESTING_Command *async_cmd;
283
284 async_cmd = sync_state->async_cmd;
285 stc = GNUNET_new (struct SyncTaskClosure);
286 stc->async_cmd = async_cmd;
287 stc->sync_cmd = cmd;
288 stc->is = is;
289 sync_state->start_finish_time = GNUNET_TIME_absolute_get ();
290 sync_state->finish_task = GNUNET_SCHEDULER_add_delayed (
291 CHECK_FINISHED_PERIOD,
292 &run_finish_task_sync,
293 stc);
294}
295
296
297/**
298 * Create (synchronous) command that waits for another command to finish.
299 * If @a cmd_ref did not finish after @a timeout, this command will fail
300 * the test case.
301 *
302 * @param finish_label label for this command
303 * @param cmd_ref reference to a previous command which we should
304 * wait for (call `finish()` on)
305 * @param timeout how long to wait at most for @a cmd_ref to finish
306 * @return a finish-command.
307 */
308const struct GNUNET_TESTING_Command
309GNUNET_TESTING_cmd_finish (const char *finish_label,
310 const char *cmd_ref,
311 struct GNUNET_TIME_Relative timeout)
312{
313 const struct GNUNET_TESTING_Command *async_cmd;
314 struct SyncState *sync_state;
315
316 async_cmd = GNUNET_TESTING_interpreter_lookup_command (cmd_ref);
317 sync_state = GNUNET_new (struct SyncState);
318 sync_state->async_cmd = async_cmd;
319
320 struct GNUNET_TESTING_Command cmd = {
321 .cls = sync_state,
322 .label = finish_label,
323 .run = &start_finish_on_ref,
324 .asynchronous_finish = GNUNET_NO
325 };
326
327 return cmd;
328}
329
330
331const struct GNUNET_TESTING_Command
332GNUNET_TESTING_cmd_make_unblocking (const struct GNUNET_TESTING_Command cmd)
333{
334
335 GNUNET_assert (NULL != cmd.finish);
336 const struct GNUNET_TESTING_Command async_cmd = {
337 .cls = cmd.cls,
338 .label = cmd.label,
339 .run = cmd.run,
340 .cleanup = cmd.cleanup,
341 .traits = cmd.traits,
342 .finish = cmd.finish,
343 .asynchronous_finish = GNUNET_YES
344 };
345
346 return async_cmd;
347}
348
349
350/**
351 * Current command failed, clean up and fail the test case.
352 *
353 * @param is interpreter of the test
354 */
355void 235void
356GNUNET_TESTING_interpreter_fail () 236GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is)
357{ 237{
358 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip]; 238 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
359 239
360 if (GNUNET_SYSERR == is->result) 240 if (GNUNET_SYSERR == is->result)
241 {
242 GNUNET_break (0);
361 return; /* ignore, we already failed! */ 243 return; /* ignore, we already failed! */
362 244 }
363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
364 "interpreter_fail!\n");
365
366 if (NULL != cmd) 245 if (NULL != cmd)
367 { 246 {
368 while (GNUNET_TESTING_cmd_is_batch (cmd)) 247 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
248 "Failed at command `%s'\n",
249 cmd->label);
250 while (GNUNET_TESTING_cmd_is_batch_ (cmd))
369 { 251 {
370 cmd = GNUNET_TESTING_cmd_batch_get_current (cmd); 252 cmd = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 253 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
372 "Batch is at command `%s'\n", 254 "Failed in batch at command `%s'\n",
373 cmd->label); 255 cmd->label);
374 } 256 }
375
376 } 257 }
377 else 258 else
378 { 259 {
379 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 260 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
380 "cmd is NULL.\n"); 261 "Failed with CMD being NULL!\n");
381 } 262 }
382
383 if (NULL == cmd->label)
384 {
385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
386 "Failed at command `%s'\n",
387 cmd->label);
388
389 }
390 else
391 {
392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
393 "cmd->label is NULL.\n");
394 }
395
396 is->result = GNUNET_SYSERR; 263 is->result = GNUNET_SYSERR;
397 GNUNET_SCHEDULER_shutdown (); 264 GNUNET_assert (NULL == is->final_task);
398} 265 is->final_task = GNUNET_SCHEDULER_add_now (&finish_test,
399 266 is);
400
401/**
402 * Create command array terminator.
403 *
404 * @return a end-command.
405 */
406struct GNUNET_TESTING_Command
407GNUNET_TESTING_cmd_end (void)
408{
409 static struct GNUNET_TESTING_Command cmd;
410 cmd.label = NULL;
411 cmd.shutdown_on_end = GNUNET_YES;
412
413 return cmd;
414}
415
416/**
417 * Create command array terminator without shutdown.
418 *
419 * @return a end-command.
420 */
421struct GNUNET_TESTING_Command
422GNUNET_TESTING_cmd_end_without_shutdown (void)
423{
424 static struct GNUNET_TESTING_Command cmd;
425 cmd.label = NULL;
426 cmd.shutdown_on_end = GNUNET_NO;
427
428 return cmd;
429} 267}
430 268
431 269
432/**
433 * Obtain current label.
434 */
435const char * 270const char *
436GNUNET_TESTING_interpreter_get_current_label (struct 271GNUNET_TESTING_interpreter_get_current_label (
437 GNUNET_TESTING_Interpreter *is) 272 struct GNUNET_TESTING_Interpreter *is)
438{ 273{
439 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip]; 274 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
440 275
@@ -450,189 +285,195 @@ GNUNET_TESTING_interpreter_get_current_label (struct
450static void 285static void
451interpreter_run (void *cls) 286interpreter_run (void *cls)
452{ 287{
453 struct FinishTaskClosure *ftc;
454 struct GNUNET_TESTING_Interpreter *is = cls; 288 struct GNUNET_TESTING_Interpreter *is = cls;
455 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip]; 289 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
456 bool shutdown_on_end = cmd->shutdown_on_end;
457 290
458 is->task = NULL; 291 is->task = NULL;
459
460 if (NULL == cmd->label) 292 if (NULL == cmd->label)
461 { 293 {
462
463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
464 "Running command END %p %u\n", 295 "Running command END\n");
465 is,
466 shutdown_on_end);
467 is->result = GNUNET_OK; 296 is->result = GNUNET_OK;
468 if (GNUNET_YES == shutdown_on_end) 297 finish_test (is);
469 {
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
471 "Running command END with shutdown\n");
472 GNUNET_SCHEDULER_shutdown ();
473 }
474 return; 298 return;
475 } 299 }
476 else if (NULL != cmd) 300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
477 { 301 "Running command `%s'\n",
478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 302 cmd->label);
479 "Running command `%s' %p\n",
480 cmd->label,
481 is);
482 }
483 cmd->start_time 303 cmd->start_time
484 = cmd->last_req_time 304 = cmd->last_req_time
485 = GNUNET_TIME_absolute_get (); 305 = GNUNET_TIME_absolute_get ();
486 cmd->num_tries = 1; 306 cmd->num_tries = 1;
307 if (NULL != cmd->ac)
308 {
309 cmd->ac->is = is;
310 cmd->ac->cont = &interpreter_next;
311 cmd->ac->cont_cls = is;
312 cmd->ac->finished = GNUNET_NO;
313 }
487 cmd->run (cmd->cls, 314 cmd->run (cmd->cls,
488 cmd,
489 is); 315 is);
490 if ((NULL != cmd->finish) && (GNUNET_NO == cmd->asynchronous_finish)) 316 if (NULL == cmd->ac)
491 { 317 {
492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 318 interpreter_next (is);
493 "Next task will not be called directly!\n");
494 ftc = GNUNET_new (struct FinishTaskClosure);
495 ftc->cmd = cmd;
496 ftc->is = is;
497 is->finish_task = GNUNET_SCHEDULER_add_delayed (CHECK_FINISHED_PERIOD,
498 &run_finish_task_next,
499 ftc);
500 } 319 }
501 else 320 else if ( (cmd->asynchronous_finish) &&
321 (NULL != cmd->ac->cont) )
502 { 322 {
323 cmd->ac->cont = NULL;
503 interpreter_next (is); 324 interpreter_next (is);
504 } 325 }
505} 326}
506 327
507 328
508/** 329/**
509 * Function run when the test terminates (good or bad). 330 * Function run when the test terminates (good or bad) with timeout.
510 * Cleans up our state.
511 * 331 *
512 * @param cls the interpreter state. 332 * @param cls the interpreter state
513 */ 333 */
514static void 334static void
515do_shutdown (void *cls) 335do_timeout (void *cls)
516{ 336{
517 (void) cls; 337 struct GNUNET_TESTING_Interpreter *is = cls;
518 struct GNUNET_TESTING_Command *cmd;
519 const char *label;
520 338
521 label = is->commands[is->ip].label; 339 is->timeout_task = NULL;
522 if (NULL == label) 340 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
523 label = "END"; 341 "Terminating test due to global timeout\n");
342 is->result = GNUNET_SYSERR;
343 finish_test (is);
344}
524 345
525 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
526 "Executing shutdown at `%s'\n",
527 label);
528 346
529 for (unsigned int j = 0; 347void
530 NULL != (cmd = &is->commands[j])->label; 348GNUNET_TESTING_run (struct GNUNET_TESTING_Command *commands,
531 j++) { 349 struct GNUNET_TIME_Relative timeout,
532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 350 GNUNET_TESTING_ResultCallback rc,
533 "Cleaning up cmd %s\n", 351 void *rc_cls)
534 cmd->label); 352{
535 cmd->cleanup (cmd->cls, 353 struct GNUNET_TESTING_Interpreter *is;
536 cmd); 354 unsigned int i;
537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
538 "Cleaned up cmd %s\n",
539 cmd->label);
540 }
541
542 if (NULL != is->finish_task)
543 {
544 GNUNET_SCHEDULER_cancel (is->finish_task);
545 cmd->finish_task = NULL;
546 }
547 355
548 if (NULL != is->task) 356 is = GNUNET_new (struct GNUNET_TESTING_Interpreter);
549 { 357 is->rc = rc;
550 GNUNET_SCHEDULER_cancel (is->task); 358 is->rc_cls = rc_cls;
551 is->task = NULL; 359 /* get the number of commands */
552 } 360 for (i = 0; NULL != commands[i].label; i++)
553 if (NULL != is->timeout_task) 361 ;
554 { 362 is->commands = GNUNET_new_array (i + 1,
555 GNUNET_SCHEDULER_cancel (is->timeout_task); 363 struct GNUNET_TESTING_Command);
556 is->timeout_task = NULL; 364 memcpy (is->commands,
557 } 365 commands,
558 GNUNET_free (is->commands); 366 sizeof (struct GNUNET_TESTING_Command) * i);
367 is->timeout_task
368 = GNUNET_SCHEDULER_add_delayed (timeout,
369 &do_timeout,
370 is);
371 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
372 is);
559} 373}
560 374
561 375
562/** 376/**
563 * Function run when the test terminates (good or bad) with timeout. 377 * Closure for #loop_run().
378 */
379struct MainParams
380{
381
382 /**
383 * NULL-label terminated array of commands.
384 */
385 struct GNUNET_TESTING_Command *commands;
386
387 /**
388 * Global timeout for the test.
389 */
390 struct GNUNET_TIME_Relative timeout;
391
392 /**
393 * Set to #EXIT_FAILURE on error.
394 */
395 int rv;
396};
397
398
399/**
400 * Function called with the final result of the test.
564 * 401 *
565 * @param cls NULL 402 * @param cls the `struct MainParams`
403 * @param rv #GNUNET_OK if the test passed
566 */ 404 */
567static void 405static void
568do_timeout (void *cls) 406handle_result (void *cls,
407 enum GNUNET_GenericReturnValue rv)
569{ 408{
570 (void) cls; 409 struct MainParams *mp = cls;
571 410
572 is->timeout_task = NULL; 411 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
573 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 412 "Test exits with status %d\n",
574 "Terminating test due to timeout\n"); 413 rv);
414 if (GNUNET_OK != rv)
415 mp->rv = EXIT_FAILURE;
575 GNUNET_SCHEDULER_shutdown (); 416 GNUNET_SCHEDULER_shutdown ();
576} 417}
577 418
578 419
579/** 420/**
580 * Run the testsuite. Note, CMDs are copied into 421 * Main function to run the test cases.
581 * the interpreter state because they are _usually_
582 * defined into the "run" method that returns after
583 * having scheduled the test interpreter.
584 * 422 *
585 * @param is the interpreter state 423 * @param cls a `struct MainParams *`
586 * @param commands the list of command to execute
587 * @param timeout how long to wait
588 */ 424 */
425static void
426loop_run (void *cls)
427{
428 struct MainParams *mp = cls;
429
430 GNUNET_TESTING_run (mp->commands,
431 mp->timeout,
432 &handle_result,
433 mp);
434}
435
436
589int 437int
590GNUNET_TESTING_run (const char *cfg_filename, 438GNUNET_TESTING_main (struct GNUNET_TESTING_Command *commands,
591 struct GNUNET_TESTING_Command *commands, 439 struct GNUNET_TIME_Relative timeout)
592 struct GNUNET_TIME_Relative timeout)
593{ 440{
594 unsigned int i; 441 struct MainParams mp = {
442 .commands = commands,
443 .timeout = timeout,
444 .rv = EXIT_SUCCESS
445 };
595 446
596 is = GNUNET_new (struct GNUNET_TESTING_Interpreter); 447 GNUNET_SCHEDULER_run (&loop_run,
448 &mp);
449 return mp.rv;
450}
597 451
598 if (NULL != is->timeout_task) 452
599 { 453void
600 GNUNET_SCHEDULER_cancel (is->timeout_task); 454GNUNET_TESTING_async_fail (struct GNUNET_TESTING_AsyncContext *ac)
601 is->timeout_task = NULL; 455{
602 } 456 GNUNET_assert (GNUNET_NO == ac->finished);
603 /* get the number of commands */ 457 ac->finished = GNUNET_SYSERR;
604 for (i = 0; NULL != commands[i].label; i++) 458 GNUNET_TESTING_interpreter_fail (ac->is);
459 if (NULL != ac->cont)
605 { 460 {
606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 461 ac->cont (ac->cont_cls);
607 "on end %u\n", 462 ac->cont = NULL;
608 commands[i].shutdown_on_end);
609 } 463 }
610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 464}
611 "on end %u\n", 465
612 commands[i].shutdown_on_end);
613 // ;
614 is->commands = GNUNET_new_array (i + 1,
615 struct GNUNET_TESTING_Command);
616 memcpy (is->commands,
617 commands,
618 sizeof (struct GNUNET_TESTING_Command) * (i + 1));
619 466
620 for (i = 0; NULL != is->commands[i].label; i++) 467void
468GNUNET_TESTING_async_finish (struct GNUNET_TESTING_AsyncContext *ac)
469{
470 GNUNET_assert (GNUNET_NO == ac->finished);
471 ac->finished = GNUNET_OK;
472 if (NULL != ac->cont)
621 { 473 {
622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 474 ac->cont (ac->cont_cls);
623 "on end %u\n", 475 ac->cont = NULL;
624 is->commands[i].shutdown_on_end);
625 } 476 }
626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
627 "on end %u\n",
628 is->commands[i].shutdown_on_end);
629 is->timeout_task = GNUNET_SCHEDULER_add_delayed
630 (timeout,
631 &do_timeout,
632 is);
633 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is);
634 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, is);
635 return GNUNET_OK;
636} 477}
637 478
638 479
diff --git a/src/testing/testing_api_trait_cmd.c b/src/testing/testing_api_trait_cmd.c
index 886baee5b..7afa8b264 100644
--- a/src/testing/testing_api_trait_cmd.c
+++ b/src/testing/testing_api_trait_cmd.c
@@ -41,7 +41,7 @@
41 * @param[out] _cmd where to write the wire details. 41 * @param[out] _cmd where to write the wire details.
42 * @return #GNUNET_OK on success. 42 * @return #GNUNET_OK on success.
43 */ 43 */
44int 44enum GNUNET_GenericReturnValue
45GNUNET_TESTING_get_trait_cmd (const struct GNUNET_TESTING_Command *cmd, 45GNUNET_TESTING_get_trait_cmd (const struct GNUNET_TESTING_Command *cmd,
46 unsigned int index, 46 unsigned int index,
47 struct GNUNET_TESTING_Command **_cmd) 47 struct GNUNET_TESTING_Command **_cmd)
diff --git a/src/testing/testing_api_traits.c b/src/testing/testing_api_traits.c
index 66626833d..2f836ddfa 100644
--- a/src/testing/testing_api_traits.c
+++ b/src/testing/testing_api_traits.c
@@ -55,7 +55,7 @@ GNUNET_TESTING_trait_end ()
55 * @param index index number of the object to extract. 55 * @param index index number of the object to extract.
56 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise. 56 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
57 */ 57 */
58int 58enum GNUNET_GenericReturnValue
59GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits, 59GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits,
60 const void **ret, 60 const void **ret,
61 const char *trait, 61 const char *trait,
diff --git a/src/testing/testing_cmds.h b/src/testing/testing_cmds.h
index 005402a73..12db87d19 100644
--- a/src/testing/testing_cmds.h
+++ b/src/testing/testing_cmds.h
@@ -83,6 +83,8 @@ struct GNUNET_CMDS_LOCAL_FINISHED
83 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED 83 * Type is GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED
84 */ 84 */
85 struct GNUNET_MessageHeader header; 85 struct GNUNET_MessageHeader header;
86
87 enum GNUNET_GenericReturnValue result;
86}; 88};
87 89
88struct GNUNET_CMDS_LOCAL_TEST_PREPARED 90struct GNUNET_CMDS_LOCAL_TEST_PREPARED