X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmesh%2Ftest_mesh_small.c;h=54c5eb45f44d6ca3d3c9997c3e4ac3545301546e;hb=782f3c0ce710d67c869d92078c6d64c55992997f;hp=c60e2c57ea1d6d9d62049875197ca3418efeebac;hpb=4a7ea21113603575b97c37eea5c4ee93d1c376bc;p=oweals%2Fgnunet.git diff --git a/src/mesh/test_mesh_small.c b/src/mesh/test_mesh_small.c index c60e2c57e..54c5eb45f 100644 --- a/src/mesh/test_mesh_small.c +++ b/src/mesh/test_mesh_small.c @@ -20,13 +20,14 @@ /** * @file mesh/test_mesh_small.c * - * @brief Test for the mesh service. + * @brief Test for the mesh service: retransmission of traffic. */ #include "platform.h" #include "gnunet_testing_lib.h" #include "gnunet_mesh_service.h" -#define VERBOSE GNUNET_NO +#define VERBOSE GNUNET_YES +#define REMOVE_DIR GNUNET_YES struct MeshPeer { @@ -46,17 +47,37 @@ struct StatsContext }; -// static struct MeshPeer *peer_head; -// -// static struct MeshPeer *peer_tail; - /** * How long until we give up on connecting the peers? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500) +/** + * Time to wait for stuff that should be rather fast + */ +#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) + +/** + * DIFFERENT TESTS TO RUN + */ +#define SETUP 0 +#define UNICAST 1 +#define MULTICAST 2 + +/** + * Which test are we running? + */ +static int test; + +/** + * How many events have happened + */ static int ok; +static int peers_in_tunnel; + +static int peers_responded; + /** * Be verbose */ @@ -77,16 +98,6 @@ static struct GNUNET_CONFIGURATION_Handle *testing_cfg; */ static unsigned long long peers_running; -/** - * Current round we are in. - */ -static unsigned long long current_round; - -/** - * Peers desired in the next round. - */ -static unsigned long long peers_next_round; - /** * Total number of connections in the whole network. */ @@ -118,18 +129,38 @@ static struct GNUNET_TIME_Relative wait_time; static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; /** - * Task called to shutdown test. + * Task To perform tests */ -static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; +static GNUNET_SCHEDULER_TaskIdentifier test_task; /** - * Task used to churn the network. + * Task called to shutdown test. */ -static GNUNET_SCHEDULER_TaskIdentifier churn_task; +static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; static char *topology_file; -static char *data_filename; +static struct GNUNET_TESTING_Daemon *d1; + +static GNUNET_PEER_Id pid1; + +static struct GNUNET_TESTING_Daemon *d2; + +static struct GNUNET_TESTING_Daemon *d3; + +static struct GNUNET_MESH_Handle *h1; + +static struct GNUNET_MESH_Handle *h2; + +static struct GNUNET_MESH_Handle *h3; + +static struct GNUNET_MESH_Tunnel *t; + +static struct GNUNET_MESH_Tunnel *incoming_t; + +static struct GNUNET_MESH_Tunnel *incoming_t2; + +static uint16_t *mesh_peers; /** * Check whether peers successfully shut down. @@ -138,342 +169,516 @@ static void shutdown_callback (void *cls, const char *emsg) { if (emsg != NULL) - { + { #if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Shutdown of peers failed!\n"); #endif - if (ok == 0) - ok = 666; - } + ok--; + } else - { + { #if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "All peers successfully shut down!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: All peers successfully shut down!\n"); #endif - ok = 0; - } + } } static void -shutdown_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { -// struct NSEPeer *pos; #if VERBOSE - fprintf(stderr, "Ending test.\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Ending test.\n"); #endif if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel(disconnect_task); - disconnect_task = GNUNET_SCHEDULER_NO_TASK; - } -// while (NULL != (pos = peer_head)) -// { -// if (pos->nse_handle != NULL) -// GNUNET_NSE_disconnect(pos->nse_handle); -// GNUNET_CONTAINER_DLL_remove(peer_head, peer_tail, pos); -// GNUNET_free(pos); -// } + { + GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = GNUNET_SCHEDULER_NO_TASK; + } if (data_file != NULL) - GNUNET_DISK_file_close(data_file); + GNUNET_DISK_file_close (data_file); GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + GNUNET_CONFIGURATION_destroy (testing_cfg); } static void -connect_mesh_service (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { -// struct NSEPeer *current_peer; - unsigned int i; - -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting to mesh service of peers\n"); -#endif - for (i = 0; i < num_peers; i++) - { -// if ((connection_limit > 0) && (i % (num_peers / connection_limit) != 0)) - continue; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test_mesh_small: connecting to mesh service of peer %d\n", i); -#endif -/* current_peer = GNUNET_malloc(sizeof(struct NSEPeer)); - current_peer->daemon = GNUNET_TESTING_daemon_get(pg, i); - if (GNUNET_YES == GNUNET_TESTING_daemon_running(GNUNET_TESTING_daemon_get(pg, i))) - { - current_peer->nse_handle = GNUNET_NSE_connect (current_peer->daemon->cfg, - &handle_estimate, - current_peer); - GNUNET_assert(current_peer->nse_handle != NULL); - } - GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer);*/ - } + "***************** test: disconnecting mesh service of peers\n"); + disconnect_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_MESH_disconnect (h1); + GNUNET_MESH_disconnect (h2); + if (test == MULTICAST) + GNUNET_MESH_disconnect (h3); + if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) + { + GNUNET_SCHEDULER_cancel (shutdown_handle); + shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); + } } -static void -churn_peers (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc); +/** + * Transmit ready callback + */ +size_t +tmt_rdy (void *cls, size_t size, void *buf) +{ + struct GNUNET_MessageHeader *msg = buf; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: tmt_rdy called\n"); + if (size < sizeof (struct GNUNET_MessageHeader) || NULL == buf) + return 0; + msg->size = htons (sizeof (struct GNUNET_MessageHeader)); + msg->type = htons ((long) cls); + return sizeof (struct GNUNET_MessageHeader); +} /** - * Continuation called by the "get_all" and "get" functions. + * Function is called whenever a message is received. * - * @param cls struct StatsContext - * @param success GNUNET_OK if statistics were - * successfully obtained, GNUNET_SYSERR if not. + * @param cls closure (set from GNUNET_MESH_connect) + * @param tunnel connection to the other end + * @param tunnel_ctx place to store local state associated with the tunnel + * @param sender who sent the message + * @param message the actual message + * @param atsi performance data for the connection + * @return GNUNET_OK to keep the connection open, + * GNUNET_SYSERR to close it (signal serious error) */ -static void -stats_finished_callback (void *cls, int success) +int +data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, + const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *message, + const struct GNUNET_ATS_Information *atsi) { - struct StatsContext *stats_context = cls; - char *buf; - int buf_len; - - if ( (GNUNET_OK == success) && - (data_file != NULL) ) + long client = (long) cls; + + switch (client) + { + case 1L: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Origin client got a response!\n"); + ok++; + peers_responded++; + if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { - /* Stats lookup successful, write out data */ - buf = NULL; - buf_len = GNUNET_asprintf(&buf, - "TOTAL_MESH_BYTES: %u\n", - stats_context->total_mesh_bytes); - if (buf_len > 0) - { - GNUNET_DISK_file_write(data_file, buf, buf_len); - } - GNUNET_free_non_null(buf); + GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = + GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, + NULL); } - - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == shutdown_handle); - shutdown_handle = GNUNET_SCHEDULER_add_now(&shutdown_task, NULL); - GNUNET_free(stats_context); + if (test == MULTICAST && peers_responded < 2) + return GNUNET_OK; + GNUNET_MESH_tunnel_destroy (tunnel); + break; + case 2L: + case 3L: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Destination client %u got a message.\n", + client); + ok++; + GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, 0, + GNUNET_TIME_UNIT_FOREVER_REL, sender, + sizeof (struct GNUNET_MessageHeader), + &tmt_rdy, (void *) 1L); + if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) + { + GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = + GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, + NULL); + } + break; + default: + break; + } + return GNUNET_OK; } /** - * Callback function to process statistic values. + * Handlers, for diverse services + */ +static struct GNUNET_MESH_MessageHandler handlers[] = { + {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)}, + {NULL, 0, 0} +}; + + +/** + * Method called whenever another peer has added us to a tunnel + * the other peer initiated. * - * @param cls struct StatsContext - * @param peer the peer the statistics belong to - * @param subsystem name of subsystem that created the statistic - * @param name the name of the datum - * @param value the current value - * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not - * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration - */ -static int -statistics_iterator (void *cls, - const struct GNUNET_PeerIdentity *peer, - const char *subsystem, - const char *name, - uint64_t value, - int is_persistent) + * @param cls closure + * @param tunnel new handle to the tunnel + * @param initiator peer that started the tunnel + * @param atsi performance information for the tunnel + * @return initial tunnel context for the tunnel + * (can be NULL -- that's not an error) + */ +static void * +incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, + const struct GNUNET_PeerIdentity *initiator, + const struct GNUNET_ATS_Information *atsi) { - struct StatsContext *stats_context = cls; -// -// if ( (0 == strstr(subsystem, "nse")) && -// (0 == strstr(name, "# flood messages received")) ) - stats_context->total_mesh_bytes += 1; //value; - return GNUNET_OK; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Incoming tunnel from %s to peer %d\n", + GNUNET_i2s (initiator), (long) cls); + ok++; + if ((long) cls == 1L) + incoming_t = tunnel; + else + incoming_t2 = tunnel; + if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) + { + GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = + GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, NULL); + } + return NULL; } - +/** + * Function called whenever an inbound tunnel is destroyed. Should clean up + * any associated state. + * + * @param cls closure (set from GNUNET_MESH_connect) + * @param tunnel connection to the other end (henceforth invalid) + * @param tunnel_ctx place where local state associated + * with the tunnel is stored + */ static void -disconnect_mesh_peers (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, + void *tunnel_ctx) { -// struct NSEPeer *pos; - char *buf; - struct StatsContext *stats_context; + long i = (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "disconnecting mesh service of peers\n"); - disconnect_task = GNUNET_SCHEDULER_NO_TASK; -// pos = peer_head; -// while (NULL != (pos = peer_head)) -// { -// if (pos->nse_handle != NULL) -// { -// GNUNET_NSE_disconnect(pos->nse_handle); -// pos->nse_handle = NULL; -// } -// GNUNET_CONTAINER_DLL_remove(peer_head, peer_tail, pos); -// GNUNET_free(pos); -// } - - GNUNET_asprintf(&buf, - "round%llu", - current_round); - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (testing_cfg, - "test_mesh_small", - buf, - &peers_next_round)) - { - current_round++; - GNUNET_assert(churn_task == GNUNET_SCHEDULER_NO_TASK); - churn_task = GNUNET_SCHEDULER_add_now(&churn_peers, NULL); - } - else /* No more rounds, let's shut it down! */ - { - stats_context = GNUNET_malloc(sizeof(struct StatsContext)); - GNUNET_SCHEDULER_cancel(shutdown_handle); - shutdown_handle = GNUNET_SCHEDULER_NO_TASK; - GNUNET_TESTING_get_statistics(pg, - &stats_finished_callback, - &statistics_iterator, - stats_context); - } - GNUNET_free(buf); + "***************** test: Incoming tunnel disconnected at peer %d\n", + i); + if (2L == i) + ok++; + else if (3L == i) + ok++; + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Unknown peer! %d\n", i); + peers_in_tunnel--; + if (peers_in_tunnel > 0) + return; + + if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) + { + GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, NULL); + } + + return; } /** - * FIXME. + * Method called whenever a tunnel falls apart. * - * @param cls unused - * @param emsg NULL on success + * @param cls closure + * @param peer peer identity the tunnel stopped working with */ -static void -topology_output_callback (void *cls, const char *emsg) +static void +dh (void *cls, const struct GNUNET_PeerIdentity *peer) { - disconnect_task = GNUNET_SCHEDULER_add_delayed(wait_time, - &disconnect_mesh_peers, NULL); - GNUNET_SCHEDULER_add_now(&connect_mesh_service, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: peer %s disconnected\n", + GNUNET_i2s (peer)); + return; } /** - * FIXME. + * Method called whenever a peer connects to a tunnel. * * @param cls closure - * @param emsg NULL on success + * @param peer peer identity the tunnel was created to, NULL on timeout + * @param atsi performance data for the connection */ static void -churn_callback (void *cls, const char *emsg) +ch (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_ATS_Information *atsi) { - char *temp_output_file; + struct GNUNET_PeerIdentity *dest; - if (emsg == NULL) /* Everything is okay! */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: peer %s connected\n", GNUNET_i2s (peer)); + + if (0 == memcmp (&d2->id, peer, sizeof (d2->id)) && (long) cls == 1L) + ok++; + if (test == MULTICAST && 0 == memcmp (&d3->id, peer, sizeof (d3->id)) && + (long) cls == 1L) + ok++; + switch (test) + { + case UNICAST: + dest = &d2->id; + break; + case MULTICAST: + peers_in_tunnel++; + if (peers_in_tunnel < 2) + return; + dest = NULL; + break; + default: + return; + } + if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) + { + GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = + GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Sending data...\n"); + peers_responded = 0; + GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO, 0, + GNUNET_TIME_UNIT_FOREVER_REL, dest, + sizeof (struct GNUNET_MessageHeader), + &tmt_rdy, (void *) 1L); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Disconnect already run?\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Aborting...\n"); + } + return; +} + + +static void +do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: test_task\n"); + if (test == MULTICAST) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: add peer 3\n"); + GNUNET_MESH_peer_request_connect_add (t, &d3->id); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: add peer 2\n"); + GNUNET_MESH_peer_request_connect_add (t, &d2->id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: schedule timeout in 30s\n"); + if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) + { + GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply + (GNUNET_TIME_UNIT_SECONDS, 30), + &disconnect_mesh_peers, NULL); + } +} + + +/** + * Prototype of a callback function indicating that two peers + * are currently connected. + * + * @param cls closure + * @param first peer id for first daemon + * @param second peer id for the second daemon + * @param distance distance between the connected peers + * @param emsg error message (NULL on success) + */ +void +topo_cb (void *cls, const struct GNUNET_PeerIdentity *first, + const struct GNUNET_PeerIdentity *second, const char *emsg) +{ + GNUNET_PEER_Id p1; + GNUNET_PEER_Id p2; + struct GNUNET_PeerIdentity id; + + GNUNET_PEER_resolve (1, &id); + p1 = GNUNET_PEER_search (first); + if (p1 == pid1) + { + p2 = GNUNET_PEER_search (second); + if (p2 == 0 || p2 > num_peers) { - peers_running = peers_next_round; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Round %llu, churn finished successfully.\n", - current_round); - GNUNET_assert(disconnect_task == GNUNET_SCHEDULER_NO_TASK); - GNUNET_asprintf(&temp_output_file, - "%s_%llu.dot", - topology_file, - current_round); - GNUNET_TESTING_peergroup_topology_to_file(pg, - temp_output_file, - &topology_output_callback, - NULL); - GNUNET_log(GNUNET_ERROR_TYPE_WARNING, - "Writing topology to file %s\n", - temp_output_file); - GNUNET_free(temp_output_file); + "***************** test: %s is UNKNOWN!? (%u)\n", + GNUNET_i2s (second), p2); + return; } - else + mesh_peers[p2]++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: %s IS a neighbor\n", + GNUNET_i2s (second)); + return; + } + p1 = GNUNET_PEER_search (second); + if (p1 == pid1) + { + p2 = GNUNET_PEER_search (first); + if (p2 == 0 || p2 > num_peers) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Round %llu, churn FAILED!!\n", - current_round); - GNUNET_SCHEDULER_cancel(shutdown_handle); - shutdown_handle = GNUNET_SCHEDULER_add_now(&shutdown_task, NULL); + "***************** test: %s is UNKNOWN!? (%u)\n", + GNUNET_i2s (first), p2); + return; } + mesh_peers[p2]++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: %s IS a neighbor\n", + GNUNET_i2s (first)); + return; + } } - +/** + * connect_mesh_service: connect to the mesh service of one of the peers + * + */ static void -churn_peers (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +connect_mesh_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - /* peers_running = GNUNET_TESTING_daemons_running(pg); */ - churn_task = GNUNET_SCHEDULER_NO_TASK; - if (peers_next_round == peers_running) - { - /* Nothing to do... */ - GNUNET_SCHEDULER_add_now(&connect_mesh_service, NULL); - GNUNET_assert(disconnect_task == GNUNET_SCHEDULER_NO_TASK); - disconnect_task = GNUNET_SCHEDULER_add_delayed(wait_time, - &disconnect_mesh_peers, NULL); - GNUNET_log(GNUNET_ERROR_TYPE_WARNING, - "Round %lu, doing nothing!\n", - current_round); - } - else + GNUNET_MESH_ApplicationType app; + unsigned int i; + struct GNUNET_PeerIdentity id; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: connect_mesh_service\n"); + + for (i = 1; i <= num_peers; i++) + { + GNUNET_PEER_resolve (i, &id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: peer %s has %u conns to d1\n", + GNUNET_i2s (&id), mesh_peers[i]); + if (mesh_peers[i] == 0) + break; + } + GNUNET_assert (i < num_peers); + d2 = GNUNET_TESTING_daemon_get_by_id (pg, &id); + if (test == MULTICAST) + { + for (i++; i <= num_peers; i++) { - if (peers_next_round > num_peers) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Asked to turn on more peers than we have!!\n"); - GNUNET_SCHEDULER_cancel(shutdown_handle); - GNUNET_SCHEDULER_add_now(&shutdown_task, NULL); - } - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Round %llu, turning off %llu peers, turning on %llu peers!\n", - current_round, - (peers_running > peers_next_round) - ? peers_running - peers_next_round - : 0, - (peers_next_round > peers_running) - ? peers_next_round - peers_running - : 0); - GNUNET_TESTING_daemons_churn (pg, "nse", - (peers_running > peers_next_round) - ? peers_running - peers_next_round - : 0, - (peers_next_round > peers_running) - ? peers_next_round - peers_running - : 0, - wait_time, - &churn_callback, NULL); + GNUNET_PEER_resolve (i, &id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: peer %s has %u conns to d1\n", + GNUNET_i2s (&id), mesh_peers[i]); + if (mesh_peers[i] == 0) + break; } + GNUNET_assert (i < num_peers); + d3 = GNUNET_TESTING_daemon_get_by_id (pg, &id); + } + app = (GNUNET_MESH_ApplicationType) 0; + +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: connecting to mesh service of peer %s (%u)\n", + GNUNET_i2s (&d1->id), mesh_peers[0]); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: connecting to mesh service of peer %s (%u)\n", + GNUNET_i2s (&d2->id), i); + if (test == MULTICAST) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: connecting to mesh service of peer %s (%u)\n", + GNUNET_i2s (&d3->id), i); + } +#endif + h1 = GNUNET_MESH_connect (d1->cfg, 10, (void *) 1L, NULL, &tunnel_cleaner, + handlers, &app); + h2 = GNUNET_MESH_connect (d2->cfg, 10, (void *) 2L, &incoming_tunnel, + &tunnel_cleaner, handlers, &app); + if (test == MULTICAST) + { + h3 = GNUNET_MESH_connect (d3->cfg, 10, (void *) 3L, &incoming_tunnel, + &tunnel_cleaner, handlers, &app); + } + t = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, (void *) 1L); + peers_in_tunnel = 0; + test_task = + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply + (GNUNET_TIME_UNIT_SECONDS, 6), &do_test, + NULL); } + +/** + * peergroup_ready: start test when all peers are connected + * @param cls closure + * @param emsg error message + */ static void -my_cb (void *cls, - const char *emsg) +peergroup_ready (void *cls, const char *emsg) { char *buf; int buf_len; + unsigned int i; + if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peergroup callback called with error, aborting test!\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n"); - ok = 1; - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - return; - } + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Peergroup callback called with error, aborting test!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Error from testing: `%s'\n", emsg); + ok--; + GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + return; + } #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peer Group started successfully!\n"); + "************************************************************\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Peer Group started successfully!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Have %u connections\n", + total_connections); #endif - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Have %u connections\n", - total_connections); - if (data_file != NULL) - { - buf = NULL; - buf_len = GNUNET_asprintf(&buf, - "CONNECTIONS_0: %u\n", - total_connections); - if (buf_len > 0) - GNUNET_DISK_file_write(data_file, buf, buf_len); - GNUNET_free (buf); - } - peers_running = GNUNET_TESTING_daemons_running(pg); - GNUNET_SCHEDULER_add_now(&connect_mesh_service, NULL); - disconnect_task = GNUNET_SCHEDULER_add_delayed(wait_time, &disconnect_mesh_peers, NULL); + if (data_file != NULL) + { + buf = NULL; + buf_len = GNUNET_asprintf (&buf, "CONNECTIONS_0: %u\n", total_connections); + if (buf_len > 0) + GNUNET_DISK_file_write (data_file, buf, buf_len); + GNUNET_free (buf); + } + peers_running = GNUNET_TESTING_daemons_running (pg); + for (i = 0; i < num_peers; i++) + { + GNUNET_PEER_Id peer_id; + + d1 = GNUNET_TESTING_daemon_get (pg, i); + peer_id = GNUNET_PEER_intern (&d1->id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: %u: %s\n", + peer_id, GNUNET_i2s (&d1->id)); + } + d1 = GNUNET_TESTING_daemon_get (pg, 0); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Peer looking: %s\n", + GNUNET_i2s (&d1->id)); + pid1 = GNUNET_PEER_intern (&d1->id); + mesh_peers[pid1] = 100; + GNUNET_TESTING_get_topology (pg, &topo_cb, NULL); + + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply + (GNUNET_TIME_UNIT_SECONDS, 4), + &connect_mesh_service, NULL); + disconnect_task = + GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_mesh_peers, NULL); } @@ -492,117 +697,143 @@ my_cb (void *cls, * @param second_daemon handle for the second daemon * @param emsg error message (NULL on success) */ -static void -connect_cb (void *cls, - const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, - uint32_t distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg) +static void +connect_cb (void *cls, const struct GNUNET_PeerIdentity *first, + const struct GNUNET_PeerIdentity *second, uint32_t distance, + const struct GNUNET_CONFIGURATION_Handle *first_cfg, + const struct GNUNET_CONFIGURATION_Handle *second_cfg, + struct GNUNET_TESTING_Daemon *first_daemon, + struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) { if (emsg == NULL) + { total_connections++; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Problem with new connection (%s)\n", + emsg); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: (%s)\n", + GNUNET_i2s (first)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: (%s)\n", + GNUNET_i2s (second)); + } + } +/** + * run: load configuration options and schedule test to run (start peergroup) + * @param cls closure + * @param args argv + * @param cfgfile configuration file name (can be NULL) + * @param cfg configuration handle + */ static void -run (void *cls, - char *const *args, - const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) { - char *temp_str; - unsigned long long temp_wait; - struct GNUNET_TESTING_Host *hosts; + char *temp_str; + unsigned long long temp_wait; + struct GNUNET_TESTING_Host *hosts; + char *data_filename; - ok = 1; - testing_cfg = (struct GNUNET_CONFIGURATION_Handle *)cfg; // GNUNET_CONFIGURATION_create(); + ok = 0; + testing_cfg = GNUNET_CONFIGURATION_dup (cfg); + + GNUNET_log_setup ("test_mesh_small", #if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); - GNUNET_CONFIGURATION_set_value_string (testing_cfg, - "testing", - "use_progressbars", - "YES"); + "DEBUG", +#else + "WARNING", #endif - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (testing_cfg, - "testing", - "num_peers", &num_peers)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Option TESTING:NUM_PEERS is required!\n"); - return; - } - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (testing_cfg, - "test_mesh_small", - "wait_time", - &temp_wait)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Option nsetest_mesh_small:wait_time is required!\n"); - return; - } - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (testing_cfg, - "testing", "topology_output_file", - &topology_file)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Option test_mesh_small:topology_output_file is required!\n"); - return; - } + NULL); - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (testing_cfg, - "test_mesh_small", "data_output_file", - &data_filename)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Option test_mesh_small:data_output_file is required!\n"); - return; - } +#if VERBOSE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "***************** test: Starting daemons.\n"); + GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing", + "use_progressbars", "YES"); +#endif - data_file = GNUNET_DISK_file_open (data_filename, - GNUNET_DISK_OPEN_READWRITE - | GNUNET_DISK_OPEN_CREATE, - GNUNET_DISK_PERM_USER_READ | - GNUNET_DISK_PERM_USER_WRITE); - if (data_file == NULL) - GNUNET_log(GNUNET_ERROR_TYPE_WARNING, - "Failed to open %s for output!\n", - data_filename); - GNUNET_free(data_filename); - - wait_time = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, temp_wait); - - if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(cfg, - "test_mesh_small", - "output_file", - &temp_str)) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing", + "num_peers", &num_peers)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Option TESTING:NUM_PEERS is required!\n"); + return; + } + + mesh_peers = GNUNET_malloc (sizeof (uint16_t) * (num_peers + 1)); + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (testing_cfg, "test_mesh_small", + "wait_time", &temp_wait)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Option test_mesh_small:wait_time is required!\n"); + return; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (testing_cfg, "testing", + "topology_output_file", + &topology_file)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Option test_mesh_small:topology_output_file is required!\n"); + return; + } + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (testing_cfg, "test_mesh_small", + "data_output_file", + &data_filename)) + { + data_file = + GNUNET_DISK_file_open (data_filename, + GNUNET_DISK_OPEN_READWRITE | + GNUNET_DISK_OPEN_CREATE, + GNUNET_DISK_PERM_USER_READ | + GNUNET_DISK_PERM_USER_WRITE); + if (data_file == NULL) { - output_file = GNUNET_DISK_file_open (temp_str, GNUNET_DISK_OPEN_READWRITE - | GNUNET_DISK_OPEN_CREATE, - GNUNET_DISK_PERM_USER_READ | - GNUNET_DISK_PERM_USER_WRITE); - if (output_file == NULL) - GNUNET_log(GNUNET_ERROR_TYPE_WARNING, - "Failed to open %s for output!\n", - temp_str); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n", + data_filename); + GNUNET_free (data_filename); } - GNUNET_free_non_null(temp_str); + } + + wait_time = + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, temp_wait); + + if (GNUNET_YES == + GNUNET_CONFIGURATION_get_value_string (cfg, "test_mesh_small", + "output_file", &temp_str)) + { + output_file = + GNUNET_DISK_file_open (temp_str, + GNUNET_DISK_OPEN_READWRITE | + GNUNET_DISK_OPEN_CREATE, + GNUNET_DISK_PERM_USER_READ | + GNUNET_DISK_PERM_USER_WRITE); + if (output_file == NULL) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n", + temp_str); + } + GNUNET_free_non_null (temp_str); hosts = GNUNET_TESTING_hosts_load (testing_cfg); - pg = GNUNET_TESTING_peergroup_start(testing_cfg, - num_peers, - TIMEOUT, - &connect_cb, - &my_cb, NULL, - hosts); + pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT, + &connect_cb, &peergroup_ready, NULL, + hosts); GNUNET_assert (pg != NULL); - shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_get_forever(), - &shutdown_task, - NULL); + shutdown_handle = + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_get_forever (), + &shutdown_task, NULL); } @@ -618,25 +849,69 @@ static struct GNUNET_GETOPT_CommandLineOption options[] = { }; +/** + * Main: start test + */ int main (int argc, char *argv[]) { - GNUNET_log_setup ("test_mesh_small", + char *const argv2[] = { + argv[0], + "-c", + "test_mesh_small.conf", #if VERBOSE - "DEBUG", -#else - "WARNING", + "-L", + "DEBUG", #endif - NULL); - GNUNET_PROGRAM_run (argc, - argv, "test_mesh_small", - gettext_noop ("Test mesh in a small network."), - options, - &run, NULL); + NULL + }; + + /* Each peer is supposed to generate the following callbacks: + * 1 incoming tunnel (@dest) + * 1 connected peer (@orig) + * 1 received data packet (@dest) + * 1 received data packet (@orig) + * 1 received tunnel destroy (@dest) + * _________________________________ + * 5 x ok expected per peer + */ + int ok_goal; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: Start\n"); + if (strstr (argv[0], "test_mesh_small_unicast") != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: UNICAST\n"); + test = UNICAST; + ok_goal = 5; + } + else if (strstr (argv[0], "test_mesh_small_multicast") != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: MULTICAST\n"); + test = MULTICAST; + ok_goal = 10; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: UNKNOWN\n"); + test = SETUP; + ok_goal = 0; + } + + GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, + "test_mesh_small", + gettext_noop ("Test mesh in a small network."), options, + &run, NULL); #if REMOVE_DIR GNUNET_DISK_directory_remove ("/tmp/test_mesh_small"); #endif - return ok; + if (ok_goal < ok) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "***************** test: FAILED! (%d/%d)\n", ok, ok_goal); + return 1; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "***************** test: success\n"); + return 0; } /* end of test_mesh_small.c */