2 This file is part of GNUnet.
3 (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
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.
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.
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.
21 * @file transport/test_transport_address_switch.c
22 * @brief base test case for transport implementations
24 * This test case tests if peers can successfully switch address when
25 * connected by monitoring statistic values.
28 #include "gnunet_transport_service.h"
29 #include "gnunet_ats_service.h"
31 #include "transport-testing.h"
34 * Testcase specific declarations
37 GNUNET_NETWORK_STRUCT_BEGIN
40 struct GNUNET_MessageHeader header;
41 uint32_t num GNUNET_PACKED;
43 GNUNET_NETWORK_STRUCT_END
46 * Message type for test messages
51 * Message size for test messages
58 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
61 * How long until we give up on transmitting the message?
63 #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
65 #define DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
66 #define DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
69 * Timeout task to send messages
71 static struct GNUNET_SCHEDULER_Task *die_task;
74 static struct GNUNET_SCHEDULER_Task *delayed_end_task;
77 * Measurement task to send messages
79 static struct GNUNET_SCHEDULER_Task *measure_task;
82 static struct PeerContext *p1;
83 static char *cfg_file_p1;
84 static struct GNUNET_STATISTICS_Handle *p1_stat;
86 static struct PeerContext *p2;
87 static char *cfg_file_p2;
88 static struct GNUNET_STATISTICS_Handle *p2_stat;
90 static struct PeerContext *sender;
92 static struct PeerContext *receiver;
94 static struct GNUNET_TRANSPORT_TransmitHandle *th;
96 static struct GNUNET_TRANSPORT_TESTING_handle *tth;
98 static GNUNET_TRANSPORT_TESTING_ConnectRequest cc;
100 static int test_connected;
106 * Statistics about peer 1
108 static unsigned int p1_addresses_avail;
109 static unsigned int p1_switch_attempts;
110 static unsigned int p1_switch_success;
111 static unsigned int p1_switch_fail;
115 * Statistics about peer 2
117 static unsigned int p2_switch_attempts;
118 static unsigned int p2_switch_success;
119 static unsigned int p2_switch_fail;
120 static unsigned int p2_addresses_avail;
123 * Transmission statistics
126 /* Amount of data transfered since last switch attempt */
127 static unsigned long long bytes_sent_after_switch;
128 static unsigned long long bytes_recv_after_switch;
131 * END Testcase specific declarations
135 #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
137 #define OKPP do { ok++; } while (0)
144 stat_start_attempt_cb (void *cls,
145 const char *subsystem,
152 p1_switch_attempts++;
153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "(1:s)");
157 p2_switch_attempts++;
158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "(2:s)");
161 bytes_recv_after_switch = 0;
162 bytes_sent_after_switch = 0;
169 stat_success_attempt_cb (void *cls,
170 const char *subsystem,
178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "(1:+)");
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "(2:+)");
191 stat_fail_attempt_cb (void *cls,
192 const char *subsystem,
203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "(1:-)");
208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "(2:-)");
216 stat_addresses_available (void *cls,
217 const char *subsystem,
224 p1_addresses_avail++;
228 p2_addresses_avail++;
237 if (measure_task != NULL)
239 GNUNET_SCHEDULER_cancel (measure_task);
243 if (delayed_end_task != NULL)
245 GNUNET_SCHEDULER_cancel (delayed_end_task);
246 delayed_end_task = NULL;
249 if (die_task != NULL)
251 GNUNET_SCHEDULER_cancel (die_task);
257 GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
258 "# Attempts to switch addresses",
259 stat_start_attempt_cb, p1);
260 GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
261 "# Successful attempts to switch addresses",
262 stat_success_attempt_cb, p1);
263 GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
264 "# Failed attempts to switch addresses (failed to send CONNECT CONT)",
265 stat_fail_attempt_cb, p1);
266 GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
267 "# Failed attempts to switch addresses (failed to send CONNECT)",
268 stat_fail_attempt_cb, p1);
269 GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
270 "# Failed attempts to switch addresses (no response)",
271 stat_fail_attempt_cb, p1);
272 GNUNET_STATISTICS_watch (p1_stat, "transport",
273 "# transport addresses",
274 stat_addresses_available, p1);
275 GNUNET_STATISTICS_destroy (p1_stat, GNUNET_NO);
280 GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
281 "# Attempts to switch addresses", stat_start_attempt_cb, p2);
282 GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
283 "# Successful attempts to switch addresses", stat_success_attempt_cb, p2);
284 GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
285 "# Failed attempts to switch addresses (failed to send CONNECT CONT)",
286 stat_fail_attempt_cb, p2);
287 GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
288 "# Failed attempts to switch addresses (failed to send CONNECT)",
289 stat_fail_attempt_cb, p2);
290 GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
291 "# Failed attempts to switch addresses (no response)",
292 stat_fail_attempt_cb, p2);
293 GNUNET_STATISTICS_watch (p2_stat, "transport",
294 "# transport addresses",
295 stat_addresses_available, p2);
296 GNUNET_STATISTICS_destroy (p2_stat, GNUNET_NO);
302 GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
307 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc);
312 GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
317 GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
332 delayed_end_task = NULL;
333 FPRINTF (stderr, "\n");
334 if (p1_switch_attempts > 0)
336 FPRINTF (stderr, "Peer 1 tried %u times to switch and succeeded %u times, failed %u times\n",
337 p1_switch_attempts, p1_switch_success, p1_switch_fail);
338 if (p1_switch_success != p1_switch_attempts)
344 else if (p1_addresses_avail > 1)
346 FPRINTF (stderr, "Peer 1 had %u addresses available, but did not try to switch\n",
349 if (p2_switch_attempts > 0)
351 FPRINTF (stderr, "Peer 2 tried %u times to switch and succeeded %u times, failed %u times\n",
352 p2_switch_attempts, p2_switch_success, p2_switch_fail);
353 if (p2_switch_success != p2_switch_attempts)
359 else if (p2_addresses_avail > 1)
361 FPRINTF (stderr, "Peer 2 had %u addresses available, but did not try to switch\n",
365 if ( ((p1_switch_attempts > 0) || (p2_switch_attempts > 0)) &&
366 (bytes_sent_after_switch == 0) )
368 FPRINTF (stderr, "No data sent after switching!\n");
372 if ( ((p1_switch_attempts > 0) || (p2_switch_attempts > 0)) &&
373 (bytes_recv_after_switch == 0) )
375 FPRINTF (stderr, "No data received after switching!\n");
390 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
391 "Fail! Stopping peers\n");
393 if (test_connected == GNUNET_YES)
394 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
395 "Peers got connected\n");
397 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
398 "Peers got NOT connected\n");
405 notify_receive (void *cls,
406 const struct GNUNET_PeerIdentity *peer,
407 const struct GNUNET_MessageHeader *message)
409 const struct TestMessage *hdr;
411 hdr = (const struct TestMessage *) message;
412 if (MTYPE != ntohs (message->type))
415 struct PeerContext *p = cls;
416 char *ps = GNUNET_strdup (GNUNET_i2s (&p->id));
418 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
419 "Peer %u (`%s') got message %u of size %u from peer (`%s')\n", p->no, ps,
421 ntohs (message->size),
423 if ( ((p1_switch_attempts >= 1) || (p2_switch_attempts >= 1)) &&
424 (p1_switch_attempts == p1_switch_fail + p1_switch_success) &&
425 (p2_switch_attempts == p2_switch_fail + p2_switch_success) )
427 bytes_recv_after_switch += ntohs(hdr->header.size);
428 if ((bytes_sent_after_switch > 0) && (bytes_recv_after_switch > 0))
430 /* A peer switched addresses and sent and received data after the
431 * switch operations */
441 notify_ready (void *cls, size_t size, void *buf)
443 static uint32_t counter;
445 struct TestMessage hdr;
450 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
451 "Timeout occurred while waiting for transmit_ready for message\n");
452 if (NULL != die_task)
453 GNUNET_SCHEDULER_cancel (die_task);
454 die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL );
459 GNUNET_assert(size >= MSIZE);
460 GNUNET_assert(buf != NULL);
463 hdr.header.size = htons (MSIZE);
464 hdr.header.type = htons (MTYPE);
465 hdr.num = htonl (counter++);
466 memcpy (&cbuf[0], &hdr, sizeof(struct TestMessage));
467 memset (&cbuf[sizeof(struct TestMessage)], '0', MSIZE - sizeof(struct TestMessage));
470 char *receiver_s = GNUNET_strdup (GNUNET_i2s (&receiver->id));
471 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
472 "Sending message %u of size %u from peer %u (`%4s') -> peer %u (`%s') !\n",
473 (unsigned int) (counter - 1),
476 GNUNET_i2s (&sender->id),
479 GNUNET_free(receiver_s);
483 th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th,
487 ¬ify_ready, NULL);
489 if ( ((p1_switch_attempts >= 1) || (p2_switch_attempts >= 1)) &&
490 (p1_switch_attempts == p1_switch_fail + p1_switch_success) &&
491 (p2_switch_attempts == p2_switch_fail + p2_switch_success) )
493 bytes_sent_after_switch += MSIZE;
500 notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
502 struct PeerContext *p = cls;
503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
504 "Peer %u (`%4s') connected to us!\n",
511 notify_disconnect (void *cls,
512 const struct GNUNET_PeerIdentity *peer)
514 struct PeerContext *p = cls;
516 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
517 "Peer %u (`%4s') disconnected!\n",
521 GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
530 th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th,
533 ¬ify_ready, NULL);
538 progress_indicator (void *cls,
539 const struct GNUNET_SCHEDULER_TaskContext *tc)
545 if ((DURATION.rel_value_us / 1000 / 1000LL) < counter)
547 FPRINTF (stderr, "%s", ".\n");
551 FPRINTF (stderr, "%s", ".");
552 measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
553 &progress_indicator, NULL);
559 testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
561 char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id));
563 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
564 "Peers connected: %u (%s) <-> %u (%s)\n",
565 p1->no, p1_c, p2->no,
566 GNUNET_i2s (&p2->id));
570 test_connected = GNUNET_YES;
572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
573 "(i:s/+/-) \t i == peer 1/2, s/+/- : switch attempt/switch ok/switch fail\n");
575 measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
578 GNUNET_SCHEDULER_add_now (&sendtask, NULL);
583 start_cb (struct PeerContext *p, void *cls)
588 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
589 "Peer %u (`%s') started\n",
591 GNUNET_i2s (&p->id));
595 test_connected = GNUNET_NO;
599 char *sender_c = GNUNET_strdup (GNUNET_i2s (&sender->id));
600 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
601 "Test tries to send from %u (%s) -> peer %u (%s)\n",
602 sender->no, sender_c,
603 receiver->no, GNUNET_i2s (&receiver->id));
604 GNUNET_free (sender_c);
605 cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2,
615 const struct GNUNET_CONFIGURATION_Handle *cfg)
617 die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL );
619 p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1,
620 ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL );
622 p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2,
623 ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL );
625 if ((p1 == NULL )|| (p2 == NULL))
627 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n");
628 if (die_task != NULL)
629 GNUNET_SCHEDULER_cancel (die_task);
630 die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
634 /* Start to watch statistics for peer 1 */
635 p1_stat = GNUNET_STATISTICS_create ("transport", p1->cfg);
636 GNUNET_STATISTICS_watch (p1_stat, "transport",
637 "# Attempts to switch addresses",
638 stat_start_attempt_cb, p1);
639 GNUNET_STATISTICS_watch (p1_stat, "transport",
640 "# Successful attempts to switch addresses",
641 stat_success_attempt_cb, p1);
642 GNUNET_STATISTICS_watch (p1_stat, "transport",
643 "# Failed attempts to switch addresses (failed to send CONNECT CONT)",
644 stat_fail_attempt_cb, p1);
645 GNUNET_STATISTICS_watch (p1_stat, "transport",
646 "# Failed attempts to switch addresses (failed to send CONNECT)",
647 stat_fail_attempt_cb, p1);
648 GNUNET_STATISTICS_watch (p1_stat, "transport",
649 "# Failed attempts to switch addresses (no response)",
650 stat_fail_attempt_cb, p1);
651 GNUNET_STATISTICS_watch (p1_stat, "transport",
652 "# transport addresses",
653 stat_addresses_available, p1);
655 /* Start to watch statistics for peer 2 */
656 p2_stat = GNUNET_STATISTICS_create ("transport", p2->cfg);
657 GNUNET_STATISTICS_watch (p2_stat, "transport",
658 "# Attempts to switch addresses",
659 stat_start_attempt_cb, p2);
660 GNUNET_STATISTICS_watch (p2_stat, "transport",
661 "# Successful attempts to switch addresses",
662 stat_success_attempt_cb, p2);
663 GNUNET_STATISTICS_watch (p2_stat, "transport",
664 "# Failed attempts to switch addresses (failed to send CONNECT CONT)",
665 stat_fail_attempt_cb, p2);
666 GNUNET_STATISTICS_watch (p2_stat, "transport",
667 "# Failed attempts to switch addresses (failed to send CONNECT)",
668 stat_fail_attempt_cb, p2);
669 GNUNET_STATISTICS_watch (p2_stat, "transport",
670 "# Failed attempts to switch addresses (no response)",
671 stat_fail_attempt_cb, p2);
672 GNUNET_STATISTICS_watch (p2_stat, "transport",
673 "# transport addresses",
674 stat_addresses_available, p2);
676 if ((p1_stat == NULL )|| (p2_stat == NULL))
678 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not create statistics for peers!\n");
679 if (die_task != NULL)
680 GNUNET_SCHEDULER_cancel (die_task);
681 die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
687 main (int argc, char *argv[])
693 static char *argv_new[] = { "test-transport-address-switch", "-c",
694 "test_transport_startonly.conf", NULL };
696 static struct GNUNET_GETOPT_CommandLineOption options[] = {
697 GNUNET_GETOPT_OPTION_END };
699 GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name);
701 GNUNET_log_setup (test_name, "WARNING", NULL );
703 GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source);
704 GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source,
707 tth = GNUNET_TRANSPORT_TESTING_init ();
709 GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1);
710 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Using cfg [%u] : %s \n", 1, cfg_file_p1);
711 GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2);
712 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Using cfg [%u] : %s \n", 2, cfg_file_p2);
714 GNUNET_PROGRAM_run ((sizeof(argv_new) / sizeof(char *)) - 1, argv_new,
715 test_name, "nohelp", options, &run, NULL );
717 GNUNET_free(cfg_file_p1);
718 GNUNET_free(cfg_file_p2);
720 GNUNET_free(test_source);
721 GNUNET_free(test_plugin);
722 GNUNET_free(test_name);
724 GNUNET_TRANSPORT_TESTING_done (tth);
729 /* end of test_transport_address_switch.c */