diff options
author | Bart Polot <bart.polot+gnunet@gmail.com> | 2017-02-21 13:30:07 +0100 |
---|---|---|
committer | Bart Polot <bart.polot+gnunet@gmail.com> | 2017-02-21 13:31:39 +0100 |
commit | 291f4c74df104728a0a0bb105650b2f33f9b3d9d (patch) | |
tree | 3f71a4c93e44c10df123db5f79f3fc98e29ca30c /src/cadet | |
parent | a5c4a4b1c66b2bab197d0690881d6f3bdc56a833 (diff) | |
download | gnunet-291f4c74df104728a0a0bb105650b2f33f9b3d9d.tar.gz gnunet-291f4c74df104728a0a0bb105650b2f33f9b3d9d.zip |
Rewrite cadet tests using MQ API
Diffstat (limited to 'src/cadet')
-rw-r--r-- | src/cadet/.gitignore | 1 | ||||
-rw-r--r-- | src/cadet/Makefile.am | 28 | ||||
-rw-r--r-- | src/cadet/cadet_test_lib_new.c | 362 | ||||
-rw-r--r-- | src/cadet/cadet_test_lib_new.h | 106 | ||||
-rw-r--r-- | src/cadet/test_cadet.c | 4 | ||||
-rw-r--r-- | src/cadet/test_cadet_new.c | 1049 |
6 files changed, 1547 insertions, 3 deletions
diff --git a/src/cadet/.gitignore b/src/cadet/.gitignore index a38b8f495..a73006dae 100644 --- a/src/cadet/.gitignore +++ b/src/cadet/.gitignore | |||
@@ -21,3 +21,4 @@ test_cadet_local | |||
21 | test_cadet_single | 21 | test_cadet_single |
22 | gnunet-service-cadet-new | 22 | gnunet-service-cadet-new |
23 | test_cadet_local_mq | 23 | test_cadet_local_mq |
24 | test_cadet_2_forward_new \ No newline at end of file | ||
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am index 1a51453c9..74791d66e 100644 --- a/src/cadet/Makefile.am +++ b/src/cadet/Makefile.am | |||
@@ -110,7 +110,7 @@ endif | |||
110 | 110 | ||
111 | 111 | ||
112 | if HAVE_TESTING | 112 | if HAVE_TESTING |
113 | noinst_LIBRARIES = libgnunetcadettest.a $(noinst_LIB_EXP) | 113 | noinst_LIBRARIES = libgnunetcadettest.a libgnunetcadettestnew.a $(noinst_LIB_EXP) |
114 | noinst_PROGRAMS = gnunet-cadet-profiler | 114 | noinst_PROGRAMS = gnunet-cadet-profiler |
115 | endif | 115 | endif |
116 | 116 | ||
@@ -124,6 +124,7 @@ libgnunetcadettest_a_LIBADD = \ | |||
124 | if HAVE_TESTING | 124 | if HAVE_TESTING |
125 | check_PROGRAMS = \ | 125 | check_PROGRAMS = \ |
126 | test_cadet_local_mq \ | 126 | test_cadet_local_mq \ |
127 | test_cadet_2_forward_new \ | ||
127 | test_cadet_single \ | 128 | test_cadet_single \ |
128 | test_cadet_local \ | 129 | test_cadet_local \ |
129 | test_cadet_2_forward \ | 130 | test_cadet_2_forward \ |
@@ -245,6 +246,31 @@ test_cadet_5_speed_reliable_backwards_SOURCES = \ | |||
245 | test_cadet_5_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) | 246 | test_cadet_5_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) |
246 | 247 | ||
247 | 248 | ||
249 | # NEW TESTS | ||
250 | libgnunetcadettestnew_a_SOURCES = \ | ||
251 | cadet_test_lib_new.c cadet_test_lib_new.h | ||
252 | libgnunetcadettestnew_a_LIBADD = \ | ||
253 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
254 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
255 | libgnunetcadetnew.la | ||
256 | |||
257 | ld_cadet_test_lib_new = \ | ||
258 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
259 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
260 | libgnunetcadetnew.la \ | ||
261 | libgnunetcadettestnew.a \ | ||
262 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
263 | $(top_builddir)/src/statistics/libgnunetstatistics.la | ||
264 | dep_cadet_test_lib_new = \ | ||
265 | libgnunetcadetnew.la \ | ||
266 | libgnunetcadettestnew.a \ | ||
267 | $(top_builddir)/src/statistics/libgnunetstatistics.la | ||
268 | |||
269 | test_cadet_2_forward_new_SOURCES = \ | ||
270 | test_cadet_new.c | ||
271 | test_cadet_2_forward_new_LDADD = $(ld_cadet_test_lib_new) | ||
272 | |||
273 | |||
248 | if ENABLE_TEST_RUN | 274 | if ENABLE_TEST_RUN |
249 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | 275 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; |
250 | TESTS = \ | 276 | TESTS = \ |
diff --git a/src/cadet/cadet_test_lib_new.c b/src/cadet/cadet_test_lib_new.c new file mode 100644 index 000000000..c3a1540f4 --- /dev/null +++ b/src/cadet/cadet_test_lib_new.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_test_lib.c | ||
22 | * @author Bartlomiej Polot | ||
23 | * @brief library for writing CADET tests | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "cadet_test_lib_new.h" | ||
28 | #include "gnunet_cadet_service.h" | ||
29 | |||
30 | |||
31 | /** | ||
32 | * Test context for a CADET Test. | ||
33 | */ | ||
34 | struct GNUNET_CADET_TEST_Context | ||
35 | { | ||
36 | /** | ||
37 | * Array of running peers. | ||
38 | */ | ||
39 | struct GNUNET_TESTBED_Peer **peers; | ||
40 | |||
41 | /** | ||
42 | * Array of handles to the CADET for each peer. | ||
43 | */ | ||
44 | struct GNUNET_CADET_Handle **cadets; | ||
45 | |||
46 | /** | ||
47 | * Operation associated with the connection to the CADET. | ||
48 | */ | ||
49 | struct GNUNET_TESTBED_Operation **ops; | ||
50 | |||
51 | /** | ||
52 | * Number of peers running, size of the arrays above. | ||
53 | */ | ||
54 | unsigned int num_peers; | ||
55 | |||
56 | /** | ||
57 | * Main function of the test to run once all CADETs are available. | ||
58 | */ | ||
59 | GNUNET_CADET_TEST_AppMain app_main; | ||
60 | |||
61 | /** | ||
62 | * Closure for 'app_main'. | ||
63 | */ | ||
64 | void *app_main_cls; | ||
65 | |||
66 | /** | ||
67 | * Handler for incoming tunnels. | ||
68 | */ | ||
69 | GNUNET_CADET_ConnectEventHandler connects; | ||
70 | |||
71 | /** | ||
72 | * Function called when the transmit window size changes. | ||
73 | */ | ||
74 | GNUNET_CADET_WindowSizeEventHandler window_changes; | ||
75 | |||
76 | /** | ||
77 | * Cleaner for destroyed incoming tunnels. | ||
78 | */ | ||
79 | GNUNET_CADET_DisconnectEventHandler disconnects; | ||
80 | |||
81 | /** | ||
82 | * Message handlers. | ||
83 | */ | ||
84 | struct GNUNET_MQ_MessageHandler *handlers; | ||
85 | |||
86 | /** | ||
87 | * Application ports. | ||
88 | */ | ||
89 | const struct GNUNET_HashCode **ports; | ||
90 | |||
91 | /** | ||
92 | * Number of ports in #ports. | ||
93 | */ | ||
94 | unsigned int port_count; | ||
95 | |||
96 | }; | ||
97 | |||
98 | |||
99 | /** | ||
100 | * Context for a cadet adapter callback. | ||
101 | */ | ||
102 | struct GNUNET_CADET_TEST_AdapterContext | ||
103 | { | ||
104 | /** | ||
105 | * Peer number for the particular peer. | ||
106 | */ | ||
107 | unsigned int peer; | ||
108 | |||
109 | /** | ||
110 | * Port handlers for open ports. | ||
111 | */ | ||
112 | struct GNUNET_CADET_Port **ports; | ||
113 | |||
114 | /** | ||
115 | * General context. | ||
116 | */ | ||
117 | struct GNUNET_CADET_TEST_Context *ctx; | ||
118 | }; | ||
119 | |||
120 | |||
121 | /** | ||
122 | * Adapter function called to establish a connection to | ||
123 | * the CADET service. | ||
124 | * | ||
125 | * @param cls closure | ||
126 | * @param cfg configuration of the peer to connect to; will be available until | ||
127 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
128 | * from GNUNET_TESTBED_service_connect() | ||
129 | * @return service handle to return in 'op_result', NULL on error | ||
130 | */ | ||
131 | static void * | ||
132 | cadet_connect_adapter (void *cls, | ||
133 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
134 | { | ||
135 | struct GNUNET_CADET_TEST_AdapterContext *actx = cls; | ||
136 | struct GNUNET_CADET_TEST_Context *ctx = actx->ctx; | ||
137 | struct GNUNET_CADET_Handle *h; | ||
138 | unsigned int i; | ||
139 | |||
140 | h = GNUNET_CADET_connecT (cfg); | ||
141 | if (NULL == ctx->ports) | ||
142 | return h; | ||
143 | |||
144 | actx->ports = GNUNET_new_array (ctx->port_count, struct GNUNET_CADET_Port *); | ||
145 | for (i = 0; i < ctx->port_count; i++) | ||
146 | { | ||
147 | actx->ports[i] = GNUNET_CADET_open_porT (h, | ||
148 | ctx->ports[i], | ||
149 | ctx->connects, | ||
150 | (void *) (long) actx->peer, | ||
151 | ctx->window_changes, | ||
152 | ctx->disconnects, | ||
153 | ctx->handlers); | ||
154 | } | ||
155 | return h; | ||
156 | } | ||
157 | |||
158 | |||
159 | /** | ||
160 | * Adapter function called to destroy a connection to | ||
161 | * the CADET service. | ||
162 | * | ||
163 | * @param cls closure | ||
164 | * @param op_result service handle returned from the connect adapter | ||
165 | */ | ||
166 | static void | ||
167 | cadet_disconnect_adapter (void *cls, | ||
168 | void *op_result) | ||
169 | { | ||
170 | struct GNUNET_CADET_Handle *cadet = op_result; | ||
171 | struct GNUNET_CADET_TEST_AdapterContext *actx = cls; | ||
172 | |||
173 | if (NULL != actx->ports) | ||
174 | { | ||
175 | for (int i = 0; i < actx->ctx->port_count; i++) | ||
176 | { | ||
177 | GNUNET_CADET_close_port (actx->ports[i]); | ||
178 | actx->ports[i] = NULL; | ||
179 | } | ||
180 | GNUNET_free (actx->ports); | ||
181 | } | ||
182 | GNUNET_free (actx); | ||
183 | GNUNET_CADET_disconnect (cadet); | ||
184 | } | ||
185 | |||
186 | |||
187 | /** | ||
188 | * Callback to be called when a service connect operation is completed. | ||
189 | * | ||
190 | * @param cls The callback closure from functions generating an operation. | ||
191 | * @param op The operation that has been finished. | ||
192 | * @param ca_result The service handle returned from | ||
193 | * GNUNET_TESTBED_ConnectAdapter() (cadet handle). | ||
194 | * @param emsg Error message in case the operation has failed. | ||
195 | * NULL if operation has executed successfully. | ||
196 | */ | ||
197 | static void | ||
198 | cadet_connect_cb (void *cls, | ||
199 | struct GNUNET_TESTBED_Operation *op, | ||
200 | void *ca_result, | ||
201 | const char *emsg) | ||
202 | { | ||
203 | struct GNUNET_CADET_TEST_Context *ctx = cls; | ||
204 | unsigned int i; | ||
205 | |||
206 | if (NULL != emsg) | ||
207 | { | ||
208 | fprintf (stderr, "Failed to connect to CADET service: %s\n", | ||
209 | emsg); | ||
210 | GNUNET_SCHEDULER_shutdown (); | ||
211 | return; | ||
212 | } | ||
213 | for (i = 0; i < ctx->num_peers; i++) | ||
214 | if (op == ctx->ops[i]) | ||
215 | { | ||
216 | ctx->cadets[i] = ca_result; | ||
217 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i); | ||
218 | } | ||
219 | for (i = 0; i < ctx->num_peers; i++) | ||
220 | if (NULL == ctx->cadets[i]) | ||
221 | return; /* still some CADET connections missing */ | ||
222 | /* all CADET connections ready! */ | ||
223 | ctx->app_main (ctx->app_main_cls, | ||
224 | ctx, | ||
225 | ctx->num_peers, | ||
226 | ctx->peers, | ||
227 | ctx->cadets); | ||
228 | } | ||
229 | |||
230 | |||
231 | void | ||
232 | GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx) | ||
233 | { | ||
234 | unsigned int i; | ||
235 | |||
236 | for (i = 0; i < ctx->num_peers; i++) | ||
237 | { | ||
238 | GNUNET_assert (NULL != ctx->ops[i]); | ||
239 | GNUNET_TESTBED_operation_done (ctx->ops[i]); | ||
240 | ctx->ops[i] = NULL; | ||
241 | } | ||
242 | GNUNET_free (ctx->ops); | ||
243 | GNUNET_free (ctx->cadets); | ||
244 | GNUNET_free (ctx); | ||
245 | GNUNET_SCHEDULER_shutdown (); | ||
246 | } | ||
247 | |||
248 | |||
249 | /** | ||
250 | * Callback run when the testbed is ready (peers running and connected to | ||
251 | * each other) | ||
252 | * | ||
253 | * @param cls Closure (context). | ||
254 | * @param h the run handle | ||
255 | * @param num_peers Number of peers that are running. | ||
256 | * @param peers Handles to each one of the @c num_peers peers. | ||
257 | * @param links_succeeded the number of overlay link connection attempts that | ||
258 | * succeeded | ||
259 | * @param links_failed the number of overlay link connection attempts that | ||
260 | * failed | ||
261 | */ | ||
262 | static void | ||
263 | cadet_test_run (void *cls, | ||
264 | struct GNUNET_TESTBED_RunHandle *h, | ||
265 | unsigned int num_peers, | ||
266 | struct GNUNET_TESTBED_Peer **peers, | ||
267 | unsigned int links_succeeded, | ||
268 | unsigned int links_failed) | ||
269 | { | ||
270 | struct GNUNET_CADET_TEST_Context *ctx = cls; | ||
271 | unsigned int i; | ||
272 | |||
273 | if (0 != links_failed) | ||
274 | { | ||
275 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Some links failed (%u), ending\n", | ||
276 | links_failed); | ||
277 | exit (2); | ||
278 | } | ||
279 | |||
280 | if (num_peers != ctx->num_peers) | ||
281 | { | ||
282 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n", | ||
283 | num_peers, ctx->num_peers); | ||
284 | exit (1); | ||
285 | } | ||
286 | |||
287 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
288 | "Testbed up, %u peers and %u links\n", | ||
289 | num_peers, links_succeeded); | ||
290 | ctx->peers = peers; | ||
291 | for (i = 0; i < num_peers; i++) | ||
292 | { | ||
293 | struct GNUNET_CADET_TEST_AdapterContext *newctx; | ||
294 | newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext); | ||
295 | newctx->peer = i; | ||
296 | newctx->ctx = ctx; | ||
297 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to cadet %u\n", i); | ||
298 | ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx, | ||
299 | peers[i], | ||
300 | "cadet", | ||
301 | &cadet_connect_cb, | ||
302 | ctx, | ||
303 | &cadet_connect_adapter, | ||
304 | &cadet_disconnect_adapter, | ||
305 | newctx); | ||
306 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "op handle %p\n", ctx->ops[i]); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | |||
311 | /** | ||
312 | * Run a test using the given name, configuration file and number of peers. | ||
313 | * All cadet callbacks will receive the peer number (long) as the closure. | ||
314 | * | ||
315 | * @param testname Name of the test (for logging). | ||
316 | * @param cfgfile Name of the configuration file. | ||
317 | * @param num_peers Number of peers to start. | ||
318 | * @param tmain Main function to run once the testbed is ready. | ||
319 | * @param tmain_cls Closure for @a tmain. | ||
320 | * @param connects Handler for incoming channels. | ||
321 | * @param window_changes Handler for the window size change notification. | ||
322 | * @param disconnects Cleaner for destroyed incoming channels. | ||
323 | * @param handlers Message handlers. | ||
324 | * @param ports Ports the peers offer, NULL-terminated. | ||
325 | */ | ||
326 | void | ||
327 | GNUNET_CADET_TEST_ruN (const char *testname, | ||
328 | const char *cfgfile, | ||
329 | unsigned int num_peers, | ||
330 | GNUNET_CADET_TEST_AppMain tmain, | ||
331 | void *tmain_cls, | ||
332 | GNUNET_CADET_ConnectEventHandler connects, | ||
333 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
334 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
335 | struct GNUNET_MQ_MessageHandler *handlers, | ||
336 | const struct GNUNET_HashCode **ports) | ||
337 | { | ||
338 | struct GNUNET_CADET_TEST_Context *ctx; | ||
339 | |||
340 | ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context); | ||
341 | ctx->num_peers = num_peers; | ||
342 | ctx->ops = GNUNET_new_array (num_peers, struct GNUNET_TESTBED_Operation *); | ||
343 | ctx->cadets = GNUNET_new_array (num_peers, struct GNUNET_CADET_Handle *); | ||
344 | ctx->app_main = tmain; | ||
345 | ctx->app_main_cls = tmain_cls; | ||
346 | ctx->connects = connects; | ||
347 | ctx->window_changes = window_changes; | ||
348 | ctx->disconnects = disconnects; | ||
349 | ctx->handlers = GNUNET_MQ_copy_handlers (handlers); | ||
350 | ctx->ports = ports; | ||
351 | ctx->port_count = 0; | ||
352 | while (NULL != ctx->ports[ctx->port_count]) | ||
353 | ctx->port_count++; | ||
354 | |||
355 | GNUNET_TESTBED_test_run (testname, | ||
356 | cfgfile, | ||
357 | num_peers, | ||
358 | 0LL, NULL, NULL, | ||
359 | &cadet_test_run, ctx); | ||
360 | } | ||
361 | |||
362 | /* end of cadet_test_lib.c */ | ||
diff --git a/src/cadet/cadet_test_lib_new.h b/src/cadet/cadet_test_lib_new.h new file mode 100644 index 000000000..4b3a6b18d --- /dev/null +++ b/src/cadet/cadet_test_lib_new.h | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012,2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_test_lib.h | ||
22 | * @author Bartlomiej Polot | ||
23 | * @brief library for writing CADET tests | ||
24 | */ | ||
25 | #ifndef CADET_TEST_LIB_H | ||
26 | #define CADET_TEST_LIB_H | ||
27 | |||
28 | #ifdef __cplusplus | ||
29 | extern "C" | ||
30 | { | ||
31 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
32 | } | ||
33 | #endif | ||
34 | #endif | ||
35 | |||
36 | #include "gnunet_testbed_service.h" | ||
37 | #include "gnunet_cadet_service.h" | ||
38 | |||
39 | /** | ||
40 | * Test context for a CADET Test. | ||
41 | */ | ||
42 | struct GNUNET_CADET_TEST_Context; | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Main function of a CADET test. | ||
47 | * | ||
48 | * @param cls Closure. | ||
49 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. | ||
50 | * @param num_peers Number of peers that are running. | ||
51 | * @param peers Array of peers. | ||
52 | * @param cadets Handle to each of the CADETs of the peers. | ||
53 | */ | ||
54 | typedef void (*GNUNET_CADET_TEST_AppMain) (void *cls, | ||
55 | struct GNUNET_CADET_TEST_Context *ctx, | ||
56 | unsigned int num_peers, | ||
57 | struct GNUNET_TESTBED_Peer **peers, | ||
58 | struct GNUNET_CADET_Handle **cadets); | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Run a test using the given name, configuration file and number of peers. | ||
63 | * All cadet callbacks will receive the peer number (long) as the closure. | ||
64 | * | ||
65 | * @param testname Name of the test (for logging). | ||
66 | * @param cfgfile Name of the configuration file. | ||
67 | * @param num_peers Number of peers to start. | ||
68 | * @param tmain Main function to run once the testbed is ready. | ||
69 | * @param tmain_cls Closure for @a tmain. | ||
70 | * @param connects Handler for incoming channels. | ||
71 | * @param window_changes Handler for the window size change notification. | ||
72 | * @param disconnects Cleaner for destroyed incoming channels. | ||
73 | * @param handlers Message handlers. | ||
74 | * @param ports Ports the peers offer, NULL-terminated. | ||
75 | */ | ||
76 | void | ||
77 | GNUNET_CADET_TEST_ruN (const char *testname, | ||
78 | const char *cfgfile, | ||
79 | unsigned int num_peers, | ||
80 | GNUNET_CADET_TEST_AppMain tmain, | ||
81 | void *tmain_cls, | ||
82 | GNUNET_CADET_ConnectEventHandler connects, | ||
83 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
84 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
85 | struct GNUNET_MQ_MessageHandler *handlers, | ||
86 | const struct GNUNET_HashCode **ports); | ||
87 | |||
88 | /** | ||
89 | * Clean up the testbed. | ||
90 | * | ||
91 | * @param ctx handle for the testbed | ||
92 | */ | ||
93 | void | ||
94 | GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx); | ||
95 | |||
96 | |||
97 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
98 | { | ||
99 | #endif | ||
100 | #ifdef __cplusplus | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | |||
105 | /* ifndef CADET_TEST_LIB_H */ | ||
106 | #endif | ||
diff --git a/src/cadet/test_cadet.c b/src/cadet/test_cadet.c index f2e639e7a..e57c01be2 100644 --- a/src/cadet/test_cadet.c +++ b/src/cadet/test_cadet.c | |||
@@ -593,8 +593,8 @@ tmt_rdy (void *cls, size_t size, void *buf) | |||
593 | "sending initializer\n"); | 593 | "sending initializer\n"); |
594 | msg_size = size_payload + 1000; | 594 | msg_size = size_payload + 1000; |
595 | msg->size = htons (msg_size); | 595 | msg->size = htons (msg_size); |
596 | if (SPEED_ACK == test) | 596 | if (SPEED_ACK == test) |
597 | data_sent++; | 597 | data_sent++; |
598 | } | 598 | } |
599 | else if ( (SPEED == test) || | 599 | else if ( (SPEED == test) || |
600 | (SPEED_ACK == test) ) | 600 | (SPEED_ACK == test) ) |
diff --git a/src/cadet/test_cadet_new.c b/src/cadet/test_cadet_new.c new file mode 100644 index 000000000..622e87ea1 --- /dev/null +++ b/src/cadet/test_cadet_new.c | |||
@@ -0,0 +1,1049 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/test_cadet_mq.c | ||
22 | * @author Bart Polot | ||
23 | * @author Christian Grothoff | ||
24 | * @brief Test for the cadet service using mq API. | ||
25 | */ | ||
26 | #include <stdio.h> | ||
27 | #include "platform.h" | ||
28 | #include "cadet_test_lib_new.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "gnunet_statistics_service.h" | ||
31 | #include <gauger.h> | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Ugly workaround to unify data handlers on incoming and outgoing channels. | ||
36 | */ | ||
37 | struct CadetTestChannelWrapper | ||
38 | { | ||
39 | /** | ||
40 | * Channel pointer. | ||
41 | */ | ||
42 | struct GNUNET_CADET_Channel *ch; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * How many messages to send | ||
47 | */ | ||
48 | #define TOTAL_PACKETS 500 /* Cannot exceed 64k! */ | ||
49 | |||
50 | /** | ||
51 | * How long until we give up on connecting the peers? | ||
52 | */ | ||
53 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | ||
54 | |||
55 | /** | ||
56 | * Time to wait for stuff that should be rather fast | ||
57 | */ | ||
58 | #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) | ||
59 | |||
60 | /** | ||
61 | * DIFFERENT TESTS TO RUN | ||
62 | */ | ||
63 | #define SETUP 0 | ||
64 | #define FORWARD 1 | ||
65 | #define KEEPALIVE 2 | ||
66 | #define SPEED 3 | ||
67 | #define SPEED_ACK 4 | ||
68 | #define SPEED_REL 8 | ||
69 | #define P2P_SIGNAL 10 | ||
70 | |||
71 | /** | ||
72 | * Which test are we running? | ||
73 | */ | ||
74 | static int test; | ||
75 | |||
76 | /** | ||
77 | * String with test name | ||
78 | */ | ||
79 | static char *test_name; | ||
80 | |||
81 | /** | ||
82 | * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic. | ||
83 | */ | ||
84 | static int test_backwards = GNUNET_NO; | ||
85 | |||
86 | /** | ||
87 | * How many events have happened | ||
88 | */ | ||
89 | static int ok; | ||
90 | |||
91 | /** | ||
92 | * Number of events expected to conclude the test successfully. | ||
93 | */ | ||
94 | static int ok_goal; | ||
95 | |||
96 | /** | ||
97 | * Size of each test packet's payload | ||
98 | */ | ||
99 | static size_t size_payload = sizeof (uint32_t); | ||
100 | |||
101 | /** | ||
102 | * Operation to get peer ids. | ||
103 | */ | ||
104 | static struct GNUNET_TESTBED_Operation *t_op[2]; | ||
105 | |||
106 | /** | ||
107 | * Peer ids. | ||
108 | */ | ||
109 | static struct GNUNET_PeerIdentity *p_id[2]; | ||
110 | |||
111 | /** | ||
112 | * Port ID | ||
113 | */ | ||
114 | static struct GNUNET_HashCode port; | ||
115 | |||
116 | /** | ||
117 | * Peer ids counter. | ||
118 | */ | ||
119 | static unsigned int p_ids; | ||
120 | |||
121 | /** | ||
122 | * Is the setup initialized? | ||
123 | */ | ||
124 | static int initialized; | ||
125 | |||
126 | /** | ||
127 | * Number of payload packes sent. | ||
128 | */ | ||
129 | static int data_sent; | ||
130 | |||
131 | /** | ||
132 | * Number of payload packets received. | ||
133 | */ | ||
134 | static int data_received; | ||
135 | |||
136 | /** | ||
137 | * Number of payload packed acknowledgements sent. | ||
138 | */ | ||
139 | static int ack_sent; | ||
140 | |||
141 | /** | ||
142 | * Number of payload packed explicitly (app level) acknowledged. | ||
143 | */ | ||
144 | static int ack_received; | ||
145 | |||
146 | /** | ||
147 | * Total number of peers asked to run. | ||
148 | */ | ||
149 | static unsigned long long peers_requested; | ||
150 | |||
151 | /** | ||
152 | * Number of currently running peers (should be same as @c peers_requested). | ||
153 | */ | ||
154 | static unsigned long long peers_running; | ||
155 | |||
156 | /** | ||
157 | * Test context (to shut down). | ||
158 | */ | ||
159 | struct GNUNET_CADET_TEST_Context *test_ctx; | ||
160 | |||
161 | /** | ||
162 | * Task called to disconnect peers. | ||
163 | */ | ||
164 | static struct GNUNET_SCHEDULER_Task *disconnect_task; | ||
165 | |||
166 | /** | ||
167 | * Task To perform tests | ||
168 | */ | ||
169 | static struct GNUNET_SCHEDULER_Task *test_task; | ||
170 | |||
171 | /** | ||
172 | * Task runnining #send_next_msg(). | ||
173 | */ | ||
174 | static struct GNUNET_SCHEDULER_Task *send_next_msg_task; | ||
175 | |||
176 | /** | ||
177 | * Cadet handle for the root peer | ||
178 | */ | ||
179 | static struct GNUNET_CADET_Handle *h1; | ||
180 | |||
181 | /** | ||
182 | * Cadet handle for the first leaf peer | ||
183 | */ | ||
184 | static struct GNUNET_CADET_Handle *h2; | ||
185 | |||
186 | /** | ||
187 | * Channel handle for the root peer | ||
188 | */ | ||
189 | static struct GNUNET_CADET_Channel *outgoing_ch; | ||
190 | |||
191 | /** | ||
192 | * Channel handle for the dest peer | ||
193 | */ | ||
194 | static struct GNUNET_CADET_Channel *incoming_ch; | ||
195 | |||
196 | /** | ||
197 | * Time we started the data transmission (after channel has been established | ||
198 | * and initilized). | ||
199 | */ | ||
200 | static struct GNUNET_TIME_Absolute start_time; | ||
201 | |||
202 | /** | ||
203 | * Peers handle. | ||
204 | */ | ||
205 | static struct GNUNET_TESTBED_Peer **testbed_peers; | ||
206 | |||
207 | /** | ||
208 | * Statistics operation handle. | ||
209 | */ | ||
210 | static struct GNUNET_TESTBED_Operation *stats_op; | ||
211 | |||
212 | /** | ||
213 | * Keepalives sent. | ||
214 | */ | ||
215 | static unsigned int ka_sent; | ||
216 | |||
217 | /** | ||
218 | * Keepalives received. | ||
219 | */ | ||
220 | static unsigned int ka_received; | ||
221 | |||
222 | /** | ||
223 | * How many messages were dropped by CADET because of full buffers? | ||
224 | */ | ||
225 | static unsigned int msg_dropped; | ||
226 | |||
227 | |||
228 | /******************************************************************************/ | ||
229 | |||
230 | |||
231 | /******************************************************************************/ | ||
232 | |||
233 | |||
234 | /** | ||
235 | * Get the channel considered as the "target" or "receiver", depending on | ||
236 | * the test type and size. | ||
237 | * | ||
238 | * @return Channel handle of the target client, either 0 (for backward tests) | ||
239 | * or the last peer in the line (for other tests). | ||
240 | */ | ||
241 | static struct GNUNET_CADET_Channel * | ||
242 | get_target_channel () | ||
243 | { | ||
244 | if (SPEED == test && GNUNET_YES == test_backwards) | ||
245 | return outgoing_ch; | ||
246 | else | ||
247 | return incoming_ch; | ||
248 | } | ||
249 | |||
250 | |||
251 | /** | ||
252 | * Show the results of the test (banwidth acheived) and log them to GAUGER | ||
253 | */ | ||
254 | static void | ||
255 | show_end_data (void) | ||
256 | { | ||
257 | static struct GNUNET_TIME_Absolute end_time; | ||
258 | static struct GNUNET_TIME_Relative total_time; | ||
259 | |||
260 | end_time = GNUNET_TIME_absolute_get (); | ||
261 | total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time); | ||
262 | FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); | ||
263 | FPRINTF (stderr, "Test time %s\n", | ||
264 | GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES)); | ||
265 | FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms | ||
266 | FPRINTF (stderr, "Test throughput: %f packets/s\n\n", TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms | ||
267 | GAUGER ("CADET", test_name, | ||
268 | TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000), | ||
269 | "packets/s"); | ||
270 | } | ||
271 | |||
272 | |||
273 | /** | ||
274 | * Disconnect from cadet services af all peers, call shutdown. | ||
275 | * | ||
276 | * @param cls Closure (line number from which termination was requested). | ||
277 | * @param tc Task Context. | ||
278 | */ | ||
279 | static void | ||
280 | disconnect_cadet_peers (void *cls) | ||
281 | { | ||
282 | long line = (long) cls; | ||
283 | unsigned int i; | ||
284 | |||
285 | disconnect_task = NULL; | ||
286 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
287 | "disconnecting cadet service of peers, called from line %ld\n", | ||
288 | line); | ||
289 | for (i = 0; i < 2; i++) | ||
290 | { | ||
291 | GNUNET_TESTBED_operation_done (t_op[i]); | ||
292 | } | ||
293 | if (NULL != outgoing_ch) | ||
294 | { | ||
295 | GNUNET_CADET_channel_destroy (outgoing_ch); | ||
296 | outgoing_ch = NULL; | ||
297 | } | ||
298 | if (NULL != incoming_ch) | ||
299 | { | ||
300 | GNUNET_CADET_channel_destroy (incoming_ch); | ||
301 | incoming_ch = NULL; | ||
302 | } | ||
303 | GNUNET_CADET_TEST_cleanup (test_ctx); | ||
304 | GNUNET_SCHEDULER_shutdown (); | ||
305 | } | ||
306 | |||
307 | |||
308 | /** | ||
309 | * Shut down peergroup, clean up. | ||
310 | * | ||
311 | * @param cls Closure (unused). | ||
312 | * @param tc Task Context. | ||
313 | */ | ||
314 | static void | ||
315 | shutdown_task (void *cls) | ||
316 | { | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); | ||
318 | if (NULL != send_next_msg_task) | ||
319 | { | ||
320 | GNUNET_SCHEDULER_cancel (send_next_msg_task); | ||
321 | send_next_msg_task = NULL; | ||
322 | } | ||
323 | if (NULL != test_task) | ||
324 | { | ||
325 | GNUNET_SCHEDULER_cancel (test_task); | ||
326 | test_task = NULL; | ||
327 | } | ||
328 | if (NULL != disconnect_task) | ||
329 | { | ||
330 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
331 | disconnect_task = | ||
332 | GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) __LINE__); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | |||
337 | /** | ||
338 | * Stats callback. Finish the stats testbed operation and when all stats have | ||
339 | * been iterated, shutdown the test. | ||
340 | * | ||
341 | * @param cls Closure (line number from which termination was requested). | ||
342 | * @param op the operation that has been finished | ||
343 | * @param emsg error message in case the operation has failed; will be NULL if | ||
344 | * operation has executed successfully. | ||
345 | */ | ||
346 | static void | ||
347 | stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) | ||
348 | { | ||
349 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " KA sent: %u, KA received: %u\n", | ||
350 | ka_sent, ka_received); | ||
351 | if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1))) | ||
352 | { | ||
353 | GNUNET_break (0); | ||
354 | ok--; | ||
355 | } | ||
356 | GNUNET_TESTBED_operation_done (stats_op); | ||
357 | |||
358 | if (NULL != disconnect_task) | ||
359 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
360 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, cls); | ||
361 | } | ||
362 | |||
363 | |||
364 | /** | ||
365 | * Process statistic values. | ||
366 | * | ||
367 | * @param cls closure (line number, unused) | ||
368 | * @param peer the peer the statistic belong to | ||
369 | * @param subsystem name of subsystem that created the statistic | ||
370 | * @param name the name of the datum | ||
371 | * @param value the current value | ||
372 | * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not | ||
373 | * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration | ||
374 | */ | ||
375 | static int | ||
376 | stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, | ||
377 | const char *subsystem, const char *name, uint64_t value, | ||
378 | int is_persistent) | ||
379 | { | ||
380 | static const char *s_sent = "# keepalives sent"; | ||
381 | static const char *s_recv = "# keepalives received"; | ||
382 | static const char *rdrops = "# messages dropped due to full buffer"; | ||
383 | static const char *cdrops = "# messages dropped due to slow client"; | ||
384 | uint32_t i; | ||
385 | |||
386 | i = GNUNET_TESTBED_get_index (peer); | ||
387 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i, | ||
388 | subsystem, name, (unsigned long long) value); | ||
389 | if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i) | ||
390 | ka_sent = value; | ||
391 | if (0 == strncmp (s_recv, name, strlen (s_recv)) && peers_requested - 1 == i) | ||
392 | ka_received = value; | ||
393 | if (0 == strncmp (rdrops, name, strlen (rdrops))) | ||
394 | msg_dropped += value; | ||
395 | if (0 == strncmp (cdrops, name, strlen (cdrops))) | ||
396 | msg_dropped += value; | ||
397 | |||
398 | return GNUNET_OK; | ||
399 | } | ||
400 | |||
401 | |||
402 | /** | ||
403 | * Task to gather all statistics. | ||
404 | * | ||
405 | * @param cls Closure (line from which the task was scheduled). | ||
406 | */ | ||
407 | static void | ||
408 | gather_stats_and_exit (void *cls) | ||
409 | { | ||
410 | long l = (long) cls; | ||
411 | |||
412 | disconnect_task = NULL; | ||
413 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
414 | "gathering statistics from line %ld\n", | ||
415 | l); | ||
416 | if (NULL != outgoing_ch) | ||
417 | { | ||
418 | GNUNET_CADET_channel_destroy (outgoing_ch); | ||
419 | outgoing_ch = NULL; | ||
420 | } | ||
421 | stats_op = GNUNET_TESTBED_get_statistics (peers_running, | ||
422 | testbed_peers, | ||
423 | "cadet", | ||
424 | NULL, | ||
425 | &stats_iterator, | ||
426 | stats_cont, | ||
427 | cls); | ||
428 | } | ||
429 | |||
430 | |||
431 | |||
432 | /** | ||
433 | * Abort test: schedule disconnect and shutdown immediately | ||
434 | * | ||
435 | * @param line Line in the code the abort is requested from (__LINE__). | ||
436 | */ | ||
437 | static void | ||
438 | abort_test (long line) | ||
439 | { | ||
440 | if (NULL != disconnect_task) | ||
441 | { | ||
442 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
443 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting test from %ld\n", line); | ||
444 | disconnect_task = | ||
445 | GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) line); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | |||
450 | /** | ||
451 | * Send a message on the channel with the appropriate size and payload. | ||
452 | * | ||
453 | * Update the appropriate *_sent counter. | ||
454 | * | ||
455 | * @param channel Channel to send the message on. | ||
456 | */ | ||
457 | static void | ||
458 | send_test_message (struct GNUNET_CADET_Channel *channel) | ||
459 | { | ||
460 | struct GNUNET_MQ_Envelope *env; | ||
461 | struct GNUNET_MessageHeader *msg; | ||
462 | uint32_t *data; | ||
463 | int *counter; | ||
464 | int size; | ||
465 | |||
466 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
467 | "Sending test message on channel %p\n", | ||
468 | channel); | ||
469 | size = size_payload; | ||
470 | if (GNUNET_NO == initialized) | ||
471 | { | ||
472 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n"); | ||
473 | size += 1000; | ||
474 | counter = &data_sent; | ||
475 | if (SPEED_ACK == test) // FIXME unify SPEED_ACK with an initializer | ||
476 | data_sent++; | ||
477 | } | ||
478 | else if (SPEED == test || SPEED_ACK == test) | ||
479 | { | ||
480 | counter = get_target_channel() == channel ? &ack_sent : &data_sent; | ||
481 | size += *counter; | ||
482 | *counter = *counter + 1; | ||
483 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending message %u\n", *counter); | ||
484 | } | ||
485 | else | ||
486 | { | ||
487 | counter = &ack_sent; | ||
488 | } | ||
489 | env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY); | ||
490 | |||
491 | data = (uint32_t *) &msg[1]; | ||
492 | *data = htonl (*counter); | ||
493 | GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env); | ||
494 | } | ||
495 | |||
496 | /** | ||
497 | * Task to request a new data transmission in a SPEED test, without waiting | ||
498 | * for previous messages to be sent/arrrive. | ||
499 | * | ||
500 | * @param cls Closure (unused). | ||
501 | */ | ||
502 | static void | ||
503 | send_next_msg (void *cls) | ||
504 | { | ||
505 | struct GNUNET_CADET_Channel *channel; | ||
506 | |||
507 | send_next_msg_task = NULL; | ||
508 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending next message: %d\n", data_sent); | ||
509 | |||
510 | channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch; | ||
511 | GNUNET_assert (NULL != channel); | ||
512 | GNUNET_assert (SPEED == test); | ||
513 | send_test_message (channel); | ||
514 | if (data_sent < TOTAL_PACKETS) | ||
515 | { | ||
516 | /* SPEED test: Send all messages as soon as possible */ | ||
517 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
518 | "Scheduling message %d\n", | ||
519 | data_sent + 1); | ||
520 | send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | |||
525 | /** | ||
526 | * Every few messages cancel the timeout task and re-schedule it again, to | ||
527 | * avoid timing out when traffic keeps coming. | ||
528 | * | ||
529 | * @param line Code line number to log if a timeout occurs. | ||
530 | */ | ||
531 | static void | ||
532 | reschedule_timeout_task (long line) | ||
533 | { | ||
534 | if ((ok % 10) == 0) | ||
535 | { | ||
536 | if (NULL != disconnect_task) | ||
537 | { | ||
538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
539 | " reschedule timeout every 10 messages\n"); | ||
540 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
541 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
542 | &gather_stats_and_exit, | ||
543 | (void *) line); | ||
544 | } | ||
545 | } | ||
546 | } | ||
547 | |||
548 | |||
549 | /** | ||
550 | * Check if payload is sane (size contains payload). | ||
551 | * | ||
552 | * @param cls should match #ch | ||
553 | * @param message The actual message. | ||
554 | * @return #GNUNET_OK to keep the channel open, | ||
555 | * #GNUNET_SYSERR to close it (signal serious error). | ||
556 | */ | ||
557 | static int | ||
558 | check_data (void *cls, const struct GNUNET_MessageHeader *message) | ||
559 | { | ||
560 | if (sizeof (struct GNUNET_MessageHeader) >= ntohs (message->size)) | ||
561 | return GNUNET_SYSERR; | ||
562 | return GNUNET_OK; /* all is well-formed */ | ||
563 | } | ||
564 | |||
565 | |||
566 | /** | ||
567 | * Function is called whenever a message is received. | ||
568 | * | ||
569 | * @param cls closure (set from GNUNET_CADET_connect(), peer number) | ||
570 | * @param message the actual message | ||
571 | */ | ||
572 | static void | ||
573 | handle_data (void *cls, const struct GNUNET_MessageHeader *message) | ||
574 | { | ||
575 | struct CadetTestChannelWrapper *ch = cls; | ||
576 | struct GNUNET_CADET_Channel *channel = ch->ch; | ||
577 | uint32_t *data; | ||
578 | uint32_t payload; | ||
579 | int *counter; | ||
580 | |||
581 | ok++; | ||
582 | counter = get_target_channel () == channel ? &data_received : &ack_received; | ||
583 | |||
584 | reschedule_timeout_task ((long) __LINE__); | ||
585 | |||
586 | if (channel == outgoing_ch) | ||
587 | { | ||
588 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); | ||
589 | } | ||
590 | else if (channel == incoming_ch) | ||
591 | { | ||
592 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client got a message.\n"); | ||
593 | } | ||
594 | else | ||
595 | { | ||
596 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown channel %p.\n", channel); | ||
597 | GNUNET_assert (0); | ||
598 | } | ||
599 | |||
600 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); | ||
601 | data = (uint32_t *) &message[1]; | ||
602 | payload = ntohl (*data); | ||
603 | if (payload == *counter) | ||
604 | { | ||
605 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload); | ||
606 | } | ||
607 | else | ||
608 | { | ||
609 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
610 | " payload %u, expected: %u\n", | ||
611 | payload, *counter); | ||
612 | } | ||
613 | |||
614 | if (GNUNET_NO == initialized) | ||
615 | { | ||
616 | initialized = GNUNET_YES; | ||
617 | start_time = GNUNET_TIME_absolute_get (); | ||
618 | if (SPEED == test) | ||
619 | { | ||
620 | GNUNET_assert (incoming_ch == channel); | ||
621 | send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL); | ||
622 | return; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | (*counter)++; | ||
627 | if (get_target_channel () == channel) /* Got "data" */ | ||
628 | { | ||
629 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received); | ||
630 | if (SPEED != test || (ok_goal - 2) == ok) | ||
631 | { | ||
632 | /* Send ACK */ | ||
633 | send_test_message (channel); | ||
634 | return; | ||
635 | } | ||
636 | else | ||
637 | { | ||
638 | if (data_received < TOTAL_PACKETS) | ||
639 | return; | ||
640 | } | ||
641 | } | ||
642 | else /* Got "ack" */ | ||
643 | { | ||
644 | if (SPEED_ACK == test || SPEED == test) | ||
645 | { | ||
646 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received); | ||
647 | /* Send more data */ | ||
648 | send_test_message (channel); | ||
649 | if (ack_received < TOTAL_PACKETS && SPEED != test) | ||
650 | return; | ||
651 | if (ok == 2 && SPEED == test) | ||
652 | return; | ||
653 | show_end_data (); | ||
654 | } | ||
655 | if (test == P2P_SIGNAL) | ||
656 | { | ||
657 | GNUNET_CADET_channel_destroy (incoming_ch); | ||
658 | incoming_ch = NULL; | ||
659 | } | ||
660 | else | ||
661 | { | ||
662 | GNUNET_CADET_channel_destroy (outgoing_ch); | ||
663 | outgoing_ch = NULL; | ||
664 | } | ||
665 | } | ||
666 | } | ||
667 | |||
668 | |||
669 | /** | ||
670 | * Method called whenever a peer connects to a port in MQ-based CADET. | ||
671 | * | ||
672 | * @param cls Closure from #GNUNET_CADET_open_porT (peer # as long). | ||
673 | * @param channel New handle to the channel. | ||
674 | * @param source Peer that started this channel. | ||
675 | * @return Closure for the incoming @a channel. It's given to: | ||
676 | * - The #GNUNET_CADET_DisconnectEventHandler (given to | ||
677 | * #GNUNET_CADET_open_porT) when the channel dies. | ||
678 | * - Each the #GNUNET_MQ_MessageCallback handlers for each message | ||
679 | * received on the @a channel. | ||
680 | */ | ||
681 | static void * | ||
682 | connect_handler (void *cls, struct GNUNET_CADET_Channel *channel, | ||
683 | const struct GNUNET_PeerIdentity *source) | ||
684 | { | ||
685 | struct CadetTestChannelWrapper *ch; | ||
686 | long peer = (long) cls; | ||
687 | |||
688 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Incoming channel from %s to peer %ld\n", | ||
689 | GNUNET_i2s (source), peer); | ||
690 | ok++; | ||
691 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | ||
692 | if (peer == peers_requested - 1) | ||
693 | { | ||
694 | if (NULL != incoming_ch) | ||
695 | { | ||
696 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
697 | "Duplicate incoming channel for client %lu\n", (long) cls); | ||
698 | GNUNET_assert (0); | ||
699 | } | ||
700 | incoming_ch = channel; | ||
701 | } | ||
702 | else | ||
703 | { | ||
704 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
705 | "Incoming channel for unexpected peer #%lu\n", (long) cls); | ||
706 | GNUNET_assert (0); | ||
707 | } | ||
708 | if (NULL != disconnect_task) | ||
709 | { | ||
710 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
711 | disconnect_task = | ||
712 | GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &gather_stats_and_exit, | ||
713 | (void *) __LINE__); | ||
714 | } | ||
715 | |||
716 | /* TODO: cannot return channel as-is, in order to unify the data handlers */ | ||
717 | ch = GNUNET_new (struct CadetTestChannelWrapper); | ||
718 | ch->ch = channel; | ||
719 | |||
720 | return ch; | ||
721 | } | ||
722 | |||
723 | |||
724 | /** | ||
725 | * Function called whenever an MQ-channel is destroyed, even if the destruction | ||
726 | * was requested by #GNUNET_CADET_channel_destroy. | ||
727 | * It must NOT call #GNUNET_CADET_channel_destroy on the channel. | ||
728 | * | ||
729 | * It should clean up any associated state, including cancelling any pending | ||
730 | * transmission on this channel. | ||
731 | * | ||
732 | * @param cls Channel closure. | ||
733 | * @param channel Connection to the other end (henceforth invalid). | ||
734 | */ | ||
735 | static void | ||
736 | disconnect_handler (void *cls, const struct GNUNET_CADET_Channel *channel) | ||
737 | { | ||
738 | long i = (long) cls; | ||
739 | |||
740 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
741 | "Channel disconnected at %p\n", cls); | ||
742 | if (peers_running - 1 == i) | ||
743 | { | ||
744 | ok++; | ||
745 | GNUNET_break (channel == incoming_ch); | ||
746 | incoming_ch = NULL; | ||
747 | } | ||
748 | else if (0L == i) | ||
749 | { | ||
750 | if (P2P_SIGNAL == test) | ||
751 | { | ||
752 | ok++; | ||
753 | } | ||
754 | GNUNET_break (channel == outgoing_ch); | ||
755 | outgoing_ch = NULL; | ||
756 | } | ||
757 | else | ||
758 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown peer! %d\n", (int) i); | ||
759 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | ||
760 | |||
761 | if (NULL != disconnect_task) | ||
762 | { | ||
763 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
764 | disconnect_task = | ||
765 | GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, (void *) __LINE__); | ||
766 | } | ||
767 | } | ||
768 | |||
769 | |||
770 | /** | ||
771 | * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES. | ||
772 | * | ||
773 | * Testcase continues when the root receives confirmation of connected peers, | ||
774 | * on callback function ch. | ||
775 | * | ||
776 | * @param cls Closure (unused). | ||
777 | */ | ||
778 | static void | ||
779 | start_test (void *cls) | ||
780 | { | ||
781 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
782 | GNUNET_MQ_hd_var_size (data, | ||
783 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
784 | struct GNUNET_MessageHeader, | ||
785 | NULL), | ||
786 | GNUNET_MQ_handler_end () | ||
787 | }; | ||
788 | struct CadetTestChannelWrapper *ch; | ||
789 | enum GNUNET_CADET_ChannelOption flags; | ||
790 | |||
791 | test_task = NULL; | ||
792 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test\n"); | ||
793 | if (NULL != disconnect_task) | ||
794 | { | ||
795 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
796 | disconnect_task = NULL; | ||
797 | } | ||
798 | |||
799 | flags = GNUNET_CADET_OPTION_DEFAULT; | ||
800 | if (SPEED_REL == test) | ||
801 | { | ||
802 | test = SPEED; | ||
803 | flags |= GNUNET_CADET_OPTION_RELIABLE; | ||
804 | } | ||
805 | |||
806 | ch = GNUNET_new (struct CadetTestChannelWrapper); | ||
807 | outgoing_ch = GNUNET_CADET_channel_creatE (h1, | ||
808 | ch, | ||
809 | p_id[1], | ||
810 | &port, | ||
811 | flags, | ||
812 | NULL, | ||
813 | &disconnect_handler, | ||
814 | handlers); | ||
815 | ch->ch = outgoing_ch; | ||
816 | |||
817 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
818 | &gather_stats_and_exit, | ||
819 | (void *) __LINE__); | ||
820 | if (KEEPALIVE == test) | ||
821 | return; /* Don't send any data. */ | ||
822 | |||
823 | |||
824 | data_received = 0; | ||
825 | data_sent = 0; | ||
826 | ack_received = 0; | ||
827 | ack_sent = 0; | ||
828 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending data initializer...\n"); | ||
829 | send_test_message (outgoing_ch); | ||
830 | } | ||
831 | |||
832 | |||
833 | /** | ||
834 | * Callback to be called when the requested peer information is available | ||
835 | * | ||
836 | * @param cls the closure from GNUNET_TESTBED_peer_get_information() | ||
837 | * @param op the operation this callback corresponds to | ||
838 | * @param pinfo the result; will be NULL if the operation has failed | ||
839 | * @param emsg error message if the operation has failed; | ||
840 | * NULL if the operation is successfull | ||
841 | */ | ||
842 | static void | ||
843 | pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op, | ||
844 | const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) | ||
845 | { | ||
846 | long i = (long) cls; | ||
847 | |||
848 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ID callback for %ld\n", i); | ||
849 | |||
850 | if ((NULL == pinfo) || (NULL != emsg)) | ||
851 | { | ||
852 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); | ||
853 | abort_test (__LINE__); | ||
854 | return; | ||
855 | } | ||
856 | p_id[i] = pinfo->result.id; | ||
857 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); | ||
858 | p_ids++; | ||
859 | if (p_ids < 2) | ||
860 | return; | ||
861 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); | ||
862 | test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL); | ||
863 | } | ||
864 | |||
865 | |||
866 | /** | ||
867 | * test main: start test when all peers are connected | ||
868 | * | ||
869 | * @param cls Closure. | ||
870 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. | ||
871 | * @param num_peers Number of peers that are running. | ||
872 | * @param peers Array of peers. | ||
873 | * @param cadets Handle to each of the CADETs of the peers. | ||
874 | */ | ||
875 | static void | ||
876 | tmain (void *cls, | ||
877 | struct GNUNET_CADET_TEST_Context *ctx, | ||
878 | unsigned int num_peers, | ||
879 | struct GNUNET_TESTBED_Peer **peers, | ||
880 | struct GNUNET_CADET_Handle **cadets) | ||
881 | { | ||
882 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n"); | ||
883 | ok = 0; | ||
884 | test_ctx = ctx; | ||
885 | peers_running = num_peers; | ||
886 | GNUNET_assert (peers_running == peers_requested); | ||
887 | testbed_peers = peers; | ||
888 | h1 = cadets[0]; | ||
889 | h2 = cadets[num_peers - 1]; | ||
890 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
891 | &disconnect_cadet_peers, | ||
892 | (void *) __LINE__); | ||
893 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
894 | t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], | ||
895 | GNUNET_TESTBED_PIT_IDENTITY, | ||
896 | &pi_cb, | ||
897 | (void *) 0L); | ||
898 | t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], | ||
899 | GNUNET_TESTBED_PIT_IDENTITY, | ||
900 | &pi_cb, | ||
901 | (void *) 1L); | ||
902 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); | ||
903 | } | ||
904 | |||
905 | |||
906 | /** | ||
907 | * Main: start test | ||
908 | */ | ||
909 | int | ||
910 | main (int argc, char *argv[]) | ||
911 | { | ||
912 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
913 | GNUNET_MQ_hd_var_size (data, | ||
914 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
915 | struct GNUNET_MessageHeader, | ||
916 | NULL), | ||
917 | GNUNET_MQ_handler_end () | ||
918 | }; | ||
919 | |||
920 | initialized = GNUNET_NO; | ||
921 | static const struct GNUNET_HashCode *ports[2]; | ||
922 | const char *config_file; | ||
923 | char port_id[] = "test port"; | ||
924 | |||
925 | GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port); | ||
926 | |||
927 | GNUNET_log_setup ("test", "DEBUG", NULL); | ||
928 | config_file = "test_cadet.conf"; | ||
929 | |||
930 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); | ||
931 | |||
932 | /* Find out requested size */ | ||
933 | if (strstr (argv[0], "_2_") != NULL) | ||
934 | { | ||
935 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DIRECT CONNECTIONs\n"); | ||
936 | peers_requested = 2; | ||
937 | } | ||
938 | else if (strstr (argv[0], "_5_") != NULL) | ||
939 | { | ||
940 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "5 PEER LINE\n"); | ||
941 | peers_requested = 5; | ||
942 | } | ||
943 | else | ||
944 | { | ||
945 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SIZE UNKNOWN, USING 2\n"); | ||
946 | peers_requested = 2; | ||
947 | } | ||
948 | |||
949 | /* Find out requested test */ | ||
950 | if (strstr (argv[0], "_forward") != NULL) | ||
951 | { | ||
952 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n"); | ||
953 | test = FORWARD; | ||
954 | test_name = "unicast"; | ||
955 | ok_goal = 4; | ||
956 | } | ||
957 | else if (strstr (argv[0], "_signal") != NULL) | ||
958 | { | ||
959 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n"); | ||
960 | test = P2P_SIGNAL; | ||
961 | test_name = "signal"; | ||
962 | ok_goal = 4; | ||
963 | } | ||
964 | else if (strstr (argv[0], "_speed_ack") != NULL) | ||
965 | { | ||
966 | /* Test is supposed to generate the following callbacks: | ||
967 | * 1 incoming channel (@dest) | ||
968 | * TOTAL_PACKETS received data packet (@dest) | ||
969 | * TOTAL_PACKETS received data packet (@orig) | ||
970 | * 1 received channel destroy (@dest) | ||
971 | */ | ||
972 | ok_goal = TOTAL_PACKETS * 2 + 2; | ||
973 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); | ||
974 | test = SPEED_ACK; | ||
975 | test_name = "speed ack"; | ||
976 | } | ||
977 | else if (strstr (argv[0], "_speed") != NULL) | ||
978 | { | ||
979 | /* Test is supposed to generate the following callbacks: | ||
980 | * 1 incoming channel (@dest) | ||
981 | * 1 initial packet (@dest) | ||
982 | * TOTAL_PACKETS received data packet (@dest) | ||
983 | * 1 received data packet (@orig) | ||
984 | * 1 received channel destroy (@dest) | ||
985 | */ | ||
986 | ok_goal = TOTAL_PACKETS + 4; | ||
987 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); | ||
988 | if (strstr (argv[0], "_reliable") != NULL) | ||
989 | { | ||
990 | test = SPEED_REL; | ||
991 | test_name = "speed reliable"; | ||
992 | config_file = "test_cadet_drop.conf"; | ||
993 | } | ||
994 | else | ||
995 | { | ||
996 | test = SPEED; | ||
997 | test_name = "speed"; | ||
998 | } | ||
999 | } | ||
1000 | else if (strstr (argv[0], "_keepalive") != NULL) | ||
1001 | { | ||
1002 | test = KEEPALIVE; | ||
1003 | /* Test is supposed to generate the following callbacks: | ||
1004 | * 1 incoming channel (@dest) | ||
1005 | * [wait] | ||
1006 | * 1 received channel destroy (@dest) | ||
1007 | */ | ||
1008 | ok_goal = 2; | ||
1009 | } | ||
1010 | else | ||
1011 | { | ||
1012 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n"); | ||
1013 | test = SETUP; | ||
1014 | ok_goal = 0; | ||
1015 | } | ||
1016 | |||
1017 | if (strstr (argv[0], "backwards") != NULL) | ||
1018 | { | ||
1019 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n"); | ||
1020 | test_backwards = GNUNET_YES; | ||
1021 | GNUNET_asprintf (&test_name, "backwards %s", test_name); | ||
1022 | } | ||
1023 | |||
1024 | p_ids = 0; | ||
1025 | ports[0] = &port; | ||
1026 | ports[1] = NULL; | ||
1027 | GNUNET_CADET_TEST_ruN ("test_cadet_small", | ||
1028 | config_file, | ||
1029 | peers_requested, | ||
1030 | &tmain, | ||
1031 | NULL, /* tmain cls */ | ||
1032 | &connect_handler, | ||
1033 | NULL, | ||
1034 | &disconnect_handler, | ||
1035 | handlers, | ||
1036 | ports); | ||
1037 | if (NULL != strstr (argv[0], "_reliable")) | ||
1038 | msg_dropped = 0; /* dropped should be retransmitted */ | ||
1039 | |||
1040 | if (ok_goal > ok - msg_dropped) | ||
1041 | { | ||
1042 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAILED! (%d/%d)\n", ok, ok_goal); | ||
1043 | return 1; | ||
1044 | } | ||
1045 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); | ||
1046 | return 0; | ||
1047 | } | ||
1048 | |||
1049 | /* end of test_cadet.c */ | ||