gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r27402 - gnunet/src/mesh


From: gnunet
Subject: [GNUnet-SVN] r27402 - gnunet/src/mesh
Date: Mon, 10 Jun 2013 16:38:06 +0200

Author: bartpolot
Date: 2013-06-10 16:38:05 +0200 (Mon, 10 Jun 2013)
New Revision: 27402

Added:
   gnunet/src/mesh/mesh2_test_lib.c
   gnunet/src/mesh/mesh2_test_lib.h
   gnunet/src/mesh/test_mesh2_small.c
Modified:
   gnunet/src/mesh/Makefile.am
Log:
- add framework for mesh2 mutipeer tests

Modified: gnunet/src/mesh/Makefile.am
===================================================================
--- gnunet/src/mesh/Makefile.am 2013-06-10 13:10:24 UTC (rev 27401)
+++ gnunet/src/mesh/Makefile.am 2013-06-10 14:38:05 UTC (rev 27402)
@@ -21,13 +21,12 @@
 AM_CLFAGS = -g
 
 if HAVE_EXPERIMENTAL
+  noinst_LIB_EXP = libgnunetmesh2test.a
   EXP_LIB = libgnunetmesh2.la
   EXP_LIBEXEC = gnunet-service-mesh-new
   EXP_TESTS = \
-  test_mesh2_local
-  MESH_DEP = $(top_builddir)/src/mesh/libgnunetmesh2.la
-else
-  MESH_DEP = $(top_builddir)/src/mesh/libgnunetmesh.la
+    test_mesh2_local \
+    test_mesh2_small_forward
 endif
 
 libexec_PROGRAMS = \
@@ -127,7 +126,7 @@
 endif
 
 
-noinst_LIBRARIES = libgnunetmeshtest.a
+noinst_LIBRARIES = libgnunetmeshtest.a $(noinst_LIB_EXP)
 
 libgnunetmeshtest_a_SOURCES = \
   mesh_test_lib.c mesh_test_lib.h
@@ -138,7 +137,16 @@
 libgnunetmeshtest_a_DEPENDENCIES = \
   libgnunetmesh.la
 
+libgnunetmesh2test_a_SOURCES = \
+  mesh2_test_lib.c mesh2_test_lib.h
+libgnunetmesh2test_a_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/testbed/libgnunettestbed.la \
+ $(top_builddir)/src/mesh/libgnunetmesh2.la
+libgnunetmesh2test_a_DEPENDENCIES = \
+  libgnunetmesh2.la
 
+
 check_PROGRAMS = \
  test_mesh_api \
  test_mesh_tree_api \
@@ -162,7 +170,7 @@
 test_mesh_api_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
  $(top_builddir)/src/testing/libgnunettesting.la \
- $(MESH_DEP)
+ $(top_builddir)/src/mesh/libgnunetmesh.la
 test_mesh_api_DEPENDENCIES = \
   libgnunetmesh.la \
    $(top_builddir)/src/util/libgnunetutil.la
@@ -273,15 +281,27 @@
 test_mesh_small_speed_nobuf_backwards_DEPENDENCIES = $(dep_mesh_test_lib)
 
 
-test_mesh2_local_SOURCES = \
- test_mesh2_local.c
-test_mesh2_local_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(MESH_DEP)
-test_mesh2_local_DEPENDENCIES = \
+ld_mesh2_test_lib = \
+  $(top_builddir)/src/mesh/libgnunetmesh2test.a \
+  $(top_builddir)/src/mesh/libgnunetmesh2.la \
+  $(top_builddir)/src/testbed/libgnunettestbed.la \
+  $(top_builddir)/src/util/libgnunetutil.la 
+
+dep_mesh2_test_lib = \
+  libgnunetmesh2test.a \
   libgnunetmesh2.la
 
+test_mesh2_local_SOURCES = \
+  test_mesh2_local.c
+test_mesh2_local_LDADD = $(ld_mesh2_test_lib)
+test_mesh2_local_DEPENDENCIES = $(dep_mesh2_test_lib)
+
+test_mesh2_small_forward_SOURCES = \
+  test_mesh2_small.c
+test_mesh2_small_forward_LDADD = $(ld_mesh2_test_lib)
+test_mesh2_small_forward_DEPENDENCIES = $(dep_mesh2_test_lib)
+
+
 if ENABLE_TEST_RUN
 TESTS = \
  $(EXP_TESTS) \

Added: gnunet/src/mesh/mesh2_test_lib.c
===================================================================
--- gnunet/src/mesh/mesh2_test_lib.c                            (rev 0)
+++ gnunet/src/mesh/mesh2_test_lib.c    2013-06-10 14:38:05 UTC (rev 27402)
@@ -0,0 +1,303 @@
+/*
+     This file is part of GNUnet.
+     (C) 2012 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file mesh/mesh2_test_lib.c
+ * @author Bartlomiej Polot
+ * @brief library for writing MESH tests
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "mesh_test_lib.h"
+#include "gnunet_mesh2_service.h"
+
+/**
+ * Test context for a MESH Test.
+ */
+struct GNUNET_MESH_TEST_Context
+{
+  /**
+   * Array of running peers.
+   */
+  struct GNUNET_TESTBED_Peer **peers;
+
+  /**
+   * Array of handles to the MESH for each peer.
+   */
+  struct GNUNET_MESH_Handle **meshes;
+
+  /**
+   * Operation associated with the connection to the MESH.
+   */
+  struct GNUNET_TESTBED_Operation **ops;
+
+  /**
+   * Main function of the test to run once all MESHs are available.
+   */
+  GNUNET_MESH_TEST_AppMain app_main;
+  
+  /**
+   * Closure for 'app_main'.
+   */
+  void *app_main_cls;
+
+  /**
+   * Number of peers running, size of the arrays above.
+   */
+  unsigned int num_peers;
+
+  /**
+   * Handler for incoming tunnels.
+   */
+  GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
+
+  /**
+   * Cleaner for destroyed incoming tunnels.
+   */
+  GNUNET_MESH_TunnelEndHandler *cleaner;
+
+  /**
+   * Message handlers.
+   */
+  struct GNUNET_MESH_MessageHandler* handlers;
+
+  /**
+   * Application types.
+   */
+  const GNUNET_MESH_ApplicationType* stypes;
+
+};
+
+
+/**
+ * Context for a mesh adapter callback.
+ */
+struct GNUNET_MESH_TEST_AdapterContext
+{
+  /**
+   * Peer number for the particular peer.
+   */
+  unsigned int peer;
+
+  /**
+   * General context.
+   */
+  struct GNUNET_MESH_TEST_Context *ctx;
+};
+
+
+/**
+ * Adapter function called to establish a connection to
+ * the MESH service.
+ *
+ * @param cls closure
+ * @param cfg configuration of the peer to connect to; will be available until
+ *          GNUNET_TESTBED_operation_done() is called on the operation returned
+ *          from GNUNET_TESTBED_service_connect()
+ * @return service handle to return in 'op_result', NULL on error
+ */
+static void *
+mesh_connect_adapter (void *cls,
+                      const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
+  struct GNUNET_MESH_TEST_Context *ctx = actx->ctx;
+  struct GNUNET_MESH_Handle *h;
+
+  h = GNUNET_MESH_connect (cfg,
+                           (void *) (long) actx->peer,
+                           ctx->new_tunnel,
+                           ctx->cleaner,
+                           ctx->handlers,
+                           ctx->stypes);
+  return h;
+}
+
+
+/**
+ * Adapter function called to destroy a connection to
+ * the MESH service.
+ *
+ * @param cls closure
+ * @param op_result service handle returned from the connect adapter
+ */
+static void 
+mesh_disconnect_adapter (void *cls,
+                         void *op_result)
+{
+  struct GNUNET_MESH_Handle *mesh = op_result;
+  struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
+
+  GNUNET_free (actx);
+  GNUNET_MESH_disconnect (mesh);
+}
+
+
+/**
+ * Callback to be called when a service connect operation is completed.
+ *
+ * @param cls The callback closure from functions generating an operation.
+ * @param op The operation that has been finished.
+ * @param ca_result The service handle returned from 
+ *                  GNUNET_TESTBED_ConnectAdapter() (mesh handle).
+ * @param emsg Error message in case the operation has failed.
+ *             NULL if operation has executed successfully.
+ */
+static void 
+mesh_connect_cb (void *cls,
+                 struct GNUNET_TESTBED_Operation *op,
+                 void *ca_result,
+                 const char *emsg)
+{
+  struct GNUNET_MESH_TEST_Context *ctx = cls;
+  unsigned int i;
+ 
+  if (NULL != emsg)
+  {
+    fprintf (stderr, "Failed to connect to MESH service: %s\n",
+             emsg);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  for (i = 0; i < ctx->num_peers; i++)
+    if (op == ctx->ops[i])
+      ctx->meshes[i] = ca_result;
+  for (i = 0; i < ctx->num_peers; i++)
+    if (NULL == ctx->meshes[i])
+      return; /* still some MESH connections missing */
+  /* all MESH connections ready! */
+  ctx->app_main (ctx->app_main_cls,
+                 ctx,
+                 ctx->num_peers,
+                 ctx->peers,
+                 ctx->meshes);
+}
+
+
+/**
+ * Clean up the testbed.
+ *
+ * @param ctx handle for the testbed
+ */
+void
+GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx)
+{
+  unsigned int i;
+
+  for (i = 0; i < ctx->num_peers; i++)
+  {
+    GNUNET_assert (NULL != ctx->ops[i]);
+    GNUNET_TESTBED_operation_done (ctx->ops[i]);
+    ctx->ops[i] = NULL;
+  }
+  GNUNET_free (ctx->ops);
+  GNUNET_free (ctx->meshes);
+  GNUNET_free (ctx);
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Callback run when the testbed is ready (peers running and connected to
+ * each other)
+ * 
+ * @param cls Closure (context).
+ * @param num_peers Number of peers that are running.
+ * @param peers Handles to each one of the @c num_peers peers.
+ * @param links_succeeded the number of overlay link connection attempts that
+ *          succeeded
+ * @param links_failed the number of overlay link connection attempts that
+ *          failed
+ */
+static void
+mesh_test_run (void *cls,
+               unsigned int num_peers,
+               struct GNUNET_TESTBED_Peer **peers,
+               unsigned int links_succeeded,
+               unsigned int links_failed)
+{
+  struct GNUNET_MESH_TEST_Context *ctx = cls;
+  unsigned int i;
+
+  GNUNET_assert (num_peers == ctx->num_peers);
+  ctx->peers = peers;
+  for (i = 0; i < num_peers; i++)
+  {
+    struct GNUNET_MESH_TEST_AdapterContext *newctx;
+    newctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_AdapterContext));
+    newctx->peer = i;
+    newctx->ctx = ctx;
+    ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
+                                                  peers[i],
+                                                  "mesh",
+                                                  &mesh_connect_cb,
+                                                  ctx,
+                                                  &mesh_connect_adapter,
+                                                  &mesh_disconnect_adapter,
+                                                  newctx);
+  }
+}
+
+
+/**
+ * Run a test using the given name, configuration file and number of
+ * peers.
+ * All mesh callbacks will receive the peer number as the closure.
+ *
+ * @param testname Name of the test (for logging).
+ * @param cfgname Name of the configuration file.
+ * @param num_peers Number of peers to start.
+ * @param tmain Main function to run once the testbed is ready.
+ * @param tmain_cls Closure for 'tmain'.
+ * @param new_tunnel Handler for incoming tunnels.
+ * @param cleaner Cleaner for destroyed incoming tunnels.
+ * @param handlers Message handlers.
+ * @param stypes Application types.
+ */
+void 
+GNUNET_MESH_TEST_run (const char *testname,
+                      const char *cfgname,
+                      unsigned int num_peers,
+                      GNUNET_MESH_TEST_AppMain tmain,
+                      void *tmain_cls,
+                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
+                      GNUNET_MESH_TunnelEndHandler cleaner,
+                      struct GNUNET_MESH_MessageHandler* handlers,
+                      const GNUNET_MESH_ApplicationType* stypes)
+{
+  struct GNUNET_MESH_TEST_Context *ctx;
+
+  ctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_Context));
+  ctx->num_peers = num_peers;
+  ctx->ops = GNUNET_malloc (num_peers * sizeof (struct 
GNUNET_TESTBED_Operation *));
+  ctx->meshes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_MESH_Handle 
*));
+  ctx->app_main = tmain;
+  ctx->app_main_cls = tmain_cls;
+  ctx->new_tunnel = new_tunnel;
+  ctx->cleaner = cleaner;
+  ctx->handlers = handlers;
+  ctx->stypes = stypes;
+  GNUNET_TESTBED_test_run (testname,
+                           cfgname,
+                           num_peers,
+                           0LL, NULL, NULL,
+                           &mesh_test_run, ctx);
+}
+
+/* end of mesh_test_lib.c */

Added: gnunet/src/mesh/mesh2_test_lib.h
===================================================================
--- gnunet/src/mesh/mesh2_test_lib.h                            (rev 0)
+++ gnunet/src/mesh/mesh2_test_lib.h    2013-06-10 14:38:05 UTC (rev 27402)
@@ -0,0 +1,106 @@
+/*
+     This file is part of GNUnet.
+     (C) 2012 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file mesh/mesh2_test_lib.h
+ * @author Bartlomiej Polot
+ * @brief library for writing MESH tests
+ */
+#ifndef MESH_TEST_LIB_H
+#define MESH_TEST_LIB_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_testbed_service.h"
+#include "gnunet_mesh2_service.h"
+
+/**
+ * Test context for a MESH Test.
+ */
+struct GNUNET_MESH_TEST_Context;
+
+
+/**
+ * Main function of a MESH test.
+ *
+ * @param cls Closure.
+ * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
+ * @param num_peers Number of peers that are running.
+ * @param peers Array of peers.
+ * @param meshes Handle to each of the MESHs of the peers.
+ */
+typedef void (*GNUNET_MESH_TEST_AppMain) (void *cls,
+                                          struct GNUNET_MESH_TEST_Context *ctx,
+                                          unsigned int num_peers,
+                                          struct GNUNET_TESTBED_Peer **peers,
+                                          struct GNUNET_MESH_Handle **meshes);
+
+
+/**
+ * Run a test using the given name, configuration file and number of
+ * peers.
+ * All mesh callbacks will receive the peer number as the closure.
+ *
+ * @param testname Name of the test (for logging).
+ * @param cfgname Name of the configuration file.
+ * @param num_peers Number of peers to start.
+ * @param tmain Main function to run once the testbed is ready.
+ * @param tmain_cls Closure for 'tmain'.
+ * @param new_tunnel Handler for incoming tunnels.
+ * @param cleaner Cleaner for destroyed incoming tunnels.
+ * @param handlers Message handlers.
+ * @param stypes Application types.
+ */
+void 
+GNUNET_MESH_TEST_run (const char *testname,
+                      const char *cfgname,
+                      unsigned int num_peers,
+                      GNUNET_MESH_TEST_AppMain tmain,
+                      void *tmain_cls,
+                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
+                      GNUNET_MESH_TunnelEndHandler cleaner,
+                      struct GNUNET_MESH_MessageHandler* handlers,
+                      const GNUNET_MESH_ApplicationType* stypes);
+
+
+/**
+ * Clean up the testbed.
+ *
+ * @param ctx handle for the testbed
+ */
+void
+GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ifndef MESH_TEST_LIB_H */
+#endif

Added: gnunet/src/mesh/test_mesh2_small.c
===================================================================
--- gnunet/src/mesh/test_mesh2_small.c                          (rev 0)
+++ gnunet/src/mesh/test_mesh2_small.c  2013-06-10 14:38:05 UTC (rev 27402)
@@ -0,0 +1,964 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file mesh/test_mesh2_small.c
+ *
+ * @brief Test for the mesh service: retransmission of traffic.
+ */
+#include <stdio.h>
+#include "platform.h"
+#include "mesh_test_lib.h"
+#include "gnunet_mesh2_service.h"
+#include <gauger.h>
+
+
+/**
+ * How namy messages to send
+ */
+#define TOTAL_PACKETS 1000
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
+
+/**
+ * Time to wait for stuff that should be rather fast
+ */
+#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
+
+/**
+ * DIFFERENT TESTS TO RUN
+ */
+#define SETUP 0
+#define UNICAST 1
+#define SPEED 3
+#define SPEED_ACK 4
+#define SPEED_MIN 5
+#define SPEED_NOBUF 6
+#define P2P_SIGNAL 10
+
+/**
+ * Which test are we running?
+ */
+static int test;
+
+/**
+ * String with test name
+ */
+char *test_name;
+
+/**
+ * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
+ */
+static int test_backwards = GNUNET_NO;
+
+/**
+ * How many events have happened
+ */
+static int ok;
+
+ /**
+  * 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;
+
+
+/**
+ * Size of each test packet
+ */
+size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
+
+/**
+ * Operation to get peer ids.
+ */
+struct GNUNET_TESTBED_Operation *t_op[3];
+
+/**
+ * Peer ids.
+ */
+struct GNUNET_PeerIdentity *p_id[3];
+
+/**
+ * Peer ids counter.
+ */
+unsigned int p_ids;
+
+/**
+ * Is the setup initialized?
+ */
+static int initialized;
+
+/**
+ * Peers that have been connected
+ */
+static int peers_in_tunnel;
+
+/**
+ * Peers that have responded
+ */
+static int peers_responded;
+
+/**
+ * Number of payload packes sent
+ */
+static int data_sent;
+
+/**
+ * Number of payload packets received
+ */
+static int data_received;
+
+/**
+ * Number of payload packed explicitly (app level) acknowledged
+ */
+static int data_ack;
+
+/**
+ * Total number of currently running peers.
+ */
+static unsigned long long peers_running;
+
+/**
+ * Test context (to shut down).
+ */
+struct GNUNET_MESH_TEST_Context *test_ctx;
+
+/**
+ * Task called to disconnect peers.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
+
+/**
+ * Task To perform tests
+ */
+static GNUNET_SCHEDULER_TaskIdentifier test_task;
+
+/**
+ * Task called to shutdown test.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
+
+/**
+ * Mesh handle for the root peer
+ */
+static struct GNUNET_MESH_Handle *h1;
+
+/**
+ * Mesh handle for the first leaf peer
+ */
+static struct GNUNET_MESH_Handle *h2;
+
+/**
+ * Mesh handle for the second leaf peer
+ */
+static struct GNUNET_MESH_Handle *h3;
+
+/**
+ * Tunnel handle for the root peer
+ */
+static struct GNUNET_MESH_Tunnel *t;
+
+/**
+ * Tunnel handle for the first leaf peer
+ */
+static struct GNUNET_MESH_Tunnel *incoming_t;
+
+/**
+ * Tunnel handle for the second leaf peer
+ */
+static struct GNUNET_MESH_Tunnel *incoming_t2;
+
+/**
+ * Time we started the data transmission (after tunnel has been established
+ * and initilized).
+ */
+static struct GNUNET_TIME_Absolute start_time;
+
+
+/**
+ * Show the results of the test (banwidth acheived) and log them to GAUGER
+ */
+static void
+show_end_data (void)
+{
+  static struct GNUNET_TIME_Absolute end_time;
+  static struct GNUNET_TIME_Relative total_time;
+
+  end_time = GNUNET_TIME_absolute_get();
+  total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
+  FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
+  FPRINTF (stderr, "Test time %llu ms\n",
+            (unsigned long long) total_time.rel_value);
+  FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
+            4 * TOTAL_PACKETS * 1.0 / total_time.rel_value); // 4bytes * ms
+  FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
+            TOTAL_PACKETS * 1000.0 / total_time.rel_value); // packets * ms
+  GAUGER ("MESH", test_name,
+          TOTAL_PACKETS * 1000.0 / total_time.rel_value,
+          "packets/s");
+}
+
+
+/**
+ * Shut down peergroup, clean up.
+ * 
+ * @param cls Closure (unused).
+ * @param tc Task Context.
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
+  shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
+}
+
+
+/**
+ * Disconnect from mesh services af all peers, call shutdown.
+ * 
+ * @param cls Closure (unused).
+ * @param tc Task Context.
+ */
+static void
+disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
+{
+  long line = (long) cls;
+  unsigned int i;
+
+  for (i = 0; i < 3; i++)
+    if (NULL != t_op[i])
+    {
+      GNUNET_TESTBED_operation_done (t_op[i]);
+      t_op[i] = NULL;
+    }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "disconnecting mesh service of peers, called from line %ld\n",
+              line);
+  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  if (NULL != t)
+  {
+    GNUNET_MESH_tunnel_destroy (t);
+    t = NULL;
+  }
+  if (NULL != incoming_t)
+  {
+    GNUNET_MESH_tunnel_destroy (incoming_t);
+    incoming_t = NULL;
+  }
+  if (NULL != incoming_t2)
+  {
+    GNUNET_MESH_tunnel_destroy (incoming_t2);
+    incoming_t2 = NULL;
+  }
+  GNUNET_MESH_TEST_cleanup (test_ctx);
+  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
+  {
+    GNUNET_SCHEDULER_cancel (shutdown_handle);
+  }
+  shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+}
+
+
+/**
+ * Abort test: schedule disconnect and shutdown immediately
+ * 
+ * @param line Line in the code the abort is requested from (__LINE__).
+ */
+void
+abort_test (long line)
+{
+  if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  }
+  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                  &disconnect_mesh_peers,
+                                                  (void *) line);
+}
+
+/**
+ * Transmit ready callback.
+ * 
+ * @param cls Closure (message type).
+ * @param size Size of the tranmist buffer.
+ * @param buf Pointer to the beginning of the buffer.
+ * 
+ * @return Number of bytes written to buf.
+ */
+static size_t
+tmt_rdy (void *cls, size_t size, void *buf);
+
+
+/**
+ * Task to schedule a new data transmission.
+ * 
+ * @param cls Closure (peer #).
+ * @param tc Task Context.
+ */
+static void
+data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_MESH_TransmitHandle *th;
+  struct GNUNET_MESH_Tunnel *tunnel;
+  struct GNUNET_PeerIdentity *destination;
+
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n");
+  if (GNUNET_YES == test_backwards)
+  {
+    tunnel = incoming_t;
+    destination = p_id[0];
+  }
+  else
+  {
+    tunnel = t;
+    destination = p_id[2];
+  }
+  th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
+                                          GNUNET_TIME_UNIT_FOREVER_REL,
+                                          destination,
+                                          size_payload,
+                                          &tmt_rdy, (void *) 1L);
+  if (NULL == th)
+  {
+    unsigned long i = (unsigned long) cls;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n");
+    if (0 == i)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "  in 1 ms\n");
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
+                                    &data_task, (void *)1UL);
+    }
+    else
+    {
+      i++;
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i);
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
+                                      GNUNET_TIME_UNIT_MILLISECONDS,
+                                      i),
+                                    &data_task, (void *)i);
+    }
+  }
+}
+
+
+/**
+ * Transmit ready callback
+ *
+ * @param cls Closure (message type).
+ * @param size Size of the buffer we have.
+ * @param buf Buffer to copy data to.
+ */
+size_t
+tmt_rdy (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_MessageHeader *msg = buf;
+  uint32_t *data;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " tmt_rdy called\n");
+  if (size < size_payload || NULL == buf)
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "size %u, buf %p, data_sent %u, data_received %u\n",
+                size,
+                buf,
+                data_sent,
+                data_received);
+    return 0;
+  }
+  msg->size = htons (size);
+  msg->type = htons ((long) cls);
+  data = (uint32_t *) &msg[1];
+  *data = htonl (data_sent);
+  if (SPEED == test && GNUNET_YES == initialized)
+  {
+    data_sent++;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " Sent packet %d\n", data_sent);
+    if (data_sent < TOTAL_PACKETS)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " Scheduling packet %d\n", data_sent + 1);
+      GNUNET_SCHEDULER_add_now(&data_task, NULL);
+    }
+  }
+  return size_payload;
+}
+
+
+/**
+ * Function is called whenever a message is received.
+ *
+ * @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)
+ */
+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)
+{
+  long client = (long) cls;
+  long expected_target_client;
+  uint32_t *data;
+
+  ok++;
+
+  if ((ok % 20) == 0)
+  {
+    if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+    {
+      GNUNET_SCHEDULER_cancel (disconnect_task);
+    }
+    disconnect_task =
+              GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
+                                            (void *) __LINE__);
+  }
+
+  switch (client)
+  {
+  case 0L:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
+    peers_responded++;
+    break;
+  case 3L:
+  case 4L:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Leaf client %li got a message.\n",
+                client);
+    client = 4L;
+    break;
+  default:
+    GNUNET_assert (0);
+    break;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
+  data = (uint32_t *) &message[1];
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data));
+  if (SPEED == test && GNUNET_YES == test_backwards)
+  {
+    expected_target_client = 0L;
+  }
+  else
+  {
+    expected_target_client = 4L;
+  }
+
+  if (GNUNET_NO == initialized)
+  {
+    initialized = GNUNET_YES;
+    start_time = GNUNET_TIME_absolute_get ();
+    if (SPEED == test)
+    {
+      GNUNET_assert (4L == client);
+      GNUNET_SCHEDULER_add_now (&data_task, NULL);
+      return GNUNET_OK;
+    }
+  }
+
+  if (client == expected_target_client) // Normally 3 or 4
+  {
+    data_received++;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                " received data %u\n", data_received);
+    if (SPEED != test || (ok_goal - 2) == ok)
+    {
+      GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
+                                        GNUNET_TIME_UNIT_FOREVER_REL, sender,
+                                               size_payload,
+                                        &tmt_rdy, (void *) 1L);
+      return GNUNET_OK;
+    }
+    else
+    {
+      if (data_received < TOTAL_PACKETS)
+        return GNUNET_OK;
+    }
+  }
+  else // Normally 0
+  {
+    if (test == SPEED_ACK || test == SPEED)
+    {
+      data_ack++;
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              " received ack %u\n", data_ack);
+      GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
+                                        GNUNET_TIME_UNIT_FOREVER_REL, sender,
+                                               size_payload,
+                                        &tmt_rdy, (void *) 1L);
+      if (data_ack < TOTAL_PACKETS && SPEED != test)
+        return GNUNET_OK;
+      if (ok == 2 && SPEED == test)
+        return GNUNET_OK;
+      show_end_data();
+    }
+    if (test == P2P_SIGNAL)
+    {
+      GNUNET_MESH_tunnel_destroy (incoming_t);
+      incoming_t = NULL;
+    }
+    else
+    {
+      GNUNET_MESH_tunnel_destroy (t);
+      t = NULL;
+    }
+  }
+
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  }
+  disconnect_task =
+        GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
+                                      (void *) __LINE__);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * 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 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)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Incoming tunnel from %s to peer %d\n",
+              GNUNET_i2s (initiator), (long) cls);
+  ok++;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
+  if ((long) cls == 4L)
+    incoming_t = tunnel;
+  else if ((long) cls == 3L)
+    incoming_t2 = tunnel;
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Incoming tunnel for unknown client %lu\n", (long) cls);
+    GNUNET_break(0);
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  }
+  disconnect_task =
+        GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
+                                      (void *) __LINE__);
+
+  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
+tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
+                void *tunnel_ctx)
+{
+  long i = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Incoming tunnel disconnected at peer %d\n",
+              i);
+  if (4L == i)
+  {
+    ok++;
+    incoming_t = NULL;
+  }
+  else if (3L == i)
+  {
+    ok++;
+    incoming_t2 = NULL;
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Unknown peer! %d\n", i);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
+  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,
+                                              (void *) __LINE__);
+
+  return;
+}
+
+
+/**
+ * Method called whenever a tunnel falls apart.
+ *
+ * @param cls closure
+ * @param peer peer identity the tunnel stopped working with
+ */
+static void
+dh (void *cls, const struct GNUNET_PeerIdentity *peer)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "peer %s disconnected\n",
+              GNUNET_i2s (peer));
+  if (P2P_SIGNAL == test)
+  {
+    ok ++;
+    if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+    {
+      GNUNET_SCHEDULER_cancel (disconnect_task);
+    }
+    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
+                                                (void *) __LINE__);
+  }
+  return;
+}
+
+
+/**
+ * Method called whenever a peer connects to a tunnel.
+ *
+ * @param cls closure
+ * @param peer peer identity the tunnel was created to, NULL on timeout
+ * @param atsi performance data for the connection
+ */
+static void
+ch (void *cls, const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_ATS_Information *atsi)
+{
+  long i = (long) cls;
+
+  struct GNUNET_PeerIdentity *dest;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "%ld peer %s connected\n", i, GNUNET_i2s (peer));
+
+  if (0 == memcmp (p_id[2], peer, sizeof (struct GNUNET_PeerIdentity)) &&
+      i == 0L)
+  {
+    ok++;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
+  switch (test)
+  {
+    case UNICAST:
+    case P2P_SIGNAL:
+    case SPEED:
+    case SPEED_ACK:
+      // incoming_t is NULL unless we send a relevant data packet
+      dest = p_id[2];
+      break;
+    default:
+      GNUNET_assert (0);
+      return;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task =
+        GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
+                                      (void *) __LINE__);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sending data initializer...\n");
+    peers_responded = 0;
+    data_ack = 0;
+    data_received = 0;
+    data_sent = 0;
+    GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
+                                       GNUNET_TIME_UNIT_FOREVER_REL, dest,
+                                           size_payload,
+                                       &tmt_rdy, (void *) 1L);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Disconnect already run?\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Aborting...\n");
+  }
+  return;
+}
+
+
+/**
+ * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES.
+ * 
+ * Testcase continues when the root receives confirmation of connected peers,
+ * on callback funtion ch.
+ * 
+ * @param cls Closure (unsued).
+ * @param tc Task Context.
+ */
+static void
+do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "add peer 2\n");
+  GNUNET_MESH_peer_request_connect_add (t, p_id[2]);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "schedule timeout in TIMEOUT\n");
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  }
+  disconnect_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+                                                  &disconnect_mesh_peers,
+                                                  (void *) __LINE__);
+}
+
+/**
+ * Callback to be called when the requested peer information is available
+ *
+ * @param cls the closure from GNUNET_TESTBED_peer_get_information()
+ * @param op the operation this callback corresponds to
+ * @param pinfo the result; will be NULL if the operation has failed
+ * @param emsg error message if the operation has failed;
+ *             NULL if the operation is successfull
+ */
+void
+pi_cb (void *cls,
+       struct GNUNET_TESTBED_Operation *op,
+       const struct GNUNET_TESTBED_PeerInformation *pinfo,
+       const char *emsg)
+{
+  long i = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i);
+  if (NULL == pinfo || NULL != emsg)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
+    abort_test (__LINE__);
+    return;
+  }
+  p_id[i] = pinfo->result.id;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  id: %s\n", GNUNET_i2s (p_id[i]));
+  p_ids++;
+  if (p_ids < 2)
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
+  test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                            &do_test, NULL);
+}
+
+/**
+ * test main: start test when all peers are connected
+ *
+ * @param cls Closure.
+ * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
+ * @param num_peers Number of peers that are running.
+ * @param peers Array of peers.
+ * @param meshes Handle to each of the MESHs of the peers.
+ */
+static void
+tmain (void *cls,
+       struct GNUNET_MESH_TEST_Context *ctx,
+       unsigned int num_peers,
+       struct GNUNET_TESTBED_Peer **peers,
+       struct GNUNET_MESH_Handle **meshes)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
+  ok = 0;
+  test_ctx = ctx;
+  peers_running = num_peers;
+  h1 = meshes[0];
+  h2 = meshes[num_peers - 1];
+  t = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, (void *) 0L);
+  if (SPEED_MIN == test)
+  {
+    GNUNET_MESH_tunnel_speed_min(t);
+    test = SPEED;
+  }
+  if (SPEED_NOBUF == test)
+  {
+    GNUNET_MESH_tunnel_buffer(t, GNUNET_NO);
+    test = SPEED;
+  }
+  peers_in_tunnel = 0;
+  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                  &disconnect_mesh_peers,
+                                                  (void *) __LINE__);
+  shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                                  &shutdown_task, NULL);
+  t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
+                                                 GNUNET_TESTBED_PIT_IDENTITY,
+                                                 &pi_cb, (void *) 0L);
+  t_op[2] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
+                                                 GNUNET_TESTBED_PIT_IDENTITY,
+                                                 &pi_cb, (void *) 2L);
+  t_op[1] = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
+}
+
+
+/**
+ * Main: start test
+ */
+int
+main (int argc, char *argv[])
+{
+  initialized = GNUNET_NO;
+
+  GNUNET_log_setup ("test", "DEBUG", NULL);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n");
+  if (strstr (argv[0], "test_mesh2_small_forward") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNICAST\n");
+    test = UNICAST;
+    test_name = "unicast";
+    ok_goal = 5;
+  }
+  else if (strstr (argv[0], "test_mesh_small_signal") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
+    test = P2P_SIGNAL;
+    test_name = "signal";
+    ok_goal = 5;
+  }
+  else if (strstr (argv[0], "test_mesh_small_speed_ack") != NULL)
+  {
+   /* Each peer is supposed to generate the following callbacks:
+    * 1 incoming tunnel (@dest)
+    * 1 connected peer (@orig)
+    * TOTAL_PACKETS received data packet (@dest)
+    * TOTAL_PACKETS received data packet (@orig)
+    * 1 received tunnel destroy (@dest)
+    * _________________________________
+    * 5 x ok expected per peer
+    */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
+    test = SPEED_ACK;
+    test_name = "speed ack";
+    ok_goal = TOTAL_PACKETS * 2 + 3;
+  }
+  else if (strstr (argv[0], "test_mesh_small_speed") != NULL)
+  {
+   /* Each peer is supposed to generate the following callbacks:
+    * 1 incoming tunnel (@dest)
+    * 1 connected peer (@orig)
+    * 1 initial packet (@dest)
+    * TOTAL_PACKETS received data packet (@dest)
+    * 1 received data packet (@orig)
+    * 1 received tunnel destroy (@dest)
+    * _________________________________
+    */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
+    ok_goal = TOTAL_PACKETS + 5;
+    if (strstr (argv[0], "_min") != NULL)
+    {
+      test = SPEED_MIN;
+      test_name = "speed min";
+    }
+    else if (strstr (argv[0], "_nobuf") != NULL)
+    {
+      test = SPEED_NOBUF;
+      test_name = "speed nobuf";
+    }
+    else
+    {
+      test = SPEED;
+      test_name = "speed";
+    }
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
+    test = SETUP;
+    ok_goal = 0;
+  }
+
+  if (strstr (argv[0], "backwards") != NULL)
+  {
+    char *aux;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
+    test_backwards = GNUNET_YES;
+    aux = GNUNET_malloc (32);
+    sprintf (aux, "backwards %s", test_name);
+    test_name = aux;
+  }
+
+  p_ids = 0;
+  GNUNET_MESH_TEST_run ("test_mesh_small",
+                        "test_mesh_small.conf",
+                        5,
+                        &tmain,
+                        NULL,
+                        &incoming_tunnel,
+                        &tunnel_cleaner,
+                        handlers,
+                        NULL);
+
+  if (ok_goal > ok)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "FAILED! (%d/%d)\n", ok, ok_goal);
+    return 1;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
+  return 0;
+}
+
+/* end of test_mesh_small.c */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]