From eb98ca5b7a3d2377f2422d453b5b0fe445cf6329 Mon Sep 17 00:00:00 2001 From: "Nathan S. Evans" Date: Fri, 26 Feb 2010 10:44:15 +0000 Subject: [PATCH] towards better topology testing, still a kink or two --- ...ology_clique.c => test_testing_topology.c} | 446 +++++++++++++----- src/testing/testing.c | 38 -- src/testing/testing_group.c | 10 +- 3 files changed, 327 insertions(+), 167 deletions(-) rename src/testing/{test_testing_topology_clique.c => test_testing_topology.c} (50%) diff --git a/src/testing/test_testing_topology_clique.c b/src/testing/test_testing_topology.c similarity index 50% rename from src/testing/test_testing_topology_clique.c rename to src/testing/test_testing_topology.c index 0521145bb..a8d1a4a8c 100644 --- a/src/testing/test_testing_topology_clique.c +++ b/src/testing/test_testing_topology.c @@ -18,14 +18,14 @@ Boston, MA 02111-1307, USA. */ /** - * @file testing/test_testing_group.c - * @brief testcase for functions to connect two peers in testing.c + * @file testing/test_testing_topology.c + * @brief base testcase for testing all the topologies provided */ #include "platform.h" #include "gnunet_testing_lib.h" #include "gnunet_core_service.h" -#define VERBOSE GNUNET_NO +#define VERBOSE GNUNET_YES /** * How long until we give up on connecting the peers? @@ -40,6 +40,12 @@ static unsigned long long num_peers; static unsigned int total_connections; +static unsigned int total_server_connections; + +static unsigned int total_messages_received; + +static unsigned int expected_messages; + static unsigned int expected_connections; static int peers_left; @@ -52,79 +58,117 @@ const struct GNUNET_CONFIGURATION_Handle *main_cfg; GNUNET_SCHEDULER_TaskIdentifier die_task; -static struct GNUNET_CORE_Handle *peer1handle; +static char *dotOutFileName = "topology.dot"; + +static FILE *dotOutFile; + +static char *topology_string; -static struct GNUNET_CORE_Handle *peer2handle; +static int transmit_ready_scheduled; + +static int transmit_ready_called; + +struct TestMessageContext *global_pos; #define MTYPE 12345 -static void -finish_testing () +struct TestMessageContext { - GNUNET_assert (pg != NULL); + /* This is a linked list */ + struct TestMessageContext *next; - if (peer1handle != NULL) - GNUNET_CORE_disconnect(peer1handle); - if (peer2handle != NULL) - GNUNET_CORE_disconnect(peer2handle); + /* Handle to the sending peer core */ + struct GNUNET_CORE_Handle *peer1handle; - GNUNET_TESTING_daemons_stop (pg); - ok = 0; -} + /* Handle to the receiving peer core */ + struct GNUNET_CORE_Handle *peer2handle; -static int -process_mtype (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) -{ -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Receiving message from `%4s' of type %d.\n", GNUNET_i2s (peer), ntohs(message->type)); -#endif - GNUNET_SCHEDULER_cancel (sched, die_task); - GNUNET_SCHEDULER_add_now (sched, &finish_testing, NULL); - return GNUNET_OK; -} + /* Handle to the sending peer daemon */ + struct GNUNET_TESTING_Daemon *peer1; + /* Handle to the receiving peer daemon */ + struct GNUNET_TESTING_Daemon *peer2; -static void -connect_notify (void *cls, - const struct GNUNET_PeerIdentity *peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + /* Maintain some state */ + int first_step_done; + +}; + +struct Connection { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Encrypted connection established to peer `%4s' with latency %llu\n", - GNUNET_i2s (peer), latency.value); -#endif -} + struct Connection *next; + struct GNUNET_TESTING_Daemon *peer; + struct GNUNET_CORE_Handle *server; +}; + +static struct Connection *global_connections; +static struct TestMessageContext *test_messages; static void -disconnect_notify (void *cls, - const struct GNUNET_PeerIdentity *peer) +finish_testing () { + GNUNET_assert (pg != NULL); + struct Connection *pos; #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer)); + "Called finish testing, stopping daemons.\n"); #endif + int count; + count = 0; + pos = global_connections; + while (pos != NULL) + { + if (pos->server != NULL) + { + GNUNET_CORE_disconnect(pos->server); + pos->server = NULL; + } + pos = pos->next; + } +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "transmit_ready's scheduled %d, transmit_ready's called %d\n", transmit_ready_scheduled, transmit_ready_called); +#endif + sleep(1); +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Calling daemons_stop\n"); +#endif + GNUNET_TESTING_daemons_stop (pg); +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "daemons_stop finished\n"); +#endif + if (dotOutFile != NULL) + { + fprintf(dotOutFile, "}"); + fclose(dotOutFile); + } + + ok = 0; } static int -outbound_notify (void *cls, - const struct GNUNET_PeerIdentity *other, - const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) +process_mtype (void *cls, + const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message, + struct GNUNET_TIME_Relative latency, + uint32_t distance) { + total_messages_received++; #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Core notifies about outbound data for `%4s'.\n", - GNUNET_i2s (other)); + "Received message from `%4s', type %d.\n", GNUNET_i2s (peer), ntohs(message->type)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Total messages received %d, expected %d.\n", total_messages_received, expected_messages); #endif + + if (total_messages_received == expected_messages) + { + GNUNET_SCHEDULER_cancel (sched, die_task); + GNUNET_SCHEDULER_add_now (sched, &finish_testing, NULL); + } return GNUNET_OK; } @@ -135,16 +179,17 @@ end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "End badly was called... stopping daemons.\n"); #endif + struct Connection *pos; - if (peer1handle != NULL) - { - GNUNET_CORE_disconnect(peer1handle); - peer1handle = NULL; - } - if (peer2handle != NULL) + pos = global_connections; + while (pos != NULL) { - GNUNET_CORE_disconnect(peer2handle); - peer2handle = NULL; + if (pos->server != NULL) + { + GNUNET_CORE_disconnect(pos->server); + pos->server = NULL; + } + pos = pos->next; } if (pg != NULL) @@ -154,22 +199,69 @@ end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) } else ok = 401; /* Never got peers started */ + + if (dotOutFile != NULL) + { + fprintf(dotOutFile, "}"); + fclose(dotOutFile); + } +} + + +/** + * Forward declaration. + */ +static size_t +transmit_ready (void *cls, size_t size, void *buf); + +static void +schedule_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) +{ + + if (global_pos != NULL) + { + if (NULL == GNUNET_CORE_notify_transmit_ready (global_pos->peer1handle, + 0, + TIMEOUT, + &global_pos->peer2->id, + sizeof (struct GNUNET_MessageHeader), + &transmit_ready, &global_pos->peer1->id)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", + GNUNET_i2s (&global_pos->peer2->id)); + } + else + { + transmit_ready_scheduled++; + } + global_pos = global_pos->next; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmit ready scheduled on %d messages\n", + transmit_ready_scheduled); + } + } static size_t transmit_ready (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *m; - + struct GNUNET_PeerIdentity *peer = cls; GNUNET_assert (buf != NULL); m = (struct GNUNET_MessageHeader *) buf; m->type = htons (MTYPE); m->size = htons (sizeof (struct GNUNET_MessageHeader)); - GNUNET_SCHEDULER_cancel(sched, die_task); - die_task = - GNUNET_SCHEDULER_add_delayed (sched, - TIMEOUT, &end_badly, "from transmit ready"); + transmit_ready_called++; +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "transmit ready for peer %s\ntransmit_ready's scheduled %d, transmit_ready's called %d\n", GNUNET_i2s(peer), transmit_ready_scheduled, transmit_ready_called); +#endif + GNUNET_SCHEDULER_add_now(sched, &schedule_transmission, NULL); return sizeof (struct GNUNET_MessageHeader); } @@ -180,95 +272,176 @@ static struct GNUNET_CORE_MessageHandler handlers[] = { }; + +static void +send_test_messages () +{ + struct TestMessageContext *pos; + struct Connection *conn_pos; + die_task = GNUNET_SCHEDULER_add_delayed (sched, + TIMEOUT, + &end_badly, "from send test messages"); + + int count = 0; + int conn_count = 0; + pos = test_messages; + while (pos != NULL) + { + conn_pos = global_connections; + conn_count = 0; + while (conn_pos != NULL) + { + if (conn_pos->peer == pos->peer1) + { + pos->peer1handle = conn_pos->server; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Peer matched conn_count %d\n", + conn_count); + break; + } + conn_count++; + conn_pos = conn_pos->next; + } + GNUNET_assert(pos->peer1handle != NULL); + + /* + if (NULL == GNUNET_CORE_notify_transmit_ready (pos->peer1handle, + 0, + TIMEOUT, + &pos->peer2->id, + sizeof (struct GNUNET_MessageHeader), + &transmit_ready, &pos->peer1->id)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", + GNUNET_i2s (&pos->peer2->id)); + } + else + { + transmit_ready_scheduled++; + } + */ + pos = pos->next; + count++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Prepared %d messages\n", + count); + } + + global_pos = test_messages; + + GNUNET_SCHEDULER_add_now(sched, &schedule_transmission, NULL); +} + + + static void init_notify (void *cls, struct GNUNET_CORE_Handle *server, const struct GNUNET_PeerIdentity *my_identity, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey) { - struct GNUNET_TESTING_Daemon *connected_peer = cls; - struct GNUNET_TESTING_Daemon *peer1; - struct GNUNET_TESTING_Daemon *peer2; + struct Connection *connection = cls; - peer1 = GNUNET_TESTING_daemon_get(pg, 0); - peer2 = GNUNET_TESTING_daemon_get(pg, 1); #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core connection to `%4s' established, setting up handles\n", GNUNET_i2s (my_identity)); #endif + connection->server = server; + total_server_connections++; - if (connected_peer == peer1) + if (total_server_connections == num_peers) { - peer1handle = server; + GNUNET_SCHEDULER_cancel(sched, die_task); + GNUNET_SCHEDULER_add_now(sched, &send_test_messages, NULL); + } +#if OLD + if (context->first_step_done == GNUNET_NO) + { + context->peer1handle = server; #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting core to peer 2\n"); #endif + context->first_step_done = GNUNET_YES; /* connect p2 */ GNUNET_CORE_connect (sched, - peer2->cfg, + context->peer2->cfg, TIMEOUT, - peer2, + context, &init_notify, NULL, - &connect_notify, - &disconnect_notify, + NULL, + NULL, NULL, GNUNET_YES, - &outbound_notify, GNUNET_YES, handlers); + NULL, GNUNET_YES, handlers); + } else { - GNUNET_assert(connected_peer == peer2); - peer2handle = server; + context->peer2handle = server; #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking core (1) for transmission to peer `%4s'\n", - GNUNET_i2s (&peer2->id)); + GNUNET_i2s (&context->peer2->id)); #endif - - if (NULL == GNUNET_CORE_notify_transmit_ready (peer1->server, + transmit_ready_scheduled++; + if (NULL == GNUNET_CORE_notify_transmit_ready (context->peer1->server, 0, TIMEOUT, - &peer2->id, + &context->peer2->id, sizeof (struct GNUNET_MessageHeader), - &transmit_ready, &peer1)) + &transmit_ready, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", - GNUNET_i2s (&peer2->id)); + GNUNET_i2s (&context->peer2->id)); } - } +#endif } static void -send_test_messages () +setup_handlers () { - struct GNUNET_TESTING_Daemon *peer1; - struct GNUNET_TESTING_Daemon *peer2; - - peer1 = GNUNET_TESTING_daemon_get(pg, 0); - peer2 = GNUNET_TESTING_daemon_get(pg, 1); + int i; + struct Connection *new_connection; + struct GNUNET_TESTING_Daemon *temp_daemon; die_task = GNUNET_SCHEDULER_add_delayed (sched, TIMEOUT, - &end_badly, "from send test messages"); + &end_badly, "from setup_handlers"); + + + /** + * Set up a single handler for each peer + */ + for (i = 0; i < num_peers; i++) + { + new_connection = GNUNET_malloc(sizeof(struct Connection)); + temp_daemon = GNUNET_TESTING_daemon_get(pg, i); + new_connection->peer = temp_daemon; + new_connection->server = NULL; + new_connection->next = global_connections; + global_connections = new_connection; - /* Send a message from peer 1 to peer 2 */ - GNUNET_CORE_connect (sched, - peer1->cfg, - TIMEOUT, - peer1, - &init_notify, - NULL, - &connect_notify, - &disconnect_notify, - NULL, - GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); + GNUNET_CORE_connect (sched, + temp_daemon->cfg, + TIMEOUT, + new_connection, + &init_notify, + NULL, + NULL, + NULL, + NULL, + GNUNET_YES, NULL, GNUNET_YES, handlers); + } } + + void topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, @@ -279,15 +452,7 @@ topology_callback (void *cls, struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) { - /* Keep track of connections here if the client needs to know? - * Still, we have no real handle to say the i'th peer of the peer group - * even though we know that X peers exist in i... But we may want to - * know about the peer for logging purposes here (I'm sure we will actually - * so the API may need changed). Question, should the API expose what - * a peer group is, or provide convenience/accessor functions? - * - * For now, I've added accessor functions, which seems like a software - * engineering kind of solution, but who knows/cares. */ + struct TestMessageContext *temp_context; if (emsg == NULL) { total_connections++; @@ -296,6 +461,18 @@ topology_callback (void *cls, first_daemon->shortname, second_daemon->shortname); #endif + temp_context = GNUNET_malloc(sizeof(struct TestMessageContext)); + temp_context->first_step_done = 0; + temp_context->peer1handle = NULL; + temp_context->peer1 = first_daemon; + temp_context->peer2 = second_daemon; + temp_context->peer2handle = NULL; + temp_context->next = test_messages; + test_messages = temp_context; + + expected_messages++; + if (dotOutFile != NULL) + fprintf(dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname, second_daemon->shortname); } #if VERBOSE else @@ -311,12 +488,12 @@ topology_callback (void *cls, { #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Created %d total connections, which is our target number! Ending test.\n", + "Created %d total connections, which is our target number! Calling send messages.\n", total_connections); #endif GNUNET_SCHEDULER_cancel (sched, die_task); - die_task = GNUNET_SCHEDULER_add_now (sched, &send_test_messages, NULL); + die_task = GNUNET_SCHEDULER_add_now (sched, &setup_handlers, NULL); } else { @@ -349,6 +526,11 @@ create_topology () } GNUNET_SCHEDULER_cancel (sched, die_task); + if (expected_connections == GNUNET_SYSERR) + { + die_task = GNUNET_SCHEDULER_add_now (sched, + &end_badly, NULL); + } die_task = GNUNET_SCHEDULER_add_delayed (sched, TIMEOUT, &end_badly, NULL); @@ -382,7 +564,7 @@ my_cb (void *cls, (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, NULL); create_topology (); - ok = 477; + ok = 0; } } @@ -395,6 +577,13 @@ run (void *cls, { sched = s; ok = 1; + + dotOutFile = fopen (dotOutFileName, "w"); + if (dotOutFile != NULL) + { + fprintf (dotOutFile, "strict graph G {\n"); + } + #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons based on config file %s\n", cfgfile); @@ -418,19 +607,18 @@ run (void *cls, peers_left, &my_cb, NULL, &topology_callback, NULL, NULL); - /* - if (ret != GNUNET_SYSERR) - ret = send_test_messages (pg); - */ - } static int check () { - char *const argv[] = { "test-testing-topology-clique", + char *binary_name; + char *config_file_name; + GNUNET_asprintf(&binary_name, "test-testing-topology-%s", topology_string); + GNUNET_asprintf(&config_file_name, "test_testing_data_topology_%s.conf", topology_string); + char *const argv[] = {binary_name, "-c", - "test_testing_data_topology_clique.conf", + config_file_name, #if VERBOSE "-L", "DEBUG", #endif @@ -440,7 +628,7 @@ check () GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, - argv, "test-testing-topology-clique", "nohelp", + argv, binary_name, "nohelp", options, &run, &ok); return ok; } @@ -449,8 +637,18 @@ int main (int argc, char *argv[]) { int ret; + char *binary_start_pos; + char *our_binary_name; + binary_start_pos = rindex(argv[0], '/'); + if (strstr(binary_start_pos, "test_testing_topology_") == NULL) + { + return GNUNET_SYSERR; + } + + topology_string = &binary_start_pos[23]; - GNUNET_log_setup ("test-testing-topology_clique", + GNUNET_asprintf(&our_binary_name, "test-testing-topology_%s", topology_string); + GNUNET_log_setup (our_binary_name, #if VERBOSE "DEBUG", #else diff --git a/src/testing/testing.c b/src/testing/testing.c index 1e9f6cf5e..78ef9bb1f 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c @@ -840,44 +840,6 @@ send_hello(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } -#if HIDDEN -/* - * Accessor function since we have hidden what GNUNET_TESTING_Daemon is - * - * FIXME: Either expose members or figure out a better way! - */ -char * -GNUNET_TESTING_daemon_get_shortname (struct GNUNET_TESTING_Daemon *d) -{ - return d->shortname; -} - -char * -GNUNET_TESTING_daemon_get_hostname (struct GNUNET_TESTING_Daemon *d) -{ - return d->hostname; -} - -char * -GNUNET_TESTING_daemon_get_username (struct GNUNET_TESTING_Daemon *d) -{ - return d->username; -} - -struct GNUNET_PeerIdentity * -GNUNET_TESTING_daemon_get_peer (struct GNUNET_TESTING_Daemon *d) -{ - return &d->id; -} - -struct GNUNET_CONFIGURATION_Handle * -GNUNET_TESTING_daemon_get_config (struct GNUNET_TESTING_Daemon *d) -{ - return d->cfg; -} -#endif - - /** * Establish a connection between two GNUnet daemons. * diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c index 54eb1eb19..2c7cc80a5 100644 --- a/src/testing/testing_group.c +++ b/src/testing/testing_group.c @@ -393,7 +393,7 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg) connect_attempts += smallWorldConnections; - return GNUNET_OK; + return connect_attempts; } @@ -410,7 +410,7 @@ create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg) if (p_string != NULL) nat_percentage = atof(p_string); else - nat_percentage = 0.0; /* FIXME: default modifier? */ + nat_percentage = 0.6; /* FIXME: default modifier? */ GNUNET_free_non_null(p_string); @@ -566,7 +566,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg) _("Total connections added for small world: %d!\n"), smallWorldConnections); #endif - return GNUNET_OK; + return connect_attempts; } @@ -589,9 +589,9 @@ create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg) } else { - probability = 0.0; /* FIXME: default probability? */ + probability = 0.5; /* FIXME: default probability? */ } - GNUNET_free (p_string); + GNUNET_free_non_null (p_string); for (outer_count = 0; outer_count < pg->total - 1; outer_count++) { for (inner_count = outer_count + 1; inner_count < pg->total; -- 2.25.1