changes to use names instead of numbers for topologies and topology options
[oweals/gnunet.git] / src / testing / testing_group.c
index 7afbbd48be29360a8089d59cd2f08f8e96b5d529..36aa42615046e735428c73d0494386b71c1aaaa8 100644 (file)
@@ -29,6 +29,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",
+
+  /**
+   * 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 +422,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
@@ -726,7 +881,7 @@ create_scale_free (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_Connectio
         {
           probability = pg->peers[i].num_connections / (double)previous_total_connections;
           random = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
-                                                      (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
+                                                      UINT64_MAX)) / ( (double) UINT64_MAX);
 #if VERBOSE_TESTING
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       "Considering connecting peer %d to peer %d\n",
@@ -820,7 +975,7 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_Conn
       for (j = 0; j < connsPerPeer / 2; j++)
         {
           random = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
-                                                     (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
+                                                     UINT64_MAX) / ( (double) UINT64_MAX));
           if (random < percentage)
             {
               /* Connect to uniformly selected random peer */
@@ -1035,7 +1190,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_Connecti
                   probability = 1.0 / (distance * distance);
                   /* Choose a random value between 0 and 1 */
                  random = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
-                                                             (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
+                                                             UINT64_MAX)) / ( (double) UINT64_MAX);
                   /* If random < probability, then connect the two nodes */
                   if (random < probability)
                     smallWorldConnections += proc (pg, j, k);
@@ -1086,7 +1241,7 @@ create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_Connecti
            inner_count++)
         {
           temp_rand = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
-                                                        (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
+                                                        UINT64_MAX)) / ( (double) UINT64_MAX);
 #if VERBOSE_TESTING
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       _("rand is %f probability is %f\n"), temp_rand,
@@ -1488,7 +1643,7 @@ create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg, char *tran
         }
       }
 
-      GNUNET_free_non_null(temp_transports);
+      GNUNET_free (temp_transports);
       fclose(temp_file_handle);
 
       if (GNUNET_OK !=
@@ -1792,49 +1947,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
@@ -2077,7 +2232,7 @@ random_connect_iterator (void *cls,
   uint32_t second_pos;
   GNUNET_HashCode first_hash;
   random_number = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
-                   (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
+                                                    UINT64_MAX)) / ( (double) UINT64_MAX);
   if (random_number < random_ctx->percentage)
   {
     GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(random_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
@@ -2202,27 +2357,29 @@ choose_random_connections(struct GNUNET_TESTING_PeerGroup *pg, double percentage
  * @param pg the peergroup we are dealing with
  * @param num how many connections at least should each peer have (if possible)?
  */
-void
+static void
 choose_minimum(struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
 {
   struct MinimumContext minimum_ctx;
   uint32_t pg_iter;
 
   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-    {
-      pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(num);
-    }
+   {
+     pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(num);
+   }
 
   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
     {
       minimum_ctx.first_uid = pg_iter;
-      minimum_ctx.pg_array = GNUNET_CRYPTO_random_permute(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers));
+      minimum_ctx.pg_array = GNUNET_CRYPTO_random_permute(GNUNET_CRYPTO_QUALITY_WEAK, 
+                                                         GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers));
       minimum_ctx.first = &pg->peers[pg_iter];
       minimum_ctx.pg = pg;
       minimum_ctx.num_to_add = num;
       minimum_ctx.current = 0;
-      pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(pg->total);
-      GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &minimum_connect_iterator, &minimum_ctx);
+      GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers,
+                                           &minimum_connect_iterator, 
+                                           &minimum_ctx);
     }
 
   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
@@ -2231,13 +2388,13 @@ choose_minimum(struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
       GNUNET_CONTAINER_multihashmap_destroy(pg->peers[pg_iter].connect_peers);
       /* And replace with the working set */
       pg->peers[pg_iter].connect_peers = pg->peers[pg_iter].connect_peers_working_set;
-      fprintf(stderr, "Finished! Hashmap size %u\n", GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers));
     }
 
 }
 
 
-static unsigned int count_workingset_connections(struct GNUNET_TESTING_PeerGroup *pg)
+static unsigned int
+count_workingset_connections(struct GNUNET_TESTING_PeerGroup *pg)
 {
   unsigned int count;
   unsigned int pg_iter;
@@ -2328,20 +2485,13 @@ perform_dfs (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
       starting_peer = dfs_ctx.second_uid;
     }
 
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-    {
-
-    }
-
   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
     {
       /* Remove the "old" connections */
       GNUNET_CONTAINER_multihashmap_destroy(pg->peers[pg_iter].connect_peers);
       /* And replace with the working set */
       pg->peers[pg_iter].connect_peers = pg->peers[pg_iter].connect_peers_working_set;
-      fprintf(stderr, "Finished! Hashmap size %u\n", GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers));
     }
-
 }
 
 /**
@@ -2368,62 +2518,66 @@ 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_NONE:
+#if VERBOSE_TOPOLOGY
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating no CONNECT topology\n"));
+#endif
         copy_allowed_topology(pg);
         break;
       default:
@@ -2434,13 +2588,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:
@@ -2542,12 +2708,12 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
     {
       off = 2;
       /* skip leading spaces */
-      while ((0 != *hostnames) && (isspace (*hostnames)))
+      while ((0 != *hostnames) && (isspace ( (unsigned char) *hostnames)))
         hostnames++;
       rpos = hostnames;
       while ('\0' != *rpos)
         {
-          if (isspace (*rpos))
+          if (isspace ( (unsigned char) *rpos))
             off++;
           rpos++;
         }
@@ -2557,7 +2723,7 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
       pos = start;
       while ('\0' != *pos)
         {
-          if (isspace (*pos))
+          if (isspace ( (unsigned char) *pos))
             {
               *pos = '\0';
               if (strlen (start) > 0)
@@ -2866,10 +3032,12 @@ GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg,
   {
     if (pg->peers[i].daemon->running == GNUNET_YES)
     {
+      GNUNET_assert(running != -1);
       running++;
     }
     else
     {
+      GNUNET_assert(stopped != -1);
       stopped++;
     }
   }