change to configs, use readable names for topologies and connect options instead...
[oweals/gnunet.git] / src / testing / testing_group.c
index 1de293617708ce760bc6eb511fb00955532ca83f..2f8db6a812f00b3473b3cba7e7a5856e60cf3edb 100644 (file)
@@ -313,8 +313,9 @@ uid_from_hash (const GNUNET_HashCode *hash, uint32_t *uid)
 struct UpdateContext
 {
   struct GNUNET_CONFIGURATION_Handle *ret;
-  unsigned int nport;
   const char *hostname;
+  unsigned int nport;
+  unsigned int upnum;
 };
 
 
@@ -351,11 +352,25 @@ update_config (void *cls,
   struct UpdateContext *ctx = cls;
   unsigned int ival;
   char cval[12];
+  char uval[128];
 
   if ((0 == strcmp (option, "PORT")) && (1 == sscanf (value, "%u", &ival)))
     {
-      GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++);
-      value = cval;
+      if (ival != 0)
+       {
+         GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++);
+         value = cval;
+       }
+    }
+
+  if (0 == strcmp (option, "UNIXPATH"))
+    {
+      GNUNET_snprintf (uval, 
+                      sizeof (uval),
+                      "/tmp/test-service-%s-%u", 
+                      section,
+                      ctx->upnum++);
+      value = uval;
     }
 
   if ((0 == strcmp (option, "HOSTNAME")) && (ctx->hostname != NULL))
@@ -376,12 +391,16 @@ update_config (void *cls,
  * @param cfg template configuration
  * @param port port numbers to use, update to reflect
  *             port numbers that were used
+ * @param upnum number to make unix domain socket names unique
  * @param hostname hostname of the controlling host, to allow control connections from
  *
  * @return new configuration, NULL on error
  */
 static struct GNUNET_CONFIGURATION_Handle *
-make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t * port, const char *hostname)
+make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, 
+            uint16_t * port,
+            uint32_t * upnum,
+            const char *hostname)
 {
   struct UpdateContext uc;
   uint16_t orig;
@@ -390,6 +409,7 @@ make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t * port, con
 
   orig = *port;
   uc.nport = *port;
+  uc.upnum = *upnum;
   uc.ret = GNUNET_CONFIGURATION_create ();
   uc.hostname = hostname;
 
@@ -420,6 +440,7 @@ make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t * port, con
     }
 
   *port = (uint16_t) uc.nport;
+  *upnum = uc.upnum;
   return uc.ret;
 }
 
@@ -705,7 +726,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",
@@ -799,7 +820,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 */
@@ -1014,7 +1035,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);
@@ -1065,7 +1086,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,
@@ -1467,7 +1488,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 !=
@@ -2056,7 +2077,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));
@@ -2181,27 +2202,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++)
@@ -2210,13 +2233,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;
@@ -2307,20 +2330,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));
     }
-
 }
 
 /**
@@ -2403,7 +2419,7 @@ GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
         create_scale_free (pg, &add_actual_connections);
         break;
       case GNUNET_TESTING_TOPOLOGY_NONE:
-        num_connections = copy_allowed_topology(pg);
+        copy_allowed_topology(pg);
         break;
       default:
         GNUNET_log(GNUNET_ERROR_TYPE_WARNING, 
@@ -2499,13 +2515,14 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
   unsigned int off;
   unsigned int hostcnt;
   uint16_t minport;
+  uint32_t upnum;
 
   if (0 == total)
     {
       GNUNET_break (0);
       return NULL;
     }
-
+  upnum = 0;
   pg = GNUNET_malloc (sizeof (struct GNUNET_TESTING_PeerGroup));
   pg->sched = sched;
   pg->cfg = cfg;
@@ -2520,12 +2537,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++;
         }
@@ -2535,7 +2552,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)
@@ -2571,12 +2588,18 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
       if (hostcnt > 0)
         {
           hostname = pg->hosts[off % hostcnt].hostname;
-          pcfg = make_config (cfg, &pg->hosts[off % hostcnt].minport, hostname);
+          pcfg = make_config (cfg, 
+                             &pg->hosts[off % hostcnt].minport,
+                             &upnum,
+                             hostname);
         }
       else
         {
           hostname = NULL;
-          pcfg = make_config (cfg, &minport, hostname);
+          pcfg = make_config (cfg,
+                             &minport,
+                             &upnum,
+                             hostname);
         }
 
       if (NULL == pcfg)
@@ -2646,6 +2669,7 @@ GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, unsigned int pos
  * Prototype of a function that will be called when a
  * particular operation was completed the testing library.
  *
+ * @param cls closure (a struct RestartContext)
  * @param id id of the peer that was restarted
  * @param cfg handle to the configuration of the peer
  * @param d handle to the daemon that was restarted
@@ -2698,17 +2722,20 @@ churn_stop_callback (void *cls, const char *emsg)
 
   error_message = NULL;
   if (emsg != NULL)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Churn stop callback failed with error `%s'\n", emsg);
-    churn_ctx->num_failed_stop++;
-  }
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, 
+                "Churn stop callback failed with error `%s'\n", emsg);
+      churn_ctx->num_failed_stop++;
+    }
   else
-  {
-    churn_ctx->num_to_stop--;
-  }
+    {
+      churn_ctx->num_to_stop--;
+    }
 
 #if DEBUG_CHURN
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Stopped peer, %d left.\n", churn_ctx->num_to_stop);
+  GNUNET_log(GNUNET_ERROR_TYPE_WARNING, 
+            "Stopped peer, %d left.\n", 
+            churn_ctx->num_to_stop);
 #endif
   total_left = (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) + (churn_ctx->num_to_start - churn_ctx->num_failed_start);
 
@@ -2716,7 +2743,10 @@ churn_stop_callback (void *cls, const char *emsg)
   {
     if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0))
       {
-        GNUNET_asprintf(&error_message, "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", churn_ctx->num_failed_start, churn_ctx->num_failed_stop);
+        GNUNET_asprintf(&error_message, 
+                       "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", 
+                       churn_ctx->num_failed_start, 
+                       churn_ctx->num_failed_stop);
       }
     churn_ctx->cb(churn_ctx->cb_cls, error_message);
     GNUNET_free_non_null(error_message);
@@ -2748,17 +2778,21 @@ churn_start_callback (void *cls,
 
   error_message = NULL;
   if (emsg != NULL)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Churn stop callback failed with error `%s'\n", emsg);
-    churn_ctx->num_failed_start++;
-  }
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 
+                 "Churn stop callback failed with error `%s'\n",
+                 emsg);
+      churn_ctx->num_failed_start++;
+    }
   else
-  {
-    churn_ctx->num_to_start--;
-  }
-
+    {
+      churn_ctx->num_to_start--;
+    }
+  
 #if DEBUG_CHURN
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Started peer, %d left.\n", churn_ctx->num_to_start);
+  GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
+            "Started peer, %d left.\n", 
+            churn_ctx->num_to_start);
 #endif
 
   total_left = (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) + (churn_ctx->num_to_start - churn_ctx->num_failed_start);
@@ -2766,14 +2800,17 @@ churn_start_callback (void *cls,
   if (total_left == 0)
   {
     if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0))
-      GNUNET_asprintf(&error_message, "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", churn_ctx->num_failed_start, churn_ctx->num_failed_stop);
+      GNUNET_asprintf(&error_message, 
+                     "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!", 
+                     churn_ctx->num_failed_start,
+                     churn_ctx->num_failed_stop);
     churn_ctx->cb(churn_ctx->cb_cls, error_message);
     GNUNET_free_non_null(error_message);
     GNUNET_free(churn_ctx);
   }
-
 }
 
+
 /**
  * Simulate churn by stopping some peers (and possibly
  * re-starting others if churn is called multiple times).  This
@@ -2824,10 +2861,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++;
     }
   }
@@ -2885,15 +2924,19 @@ GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg,
 #if DEBUG_CHURN
     GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Stopping peer %d!\n", running_permute[i]);
 #endif
-    GNUNET_TESTING_daemon_stop(pg->peers[running_arr[running_permute[i]]].daemon, timeout, &churn_stop_callback, churn_ctx, GNUNET_NO, GNUNET_YES);
+    GNUNET_TESTING_daemon_stop (pg->peers[running_arr[running_permute[i]]].daemon,
+                               timeout, 
+                               &churn_stop_callback, churn_ctx, 
+                               GNUNET_NO, GNUNET_YES);
   }
 
   for (i = 0; i < von; i++)
-  {
+    {
 #if DEBUG_CHURN
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Starting up peer %d!\n", stopped_permute[i]);
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Starting up peer %d!\n", stopped_permute[i]);
 #endif
-    GNUNET_TESTING_daemon_start_stopped(pg->peers[stopped_arr[stopped_permute[i]]].daemon, timeout, &churn_start_callback, churn_ctx);
+      GNUNET_TESTING_daemon_start_stopped(pg->peers[stopped_arr[stopped_permute[i]]].daemon, 
+                                         timeout, &churn_start_callback, churn_ctx);
   }
 
   GNUNET_free(running_arr);
@@ -2932,36 +2975,85 @@ GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TEST
 }
 
 /**
- * Shutdown all peers started in the given group.
+ * Start or stop an individual peer from the given group.
  *
  * @param pg handle to the peer group
+ * @param offset which peer to start or stop
+ * @param desired_status GNUNET_YES to have it running, GNUNET_NO to stop it
  * @param timeout how long to wait for shutdown
+ * @param cb function to call at the end
+ * @param cb_cls closure for cb
+ */
+void
+GNUNET_TESTING_daemons_vary (struct GNUNET_TESTING_PeerGroup *pg, 
+                            unsigned int offset,
+                            int desired_status,
+                            struct GNUNET_TIME_Relative timeout,
+                            GNUNET_TESTING_NotifyCompletion cb,
+                            void *cb_cls)
+{
+  struct ChurnContext *churn_ctx;
+
+  if (GNUNET_NO == desired_status)
+    {
+      if (NULL != pg->peers[offset].daemon)
+       {
+         churn_ctx = GNUNET_malloc(sizeof(struct ChurnContext));
+         churn_ctx->num_to_start = 0;
+         churn_ctx->num_to_stop = 1;
+         churn_ctx->cb = cb;
+         churn_ctx->cb_cls = cb_cls;  
+         GNUNET_TESTING_daemon_stop(pg->peers[offset].daemon, 
+                                    timeout, &churn_stop_callback, churn_ctx, 
+                                    GNUNET_NO, GNUNET_YES);     
+       }
+    }
+  else if (GNUNET_YES == desired_status)
+    {
+      if (NULL == pg->peers[offset].daemon)
+       {
+         churn_ctx = GNUNET_malloc(sizeof(struct ChurnContext));
+         churn_ctx->num_to_start = 1;
+         churn_ctx->num_to_stop = 0;
+         churn_ctx->cb = cb;
+         churn_ctx->cb_cls = cb_cls;  
+         GNUNET_TESTING_daemon_start_stopped(pg->peers[offset].daemon, 
+                                             timeout, &churn_start_callback, churn_ctx);
+       }
+    }
+  else
+    GNUNET_break (0);
+}
+
+
+/**
+ * Shutdown all peers started in the given group.
  *
+ * @param pg handle to the peer group
+ * @param timeout how long to wait for shutdown
  */
 void
-GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg, struct GNUNET_TIME_Relative timeout)
+GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg, 
+                            struct GNUNET_TIME_Relative timeout)
 {
   unsigned int off;
 
   for (off = 0; off < pg->total; off++)
     {
-      /* FIXME: should we wait for our
-         continuations to be called here? This
-         would require us to take a continuation
-         as well... */
+      /* FIXME: should we wait for our continuations to be called
+         here? This would require us to take a continuation as
+         well... */
 
       if (NULL != pg->peers[off].daemon)
         GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, timeout, NULL, NULL, GNUNET_YES, GNUNET_NO);
       if (NULL != pg->peers[off].cfg)
         GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg);
-
       if (pg->peers[off].allowed_peers != NULL)
         GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].allowed_peers);
       if (pg->peers[off].connect_peers != NULL)
         GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].connect_peers);
       if (pg->peers[off].blacklisted_peers != NULL)
         GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].blacklisted_peers);
-
     }
   GNUNET_free (pg->peers);
   if (NULL != pg->hosts)