diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2014-01-09 09:40:15 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2014-01-09 09:40:15 +0000 |
commit | 6bb3d7d95c4a40deac7879d71c50c5ef7beb173f (patch) | |
tree | 19b407a81f1c02b2bba992a888a49c7c27ec61c9 /src/transport/test_transport_api_monitoring.c | |
parent | 92d84a56c7dda17af546dfa8991cd8dc2255f974 (diff) | |
download | gnunet-6bb3d7d95c4a40deac7879d71c50c5ef7beb173f.tar.gz gnunet-6bb3d7d95c4a40deac7879d71c50c5ef7beb173f.zip |
test + documentation
Diffstat (limited to 'src/transport/test_transport_api_monitoring.c')
-rw-r--r-- | src/transport/test_transport_api_monitoring.c | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/src/transport/test_transport_api_monitoring.c b/src/transport/test_transport_api_monitoring.c new file mode 100644 index 000000000..dc2a8b097 --- /dev/null +++ b/src/transport/test_transport_api_monitoring.c | |||
@@ -0,0 +1,472 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009, 2010 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file transport/test_transport_api.c | ||
22 | * @brief base test case for transport implementations | ||
23 | * | ||
24 | * This test case serves as a base for tcp, udp, and udp-nat | ||
25 | * transport test cases. Based on the executable being run | ||
26 | * the correct test case will be performed. Conservation of | ||
27 | * C code apparently. | ||
28 | */ | ||
29 | #include "platform.h" | ||
30 | #include "gnunet_transport_service.h" | ||
31 | #include "transport-testing.h" | ||
32 | |||
33 | /** | ||
34 | * How long until we give up on transmitting the message? | ||
35 | */ | ||
36 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | ||
37 | |||
38 | /** | ||
39 | * How long until we give up on transmitting the message? | ||
40 | */ | ||
41 | #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
42 | |||
43 | #define TEST_MESSAGE_SIZE 2600 | ||
44 | |||
45 | #define TEST_MESSAGE_TYPE 12345 | ||
46 | |||
47 | static char *test_source; | ||
48 | |||
49 | static char *test_plugin; | ||
50 | |||
51 | static char *test_name; | ||
52 | |||
53 | static int ok; | ||
54 | |||
55 | static int s_started; | ||
56 | |||
57 | static int s_connected; | ||
58 | |||
59 | static int s_sending; | ||
60 | |||
61 | static GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
62 | |||
63 | static GNUNET_SCHEDULER_TaskIdentifier send_task; | ||
64 | |||
65 | static struct PeerContext *p1; | ||
66 | |||
67 | static struct PeerContext *p2; | ||
68 | |||
69 | static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; | ||
70 | |||
71 | static struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
72 | |||
73 | static struct GNUNET_TRANSPORT_TESTING_handle *tth; | ||
74 | |||
75 | static char *cfg_file_p1; | ||
76 | |||
77 | static char *cfg_file_p2; | ||
78 | |||
79 | static struct GNUNET_TRANSPORT_PeerMonitoringContext *pmc_p1; | ||
80 | static struct GNUNET_TRANSPORT_PeerMonitoringContext *pmc_p2; | ||
81 | |||
82 | |||
83 | static void | ||
84 | end () | ||
85 | { | ||
86 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping peers\n"); | ||
87 | |||
88 | |||
89 | if (send_task != GNUNET_SCHEDULER_NO_TASK) | ||
90 | GNUNET_SCHEDULER_cancel (send_task); | ||
91 | |||
92 | if (die_task != GNUNET_SCHEDULER_NO_TASK) | ||
93 | GNUNET_SCHEDULER_cancel (die_task); | ||
94 | |||
95 | if (th != NULL) | ||
96 | GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); | ||
97 | th = NULL; | ||
98 | |||
99 | if (NULL != pmc_p1) | ||
100 | { | ||
101 | GNUNET_TRANSPORT_monitor_peers_cancel (pmc_p1); | ||
102 | pmc_p1 = NULL; | ||
103 | } | ||
104 | if (NULL != pmc_p2) | ||
105 | { | ||
106 | GNUNET_TRANSPORT_monitor_peers_cancel (pmc_p2); | ||
107 | pmc_p2 = NULL; | ||
108 | } | ||
109 | |||
110 | GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); | ||
111 | p1 = NULL; | ||
112 | GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); | ||
113 | p2 = NULL; | ||
114 | } | ||
115 | |||
116 | static void | ||
117 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
118 | { | ||
119 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
120 | |||
121 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Fail! Stopping peers\n"); | ||
122 | |||
123 | |||
124 | if (send_task != GNUNET_SCHEDULER_NO_TASK) | ||
125 | GNUNET_SCHEDULER_cancel (send_task); | ||
126 | |||
127 | if (cc != NULL) | ||
128 | { | ||
129 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); | ||
130 | GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); | ||
131 | cc = NULL; | ||
132 | } | ||
133 | |||
134 | if (th != NULL) | ||
135 | GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); | ||
136 | else | ||
137 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); | ||
138 | |||
139 | if (s_started == GNUNET_NO) | ||
140 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were not started \n")); | ||
141 | else | ||
142 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were started \n")); | ||
143 | |||
144 | if (s_connected == GNUNET_NO) | ||
145 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not connected\n")); | ||
146 | else | ||
147 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were connected\n")); | ||
148 | |||
149 | if (s_sending == GNUNET_NO) | ||
150 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); | ||
151 | else | ||
152 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were ready to send data\n")); | ||
153 | |||
154 | th = NULL; | ||
155 | |||
156 | if (p1 != NULL) | ||
157 | GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); | ||
158 | else | ||
159 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 1 was not started\n")); | ||
160 | if (p2 != NULL) | ||
161 | GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); | ||
162 | else | ||
163 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 2 was not started\n")); | ||
164 | |||
165 | ok = GNUNET_SYSERR; | ||
166 | } | ||
167 | |||
168 | |||
169 | static void | ||
170 | notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
171 | const struct GNUNET_MessageHeader *message) | ||
172 | { | ||
173 | struct PeerContext *p = cls; | ||
174 | struct PeerContext *t = NULL; | ||
175 | |||
176 | if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) | ||
177 | t = p1; | ||
178 | if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) | ||
179 | t = p2; | ||
180 | GNUNET_assert (t != NULL); | ||
181 | |||
182 | char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); | ||
183 | |||
184 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
185 | "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", | ||
186 | p->no, ps, ntohs (message->type), ntohs (message->size), t->no, | ||
187 | GNUNET_i2s (&t->id)); | ||
188 | GNUNET_free (ps); | ||
189 | } | ||
190 | |||
191 | |||
192 | static size_t | ||
193 | notify_ready (void *cls, size_t size, void *buf) | ||
194 | { | ||
195 | struct PeerContext *p = cls; | ||
196 | struct GNUNET_MessageHeader *hdr; | ||
197 | |||
198 | th = NULL; | ||
199 | |||
200 | if (buf == NULL) | ||
201 | { | ||
202 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
203 | "Timeout occurred while waiting for transmit_ready\n"); | ||
204 | if (GNUNET_SCHEDULER_NO_TASK != die_task) | ||
205 | GNUNET_SCHEDULER_cancel (die_task); | ||
206 | die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); | ||
207 | ok = 42; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | GNUNET_assert (size >= TEST_MESSAGE_SIZE); | ||
212 | if (buf != NULL) | ||
213 | { | ||
214 | memset (buf, '\0', TEST_MESSAGE_SIZE); | ||
215 | hdr = buf; | ||
216 | hdr->size = htons (TEST_MESSAGE_SIZE); | ||
217 | hdr->type = htons (TEST_MESSAGE_TYPE); | ||
218 | } | ||
219 | |||
220 | char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); | ||
221 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
222 | "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", | ||
223 | p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, | ||
224 | GNUNET_i2s (&p->id)); | ||
225 | GNUNET_free (ps); | ||
226 | |||
227 | return TEST_MESSAGE_SIZE; | ||
228 | } | ||
229 | |||
230 | |||
231 | static void | ||
232 | sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
233 | { | ||
234 | send_task = GNUNET_SCHEDULER_NO_TASK; | ||
235 | |||
236 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
237 | return; | ||
238 | char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); | ||
239 | |||
240 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
241 | "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", | ||
242 | p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); | ||
243 | GNUNET_free (receiver_s); | ||
244 | s_sending = GNUNET_YES; | ||
245 | th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, 0, | ||
246 | TIMEOUT_TRANSMIT, ¬ify_ready, | ||
247 | p1); | ||
248 | } | ||
249 | |||
250 | |||
251 | static void | ||
252 | notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) | ||
253 | { | ||
254 | static int c; | ||
255 | |||
256 | c++; | ||
257 | struct PeerContext *p = cls; | ||
258 | struct PeerContext *t = NULL; | ||
259 | |||
260 | if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) | ||
261 | t = p1; | ||
262 | if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) | ||
263 | t = p2; | ||
264 | GNUNET_assert (t != NULL); | ||
265 | |||
266 | char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); | ||
267 | |||
268 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
269 | "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, | ||
270 | t->no, GNUNET_i2s (peer)); | ||
271 | GNUNET_free (ps); | ||
272 | } | ||
273 | |||
274 | |||
275 | static void | ||
276 | notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) | ||
277 | { | ||
278 | struct PeerContext *p = cls; | ||
279 | char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); | ||
280 | |||
281 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
282 | "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, | ||
283 | GNUNET_i2s (peer)); | ||
284 | |||
285 | GNUNET_free (ps); | ||
286 | |||
287 | if (th != NULL) | ||
288 | GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); | ||
289 | th = NULL; | ||
290 | } | ||
291 | |||
292 | |||
293 | static void | ||
294 | testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) | ||
295 | { | ||
296 | cc = NULL; | ||
297 | char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); | ||
298 | |||
299 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peers connected: %u (%s) <-> %u (%s)\n", | ||
300 | p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); | ||
301 | GNUNET_free (p1_c); | ||
302 | |||
303 | s_connected = GNUNET_YES; | ||
304 | send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); | ||
305 | } | ||
306 | |||
307 | |||
308 | static void | ||
309 | start_cb (struct PeerContext *p, void *cls) | ||
310 | { | ||
311 | static int started; | ||
312 | |||
313 | started++; | ||
314 | |||
315 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%s') started\n", p->no, | ||
316 | GNUNET_i2s (&p->id)); | ||
317 | |||
318 | if (started != 2) | ||
319 | return; | ||
320 | else | ||
321 | s_started = GNUNET_YES; | ||
322 | char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); | ||
323 | |||
324 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
325 | "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", | ||
326 | p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); | ||
327 | GNUNET_free (sender_c); | ||
328 | |||
329 | cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, | ||
330 | NULL); | ||
331 | |||
332 | } | ||
333 | static int p1_c = GNUNET_NO; | ||
334 | static int p2_c = GNUNET_NO; | ||
335 | |||
336 | static void done () | ||
337 | { | ||
338 | if ((GNUNET_YES == p1_c) && (GNUNET_YES == p2_c)) | ||
339 | end(); | ||
340 | } | ||
341 | |||
342 | static void monitor1_cb (void *cls, | ||
343 | const struct GNUNET_PeerIdentity *peer, | ||
344 | const struct GNUNET_HELLO_Address *address, | ||
345 | enum GNUNET_TRANSPORT_PeerState state, | ||
346 | struct GNUNET_TIME_Absolute state_timeout) | ||
347 | { | ||
348 | if ((NULL == peer) || (NULL == p1)) | ||
349 | return; | ||
350 | |||
351 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitor 1: %s %s %s\n", | ||
352 | GNUNET_i2s (peer), GNUNET_TRANSPORT_p2s(state), GNUNET_STRINGS_absolute_time_to_string(state_timeout)); | ||
353 | if ((0 == memcmp (peer, &p2->id, sizeof (p2->id)) && | ||
354 | (GNUNET_YES == GNUNET_TRANSPORT_is_connected(state)) && | ||
355 | GNUNET_NO == p1_c) ) | ||
356 | { | ||
357 | p1_c = GNUNET_YES; | ||
358 | GNUNET_SCHEDULER_add_now (&done, NULL); | ||
359 | } | ||
360 | |||
361 | } | ||
362 | |||
363 | |||
364 | static void monitor2_cb (void *cls, | ||
365 | const struct GNUNET_PeerIdentity *peer, | ||
366 | const struct GNUNET_HELLO_Address *address, | ||
367 | enum GNUNET_TRANSPORT_PeerState state, | ||
368 | struct GNUNET_TIME_Absolute state_timeout) | ||
369 | { | ||
370 | if ((NULL == peer) || (NULL == p2)) | ||
371 | return; | ||
372 | |||
373 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitor 2: %s %s %s\n", | ||
374 | GNUNET_i2s (peer), GNUNET_TRANSPORT_p2s (state), GNUNET_STRINGS_absolute_time_to_string(state_timeout)); | ||
375 | if ((0 == memcmp (peer, &p1->id, sizeof (p1->id)) && | ||
376 | (GNUNET_YES == GNUNET_TRANSPORT_is_connected(state)) && | ||
377 | GNUNET_NO == p2_c) ) | ||
378 | { | ||
379 | p2_c = GNUNET_YES; | ||
380 | GNUNET_SCHEDULER_add_now (&done, NULL); | ||
381 | } | ||
382 | } | ||
383 | |||
384 | |||
385 | |||
386 | static void | ||
387 | run (void *cls, char *const *args, const char *cfgfile, | ||
388 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
389 | { | ||
390 | die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); | ||
391 | |||
392 | s_started = GNUNET_NO; | ||
393 | s_connected = GNUNET_NO; | ||
394 | s_sending = GNUNET_NO; | ||
395 | |||
396 | p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, | ||
397 | ¬ify_receive, ¬ify_connect, | ||
398 | ¬ify_disconnect, &start_cb, | ||
399 | NULL); | ||
400 | pmc_p1 = GNUNET_TRANSPORT_monitor_peers (p1->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor1_cb, NULL); | ||
401 | |||
402 | p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, | ||
403 | ¬ify_receive, ¬ify_connect, | ||
404 | ¬ify_disconnect, &start_cb, | ||
405 | NULL); | ||
406 | pmc_p2 = GNUNET_TRANSPORT_monitor_peers (p2->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor2_cb, NULL); | ||
407 | |||
408 | if ((p1 == NULL) || (p2 == NULL)) | ||
409 | { | ||
410 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); | ||
411 | if (die_task != GNUNET_SCHEDULER_NO_TASK) | ||
412 | GNUNET_SCHEDULER_cancel (die_task); | ||
413 | die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); | ||
414 | return; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | |||
419 | static int | ||
420 | check () | ||
421 | { | ||
422 | static char *const argv[] = { "test-transport-api", | ||
423 | "-c", | ||
424 | "test_transport_api_data.conf", | ||
425 | NULL | ||
426 | }; | ||
427 | static struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
428 | GNUNET_GETOPT_OPTION_END | ||
429 | }; | ||
430 | |||
431 | send_task = GNUNET_SCHEDULER_NO_TASK; | ||
432 | |||
433 | ok = 1; | ||
434 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, | ||
435 | "nohelp", options, &run, &ok); | ||
436 | |||
437 | return ok; | ||
438 | } | ||
439 | |||
440 | int | ||
441 | main (int argc, char *argv[]) | ||
442 | { | ||
443 | int ret; | ||
444 | |||
445 | GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); | ||
446 | GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); | ||
447 | GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, | ||
448 | &test_plugin); | ||
449 | |||
450 | GNUNET_log_setup (test_name, | ||
451 | "WARNING", | ||
452 | NULL); | ||
453 | tth = GNUNET_TRANSPORT_TESTING_init (); | ||
454 | |||
455 | GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); | ||
456 | GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); | ||
457 | |||
458 | ret = check (); | ||
459 | |||
460 | GNUNET_free (cfg_file_p1); | ||
461 | GNUNET_free (cfg_file_p2); | ||
462 | |||
463 | GNUNET_free (test_source); | ||
464 | GNUNET_free (test_plugin); | ||
465 | GNUNET_free (test_name); | ||
466 | |||
467 | GNUNET_TRANSPORT_TESTING_done (tth); | ||
468 | |||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | /* end of test_transport_api.c */ | ||