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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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"
52 * Testcase timeout (set aggressively as we know this test doesn't work right now)
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, "Switch attempted (%p)", stat);
97 bytes_recv_after_switch = 0;
98 bytes_sent_after_switch = 0;
105 stat_success_attempt_cb (void *cls,
106 const char *subsystem,
111 struct PeerStats *stat = cls;
113 stat->switch_success++;
114 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Switch succeeded (%p)", stat);
120 stat_fail_attempt_cb (void *cls,
121 const char *subsystem,
126 struct PeerStats *stat = cls;
132 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Switch failed (%p)", stat);
138 stat_addresses_available (void *cls,
139 const char *subsystem,
144 struct PeerStats *stat = cls;
146 stat->addresses_avail++;
152 * List of statistics entries we care about.
154 static struct WatchEntry
158 * Name of the statistic we watch.
160 const char *stat_name;
163 * Handler to register;
165 GNUNET_STATISTICS_Iterator stat_handler;
167 {{"# Attempts to switch addresses", &stat_start_attempt_cb},
168 {"# Successful attempts to switch addresses", &stat_success_attempt_cb},
169 {"# Failed attempts to switch addresses (failed to send CONNECT CONT)",
170 &stat_fail_attempt_cb},
171 {"# Failed attempts to switch addresses (failed to send CONNECT)",
172 &stat_fail_attempt_cb},
173 {"# Failed attempts to switch addresses (no response)",
174 &stat_fail_attempt_cb},
175 {"# transport addresses", &stat_addresses_available},
180 custom_shutdown (void *cls)
184 if (NULL != measure_task)
186 GNUNET_SCHEDULER_cancel (measure_task);
189 if (0 == stats[0].switch_attempts + stats[1].switch_attempts)
191 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
192 "Test did not work, as peers didn't switch (flawed testcase)!\n");
193 ccc->global_ret = 77;
197 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
198 "Fail (timeout)! No transmission after switch! Stopping peers\n");
199 ccc->global_ret = 77; /* GNUNET_SYSERR; */
202 /* stop statistics */
203 for (unsigned int i = 0; i < 2; i++)
205 if (NULL != stats[i].stat)
207 for (unsigned int j = 0; NULL != watches[j].stat_name; j++)
208 GNUNET_assert (GNUNET_OK ==
209 GNUNET_STATISTICS_watch_cancel (stats[i].stat,
211 watches[j].stat_name,
212 watches[j].stat_handler,
214 GNUNET_STATISTICS_destroy (stats[i].stat, GNUNET_NO);
215 stats[i].stat = NULL;
220 FPRINTF (stderr, "\n");
221 if (stats[0].switch_attempts > 0)
225 "Peer 1 tried %u times to switch and succeeded %u times, failed %u times\n",
226 stats[0].switch_attempts,
227 stats[0].switch_success,
228 stats[0].switch_fail);
229 if (stats[0].switch_success != stats[0].switch_attempts)
235 else if (stats[0].addresses_avail > 1)
238 "Peer 1 had %u addresses available, but did not try to switch\n",
239 stats[0].addresses_avail);
241 if (stats[1].switch_attempts > 0)
245 "Peer 2 tried %u times to switch and succeeded %u times, failed %u times\n",
246 stats[1].switch_attempts,
247 stats[1].switch_success,
248 stats[1].switch_fail);
249 if (stats[1].switch_success != stats[1].switch_attempts)
255 else if (stats[1].addresses_avail > 1)
258 "Peer 2 had %u addresses available, but did not try to switch\n",
259 stats[1].addresses_avail);
262 if (((stats[0].switch_attempts > 0) || (stats[1].switch_attempts > 0)) &&
263 (bytes_sent_after_switch == 0))
265 FPRINTF (stderr, "No data sent after switching!\n");
269 if (((stats[0].switch_attempts > 0) || (stats[1].switch_attempts > 0)) &&
270 (bytes_recv_after_switch == 0))
272 FPRINTF (stderr, "No data received after switching!\n");
277 /* This test is not really expected to pass right now... */
279 ccc->global_ret = GNUNET_SYSERR;
285 notify_receive (void *cls,
286 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
287 const struct GNUNET_PeerIdentity *sender,
288 const struct GNUNET_TRANSPORT_TESTING_TestMessage *hdr)
290 if (GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE != ntohs (hdr->header.type))
294 char *ps = GNUNET_strdup (GNUNET_i2s (&receiver->id));
296 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
297 "Peer %u (`%s') got message %u of size %u from peer (`%s')\n",
300 (uint32_t) ntohl (hdr->num),
301 ntohs (hdr->header.size),
302 GNUNET_i2s (sender));
305 if (((stats[0].switch_attempts >= 1) || (stats[1].switch_attempts >= 1)) &&
306 (stats[0].switch_attempts ==
307 stats[0].switch_fail + stats[0].switch_success) &&
308 (stats[1].switch_attempts ==
309 stats[1].switch_fail + stats[1].switch_success))
311 bytes_recv_after_switch += ntohs (hdr->header.size);
312 if ((bytes_sent_after_switch > 0) && (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)
329 GNUNET_TRANSPORT_TESTING_send (ccc->p[1],
331 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
332 GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE,
336 if (((stats[0].switch_attempts >= 1) || (stats[1].switch_attempts >= 1)) &&
337 (stats[0].switch_attempts ==
338 stats[0].switch_fail + stats[0].switch_success) &&
339 (stats[1].switch_attempts ==
340 stats[1].switch_fail + stats[1].switch_success))
342 bytes_sent_after_switch += GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE;
348 progress_indicator (void *cls)
354 if ((TIMEOUT.rel_value_us / 1000 / 1000LL) < counter)
356 FPRINTF (stderr, "%s", ".\n");
360 FPRINTF (stderr, "%s", ".");
361 measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
369 connected_cb (void *cls)
371 for (unsigned int i = 0; i < 2; i++)
373 stats[i].stat = GNUNET_STATISTICS_create ("transport", ccc->p[i]->cfg);
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 */
399 GNUNET_TRANSPORT_TESTING_send (ccc->p[1],
401 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
402 GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE,
410 main (int argc, char *argv[])
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,
422 ret = GNUNET_TRANSPORT_TESTING_main (2,
423 &GNUNET_TRANSPORT_TESTING_connect_check,
427 if (GNUNET_OK != ret)
431 /* end of test_transport_address_switch.c */