some testing changes, including an api change that likely breaks things for others
[oweals/gnunet.git] / src / testing / testing_group.c
index 2f8db6a812f00b3473b3cba7e7a5856e60cf3edb..b6ae14036c7508824858d08a7fcf7c8dfd1c0c7b 100644 (file)
  * @file testing/testing_group.c
  * @brief convenience API for writing testcases for GNUnet
  * @author Christian Grothoff
+ *
+ * FIXME: have connection processor functions take a cls argument
+ *        which specifies where to write the connection information
+ *        instead of assuming it's certain peergroup places. (maybe?)
+ * FIXME: create static struct which contains the TOPOLOGY enum, the
+ *        associated string, and the function used to create it.
+ *        Then replace the create_X calls with topology_struct[i][2]
+ *        or something. (Store function pointers instead of using
+ *        switch statements)
  */
 #include "platform.h"
 #include "gnunet_arm_service.h"
@@ -29,6 +38,8 @@
 
 #define VERBOSE_TESTING GNUNET_NO
 
+#define VERBOSE_TOPOLOGY GNUNET_NO
+
 #define DEBUG_CHURN GNUNET_NO
 
 /**
 typedef int (*GNUNET_TESTING_ConnectionProcessor)
 (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second);
 
+/**
+ * Strings representing topologies in enum
+ */
+static char * GNUNET_TESTING_TopologyStrings[] =
+{
+  /**
+   * A clique (everyone connected to everyone else).
+   */
+  "CLIQUE",
+
+  /**
+   * Small-world network (2d torus plus random links).
+   */
+  "SMALL_WORLD",
+
+  /**
+   * Small-world network (ring plus random links).
+   */
+  "SMALL_WORLD_RING",
+
+  /**
+   * Ring topology.
+   */
+  "RING",
+
+  /**
+   * 2-d torus.
+   */
+  "2D_TORUS",
+
+  /**
+   * Random graph.
+   */
+  "ERDOS_RENYI",
+
+  /**
+   * Certain percentage of peers are unable to communicate directly
+   * replicating NAT conditions
+   */
+  "INTERNAT",
+
+  /**
+   * Scale free topology.
+   */
+  "SCALE_FREE",
+
+  /**
+   * Straight line topology.
+   */
+  "LINE",
+
+  /**
+   * All peers are disconnected.
+   */
+  "NONE"
+};
+
+/**
+ * Options for connecting a topology as strings.
+ */
+static char * GNUNET_TESTING_TopologyOptionStrings[] =
+{
+  /**
+   * Try to connect all peers specified in the topology.
+   */
+  "CONNECT_ALL",
+
+  /**
+   * Choose a random subset of connections to create.
+   */
+  "CONNECT_RANDOM_SUBSET",
+
+  /**
+   * Create at least X connections for each peer.
+   */
+  "CONNECT_MINIMUM",
+
+  /**
+   * Using a depth first search, create one connection
+   * per peer.  If any are missed (graph disconnected)
+   * start over at those peers until all have at least one
+   * connection.
+   */
+  "CONNECT_DFS",
+
+  /**
+   * No options specified.
+   */
+  "CONNECT_NONE"
+};
+
 /**
  * Context for handling churning a peer group
  */
@@ -334,6 +436,73 @@ struct ConnectContext
  */
 static int outstanding_connects;
 
+/**
+ * Get a topology from a string input.
+ *
+ * @param topology where to write the retrieved topology
+ * @param topology_string The string to attempt to
+ *        get a configuration value from
+ * @return GNUNET_YES if topology string matched a
+ *         known topology, GNUNET_NO if not
+ */
+int
+GNUNET_TESTING_topology_get(enum GNUNET_TESTING_Topology *topology, char * topology_string)
+{
+  int found = 0;
+  int curr = 0;
+
+  if (topology_string == NULL)
+    return GNUNET_NO;
+
+  do
+  {
+    if (strcmp(GNUNET_TESTING_TopologyStrings[curr], topology_string) == 0)
+    {
+      found = GNUNET_YES;
+      break;
+    }
+    curr++;
+  } while (strcmp(GNUNET_TESTING_TopologyStrings[curr], "NONE") != 0);
+  *topology = curr;
+  if (found)
+    return GNUNET_YES;
+  else
+    return GNUNET_NO;
+}
+
+/**
+ * Get connect topology option from string input.
+ *
+ * @param topology where to write the retrieved topology
+ * @param topology_string The string to attempt to
+ *        get a configuration value from
+ * @return GNUNET_YES if string matched a known
+ *         topology option, GNUNET_NO if not
+ */
+int
+GNUNET_TESTING_topology_option_get(enum GNUNET_TESTING_TopologyOption *topology, char * topology_string)
+{
+  int found = 0;
+  int curr = 0;
+
+  if (topology_string == NULL)
+    return GNUNET_NO;
+
+  do
+  {
+    if (strcmp(GNUNET_TESTING_TopologyOptionStrings[curr], topology_string) == 0)
+    {
+      found = GNUNET_YES;
+      break;
+    }
+    curr++;
+  } while (strcmp(GNUNET_TESTING_TopologyOptionStrings[curr], "CONNECT_NONE") != 0);
+  *topology = curr;
+  if (found)
+    return GNUNET_YES;
+  else
+    return GNUNET_NO;
+}
 
 /**
  * Function to iterate over options.  Copies
@@ -747,6 +916,17 @@ create_scale_free (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_Connectio
   return total_connections;
 }
 
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ *
+ * @return the number of connections that were set up
+ *
+ */
 int
 create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
 {
@@ -858,7 +1038,17 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_Conn
   return connect_attempts;
 }
 
-
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ *
+ * @return the number of connections that were set up
+ *
+ */
 static int
 create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
 {
@@ -910,8 +1100,17 @@ create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_Conne
 
 }
 
-
-
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ *
+ * @return the number of connections that were set up
+ *
+ */
 static int
 create_small_world (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
 {
@@ -1053,8 +1252,17 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_Connecti
   return connect_attempts;
 }
 
-
-
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ *
+ * @return the number of connections that were set up
+ *
+ */
 static int
 create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
 {
@@ -1102,6 +1310,17 @@ create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_Connecti
   return connect_attempts;
 }
 
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ *
+ * @return the number of connections that were set up
+ *
+ */
 static int
 create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
 {
@@ -1179,7 +1398,17 @@ create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionP
 }
 
 
-
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ *
+ * @return the number of connections that were set up
+ *
+ */
 static int
 create_clique (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
 {
@@ -1206,7 +1435,50 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionPro
   return connect_attempts;
 }
 
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static int
+create_line (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
+{
+  unsigned int count;
+  int connect_attempts;
+
+  connect_attempts = 0;
 
+  /* Connect each peer to the next highest numbered peer */
+  for (count = 0; count < pg->total - 1; count++)
+    {
+#if VERBOSE_TESTING
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "Connecting peer %d to peer %d\n",
+                      count, count + 1);
+#endif
+      connect_attempts += proc(pg, count, count + 1);
+    }
+
+  return connect_attempts;
+}
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ *
+ * @return the number of connections that were set up
+ *
+ */
 static int
 create_ring (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
 {
@@ -1590,6 +1862,7 @@ create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg, char *tran
 static void internal_connect_notify (void *cls,
                                      const struct GNUNET_PeerIdentity *first,
                                      const struct GNUNET_PeerIdentity *second,
+                                     uint32_t distance,
                                      const struct GNUNET_CONFIGURATION_Handle *first_cfg,
                                      const struct GNUNET_CONFIGURATION_Handle *second_cfg,
                                      struct GNUNET_TESTING_Daemon *first_daemon,
@@ -1599,10 +1872,20 @@ static void internal_connect_notify (void *cls,
   struct GNUNET_TESTING_PeerGroup *pg = cls;
   outstanding_connects--;
 
-  pg->notify_connection(pg->notify_connection_cls, first, second, first_cfg, second_cfg, first_daemon, second_daemon, emsg);
+<<<<<<< .mine
+  pg->notify_connection(pg->notify_connection_cls, first, second, distance, first_cfg, second_cfg, first_daemon, second_daemon, emsg);
+=======
+  pg->notify_connection(pg->notify_connection_cls, 
+                       first,
+                       second, 
+                       first_cfg, second_cfg, 
+                       first_daemon, second_daemon, 
+                       emsg);
+>>>>>>> .r11782
 
 }
 
+
 static void schedule_connect(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct ConnectContext *connect_context = cls;
@@ -1635,6 +1918,7 @@ static void schedule_connect(void *cls, const struct GNUNET_SCHEDULER_TaskContex
     }
 }
 
+
 /**
  * Iterator for actually scheduling connections to be created
  * between two peers.
@@ -1663,6 +1947,7 @@ connect_iterator (void *cls,
   return GNUNET_YES;
 }
 
+
 /**
  * Iterator for copying all entries in the allowed hashmap to the
  * connect hashmap.
@@ -1792,49 +2077,49 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg,
   switch (topology)
     {
     case GNUNET_TESTING_TOPOLOGY_CLIQUE:
-#if VERBOSE_TESTING
+#if VERBOSE_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   _("Creating clique topology\n"));
 #endif
       num_connections = create_clique (pg, &add_allowed_connections);
       break;
     case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
-#if VERBOSE_TESTING
+#if VERBOSE_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   _("Creating small world (ring) topology\n"));
 #endif
       num_connections = create_small_world_ring (pg, &add_allowed_connections);
       break;
     case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
-#if VERBOSE_TESTING
+#if VERBOSE_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   _("Creating small world (2d-torus) topology\n"));
 #endif
       num_connections = create_small_world (pg, &add_allowed_connections);
       break;
     case GNUNET_TESTING_TOPOLOGY_RING:
-#if VERBOSE_TESTING
+#if VERBOSE_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   _("Creating ring topology\n"));
 #endif
       num_connections = create_ring (pg, &add_allowed_connections);
       break;
     case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
-#if VERBOSE_TESTING
+#if VERBOSE_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   _("Creating 2d torus topology\n"));
 #endif
       num_connections = create_2d_torus (pg, &add_allowed_connections);
       break;
     case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
-#if VERBOSE_TESTING
+#if VERBOSE_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   _("Creating Erdos-Renyi topology\n"));
 #endif
       num_connections = create_erdos_renyi (pg, &add_allowed_connections);
       break;
     case GNUNET_TESTING_TOPOLOGY_INTERNAT:
-#if VERBOSE_TESTING
+#if VERBOSE_TOPOLOGY
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   _("Creating InterNAT topology\n"));
 #endif
@@ -1847,6 +2132,13 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg,
 #endif
       num_connections = create_scale_free (pg, &add_allowed_connections);
       break;
+    case GNUNET_TESTING_TOPOLOGY_LINE:
+#if VERBOSE_TESTING
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating straight line topology\n"));
+#endif
+      num_connections = create_line (pg, &add_allowed_connections);
+      break;
     case GNUNET_TESTING_TOPOLOGY_NONE:
       num_connections = 0;
       break;
@@ -1940,6 +2232,13 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg,
 #endif
       unblacklisted_connections = create_scale_free (pg, &unblacklist_connections);
       break;
+    case GNUNET_TESTING_TOPOLOGY_LINE:
+#if VERBOSE_TESTING
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Blacklisting all but straight line topology\n"));
+#endif
+      unblacklisted_connections = create_line (pg, &unblacklist_connections);
+      break;
     case GNUNET_TESTING_TOPOLOGY_NONE:
       /* Fall through */
     default:
@@ -2363,62 +2662,73 @@ GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
   switch (topology)
       {
       case GNUNET_TESTING_TOPOLOGY_CLIQUE:
-  #if VERBOSE_TESTING
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    _("Creating clique topology\n"));
-  #endif
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating clique CONNECT topology\n"));
+#endif
         create_clique (pg, &add_actual_connections);
         break;
       case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
-  #if VERBOSE_TESTING
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    _("Creating small world (ring) topology\n"));
-  #endif
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating small world (ring) CONNECT topology\n"));
+#endif
         create_small_world_ring (pg, &add_actual_connections);
         break;
       case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
-  #if VERBOSE_TESTING
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    _("Creating small world (2d-torus) topology\n"));
-  #endif
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating small world (2d-torus) CONNECT topology\n"));
+#endif
         create_small_world (pg, &add_actual_connections);
         break;
       case GNUNET_TESTING_TOPOLOGY_RING:
-  #if VERBOSE_TESTING
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    _("Creating ring topology\n"));
-  #endif
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating ring CONNECT topology\n"));
+#endif
         create_ring (pg, &add_actual_connections);
         break;
       case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
-  #if VERBOSE_TESTING
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    _("Creating 2d torus topology\n"));
-  #endif
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating 2d torus CONNECT topology\n"));
+#endif
         create_2d_torus (pg, &add_actual_connections);
         break;
       case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
-  #if VERBOSE_TESTING
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    _("Creating Erdos-Renyi topology\n"));
-  #endif
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating Erdos-Renyi CONNECT topology\n"));
+#endif
         create_erdos_renyi (pg, &add_actual_connections);
         break;
       case GNUNET_TESTING_TOPOLOGY_INTERNAT:
-  #if VERBOSE_TESTING
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    _("Creating InterNAT topology\n"));
-  #endif
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating InterNAT CONNECT topology\n"));
+#endif
         create_nated_internet (pg, &add_actual_connections);
         break;
       case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
-  #if VERBOSE_TESTING
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    _("Creating Scale Free topology\n"));
-  #endif
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating Scale Free CONNECT topology\n"));
+#endif
         create_scale_free (pg, &add_actual_connections);
         break;
+      case GNUNET_TESTING_TOPOLOGY_LINE:
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating straight line CONNECT topology\n"));
+#endif
+        create_line (pg, &add_actual_connections);
+        break;
       case GNUNET_TESTING_TOPOLOGY_NONE:
+#if VERBOSE_TOPOLOGY
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating no CONNECT topology\n"));
+#endif
         copy_allowed_topology(pg);
         break;
       default:
@@ -2429,13 +2739,25 @@ GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
 
   switch (options)
     {
-    case GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM: 
+    case GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM:
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Connecting random subset (%'.2f percent) of possible peers\n"), 100 * option_modifier);
+#endif
       choose_random_connections(pg, option_modifier);
       break;
-    case GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM: 
+    case GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM:
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Connecting a minimum of %u peers each (if possible)\n"), (unsigned int)option_modifier);
+#endif
       choose_minimum(pg, (unsigned int)option_modifier);
       break;
-    case GNUNET_TESTING_TOPOLOGY_OPTION_DFS: 
+    case GNUNET_TESTING_TOPOLOGY_OPTION_DFS:
+#if VERBOSE_TOPOLOGY
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Using DFS to connect a minimum of %u peers each (if possible)\n"), (unsigned int)option_modifier);
+#endif
       perform_dfs(pg, (int)option_modifier);
       break;
     case GNUNET_TESTING_TOPOLOGY_OPTION_NONE: