change to configs, use readable names for topologies and connect options instead...
[oweals/gnunet.git] / src / testing / test_testing_topology.c
index 2006cc468454c51dfe4838b6e4cf52be7fe56e61..5d71d201646943cbe172fab1bbc51135700d4fd9 100644 (file)
@@ -25,7 +25,7 @@
 #include "gnunet_testing_lib.h"
 #include "gnunet_core_service.h"
 
-#define VERBOSE GNUNET_YES
+#define VERBOSE GNUNET_NO
 
 /**
  * How long until we fail the whole testcase?
@@ -33,9 +33,9 @@
 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
 
 /**
- * How long until we give up on connecting the peers?
+ * How long until we give up on starting the peers?
  */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 500)
 
 #define DEFAULT_NUM_PEERS 4
 
@@ -69,18 +69,32 @@ const struct GNUNET_CONFIGURATION_Handle *main_cfg;
 
 GNUNET_SCHEDULER_TaskIdentifier die_task;
 
-static char *dotOutFileName = "topology.dot";
+static char *dotOutFileName;
 
 static FILE *dotOutFile;
 
 static char *topology_string;
 
+static char *blacklist_transports;
+
 static int transmit_ready_scheduled;
 
 static int transmit_ready_failed;
 
 static int transmit_ready_called;
 
+static enum GNUNET_TESTING_Topology topology;
+
+static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* Don't do any blacklisting */
+
+static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */
+
+static enum GNUNET_TESTING_TopologyOption connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL;
+
+static double connect_topology_option_modifier = 0.0;
+
+static char *test_directory;
+
 #define MTYPE 12345
 
 struct GNUNET_TestMessage
@@ -160,12 +174,12 @@ finish_testing ()
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       "transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n", transmit_ready_scheduled, transmit_ready_failed, transmit_ready_called);
 #endif
-  sleep(1);
+
 #if VERBOSE
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       "Calling daemons_stop\n");
 #endif
-  GNUNET_TESTING_daemons_stop (pg);
+  GNUNET_TESTING_daemons_stop (pg, TIMEOUT);
 #if VERBOSE
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       "daemons_stop finished\n");
@@ -268,7 +282,7 @@ end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
 
   if (pg != NULL)
     {
-      GNUNET_TESTING_daemons_stop (pg);
+      GNUNET_TESTING_daemons_stop (pg, TIMEOUT);
       ok = 7331;                /* Opposite of leet */
     }
   else
@@ -478,7 +492,8 @@ topology_callback (void *cls,
 
       GNUNET_SCHEDULER_cancel (sched, die_task);
       die_task = GNUNET_SCHEDULER_NO_TASK;
-      GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1), &send_test_messages, test_messages);
+      GNUNET_SCHEDULER_add_now (sched, &send_test_messages, test_messages);
+      //GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1), &send_test_messages, test_messages);
     }
   else if (total_connections + failed_connections == expected_connections)
     {
@@ -486,7 +501,8 @@ topology_callback (void *cls,
         {
           GNUNET_SCHEDULER_cancel (sched, die_task);
           die_task = GNUNET_SCHEDULER_NO_TASK;
-          GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1), &send_test_messages, test_messages);
+          GNUNET_SCHEDULER_add_now (sched, &send_test_messages, test_messages);
+          //GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1), &send_test_messages, test_messages);
         }
       else
         {
@@ -505,20 +521,13 @@ topology_callback (void *cls,
     }
 }
 
-
 static void
-create_topology ()
+connect_topology ()
 {
   expected_connections = -1;
   if ((pg != NULL) && (peers_left == 0))
     {
-      /* create_topology will read the topology information from
-         the config already contained in the peer group, so should
-         we have create_topology called from start peers?  I think
-         maybe this way is best so that the client can know both
-         when peers are started, and when they are connected.
-       */
-      expected_connections = GNUNET_TESTING_create_topology (pg);
+      expected_connections = GNUNET_TESTING_connect_topology (pg, connection_topology, connect_topology_option, connect_topology_option_modifier);
 #if VERBOSE
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Have %d expected connections\n", expected_connections);
@@ -528,21 +537,52 @@ create_topology ()
   GNUNET_SCHEDULER_cancel (sched, die_task);
   if (expected_connections == GNUNET_SYSERR)
     {
+      die_task = GNUNET_SCHEDULER_add_now (sched,
+                                           &end_badly, "from connect topology (bad return)");
+    }
+
+  die_task = GNUNET_SCHEDULER_add_delayed (sched,
+                                           TEST_TIMEOUT,
+                                           &end_badly, "from connect topology (timeout)");
+}
+
+static void
+create_topology ()
+{
+  peers_left = num_peers; /* Reset counter */
+  if (GNUNET_TESTING_create_topology (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR)
+    {
+#if VERBOSE
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Topology set up, now starting peers!\n");
+#endif
+      GNUNET_TESTING_daemons_continue_startup(pg);
+    }
+  else
+    {
+      GNUNET_SCHEDULER_cancel (sched, die_task);
       die_task = GNUNET_SCHEDULER_add_now (sched,
                                            &end_badly, "from create topology (bad return)");
     }
+  GNUNET_SCHEDULER_cancel (sched, die_task);
   die_task = GNUNET_SCHEDULER_add_delayed (sched,
                                            TEST_TIMEOUT,
-                                           &end_badly, "from create topology (timeout)");
+                                           &end_badly, "from continue startup (timeout)");
 }
 
 
 static void
-my_cb (void *cls,
+peers_started_callback (void *cls,
        const struct GNUNET_PeerIdentity *id,
        const struct GNUNET_CONFIGURATION_Handle *cfg,
        struct GNUNET_TESTING_Daemon *d, const char *emsg)
 {
+  if (emsg != NULL)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to start daemon with error: `%s'\n",
+                  emsg);
+      return;
+    }
   GNUNET_assert (id != NULL);
 #if VERBOSE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
@@ -562,12 +602,55 @@ my_cb (void *cls,
       die_task = GNUNET_SCHEDULER_add_delayed (sched,
                                                GNUNET_TIME_relative_multiply
                                                (GNUNET_TIME_UNIT_MINUTES, 5),
-                                               &end_badly, "from my_cb");
-      create_topology ();
+                                               &end_badly, "from peers_started_callback");
+
+      connect_topology ();
       ok = 0;
     }
 }
 
+/**
+ * Callback indicating that the hostkey was created for a peer.
+ *
+ * @param cls NULL
+ * @param id the peer identity
+ * @param d the daemon handle (pretty useless at this point, remove?)
+ * @param emsg non-null on failure
+ */
+void hostkey_callback (void *cls,
+                       const struct GNUNET_PeerIdentity *id,
+                       struct GNUNET_TESTING_Daemon *d,
+                       const char *emsg)
+{
+  if (emsg != NULL)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Hostkey callback received error: %s\n", emsg);
+    }
+
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Hostkey created for peer `%s'\n",
+                GNUNET_i2s(id));
+#endif
+    peers_left--;
+    if (peers_left == 0)
+      {
+#if VERBOSE
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "All %d hostkeys created, now creating topology!\n",
+                    num_peers);
+#endif
+        GNUNET_SCHEDULER_cancel (sched, die_task);
+        /* Set up task in case topology creation doesn't finish
+         * within a reasonable amount of time */
+        die_task = GNUNET_SCHEDULER_add_delayed (sched,
+                                                 GNUNET_TIME_relative_multiply
+                                                 (GNUNET_TIME_UNIT_MINUTES, 5),
+                                                 &end_badly, "from hostkey_callback");
+        GNUNET_SCHEDULER_add_now(sched, &create_topology, NULL);
+        ok = 0;
+      }
+}
 
 static void
 run (void *cls,
@@ -575,6 +658,11 @@ run (void *cls,
      char *const *args,
      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
+  unsigned long long topology_num;
+  unsigned long long connect_topology_num;
+  unsigned long long blacklist_topology_num;
+  unsigned long long connect_topology_option_num;
+  char *connect_topology_option_modifier_string;
   sched = s;
   ok = 1;
 
@@ -588,6 +676,52 @@ run (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Starting daemons based on config file %s\n", cfgfile);
 #endif
+
+  if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_string(cfg, "paths", "servicehome", &test_directory))
+    {
+      ok = 404;
+      return;
+    }
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "topology",
+                                             &topology_num))
+    topology = topology_num;
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_topology",
+                                             &connect_topology_num))
+    connection_topology = connect_topology_num;
+
+  if (GNUNET_YES ==
+        GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_topology_option",
+                                               &connect_topology_option_num))
+    connect_topology_option = connect_topology_option_num;
+
+  if (GNUNET_YES ==
+        GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "connect_topology_option_modifier",
+                                               &connect_topology_option_modifier_string))
+    {
+      if (sscanf(connect_topology_option_modifier_string, "%lf", &connect_topology_option_modifier) != 1)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+        _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+        connect_topology_option_modifier_string,
+        "connect_topology_option_modifier",
+        "TESTING");
+      }
+      GNUNET_free (connect_topology_option_modifier_string);
+    }
+
+  if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "blacklist_transports",
+                                         &blacklist_transports))
+    blacklist_transports = NULL;
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "blacklist_topology",
+                                             &blacklist_topology_num))
+    blacklist_topology = blacklist_topology_num;
+
   if (GNUNET_SYSERR ==
       GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
                                              &num_peers))
@@ -604,7 +738,7 @@ run (void *cls,
                                            &end_badly, "didn't start all daemons in reasonable amount of time!!!");
 
   pg = GNUNET_TESTING_daemons_start (sched, cfg,
-                                     peers_left, &my_cb, NULL,
+                                     peers_left, TIMEOUT, &hostkey_callback, NULL, &peers_started_callback, NULL,
                                      &topology_callback, NULL, NULL);
 
 }
@@ -616,6 +750,7 @@ check ()
   char *config_file_name;
   GNUNET_asprintf(&binary_name, "test-testing-topology-%s", topology_string);
   GNUNET_asprintf(&config_file_name, "test_testing_data_topology_%s.conf", topology_string);
+  int ret;
   char *const argv[] = {binary_name,
     "-c",
     config_file_name,
@@ -627,9 +762,13 @@ check ()
   struct GNUNET_GETOPT_CommandLineOption options[] = {
     GNUNET_GETOPT_OPTION_END
   };
-  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
+  ret = GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
                       argv, binary_name, "nohelp",
                       options, &run, &ok);
+  if (ret != GNUNET_OK)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "`test-testing-topology-%s': Failed with error code %d\n", topology_string, ret);
+    }
   GNUNET_free(binary_name);
   GNUNET_free(config_file_name);
   return ok;
@@ -652,6 +791,8 @@ main (int argc, char *argv[])
   topology_string++;
 
   GNUNET_asprintf(&our_binary_name, "test-testing-topology_%s", topology_string);
+  GNUNET_asprintf(&dotOutFileName, "topology_%s.dot", topology_string);
+
   GNUNET_log_setup (our_binary_name,
 #if VERBOSE
                     "DEBUG",
@@ -665,9 +806,12 @@ main (int argc, char *argv[])
    * Need to remove base directory, subdirectories taken care
    * of by the testing framework.
    */
-  GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
+  if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Failed to remove testing directory %s\n", test_directory);
+    }
   GNUNET_free(our_binary_name);
   return ret;
 }
 
-/* end of test_testing_group.c */
+/* end of test_testing_topology.c */