gnunet-svn
[Top][All Lists]
Advanced

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

[gnunet] branch master updated: -start TNG transport test logic


From: gnunet
Subject: [gnunet] branch master updated: -start TNG transport test logic
Date: Mon, 30 Nov 2020 10:08:47 +0100

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new 172ef59b9 -start TNG transport test logic
172ef59b9 is described below

commit 172ef59b934c067dd7ec8e72650e196c7ae2a04b
Author: Martin Schanzenbach <schanzen@gnunet.org>
AuthorDate: Mon Nov 30 18:08:25 2020 +0900

    -start TNG transport test logic
---
 src/transport/Makefile.am          |   5 +
 src/transport/transport-testing2.c | 923 ++++++++++++++++++++++++++++++++++++
 src/transport/transport-testing2.h | 924 +++++++++++++++++++++++++++++++++++++
 3 files changed, 1852 insertions(+)

diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 477973af9..605d89cc0 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -168,10 +168,15 @@ libgnunettransporttesting_la_LDFLAGS = \
  $(GN_LIB_LDFLAGS)
 
 libgnunettransporttesting2_la_SOURCES = \
+  transport-testing2.c transport-testing2.h \
   transport-testing-communicator.c transport-testing-communicator.h
 libgnunettransporttesting2_la_LIBADD = \
   libgnunettransport.la \
+  libgnunettransportapplication.la \
+  libgnunettransportcore.la \
+  $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/hello/libgnunethello.la \
+  $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
   $(top_builddir)/src/util/libgnunetutil.la
 libgnunettransporttesting2_la_LDFLAGS = \
   $(GN_LIBINTL) \
diff --git a/src/transport/transport-testing2.c 
b/src/transport/transport-testing2.c
new file mode 100644
index 000000000..ca338c52f
--- /dev/null
+++ b/src/transport/transport-testing2.c
@@ -0,0 +1,923 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2006, 2009, 2015, 2016 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file transport-testing.c
+ * @brief testing lib for transport service
+ * @author Matthias Wachs
+ * @author Christian Grothoff
+ */
+#include "transport-testing2.h"
+
+
+#define LOG(kind, ...) GNUNET_log_from (kind, "transport-testing", __VA_ARGS__)
+
+
+static struct GNUNET_TRANSPORT_TESTING_PeerContext *
+find_peer_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth,
+                   const struct GNUNET_PeerIdentity *peer)
+{
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *t;
+
+  for (t = tth->p_head; NULL != t; t = t->next)
+    if (0 == memcmp (&t->id,
+                     peer,
+                     sizeof(struct GNUNET_PeerIdentity)))
+      return t;
+  return NULL;
+}
+
+
+/**
+ * Find any connecting context matching the given pair of peers.
+ *
+ * @param p1 first peer
+ * @param p2 second peer
+ * @param cb function to call
+ * @param cb_cls closure for @a cb
+ */
+void
+GNUNET_TRANSPORT_TESTING_find_connecting_context (struct
+                                                  
GNUNET_TRANSPORT_TESTING_PeerContext
+                                                  *p1,
+                                                  struct
+                                                  
GNUNET_TRANSPORT_TESTING_PeerContext
+                                                  *p2,
+                                                  
GNUNET_TRANSPORT_TESTING_ConnectContextCallback
+                                                  cb,
+                                                  void *cb_cls)
+{
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
+
+  for (cc = tth->cc_head; NULL != cc; cc = ccn)
+  {
+    ccn = cc->next;
+    if ((cc->p1 == p1) &&
+        (cc->p2 == p2))
+      cb (cb_cls,
+          cc);
+  }
+}
+
+
+static void
+set_p1c (void *cls,
+         struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
+{
+  int *found = cls;
+
+  if (NULL != found)
+    *found = GNUNET_YES;
+  cx->p1_c = GNUNET_YES;
+}
+
+
+static void
+set_mq (void *cls,
+        struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
+{
+  struct GNUNET_MQ_Handle *mq = cls;
+
+  cx->mq = mq;
+}
+
+
+static void
+set_p2c (void *cls,
+         struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
+{
+  int *found = cls;
+
+  if (NULL != found)
+    *found = GNUNET_YES;
+  cx->p2_c = GNUNET_YES;
+}
+
+
+static void
+clear_p1c (void *cls,
+           struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
+{
+  int *found = cls;
+
+  if (NULL != found)
+    *found = GNUNET_YES;
+  cx->p1_c = GNUNET_NO;
+}
+
+
+static void
+clear_p2c (void *cls,
+           struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
+{
+  int *found = cls;
+
+  if (NULL != found)
+    *found = GNUNET_YES;
+  cx->p2_c = GNUNET_NO;
+}
+
+
+static void *
+notify_connect (void *cls,
+                const struct GNUNET_PeerIdentity *peer,
+                struct GNUNET_MQ_Handle *mq)
+{
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
+  char *p2_s;
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
+  int found;
+  void *ret;
+
+  p2 = find_peer_context (p->tth,
+                          peer);
+  if (NULL != p->nc)
+    ret = p->nc (p->cb_cls,
+                 peer,
+                 mq);
+  else
+    ret = NULL;
+
+  if (NULL != p2)
+    GNUNET_asprintf (&p2_s,
+                     "%u (`%s')",
+                     p2->no,
+                     GNUNET_i2s (&p2->id));
+  else
+    GNUNET_asprintf (&p2_s,
+                     "`%s'",
+                     GNUNET_i2s (peer));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Peers %s connected to peer %u (`%s')\n",
+       p2_s,
+       p->no,
+       GNUNET_i2s (&p->id));
+  GNUNET_free (p2_s);
+  /* update flags in connecting contexts */
+  found = GNUNET_NO;
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
+                                                    p2,
+                                                    &set_p1c,
+                                                    &found);
+  if (GNUNET_NO == found)
+  {
+    cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
+    cc->p1 = p;
+    cc->p2 = p2;
+    cc->p1_c = GNUNET_YES;
+    GNUNET_CONTAINER_DLL_insert (tth->cc_head,
+                                 tth->cc_tail,
+                                 cc);
+  }
+  found = GNUNET_NO;
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
+                                                    p,
+                                                    &set_p2c,
+                                                    &found);
+  if (GNUNET_NO == found)
+  {
+    cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
+    cc->p1 = p2;
+    cc->p2 = p;
+    cc->p1_c = GNUNET_YES;
+    GNUNET_CONTAINER_DLL_insert (tth->cc_head,
+                                 tth->cc_tail,
+                                 cc);
+  }
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
+                                                    p2,
+                                                    &set_mq,
+                                                    mq);
+  /* update set connected flag for all requests */
+  for (cc = tth->cc_head; NULL != cc; cc = cc->next)
+  {
+    if (GNUNET_YES == cc->connected)
+      continue;
+    if ((GNUNET_YES == cc->p1_c) &&
+        (GNUNET_YES == cc->p2_c))
+    {
+      cc->connected = GNUNET_YES;
+      /* stop trying to connect */
+      if (NULL != cc->tct)
+      {
+        GNUNET_SCHEDULER_cancel (cc->tct);
+        cc->tct = NULL;
+      }
+      if (NULL != cc->ats_sh)
+      {
+        GNUNET_ATS_connectivity_suggest_cancel (cc->ats_sh);
+        cc->ats_sh = NULL;
+      }
+    }
+  }
+  /* then notify application */
+  for (cc = tth->cc_head; NULL != cc; cc = ccn)
+  {
+    ccn = cc->next;
+    if ((GNUNET_YES == cc->connected) &&
+        (NULL != cc->cb))
+    {
+      cc->cb (cc->cb_cls);
+      cc->cb = NULL;     /* only notify once! */
+    }
+  }
+  return ret;
+}
+
+
+/**
+ * Offer the current HELLO of P2 to P1.
+ *
+ * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
+ */
+static void
+offer_hello (void *cls);
+
+
+static void
+notify_disconnect (void *cls,
+                   const struct GNUNET_PeerIdentity *peer,
+                   void *handler_cls)
+{
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
+  char *p2_s;
+  /* Find PeerContext */
+  int no = 0;
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = NULL;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+
+  p2 = find_peer_context (p->tth,
+                          peer);
+  no = p->no;
+  if (NULL != p2)
+    GNUNET_asprintf (&p2_s,
+                     "%u (`%s')",
+                     p2->no,
+                     GNUNET_i2s (&p2->id));
+  else
+    GNUNET_asprintf (&p2_s,
+                     "`%s'",
+                     GNUNET_i2s (peer));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Peers %s disconnected from peer %u (`%s')\n",
+       p2_s,
+       no,
+       GNUNET_i2s (&p->id));
+  GNUNET_free (p2_s);
+  /* notify about disconnect */
+  if (NULL != p->nd)
+    p->nd (p->cb_cls,
+           peer,
+           handler_cls);
+  if (NULL == p2)
+    return;
+  /* clear MQ, it is now invalid */
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
+                                                    p2,
+                                                    &set_mq,
+                                                    NULL);
+  /* update set connected flags for all requests */
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
+                                                    p2,
+                                                    &clear_p1c,
+                                                    NULL);
+  GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
+                                                    p,
+                                                    &clear_p2c,
+                                                    NULL);
+  /* resume connectivity requests as necessary */
+  for (cc = tth->cc_head; NULL != cc; cc = cc->next)
+  {
+    if (GNUNET_NO == cc->connected)
+      continue;
+    if ((GNUNET_YES != cc->p1_c) ||
+        (GNUNET_YES != cc->p2_c))
+    {
+      cc->connected = GNUNET_NO;
+      /* start trying to connect */
+      if (NULL == cc->tct)
+        cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
+                                            cc);
+      if (NULL == cc->ats_sh)
+        cc->ats_sh = GNUNET_ATS_connectivity_suggest (cc->p1->ats,
+                                                      &p2->id,
+                                                      1);
+    }
+  }
+}
+
+
+static void
+hello_iter_cb (void *cb_cls,
+               const struct GNUNET_PEERSTORE_Record *record,
+               const char *emsg)
+{
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cb_cls;
+  //Check record type et al?
+  p->hello = GNUNET_malloc (record->value_size);
+  memcpy (p->hello, record->value, record->value_size);
+
+  GNUNET_PEERSTORE_iterate_cancel (p->pic);
+  if (NULL != p->start_cb)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Peer %u (`%s') successfully started\n",
+         p->no,
+         GNUNET_i2s (&p->id));
+    p->start_cb (p->start_cb_cls);
+    p->start_cb = NULL;
+  }
+}
+
+
+/**
+ * Start a peer with the given configuration
+ * @param tth the testing handle
+ * @param cfgname configuration file
+ * @param peer_id a unique number to identify the peer
+ * @param handlers functions for receiving messages
+ * @param nc connect callback
+ * @param nd disconnect callback
+ * @param cb_cls closure for callback
+ * @param start_cb start callback
+ * @param start_cb_cls closure for callback
+ * @return the peer context
+ */
+struct GNUNET_TRANSPORT_TESTING_PeerContext *
+GNUNET_TRANSPORT_TESTING_start_peer (struct
+                                     GNUNET_TRANSPORT_TESTING_Handle *tth,
+                                     const char *cfgname,
+                                     int peer_id,
+                                     const struct
+                                     GNUNET_MQ_MessageHandler *handlers,
+                                     GNUNET_TRANSPORT_NotifyConnect nc,
+                                     GNUNET_TRANSPORT_NotifyDisconnect nd,
+                                     void *cb_cls,
+                                     GNUNET_SCHEDULER_TaskCallback start_cb,
+                                     void *start_cb_cls)
+{
+  char *emsg = NULL;
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
+  struct GNUNET_PeerIdentity dummy;
+  unsigned int i;
+
+  if (GNUNET_NO == GNUNET_DISK_file_test (cfgname))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "File not found: `%s'\n",
+         cfgname);
+    return NULL;
+  }
+
+  p = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_PeerContext);
+  p->tth = tth;
+  p->nc = nc;
+  p->nd = nd;
+  if (NULL != handlers)
+  {
+    for (i = 0; NULL != handlers[i].cb; i++)
+      ;
+    p->handlers = GNUNET_new_array (i + 1,
+                                    struct GNUNET_MQ_MessageHandler);
+    GNUNET_memcpy (p->handlers,
+                   handlers,
+                   i * sizeof(struct GNUNET_MQ_MessageHandler));
+  }
+  if (NULL != cb_cls)
+    p->cb_cls = cb_cls;
+  else
+    p->cb_cls = p;
+  p->start_cb = start_cb;
+  if (NULL != start_cb_cls)
+    p->start_cb_cls = start_cb_cls;
+  else
+    p->start_cb_cls = p;
+  GNUNET_CONTAINER_DLL_insert (tth->p_head,
+                               tth->p_tail,
+                               p);
+
+  /* Create configuration and call testing lib to modify it */
+  p->cfg = GNUNET_CONFIGURATION_create ();
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_load (p->cfg, cfgname));
+  if (GNUNET_SYSERR ==
+      GNUNET_TESTING_configuration_create (tth->tl_system,
+                                           p->cfg))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Testing library failed to create unique configuration based on 
`%s'\n",
+         cfgname);
+    GNUNET_CONFIGURATION_destroy (p->cfg);
+    GNUNET_free (p);
+    return NULL;
+  }
+
+  p->no = peer_id;
+  /* Configure peer with configuration */
+  p->peer = GNUNET_TESTING_peer_configure (tth->tl_system,
+                                           p->cfg,
+                                           p->no,
+                                           NULL,
+                                           &emsg);
+  if (NULL == p->peer)
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Testing library failed to create unique configuration based on `%s': 
`%s'\n",
+         cfgname,
+         emsg);
+    GNUNET_TRANSPORT_TESTING_stop_peer (p);
+    GNUNET_free (emsg);
+    return NULL;
+  }
+  GNUNET_free (emsg);
+  if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Testing library failed to create unique configuration based on 
`%s'\n",
+         cfgname);
+    GNUNET_TRANSPORT_TESTING_stop_peer (p);
+    return NULL;
+  }
+
+  memset (&dummy,
+          '\0',
+          sizeof(dummy));
+  GNUNET_TESTING_peer_get_identity (p->peer,
+                                    &p->id);
+  if (0 == memcmp (&dummy,
+                   &p->id,
+                   sizeof(struct GNUNET_PeerIdentity)))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Testing library failed to obtain peer identity for peer %u\n",
+         p->no);
+    GNUNET_TRANSPORT_TESTING_stop_peer (p);
+    return NULL;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Peer %u configured with identity `%s'\n",
+       p->no,
+       GNUNET_i2s_full (&p->id));
+  p->tmh = GNUNET_TRANSPORT_manipulation_connect (p->cfg);
+  p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
+                                         NULL,
+                                         handlers,
+                                         p,
+                                         &notify_connect,
+                                         &notify_disconnect);
+  if ((NULL == p->th) ||
+      (NULL == p->tmh))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Failed to connect to transport service for peer `%s': `%s'\n",
+         cfgname,
+         emsg);
+    GNUNET_TRANSPORT_TESTING_stop_peer (p);
+    return NULL;
+  }
+  p->ats = GNUNET_ATS_connectivity_init (p->cfg);
+  if (NULL == p->ats)
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Failed to connect to ATS service for peer `%s': `%s'\n",
+         cfgname,
+         emsg);
+    GNUNET_TRANSPORT_TESTING_stop_peer (p);
+    return NULL;
+  }
+  p->pic = GNUNET_PEERSTORE_iterate (p->ph,
+                                     "transport",
+                                     &p->id,
+                                     GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
+                                     hello_iter_cb,
+                                     p);
+  GNUNET_assert (NULL != p->pic);
+
+  return p;
+}
+
+
+/**
+ * Stops and restarts the given peer, sleeping (!) for 5s in between.
+ *
+ * @param p the peer
+ * @param restart_cb callback to call when restarted
+ * @param restart_cb_cls callback closure
+ * @return #GNUNET_OK in success otherwise #GNUNET_SYSERR
+ */
+int
+GNUNET_TRANSPORT_TESTING_restart_peer (struct
+                                       GNUNET_TRANSPORT_TESTING_PeerContext *p,
+                                       GNUNET_SCHEDULER_TaskCallback 
restart_cb,
+                                       void *restart_cb_cls)
+{
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
+
+  /* shutdown */
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Stopping peer %u (`%s')\n",
+       p->no,
+       GNUNET_i2s (&p->id));
+  if (NULL != p->pic)
+  {
+    GNUNET_PEERSTORE_iterate_cancel (p->pic);
+    p->pic = NULL;
+  }
+  if (NULL != p->th)
+  {
+    GNUNET_TRANSPORT_core_disconnect (p->th);
+    p->th = NULL;
+  }
+  if (NULL != p->tmh)
+  {
+    GNUNET_TRANSPORT_manipulation_disconnect (p->tmh);
+    p->tmh = NULL;
+  }
+  for (cc = p->tth->cc_head; NULL != cc; cc = ccn)
+  {
+    ccn = cc->next;
+    if ((cc->p1 == p) ||
+        (cc->p2 == p))
+      GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
+  }
+  if (NULL != p->ats)
+  {
+    GNUNET_ATS_connectivity_done (p->ats);
+    p->ats = NULL;
+  }
+  if (GNUNET_SYSERR ==
+      GNUNET_TESTING_peer_stop (p->peer))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Failed to stop peer %u (`%s')\n",
+         p->no,
+         GNUNET_i2s (&p->id));
+    return GNUNET_SYSERR;
+  }
+
+  sleep (5);  // YUCK!
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Restarting peer %u (`%s')\n",
+       p->no,
+       GNUNET_i2s (&p->id));
+  /* restart */
+  if (GNUNET_SYSERR == GNUNET_TESTING_peer_start (p->peer))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Failed to restart peer %u (`%s')\n",
+         p->no,
+         GNUNET_i2s (&p->id));
+    return GNUNET_SYSERR;
+  }
+
+  GNUNET_assert (NULL == p->start_cb);
+  p->start_cb = restart_cb;
+  p->start_cb_cls = restart_cb_cls;
+
+  p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
+                                         NULL,
+                                         p->handlers,
+                                         p,
+                                         &notify_connect,
+                                         &notify_disconnect);
+  GNUNET_assert (NULL != p->th);
+  p->ats = GNUNET_ATS_connectivity_init (p->cfg);
+  p->pic = GNUNET_PEERSTORE_iterate (p->ph,
+                                     "transport",
+                                     &p->id,
+                                     GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
+                                     hello_iter_cb,
+                                     p);
+  GNUNET_assert (NULL != p->pic);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Shutdown the given peer
+ *
+ * @param p the peer
+ */
+void
+GNUNET_TRANSPORT_TESTING_stop_peer (struct
+                                    GNUNET_TRANSPORT_TESTING_PeerContext *p)
+{
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
+
+  for (cc = tth->cc_head; NULL != cc; cc = ccn)
+  {
+    ccn = cc->next;
+    if ((cc->p1 == p) ||
+        (cc->p2 == p))
+      GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
+  }
+  if (NULL != p->pic)
+  {
+    GNUNET_PEERSTORE_iterate_cancel (p->pic);
+    p->pic = NULL;
+  }
+  if (NULL != p->tmh)
+  {
+    GNUNET_TRANSPORT_manipulation_disconnect (p->tmh);
+    p->tmh = NULL;
+  }
+  if (NULL != p->th)
+  {
+    GNUNET_TRANSPORT_core_disconnect (p->th);
+    p->th = NULL;
+  }
+  if (NULL != p->peer)
+  {
+    if (GNUNET_OK !=
+        GNUNET_TESTING_peer_stop (p->peer))
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Testing lib failed to stop peer %u (`%s')\n",
+           p->no,
+           GNUNET_i2s (&p->id));
+    }
+    GNUNET_TESTING_peer_destroy (p->peer);
+    p->peer = NULL;
+  }
+  if (NULL != p->ats)
+  {
+    GNUNET_ATS_connectivity_done (p->ats);
+    p->ats = NULL;
+  }
+  if (NULL != p->hello)
+  {
+    GNUNET_free (p->hello);
+    p->hello = NULL;
+  }
+  if (NULL != p->cfg)
+  {
+    GNUNET_CONFIGURATION_destroy (p->cfg);
+    p->cfg = NULL;
+  }
+  if (NULL != p->handlers)
+  {
+    GNUNET_free (p->handlers);
+    p->handlers = NULL;
+  }
+  GNUNET_CONTAINER_DLL_remove (tth->p_head,
+                               tth->p_tail,
+                               p);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Peer %u (`%s') stopped\n",
+       p->no,
+       GNUNET_i2s (&p->id));
+  GNUNET_free (p);
+}
+
+
+/**
+ * Function called after the HELLO was passed to the
+ * transport service.
+ * FIXME maybe schedule the application_validate somehow
+ */
+/*
+static void
+hello_offered (void *cls)
+{
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
+
+  cc->oh = NULL;
+  cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                          &offer_hello,
+                                          cc);
+}*/
+
+
+/**
+ * Offer the current HELLO of P2 to P1.
+ *
+ * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
+ */
+static void
+offer_hello (void *cls)
+{
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p1 = cc->p1;
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = cc->p2;
+  struct GNUNET_TIME_Absolute t;
+  enum GNUNET_NetworkType nt;
+  char *addr;
+
+  cc->tct = NULL;
+  {
+    char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id));
+
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO 
with %s\n",
+         p1->no,
+         GNUNET_i2s (&p1->id),
+         p2->no,
+         p2_s,
+         cc->p2->hello);
+    GNUNET_free (p2_s);
+  }
+
+  addr = GNUNET_HELLO_extract_address (cc->p2->hello,
+                                       cc->p2->hello_size,
+                                       &cc->p2->id,
+                                       &nt,
+                                       &t);
+  GNUNET_assert (NULL == addr);
+  GNUNET_TRANSPORT_application_validate (cc->p1->ah,
+                                         &cc->p2->id,
+                                         nt,
+                                         addr);
+  GNUNET_free (addr);
+}
+
+
+/**
+ * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message
+ *
+ * Remarks: start_peer's notify_connect callback can be called before.
+ *
+ * @param tth transport testing handle
+ * @param p1 peer 1
+ * @param p2 peer 2
+ * @param cb the callback to call when both peers notified that they are 
connected
+ * @param cls callback cls
+ * @return a connect request handle
+ */
+struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
+GNUNET_TRANSPORT_TESTING_connect_peers (struct
+                                        GNUNET_TRANSPORT_TESTING_PeerContext 
*p1,
+                                        struct
+                                        GNUNET_TRANSPORT_TESTING_PeerContext 
*p2,
+                                        GNUNET_SCHEDULER_TaskCallback cb,
+                                        void *cls)
+{
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
+
+  ccn = NULL;
+  for (cc = tth->cc_head; NULL != cc; cc = cc->next)
+  {
+    if ((cc->p1 == p1) &&
+        (cc->p2 == p2))
+    {
+      ccn = cc;
+      break;
+    }
+  }
+
+  cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
+  cc->p1 = p1;
+  cc->p2 = p2;
+  cc->cb = cb;
+  if (NULL != cls)
+    cc->cb_cls = cls;
+  else
+    cc->cb_cls = cc;
+  if (NULL != ccn)
+  {
+    cc->p1_c = ccn->p1_c;
+    cc->p2_c = ccn->p2_c;
+    cc->connected = ccn->connected;
+  }
+  GNUNET_CONTAINER_DLL_insert (tth->cc_head,
+                               tth->cc_tail,
+                               cc);
+  cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
+                                      cc);
+  cc->ats_sh = GNUNET_ATS_connectivity_suggest (cc->p1->ats,
+                                                &p2->id,
+                                                1);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "New connect request %p\n",
+       cc);
+  return cc;
+}
+
+
+/**
+ * Cancel the request to connect two peers
+ * Tou MUST cancel the request if you stop the peers before the peers 
connected succesfully
+ *
+ * @param tth transport testing handle
+ * @param cc a connect request handle
+ */
+void
+GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct
+                                               
GNUNET_TRANSPORT_TESTING_ConnectRequest
+                                               *cc)
+{
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth = cc->p1->tth;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Canceling connect request!\n");
+  if (NULL != cc->tct)
+  {
+    GNUNET_SCHEDULER_cancel (cc->tct);
+    cc->tct = NULL;
+  }
+  if (NULL != cc->ats_sh)
+  {
+    GNUNET_ATS_connectivity_suggest_cancel (cc->ats_sh);
+    cc->ats_sh = NULL;
+  }
+  GNUNET_CONTAINER_DLL_remove (tth->cc_head,
+                               tth->cc_tail,
+                               cc);
+  GNUNET_free (cc);
+}
+
+
+/**
+ * Clean up the transport testing
+ *
+ * @param tth transport testing handle
+ */
+void
+GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth)
+{
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ct;
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *t;
+
+  if (NULL == tth)
+    return;
+  cc = tth->cc_head;
+  while (NULL != cc)
+  {
+    ct = cc->next;
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Developer forgot to cancel connect request!\n");
+    GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
+    cc = ct;
+  }
+  p = tth->p_head;
+  while (NULL != p)
+  {
+    t = p->next;
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Developer forgot to stop peer!\n");
+    GNUNET_TRANSPORT_TESTING_stop_peer (p);
+    p = t;
+  }
+  GNUNET_TESTING_system_destroy (tth->tl_system,
+                                 GNUNET_YES);
+
+  GNUNET_free (tth);
+}
+
+
+/**
+ * Initialize the transport testing
+ *
+ * @return transport testing handle
+ */
+struct GNUNET_TRANSPORT_TESTING_Handle *
+GNUNET_TRANSPORT_TESTING_init ()
+{
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth;
+
+  tth = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_Handle);
+  tth->tl_system = GNUNET_TESTING_system_create ("transport-testing",
+                                                 NULL,
+                                                 NULL,
+                                                 NULL);
+  if (NULL == tth->tl_system)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to initialize testing library!\n");
+    GNUNET_free (tth);
+    return NULL;
+  }
+  return tth;
+}
+
+
+/* end of transport-testing.c */
diff --git a/src/transport/transport-testing2.h 
b/src/transport/transport-testing2.h
new file mode 100644
index 000000000..3554436d8
--- /dev/null
+++ b/src/transport/transport-testing2.h
@@ -0,0 +1,924 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2006, 2009, 2015, 2016 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file transport-testing.h
+ * @brief testing lib for transport service
+ * @author Matthias Wachs
+ * @author Christian Grothoff
+ */
+#ifndef TRANSPORT_TESTING_H
+#define TRANSPORT_TESTING_H
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_hello_lib.h"
+#include "gnunet_peerstore_service.h"
+#include "gnunet_transport_core_service.h"
+#include "gnunet_transport_application_service.h"
+#include "gnunet_transport_manipulation_service.h"
+#include "gnunet_testing_lib.h"
+
+
+/* ************* Basic functions for starting/stopping/connecting *********** 
*/
+
+/**
+ * Context for a single peer
+ */
+struct GNUNET_TRANSPORT_TESTING_PeerContext;
+
+/**
+ * Definition for a transport testing handle
+ */
+struct GNUNET_TRANSPORT_TESTING_Handle;
+
+
+/**
+ * Context for a single peer
+ */
+struct GNUNET_TRANSPORT_TESTING_PeerContext
+{
+  /**
+   * Next element in the DLL
+   */
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *next;
+
+  /**
+   * Previous element in the DLL
+   */
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *prev;
+
+  /**
+   * Transport testing handle this peer belongs to
+   */
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth;
+
+  /**
+   * Application handle
+   */
+  struct GNUNET_TRANSPORT_ApplicationHandle *ah;
+
+  /**
+   * Peer's configuration
+   */
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Peer's transport service handle
+   */
+  struct GNUNET_TRANSPORT_CoreHandle *th;
+
+  /**
+   * Peer's transport service manipulation handle
+   */
+  struct GNUNET_TRANSPORT_ManipulationHandle *tmh;
+
+  /**
+   * Peer's ATS handle.
+   */
+  struct GNUNET_ATS_ConnectivityHandle *ats;
+
+  /**
+   * Peer's PEERSTORE Handle
+   */
+  struct GNUNET_PEERSTORE_Handle *ph;
+
+  /**
+   * Peer's transport get hello handle to retrieve peer's HELLO message
+   */
+  struct GNUNET_PEERSTORE_IterateContext *pic;
+
+  /**
+   * Hello
+   */
+  char *hello;
+
+  /**
+   * Hello size
+   */
+  size_t hello_size;
+
+  /**
+   * Peer's testing handle
+   */
+  struct GNUNET_TESTING_Peer *peer;
+
+  /**
+   * Peer identity
+   */
+  struct GNUNET_PeerIdentity id;
+
+  /**
+   * Handle for the peer's ARM process
+   */
+  struct GNUNET_OS_Process *arm_proc;
+
+  /**
+   * Receive callback
+   */
+  struct GNUNET_MQ_MessageHandler *handlers;
+
+  /**
+   * Notify connect callback
+   */
+  GNUNET_TRANSPORT_NotifyConnect nc;
+
+  /**
+   * Notify disconnect callback
+   */
+  GNUNET_TRANSPORT_NotifyDisconnect nd;
+
+  /**
+   * Startup completed callback
+   */
+  GNUNET_SCHEDULER_TaskCallback start_cb;
+
+  /**
+   * Closure for the @a nc and @a nd callbacks
+   */
+  void *cb_cls;
+
+  /**
+   * Closure for @e start_cb.
+   */
+  void *start_cb_cls;
+
+  /**
+   * An unique number to identify the peer
+   */
+  unsigned int no;
+};
+
+
+/**
+ * Handle for a request to connect two peers.
+ */
+struct GNUNET_TRANSPORT_TESTING_ConnectRequest
+{
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *prev;
+
+  /**
+   * Peer we want to connect.
+   */
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p1;
+
+  /**
+   * Peer we want to connect.
+   */
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
+
+  /**
+   * Task by which we accomplish the connection.
+   */
+  struct GNUNET_SCHEDULER_Task *tct;
+
+  /**
+   * Handle by which we ask ATS to faciliate the connection.
+   */
+  struct GNUNET_ATS_ConnectivitySuggestHandle *ats_sh;
+
+  /**
+   * Function to call upon completion.
+   */
+  GNUNET_SCHEDULER_TaskCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Message queue for sending from @a p1 to @a p2.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Set if peer1 says the connection is up to peer2.
+   */
+  int p1_c;
+
+  /**
+   * Set if peer2 says the connection is up to peer1.
+   */
+  int p2_c;
+
+  /**
+   * #GNUNET_YES if both @e p1_c and @e p2_c are #GNUNET_YES.
+   */
+  int connected;
+};
+
+
+/**
+ * Handle for a test run.
+ */
+struct GNUNET_TRANSPORT_TESTING_Handle
+{
+  /**
+   * Testing library system handle
+   */
+  struct GNUNET_TESTING_System *tl_system;
+
+  /**
+   * head DLL of connect contexts
+   */
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_head;
+
+  /**
+   * head DLL of connect contexts
+   */
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_tail;
+
+  /**
+   * head DLL of peers
+   */
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p_head;
+
+  /**
+   * tail DLL of peers
+   */
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p_tail;
+};
+
+
+/**
+ * Initialize the transport testing
+ *
+ * @return transport testing handle
+ */
+struct GNUNET_TRANSPORT_TESTING_Handle *
+GNUNET_TRANSPORT_TESTING_init (void);
+
+
+/**
+ * Clean up the transport testing
+ *
+ * @param tth transport testing handle
+ */
+void
+GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth);
+
+
+/**
+ * Start a peer with the given configuration
+ *
+ * @param tth the testing handle
+ * @param cfgname configuration file
+ * @param peer_id the peer_id
+ * @param handlers functions for receiving messages
+ * @param nc connect callback
+ * @param nd disconnect callback
+ * @param cb_cls closure for @a nc and @a nd callback
+ * @param start_cb start callback
+ * @param start_cb_cls closure for @a start_cb
+ * @return the peer context
+ */
+struct GNUNET_TRANSPORT_TESTING_PeerContext *
+GNUNET_TRANSPORT_TESTING_start_peer (
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth,
+  const char *cfgname,
+  int peer_id,
+  const struct GNUNET_MQ_MessageHandler *handlers,
+  GNUNET_TRANSPORT_NotifyConnect nc,
+  GNUNET_TRANSPORT_NotifyDisconnect nd,
+  void *cb_cls,
+  GNUNET_SCHEDULER_TaskCallback start_cb,
+  void *start_cb_cls);
+
+
+/**
+ * Shutdown the given peer
+ *
+ * @param p the peer
+ */
+void
+GNUNET_TRANSPORT_TESTING_stop_peer (
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *pc);
+
+
+/**
+ * Stops and restarts the given peer, sleeping (!) for 5s in between.
+ *
+ * @param p the peer
+ * @param restart_cb restart callback
+ * @param restart_cb_cls callback closure
+ * @return #GNUNET_OK in success otherwise #GNUNET_SYSERR
+ */
+int
+GNUNET_TRANSPORT_TESTING_restart_peer (
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p,
+  GNUNET_SCHEDULER_TaskCallback restart_cb,
+  void *restart_cb_cls);
+
+
+/**
+ * Connect the given peers and call the callback when both peers
+ * report the inbound connection. Remarks: start_peer's notify_connect
+ * callback can be called before.
+ *
+ * @param p1 peer 1
+ * @param p2 peer 2
+ * @param cb the callback to call when both peers notified that they are
+ * connected
+ * @param cls callback cls
+ * @return a connect request handle
+ */
+struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
+GNUNET_TRANSPORT_TESTING_connect_peers (
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p1,
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p2,
+  GNUNET_SCHEDULER_TaskCallback cb,
+  void *cls);
+
+
+/**
+ * Cancel the request to connect two peers.  You MUST cancel the
+ * request if you stop the peers before the peers connected
+ * succesfully.
+ *
+ * @param cc a connect request handle
+ */
+void
+GNUNET_TRANSPORT_TESTING_connect_peers_cancel (
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc);
+
+
+/**
+ * Function called on matching connect requests.
+ *
+ * @param cls closure
+ * @param cc request matching the query
+ */
+typedef void (*GNUNET_TRANSPORT_TESTING_ConnectContextCallback) (
+  void *cls,
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc);
+
+
+/**
+ * Find any connecting context matching the given pair of peers.
+ *
+ * @param p1 first peer
+ * @param p2 second peer
+ * @param cb function to call
+ * @param cb_cls closure for @a cb
+ */
+void
+GNUNET_TRANSPORT_TESTING_find_connecting_context (
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p1,
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p2,
+  GNUNET_TRANSPORT_TESTING_ConnectContextCallback cb,
+  void *cb_cls);
+
+
+/* ********************** high-level process functions *************** */
+
+
+/**
+ * Function called once the peers have been launched and
+ * connected by #GNUNET_TRANSPORT_TESTING_connect_check().
+ *
+ * @param cls closure
+ * @param num_peers size of the @a p array
+ * @param p the peers that were launched
+ */
+typedef void (*GNUNET_TRANSPORT_TESTING_ConnectContinuation) (
+  void *cls,
+  unsigned int num_peers,
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *p[]);
+
+
+/**
+ * Internal data structure.
+ */
+struct GNUNET_TRANSPORT_TESTING_ConnectRequestList;
+
+/**
+ * Internal data structure.
+ */
+struct GNUNET_TRANSPORT_TESTING_InternalPeerContext;
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+struct GNUNET_TRANSPORT_TESTING_TestMessage
+{
+  /**
+   * Type is (usually) #GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Monotonically increasing counter throughout the test.
+   */
+  uint32_t num GNUNET_PACKED;
+};
+GNUNET_NETWORK_STRUCT_END
+
+
+/**
+ * Function called by the transport for each received message.
+ *
+ * @param cls closure
+ * @param receiver receiver of the message
+ * @param sender sender of the message
+ * @param message the message
+ */
+typedef void (*GNUNET_TRANSPORT_TESTING_ReceiveCallback) (
+  void *cls,
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
+  const struct GNUNET_PeerIdentity *sender,
+  const struct GNUNET_TRANSPORT_TESTING_TestMessage *message);
+
+
+/**
+ * Function called to notify transport users that another
+ * peer connected to us.
+ *
+ * @param cls closure
+ * @param me peer experiencing the event
+ * @param other peer that connected to @a me
+ */
+typedef void (*GNUNET_TRANSPORT_TESTING_NotifyConnect) (
+  void *cls,
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
+  const struct GNUNET_PeerIdentity *other);
+
+
+/**
+ * Function called to notify transport users that another
+ * peer disconnected from us.
+ *
+ * @param cls closure
+ * @param me peer experiencing the event
+ * @param other peer that disconnected from @a me
+ */
+typedef void (*GNUNET_TRANSPORT_TESTING_NotifyDisconnect) (
+  void *cls,
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
+  const struct GNUNET_PeerIdentity *other);
+
+
+/**
+ * Closure that must be passed to
+ * #GNUNET_TRANSPORT_TESTING_connect_check.
+ */
+struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext
+{
+  /**
+   * How should we continue after the connect?
+   */
+  GNUNET_SCHEDULER_TaskCallback connect_continuation;
+
+  /**
+   * Closure for @e connect_continuation.
+   */
+  void *connect_continuation_cls;
+
+  /**
+   * Which configuration file should we pass to the
+   * #GNUNET_PROGRAM_run() of the testcase?
+   */
+  const char *config_file;
+
+  /**
+   * Receiver argument to give for peers we start.
+   */
+  GNUNET_TRANSPORT_TESTING_ReceiveCallback rec;
+
+  /**
+   * Notify connect argument to give for peers we start.
+   */
+  GNUNET_TRANSPORT_TESTING_NotifyConnect nc;
+
+  /**
+   * Notify disconnect argument to give for peers we start.
+   */
+  GNUNET_TRANSPORT_TESTING_NotifyDisconnect nd;
+
+  /**
+   * Closure for @e rec, @e nc and @e nd.
+   */
+  void *cls;
+
+  /**
+   * Custom task to run on shutdown.
+   */
+  GNUNET_SCHEDULER_TaskCallback shutdown_task;
+
+  /**
+   * Closure for @e shutdown_task.
+   */
+  void *shutdown_task_cls;
+
+  /**
+   * Custom task to run after peers were started but before we try to
+   * connect them.  If this function is set, we wait ONE second after
+   * running this function until we continue with connecting the
+   * peers.
+   */
+  GNUNET_SCHEDULER_TaskCallback pre_connect_task;
+
+  /**
+   * Closure for @e shutdown_task.
+   */
+  void *pre_connect_task_cls;
+
+  /**
+   * When should the testcase time out?
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * Should we try to create connections in both directions?
+   */
+  int bi_directional;
+
+  /* ******* fields set by #GNUNET_TRANSPORT_TESTING_connect_check **** */
+
+  /**
+   * Number of peers involved in the test.
+   */
+  unsigned int num_peers;
+
+  /**
+   * Configuration files we have, array with @e num_peers entries.
+   */
+  char **cfg_files;
+
+  /**
+   * Array with @e num_peers entries.
+   */
+  struct GNUNET_TRANSPORT_TESTING_PeerContext **p;
+
+  /**
+   * Name of the plugin.
+   */
+  const char *test_plugin;
+
+  /**
+   * Name of the testcase.
+   */
+  const char *test_name;
+
+  /**
+   * Configuration object for the testcase.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Main testing handle.
+   */
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth;
+
+  /**
+   * Result from the main function, set to #GNUNET_OK on success.
+   * Clients should set to #GNUNET_SYSERR to indicate test failure.
+   */
+  int global_ret;
+
+  /**
+   * Generator for the `num` field in test messages.  Incremented each
+   * time #GNUNET_TRANSPORT_TESTING_simple_send or
+   * #GNUNET_TRANSPORT_TESTING_large_send are used to transmit a
+   * message.
+   */
+  uint32_t send_num_gen;
+
+  /* ******* internal state, clients should not mess with this **** */
+
+  /**
+   * Task run on timeout.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * Task run to connect peers.
+   */
+  struct GNUNET_SCHEDULER_Task *connect_task;
+
+  /**
+   * Number of peers that have been started.
+   */
+  unsigned int started;
+
+  /**
+   * DLL of active connect requests.
+   */
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl_head;
+
+  /**
+   * DLL of active connect requests.
+   */
+  struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl_tail;
+
+  /**
+   * Array with @e num_peers entries.
+   */
+  struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ip;
+};
+
+
+/**
+ * Find peer by peer ID.
+ *
+ * @param ccc context to search
+ * @param peer peer to look for
+ * @return NULL if @a peer was not found
+ */
+struct GNUNET_TRANSPORT_TESTING_PeerContext *
+GNUNET_TRANSPORT_TESTING_find_peer (
+  struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc,
+  const struct GNUNET_PeerIdentity *peer);
+
+
+/**
+ * Common implementation of the #GNUNET_TRANSPORT_TESTING_CheckCallback.
+ * Starts and connects the two peers, then invokes the
+ * `connect_continuation` from @a cls.  Sets up a timeout to
+ * abort the test, and a shutdown handler to clean up properly
+ * on exit.
+ *
+ * @param cls closure of type `struct
+ * GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
+ * @param tth_ initialized testing handle
+ * @param test_plugin_ name of the plugin
+ * @param test_name_ name of the test
+ * @param num_peers number of entries in the @a cfg_file array
+ * @param cfg_files array of names of configuration files for the peers
+ * @return #GNUNET_SYSERR on error
+ */
+int
+GNUNET_TRANSPORT_TESTING_connect_check (
+  void *cls,
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
+  const char *test_plugin_,
+  const char *test_name_,
+  unsigned int num_peers,
+  char *cfg_files[]);
+
+
+/**
+ * Main function of a testcase.  Called with the initial setup data
+ * for the test as derived from the source name and the binary name.
+ *
+ * @param cls closure
+ * @param tth_ initialized testing handle
+ * @param test_plugin_ name of the plugin
+ * @param test_name_ name of the test
+ * @param num_peers number of entries in the @a cfg_file array
+ * @param cfg_files array of names of configuration files for the peers
+ * @return #GNUNET_SYSERR on error
+ */
+typedef int (*GNUNET_TRANSPORT_TESTING_CheckCallback) (
+  void *cls,
+  struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
+  const char *test_plugin_,
+  const char *test_name_,
+  unsigned int num_peers,
+  char *cfg_files[]);
+
+
+/**
+ * Setup testcase.  Calls @a check with the data the test needs.
+ *
+ * @param argv0 binary name (argv[0])
+ * @param filename source file name (__FILE__)
+ * @param num_peers number of peers to start
+ * @param check main function to run
+ * @param check_cls closure for @a check
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_TRANSPORT_TESTING_main_ (const char *argv0,
+                                const char *filename,
+                                unsigned int num_peers,
+                                GNUNET_TRANSPORT_TESTING_CheckCallback check,
+                                void *check_cls);
+
+
+/**
+ * Setup testcase.  Calls @a check with the data the test needs.
+ *
+ * @param num_peers number of peers to start
+ * @param check main function to run
+ * @param check_cls closure for @a check
+ * @return #GNUNET_OK on success
+ */
+#define GNUNET_TRANSPORT_TESTING_main(num_peers, check, check_cls) \
+  GNUNET_TRANSPORT_TESTING_main_ (argv[0],                         \
+                                  __FILE__,                        \
+                                  num_peers,                       \
+                                  check,                           \
+                                  check_cls)
+
+/* ***************** Convenience functions for sending ********* */
+
+/**
+ * Send a test message of type @a mtype and size @a msize from
+ * peer @a sender to peer @a receiver.  The peers should be
+ * connected when this function is called.
+ *
+ * @param sender the sending peer
+ * @param receiver the receiving peer
+ * @param mtype message type to use
+ * @param msize size of the message, at least `sizeof (struct
+ * GNUNET_TRANSPORT_TESTING_TestMessage)`
+ * @param num unique message number
+ * @param cont continuation to call after transmission
+ * @param cont_cls closure for @a cont
+ * @return #GNUNET_OK if message was queued,
+ *         #GNUNET_NO if peers are not connected
+ *         #GNUNET_SYSERR if @a msize is illegal
+ */
+int
+GNUNET_TRANSPORT_TESTING_send (
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *sender,
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
+  uint16_t mtype,
+  uint16_t msize,
+  uint32_t num,
+  GNUNET_SCHEDULER_TaskCallback cont,
+  void *cont_cls);
+
+
+/**
+ * Message type used by #GNUNET_TRANSPORT_TESTING_simple_send().
+ */
+#define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE 12345
+
+/**
+ * Alternative message type for tests.
+ */
+#define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE2 12346
+
+
+/**
+ * Type of the closure argument to pass to
+ * #GNUNET_TRANSPORT_TESTING_simple_send() and
+ * #GNUNET_TRANSPORT_TESTING_large_send().
+ */
+struct GNUNET_TRANSPORT_TESTING_SendClosure
+{
+  /**
+   * Context for the transmission.
+   */
+  struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
+
+  /**
+   * Function that returns the desired message size. Overrides
+   * the message size, can be NULL in which case the message
+   * size is the default.
+   */
+  size_t (*get_size_cb) (unsigned int n);
+
+  /**
+   * Number of messages to be transmitted in a loop.
+   * Use zero for "forever" (until external shutdown).
+   */
+  unsigned int num_messages;
+
+  /**
+   * Function to call after all transmissions, can be NULL.
+   */
+  GNUNET_SCHEDULER_TaskCallback cont;
+
+  /**
+   * Closure for @e cont.
+   */
+  void *cont_cls;
+};
+
+
+/**
+ * Task that sends a minimalistic test message from the
+ * first peer to the second peer.
+ *
+ * @param cls the `struct GNUNET_TRANSPORT_TESTING_SendClosure`
+ *        which should contain at least two peers, the first two
+ *        of which should be currently connected
+ */
+void
+GNUNET_TRANSPORT_TESTING_simple_send (void *cls);
+
+/**
+ * Size of a message sent with
+ * #GNUNET_TRANSPORT_TESTING_large_send().  Big enough
+ * to usually force defragmentation.
+ */
+#define GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE 2600
+
+/**
+ * Task that sends a large test message from the
+ * first peer to the second peer.
+ *
+ * @param cls the `struct GNUNET_TRANSPORT_TESTING_SendClosure`
+ *        which should contain at least two peers, the first two
+ *        of which should be currently connected
+ */
+void
+GNUNET_TRANSPORT_TESTING_large_send (void *cls);
+
+
+/* ********************** log-only convenience functions ************* */
+
+
+/**
+ * Log a connect event.
+ *
+ * @param cls NULL
+ * @param me peer that had the event
+ * @param other peer that connected.
+ */
+void
+GNUNET_TRANSPORT_TESTING_log_connect (
+  void *cls,
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
+  const struct GNUNET_PeerIdentity *other);
+
+
+/**
+ * Log a disconnect event.
+ *
+ * @param cls NULL
+ * @param me peer that had the event
+ * @param other peer that disconnected.
+ */
+void
+GNUNET_TRANSPORT_TESTING_log_disconnect (
+  void *cls,
+  struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
+  const struct GNUNET_PeerIdentity *other);
+
+
+/* ********************** low-level filename functions *************** */
+
+
+/**
+ * Extracts the test filename from an absolute file name and removes
+ * the extension.
+ *
+ * @param file absolute file name
+ * @return resulting test name
+ */
+char *
+GNUNET_TRANSPORT_TESTING_get_test_name (const char *file);
+
+
+/**
+ * This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and
+ * if existing ".exe"-prefix and adds the peer-number
+ *
+ * @param file filename of the test, e.g. argv[0]
+ * @param count peer number
+ * @return configuration name to use
+ */
+char *
+GNUNET_TRANSPORT_TESTING_get_config_name (const char *file, int count);
+
+
+/**
+ * Extracts the plugin anme from an absolute file name and the test name
+ * @param file absolute file name
+ * @param test test name
+ * @return the plugin name
+ */
+char *
+GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *executable,
+                                               const char *testname);
+
+
+/**
+ * Extracts the filename from an absolute file name and removes the
+ * extenstion
+ *
+ * @param file absolute file name
+ * @return the source name
+ */
+char *
+GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file);
+
+#endif
+/* end of transport_testing.h */

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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