From e2d3ca4d4eee401515f94382c160fd9a65230a3c Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Tue, 20 May 2014 11:37:19 +0000 Subject: remove unreliability test - update reliabilitility test: this test only ensures that all messages are delivered and are not corrupted out of order delivery is not checked any longer --- src/transport/test_transport_api_reliability.c | 403 ++++++++++++++++--------- 1 file changed, 253 insertions(+), 150 deletions(-) (limited to 'src/transport/test_transport_api_reliability.c') diff --git a/src/transport/test_transport_api_reliability.c b/src/transport/test_transport_api_reliability.c index d2a78d17f..07213722e 100644 --- a/src/transport/test_transport_api_reliability.c +++ b/src/transport/test_transport_api_reliability.c @@ -21,87 +21,141 @@ * @file transport/test_transport_api_reliability.c * @brief base test case for transport implementations * - * This test case serves as a base for tcp and http - * transport test cases to check that the transports - * achieve reliable message delivery. + * This test case serves ensures that messages are reliably sent between peers + * + * This test sends TOTAL_MSGS with message type MTYPE from peer 1 to peer 2 + * and ensures that all message were received. */ #include "platform.h" #include "gnunet_transport_service.h" #include "gauger.h" #include "transport-testing.h" + +/** + * Total number of messages to send + * + * Note that this value must not significantly exceed + * 'MAX_PENDING' in 'gnunet-service-transport_clients.c', otherwise + * messages may be dropped even for a reliable transport. + */ +#define TOTAL_MSGS (1024 * 3) + +/** + * Message type of test messages + */ +#define MTYPE 12345 + /** * Testcase timeout */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 900) /** * How long until we give up on transmitting the message? */ -#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) +#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) + + +/** + * Struct for the test message + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct TestMessage +{ + struct GNUNET_MessageHeader header; + uint32_t num; +}; +GNUNET_NETWORK_STRUCT_END -static char *test_source; +/** + * Name of the plugin to test + */ static char *test_plugin; +/** + * Name of the test + */ static char *test_name; +/** + * Return value of the test + */ static int ok; -static GNUNET_SCHEDULER_TaskIdentifier die_task; - +/** + * Context of peer 1 + */ struct PeerContext *p1; +/** + * Configuration file of peer 1 + */ +char *cfg_file_p1; + +/** + * Context of peer 2 + */ struct PeerContext *p2; -struct PeerContext *sender; +/** + * Configuration file of peer 1 + */ +char *cfg_file_p2; -struct PeerContext *receiver; +/** + * Timeout task + */ +static GNUNET_SCHEDULER_TaskIdentifier die_task; +/** + * Transport transmit handle used + */ struct GNUNET_TRANSPORT_TransmitHandle *th; -char *cfg_file_p1; - -char *cfg_file_p2; - +/** + * Transport testing handle + */ struct GNUNET_TRANSPORT_TESTING_handle *tth; -static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; - - /* - * Testcase specific declarations + * Total amount of bytes sent */ +static unsigned long long total_bytes; /** - * Note that this value must not significantly exceed - * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise - * messages may be dropped even for a reliable transport. + * Time of start */ -#define TOTAL_MSGS (1024 * 2) - -#define MTYPE 12345 - -GNUNET_NETWORK_STRUCT_BEGIN - -struct TestMessage -{ - struct GNUNET_MessageHeader header; - uint32_t num; -}; -GNUNET_NETWORK_STRUCT_END +static struct GNUNET_TIME_Absolute start_time; +/** + * No. of message currently scheduled to be send + */ static int msg_scheduled; + +/** + * No. of last message sent + */ static int msg_sent; -static int msg_recv_expected; + +/** + * No. of last message received + */ static int msg_recv; -static int test_failed; static int test_connected; +static int test_sending; +static int test_send_timeout; -static unsigned long long total_bytes; -static struct GNUNET_TIME_Absolute start_time; +/** + * Bitmap storing which messages were received + */ + +static char bitmap[TOTAL_MSGS / 8]; + +static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; /* * END Testcase specific declarations @@ -113,6 +167,8 @@ static struct GNUNET_TIME_Absolute start_time; #define OKPP do { ok++; } while (0) #endif +static int +get_bit (const char *map, unsigned int bit); static void end () @@ -121,15 +177,15 @@ end () unsigned long long rate; char *value_name; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); + /* Calculcate statistics */ delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; - rate = (1000LL * 1000LL * total_bytes) / (1024 * delta); + rate = (1000LL* 1000ll * total_bytes) / (1024 * delta); FPRINTF (stderr, "\nThroughput was %llu KiBytes/s\n", rate); - GNUNET_asprintf (&value_name, "reliable_%s", test_plugin); + GNUNET_asprintf (&value_name, "unreliable_%s", test_plugin); GAUGER ("TRANSPORT", value_name, (int) rate, "kb/s"); GNUNET_free (value_name); @@ -143,16 +199,31 @@ end () if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); + cc = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); GNUNET_TRANSPORT_TESTING_done (tth); + + ok = 0; + + int i; + + for (i = 0; i < TOTAL_MSGS; i++) + { + if (get_bit (bitmap, i) == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not receive message %d\n", i); + ok = -1; + } + } } static void end_badly () { + int i; die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); @@ -161,20 +232,34 @@ end_badly () else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers got NOT connected\n"); + if (test_sending == GNUNET_NO) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Testcase did not send any messages before timeout\n"); + if (test_send_timeout == GNUNET_YES) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Test had timeout while waiting to send data\n"); + for (i = 0; i < TOTAL_MSGS; i++) + { + if (get_bit (bitmap, i) == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not receive message %d\n", i); + ok = -1; + } + } + if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); + cc = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); - GNUNET_TRANSPORT_TESTING_done (tth); - ok = GNUNET_SYSERR; } @@ -185,84 +270,126 @@ get_size (unsigned int iter) unsigned int ret; ret = (iter * iter * iter); + +#ifndef LINUX + /* FreeBSD/OSX etc. Unix DGRAMs do not work + * with large messages */ + if (0 == strcmp ("unix", test_plugin)) + return sizeof (struct TestMessage) + (ret % 1024); +#endif return sizeof (struct TestMessage) + (ret % 60000); } +/** + * Sets a bit active in the bitmap. + * + * @param bitIdx which bit to set + * @return GNUNET_SYSERR on error, GNUNET_OK on success + */ +static int +set_bit (unsigned int bitIdx) +{ + size_t arraySlot; + unsigned int targetBit; + + if (bitIdx >= sizeof (bitmap) * 8) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "tried to set bit %d of %d(!?!?)\n", + bitIdx, sizeof (bitmap) * 8); + return GNUNET_SYSERR; + } + arraySlot = bitIdx / 8; + targetBit = (1L << (bitIdx % 8)); + bitmap[arraySlot] |= targetBit; + return GNUNET_OK; +} + +/** + * Obtain a bit from bitmap. + * @param map the bitmap + * @param bit index from bitmap + * + * @return Bit \a bit from hashcode \a code + */ +static int +get_bit (const char *map, unsigned int bit) +{ + if (bit > TOTAL_MSGS) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "get bit %d of %d(!?!?)\n", bit, + sizeof (bitmap) * 8); + return 0; + } + return ((map)[bit >> 3] & (1 << (bit & 7))) > 0; +} + + static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { static int n; + unsigned int s; char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; const struct TestMessage *hdr; hdr = (const struct TestMessage *) message; - s = get_size (n); + if (MTYPE != ntohs (message->type)) return; - msg_recv_expected = n; msg_recv = ntohl (hdr->num); - if (ntohs (message->size) != (s)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Expected message %u of size %u, got %u bytes of message %u\n", - n, s, ntohs (message->size), ntohl (hdr->num)); - if (die_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (die_task); - test_failed = GNUNET_YES; - die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); - return; - } - if (ntohl (hdr->num) != n) + s = get_size (ntohl (hdr->num)); + + if (ntohs (message->size) != s) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", - n, s, ntohs (message->size), ntohl (hdr->num)); - if (die_task != GNUNET_SCHEDULER_NO_TASK) + ntohl (hdr->num), s, ntohs (message->size), ntohl (hdr->num)); + if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); - test_failed = GNUNET_YES; + test_sending = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } - memset (cbuf, n, s - sizeof (struct TestMessage)); + + memset (cbuf, ntohl (hdr->num), s - sizeof (struct TestMessage)); if (0 != memcmp (cbuf, &hdr[1], s - sizeof (struct TestMessage))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Expected message %u with bits %u, but body did not match at position %u\n", n, - (unsigned char) n); - if (die_task != GNUNET_SCHEDULER_NO_TASK) + "Expected message %u with bits %u, but body did not match\n", + ntohl (hdr->num), (unsigned char) n); + if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); - test_failed = GNUNET_YES; + test_sending = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } #if VERBOSE - if (ntohl (hdr->num) % 5000 == 0) + if (ntohl (hdr->num) % 5 == 0) { - struct PeerContext *p = cls; - char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peer %u (`%s') got message %u of size %u from peer (`%s')\n", - p->no, ps, ntohl (hdr->num), ntohs (message->size), - GNUNET_i2s (peer)); - GNUNET_free (ps); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got message %u of size %u\n", + ntohl (hdr->num), ntohs (message->size)); } #endif n++; + if (GNUNET_SYSERR == set_bit (ntohl (hdr->num))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Message id %u is bigger than maxmimum number of messages %u expected\n"), + ntohl (hdr->num), TOTAL_MSGS); + } + test_sending = GNUNET_YES; if (0 == (n % (TOTAL_MSGS / 100))) { FPRINTF (stderr, "%s", "."); - if (die_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); } if (n == TOTAL_MSGS) { - ok = 0; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\nAll messages received\n"); end (); } } @@ -278,10 +405,12 @@ notify_ready (void *cls, size_t size, void *buf) unsigned int ret; th = NULL; + if (buf == NULL) { + test_send_timeout = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Timeout occurred while waiting for transmit_ready for message %u of %u\n", + "Timeout occurred while waiting for transmit_ready for msg %u of %u\n", msg_scheduled, TOTAL_MSGS); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); @@ -289,14 +418,15 @@ notify_ready (void *cls, size_t size, void *buf) ok = 42; return 0; } - ret = 0; s = get_size (n); GNUNET_assert (size >= s); GNUNET_assert (buf != NULL); + GNUNET_assert (n < TOTAL_MSGS); cbuf = buf; do { + GNUNET_assert (n < TOTAL_MSGS); hdr.header.size = htons (s); hdr.header.type = htons (MTYPE); hdr.num = htonl (n); @@ -305,17 +435,12 @@ notify_ready (void *cls, size_t size, void *buf) ret += sizeof (struct TestMessage); memset (&cbuf[ret], n, s - sizeof (struct TestMessage)); ret += s - sizeof (struct TestMessage); + #if VERBOSE if (n % 5000 == 0) { - - char *receiver_s = GNUNET_strdup (GNUNET_i2s (&receiver->id)); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending message of size %u from peer %u (`%4s') -> peer %u (`%s') !\n", - n, sender->no, GNUNET_i2s (&sender->id), receiver->no, - receiver_s); - GNUNET_free (receiver_s); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message %u of size %u\n", n, + s); } #endif n++; @@ -323,26 +448,28 @@ notify_ready (void *cls, size_t size, void *buf) if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16)) break; /* sometimes pack buffer full, sometimes not */ } - while (size - ret >= s); + while ((size - ret >= s) && (n < TOTAL_MSGS)); if (n < TOTAL_MSGS) { - if (th == NULL) - th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, s, - TIMEOUT_TRANSMIT, - ¬ify_ready, NULL); + th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, s, + TIMEOUT_TRANSMIT, + ¬ify_ready, NULL); msg_scheduled = n; } + else + { + FPRINTF (stderr, "%s", "\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All messages scheduled to be sent\n"); + if (GNUNET_SCHEDULER_NO_TASK != die_task) + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + } if (n % 5000 == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning total message block of size %u\n", ret); } total_bytes += ret; - if (n == TOTAL_MSGS) - { - FPRINTF (stderr, "%s", "\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All messages sent\n"); - } return ret; } @@ -350,31 +477,27 @@ notify_ready (void *cls, size_t size, void *buf) static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { - - struct PeerContext *p = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') connected to us!\n", - p->no, GNUNET_i2s (peer)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' connected to us (%p)!\n", + GNUNET_i2s (peer), cls); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { - struct PeerContext *p = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') disconnected!\n", p->no, - GNUNET_i2s (peer)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' disconnected (%p)!\n", + GNUNET_i2s (peer), cls); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; - } static void sendtask () { start_time = GNUNET_TIME_absolute_get (); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to send %u messages\n", + TOTAL_MSGS); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, get_size (0), TIMEOUT_TRANSMIT, ¬ify_ready, NULL); @@ -385,22 +508,20 @@ testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", - p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %s <-> %s\n", p1_c, + GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); test_connected = GNUNET_YES; cc = NULL; GNUNET_SCHEDULER_add_now (&sendtask, NULL); - } -void +static void start_cb (struct PeerContext *p, void *cls) { static int started; - started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, @@ -410,35 +531,17 @@ start_cb (struct PeerContext *p, void *cls) return; test_connected = GNUNET_NO; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peer %u: `%s' using configuration file `%s'\n", p1->no, - GNUNET_i2s (&p1->id), cfg_file_p1); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peer %u: `%s' using configuration file `%s'\n", p2->no, - GNUNET_i2s (&p2->id), cfg_file_p2); - - sender = p2; - receiver = p1; - - char *sender_c = GNUNET_strdup (GNUNET_i2s (&sender->id)); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Test triest to send from %u (%s) -> peer %u (%s)\n", sender->no, - sender_c, receiver->no, GNUNET_i2s (&receiver->id)); - GNUNET_free (sender_c); - cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } - static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + test_send_timeout = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, @@ -448,21 +551,24 @@ run (void *cls, char *const *args, const char *cfgfile, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); - if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); + //die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } -static int -check () + +int +main (int argc, char *argv[]) { - static char *argv[] = { "test_transport", + char *test_source; + int ret; + + static char *const argv_new[] = { "test-transport-api-reliability", "-c", "test_transport_api_data.conf", NULL @@ -471,18 +577,6 @@ check () GNUNET_GETOPT_OPTION_END }; - ok = 1; - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, - "nohelp", options, &run, &ok); - - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, @@ -498,7 +592,17 @@ main (int argc, char *argv[]) GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); - ret = check (); + + +#if WRITECONFIG + setTransportOptions ("test_transport_api_data.conf"); +#endif + ok = GNUNET_SYSERR; + + ret = GNUNET_PROGRAM_run ((sizeof (argv_new) / sizeof (char *)) - 1, argv_new, test_name, + "nohelp", options, &run, &ok); + if (GNUNET_SYSERR == ret) + ok = -1; GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); @@ -507,8 +611,7 @@ main (int argc, char *argv[]) GNUNET_free (test_plugin); GNUNET_free (test_name); - return ret; + return ok; } - /* end of test_transport_api_reliability.c */ -- cgit v1.2.3