2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 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_api_reliability.c
22 * @brief base test case for transport implementations
24 * This test case serves ensures that messages are reliably sent between peers
26 * This test sends TOTAL_MSGS with message type MTYPE from peer 1 to peer 2
27 * and ensures that all message were received.
30 #include "gnunet_transport_service.h"
32 #include "transport-testing.h"
35 * Allow making the problem "bigger".
40 * Total number of messages to send
42 * Note that this value must not significantly exceed
43 * 'MAX_PENDING' in 'gnunet-service-transport_clients.c', otherwise
44 * messages may be dropped even for a reliable transport.
46 #define TOTAL_MSGS (1024 * 3 * FACTOR)
49 * Message type of test messages
56 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90 * FACTOR)
59 * How long until we give up on transmitting the message?
61 #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60 * FACTOR)
64 GNUNET_NETWORK_STRUCT_BEGIN
67 * Struct for the test message
71 struct GNUNET_MessageHeader header;
72 uint32_t num GNUNET_PACKED;
74 GNUNET_NETWORK_STRUCT_END
77 static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
79 static struct GNUNET_TRANSPORT_TransmitHandle *th;
82 * Total amount of bytes sent
84 static unsigned long long total_bytes;
89 static struct GNUNET_TIME_Absolute start_time;
92 * No. of message currently scheduled to be send
94 static int msg_scheduled;
97 * No. of last message sent
102 * No. of last message received
107 * Bitmap storing which messages were received
109 static char bitmap[TOTAL_MSGS / 8];
113 get_size (unsigned int iter)
117 ret = (iter * iter * iter);
120 /* FreeBSD/OSX etc. Unix DGRAMs do not work
121 * with large messages */
122 if (0 == strcmp ("unix", test_plugin))
123 return sizeof (struct TestMessage) + (ret % 1024);
125 return sizeof (struct TestMessage) + (ret % 60000);
130 * Sets a bit active in the bitmap.
132 * @param bitIdx which bit to set
133 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
136 set_bit (unsigned int bitIdx)
139 unsigned int targetBit;
141 if (bitIdx >= sizeof (bitmap) * 8)
143 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
144 "tried to set bit %u of %u(!?!?)\n",
146 (unsigned int) sizeof (bitmap) * 8);
147 return GNUNET_SYSERR;
149 arraySlot = bitIdx / 8;
150 targetBit = (1L << (bitIdx % 8));
151 bitmap[arraySlot] |= targetBit;
157 * Obtain a bit from bitmap.
158 * @param map the bitmap
159 * @param bit index from bitmap
161 * @return Bit @a bit from @a map
164 get_bit (const char *map,
167 if (bit > TOTAL_MSGS)
169 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
170 "get bit %u of %u(!?!?)\n",
172 (unsigned int) sizeof (bitmap) * 8);
175 return ((map)[bit >> 3] & (1 << (bit & 7))) > 0;
180 custom_shutdown (void *cls)
182 unsigned long long delta;
183 unsigned long long rate;
189 GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
192 /* Calculcate statistics */
193 delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us;
194 rate = (1000LL* 1000ll * total_bytes) / (1024 * delta);
196 "\nThroughput was %llu KiBytes/s\n",
200 GNUNET_asprintf (&value_name,
207 GNUNET_free (value_name);
211 for (i = 0; i < TOTAL_MSGS; i++)
213 if (get_bit (bitmap, i) == 0)
215 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
216 "Did not receive message %d\n",
222 ccc->global_ret = GNUNET_SYSERR; /* fail: messages missing! */
227 notify_receive (void *cls,
228 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
229 const struct GNUNET_PeerIdentity *sender,
230 const struct GNUNET_MessageHeader *message)
235 char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
236 const struct TestMessage *hdr;
238 hdr = (const struct TestMessage *) message;
240 if (MTYPE != ntohs (message->type))
242 msg_recv = ntohl (hdr->num);
243 s = get_size (ntohl (hdr->num));
245 if (ntohs (message->size) != s)
247 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
248 "Expected message %u of size %u, got %u bytes of message %u\n",
251 ntohs (message->size),
253 ccc->global_ret = GNUNET_SYSERR;
254 GNUNET_SCHEDULER_shutdown ();
258 memset (cbuf, ntohl (hdr->num), s - sizeof (struct TestMessage));
259 if (0 != memcmp (cbuf, &hdr[1], s - sizeof (struct TestMessage)))
261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
262 "Expected message %u with bits %u, but body did not match\n",
265 ccc->global_ret = GNUNET_SYSERR;
266 GNUNET_SCHEDULER_shutdown ();
270 if (ntohl (hdr->num) % 5 == 0)
272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
273 "Got message %u of size %u\n",
275 ntohs (message->size));
279 if (GNUNET_SYSERR == set_bit (ntohl (hdr->num)))
281 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
282 "Message id %u is bigger than maxmimum number of messages %u expected\n",
286 if (0 == (n % (TOTAL_MSGS / 100)))
288 FPRINTF (stderr, "%s", ".");
292 /* end testcase with success */
293 GNUNET_SCHEDULER_shutdown ();
299 notify_ready (void *cls,
305 struct TestMessage hdr;
312 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
313 "Timeout occurred while waiting for transmit_ready for msg %u of %u\n",
316 GNUNET_SCHEDULER_shutdown ();
317 ccc->global_ret = 42;
322 GNUNET_assert (size >= s);
323 GNUNET_assert (buf != NULL);
324 GNUNET_assert (n < TOTAL_MSGS);
328 GNUNET_assert (n < TOTAL_MSGS);
329 hdr.header.size = htons (s);
330 hdr.header.type = htons (MTYPE);
333 GNUNET_memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage));
334 ret += sizeof (struct TestMessage);
335 memset (&cbuf[ret], n, s - sizeof (struct TestMessage));
336 ret += s - sizeof (struct TestMessage);
341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
342 "Sending message %u of size %u\n",
349 if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16))
350 break; /* sometimes pack buffer full, sometimes not */
352 while ((size - ret >= s) && (n < TOTAL_MSGS));
355 th = GNUNET_TRANSPORT_notify_transmit_ready (ccc->p[1]->th,
368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
369 "All messages scheduled to be sent\n");
373 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
374 "Returning total message block of size %u\n",
385 start_time = GNUNET_TIME_absolute_get ();
386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
387 "Starting to send %u messages\n",
389 th = GNUNET_TRANSPORT_notify_transmit_ready (ccc->p[1]->th,
399 notify_disconnect (void *cls,
400 struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
401 const struct GNUNET_PeerIdentity *other)
403 GNUNET_TRANSPORT_TESTING_log_disconnect (cls,
408 GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
415 main (int argc, char *argv[])
417 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = {
418 .connect_continuation = &sendtask,
419 .config_file = "test_transport_api_data.conf",
420 .rec = ¬ify_receive,
421 .nc = &GNUNET_TRANSPORT_TESTING_log_connect,
422 .nd = ¬ify_disconnect,
423 .shutdown_task = &custom_shutdown,
429 GNUNET_TRANSPORT_TESTING_main (2,
430 &GNUNET_TRANSPORT_TESTING_connect_check,
437 /* end of test_transport_api_reliability.c */