2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2016 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, 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 addresses when
25 * connected for plugins supporting multiple addresses by monitoring transport's
28 * This test starts 2 peers and connects them. When connected test messages
29 * are transmitted from peer 2 to peer 1. The test monitors transport's
30 * statistics values for information about address switch attempts.
32 * The test passes with success if one of the peers could successfully switch
33 * addresses in connected state and a test message was successfully transmitted
36 * Since it is not possible to trigger an address switch from outside,
37 * the test returns "77" (skipped) when no address switching attempt
38 * takes place. It fails if an address switch attempt fails.
40 * NOTE: The test seems largely useless right now, as we simply NEVER
41 * switch addresses under the test conditions. However, it may be a
42 * good starting point for a future test. For now, it always times
43 * out and returns "77" (skipped), so we set the timeout suitably low.
46 #include "gnunet_transport_service.h"
47 #include "gnunet_ats_service.h"
48 #include "transport-testing.h"
54 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
57 static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
59 static struct GNUNET_SCHEDULER_Task *measure_task;
63 * Statistics we track per peer.
67 struct GNUNET_STATISTICS_Handle *stat;
69 unsigned int addresses_avail;
71 unsigned int switch_attempts;
73 unsigned int switch_success;
75 unsigned int switch_fail;
78 static struct PeerStats stats[2];
80 /* Amount of data transfered since last switch attempt */
81 static unsigned long long bytes_sent_after_switch;
83 static unsigned long long bytes_recv_after_switch;
87 stat_start_attempt_cb (void *cls,
88 const char *subsystem,
93 struct PeerStats *stat = cls;
95 stat->switch_attempts++;
96 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
97 "Switch attempted (%p)",
99 bytes_recv_after_switch = 0;
100 bytes_sent_after_switch = 0;
107 stat_success_attempt_cb (void *cls,
108 const char *subsystem,
113 struct PeerStats *stat = cls;
115 stat->switch_success++;
116 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
117 "Switch succeeded (%p)",
124 stat_fail_attempt_cb (void *cls,
125 const char *subsystem,
130 struct PeerStats *stat = cls;
136 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
137 "Switch failed (%p)",
144 stat_addresses_available (void *cls,
145 const char *subsystem,
150 struct PeerStats *stat = cls;
152 stat->addresses_avail++;
158 * List of statistics entries we care about.
160 static struct WatchEntry {
163 * Name of the statistic we watch.
165 const char *stat_name;
168 * Handler to register;
170 GNUNET_STATISTICS_Iterator stat_handler;
172 { "# Attempts to switch addresses", &stat_start_attempt_cb },
173 { "# Successful attempts to switch addresses", &stat_success_attempt_cb },
174 { "# Failed attempts to switch addresses (failed to send CONNECT CONT)", &stat_fail_attempt_cb },
175 { "# Failed attempts to switch addresses (failed to send CONNECT)", &stat_fail_attempt_cb },
176 { "# Failed attempts to switch addresses (no response)", &stat_fail_attempt_cb },
177 { "# transport addresses", &stat_addresses_available },
183 custom_shutdown (void *cls)
187 if (NULL != measure_task)
189 GNUNET_SCHEDULER_cancel (measure_task);
192 if (0 == stats[0].switch_attempts + stats[1].switch_attempts)
194 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
195 "Test did not work, as peers didn't switch (flawed testcase)!\n");
196 ccc->global_ret = 77;
200 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
201 "Fail (timeout)! No transmission after switch! Stopping peers\n");
202 ccc->global_ret = GNUNET_SYSERR;
205 /* stop statistics */
206 for (unsigned int i=0;i<2;i++)
208 if (NULL != stats[i].stat)
210 for (unsigned int j=0;NULL != watches[j].stat_name; j++)
211 GNUNET_STATISTICS_watch_cancel (stats[i].stat,
213 watches[j].stat_name,
214 watches[j].stat_handler,
217 GNUNET_STATISTICS_destroy (stats[i].stat,
219 stats[i].stat = NULL;
224 FPRINTF (stderr, "\n");
225 if (stats[0].switch_attempts > 0)
228 "Peer 1 tried %u times to switch and succeeded %u times, failed %u times\n",
229 stats[0].switch_attempts,
230 stats[0].switch_success,
231 stats[0].switch_fail);
232 if (stats[0].switch_success != stats[0].switch_attempts)
238 else if (stats[0].addresses_avail > 1)
241 "Peer 1 had %u addresses available, but did not try to switch\n",
242 stats[0].addresses_avail);
244 if (stats[1].switch_attempts > 0)
247 "Peer 2 tried %u times to switch and succeeded %u times, failed %u times\n",
248 stats[1].switch_attempts,
249 stats[1].switch_success,
250 stats[1].switch_fail);
251 if (stats[1].switch_success != stats[1].switch_attempts)
257 else if (stats[1].addresses_avail > 1)
260 "Peer 2 had %u addresses available, but did not try to switch\n",
261 stats[1].addresses_avail);
264 if ( ((stats[0].switch_attempts > 0) || (stats[1].switch_attempts > 0)) &&
265 (bytes_sent_after_switch == 0) )
268 "No data sent after switching!\n");
272 if ( ((stats[0].switch_attempts > 0) || (stats[1].switch_attempts > 0)) &&
273 (bytes_recv_after_switch == 0) )
276 "No data received after switching!\n");
281 ccc->global_ret = GNUNET_SYSERR;
286 notify_receive (void *cls,
287 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
288 const struct GNUNET_PeerIdentity *sender,
289 const struct GNUNET_TRANSPORT_TESTING_TestMessage *hdr)
291 if (GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE != ntohs (hdr->header.type))
295 char *ps = GNUNET_strdup (GNUNET_i2s (&receiver->id));
297 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
298 "Peer %u (`%s') got message %u of size %u from peer (`%s')\n",
302 ntohs (hdr->header.size),
303 GNUNET_i2s (sender));
306 if ( ((stats[0].switch_attempts >= 1) || (stats[1].switch_attempts >= 1)) &&
307 (stats[0].switch_attempts == stats[0].switch_fail + stats[0].switch_success) &&
308 (stats[1].switch_attempts == stats[1].switch_fail + stats[1].switch_success) )
310 bytes_recv_after_switch += ntohs(hdr->header.size);
311 if ( (bytes_sent_after_switch > 0) &&
312 (bytes_recv_after_switch > 0) )
314 /* A peer switched addresses and sent and received data after the
315 * switch operations */
316 GNUNET_SCHEDULER_shutdown ();
323 notify_send (void *cls)
327 GNUNET_assert (GNUNET_OK ==
328 GNUNET_TRANSPORT_TESTING_send (ccc->p[1],
330 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
331 GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE,
335 if ( ( (stats[0].switch_attempts >= 1) ||
336 (stats[1].switch_attempts >= 1) ) &&
337 (stats[0].switch_attempts == stats[0].switch_fail + stats[0].switch_success) &&
338 (stats[1].switch_attempts == stats[1].switch_fail + stats[1].switch_success) )
340 bytes_sent_after_switch
341 += GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE;
347 progress_indicator (void *cls)
353 if ((TIMEOUT.rel_value_us / 1000 / 1000LL) < counter)
355 FPRINTF (stderr, "%s", ".\n");
359 FPRINTF (stderr, "%s", ".");
360 measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
368 connected_cb (void *cls)
370 for (unsigned int i=0;i<2;i++)
372 stats[i].stat = GNUNET_STATISTICS_create ("transport",
374 if (NULL == stats[i].stat)
376 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
377 "Fail! Could not create statistics for peers!\n");
378 ccc->global_ret = GNUNET_SYSERR;
379 GNUNET_SCHEDULER_shutdown ();
382 for (unsigned int j=0;NULL != watches[j].stat_name; j++)
384 GNUNET_STATISTICS_watch (stats[i].stat,
386 watches[j].stat_name,
387 watches[j].stat_handler,
392 ccc->global_ret = GNUNET_OK;
393 measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
396 /* Peers are connected, start transmit test messages */
397 GNUNET_assert (GNUNET_OK ==
398 GNUNET_TRANSPORT_TESTING_send (ccc->p[1],
400 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
401 GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE,
412 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = {
413 .connect_continuation = &connected_cb,
414 .config_file = "test_transport_api_data.conf",
415 .rec = ¬ify_receive,
416 .nc = &GNUNET_TRANSPORT_TESTING_log_connect,
417 .shutdown_task = &custom_shutdown,
423 ret = GNUNET_TRANSPORT_TESTING_main (2,
424 &GNUNET_TRANSPORT_TESTING_connect_check,
428 if (GNUNET_OK != ret)
432 /* end of test_transport_address_switch.c */