Update from OSX
[m6w6/libmemcached] / libtest / test.cc
index 52dd03e7b4e60263b744b42e68df826fe9faa545..ef10028c5800160dabb687448ec433b0bc0ba321 100644 (file)
@@ -19,6 +19,7 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <config.h>
 #include <libtest/common.h>
 
 #include <cassert>
 
 #include <signal.h>
 
-#if defined(HAVE_CURL_CURL_H) && HAVE_CURL_CURL_H
-#include <curl/curl.h>
-#endif
-
 #ifndef __INTEL_COMPILER
 #pragma GCC diagnostic ignored "-Wold-style-cast"
 #endif
@@ -74,33 +71,14 @@ static long int timedif(struct timeval a, struct timeval b)
   return s + us;
 }
 
-static void cleanup_curl(void)
-{
-#if defined(HAVE_CURL_CURL_H) && HAVE_CURL_CURL_H
-  curl_global_cleanup();
-#endif
-}
-
 #include <getopt.h>
 #include <unistd.h>
 
 int main(int argc, char *argv[])
 {
-#if defined(HAVE_CURL_CURL_H) && HAVE_CURL_CURL_H
-  if (curl_global_init(CURL_GLOBAL_ALL))
-  {
-    Error << "curl_global_init(CURL_GLOBAL_ALL) failed";
-    return EXIT_FAILURE;
-  }
-#endif
-
-  if (atexit(cleanup_curl))
-  {
-    Error << "atexit() failed";
-    return EXIT_FAILURE;
-  }
-
-  bool opt_repeat= false;
+  bool opt_massive= false;
+  unsigned long int opt_repeat= 1; // Run all tests once
+  bool opt_quiet= false;
   std::string collection_to_run;
 
   // Options parsing
@@ -108,14 +86,19 @@ int main(int argc, char *argv[])
     enum long_option_t {
       OPT_LIBYATL_VERSION,
       OPT_LIBYATL_MATCH_COLLECTION,
+      OPT_LIBYATL_MASSIVE,
+      OPT_LIBYATL_QUIET,
       OPT_LIBYATL_REPEAT
     };
 
     static struct option long_options[]=
     {
-      {"repeat", no_argument, NULL, OPT_LIBYATL_REPEAT},
-      {"collection", required_argument, NULL, OPT_LIBYATL_MATCH_COLLECTION},
-      {0, 0, 0, 0}
+      { "version", no_argument, NULL, OPT_LIBYATL_VERSION },
+      { "quiet", no_argument, NULL, OPT_LIBYATL_QUIET },
+      { "repeat", no_argument, NULL, OPT_LIBYATL_REPEAT },
+      { "collection", required_argument, NULL, OPT_LIBYATL_MATCH_COLLECTION },
+      { "massive", no_argument, NULL, OPT_LIBYATL_MASSIVE },
+      { 0, 0, 0, 0 }
     };
 
     int option_index= 0;
@@ -132,14 +115,22 @@ int main(int argc, char *argv[])
       case OPT_LIBYATL_VERSION:
         break;
 
+      case OPT_LIBYATL_QUIET:
+        opt_quiet= true;
+        break;
+
       case OPT_LIBYATL_REPEAT:
-        opt_repeat= true;
+        opt_repeat= strtoul(optarg, (char **) NULL, 10);
         break;
 
       case OPT_LIBYATL_MATCH_COLLECTION:
         collection_to_run= optarg;
         break;
 
+      case OPT_LIBYATL_MASSIVE:
+        opt_massive= true;
+        break;
+
       case '?':
         /* getopt_long already printed an error message. */
         Error << "unknown option to getopt_long()";
@@ -153,11 +144,26 @@ int main(int argc, char *argv[])
 
   srandom((unsigned int)time(NULL));
 
-  if (getenv("LIBTEST_QUIET") and strcmp(getenv("LIBTEST_QUIET"), "0") == 0)
+  if (bool(getenv("YATL_REPEAT")) and (strtoul(getenv("YATL_REPEAT"), (char **) NULL, 10) > 1))
   {
-    close(STDOUT_FILENO);
+    opt_repeat= strtoul(getenv("YATL_REPEAT"), (char **) NULL, 10);
+  }
+
+  if ((bool(getenv("YATL_QUIET")) and (strcmp(getenv("YATL_QUIET"), "0") == 0)) or opt_quiet)
+  {
+    opt_quiet= true;
   }
   else if (getenv("JENKINS_URL"))
+  {
+    if (bool(getenv("YATL_QUIET")) and (strcmp(getenv("YATL_QUIET"), "1") == 0))
+    { }
+    else
+    {
+      opt_quiet= true;
+    }
+  }
+
+  if (opt_quiet)
   {
     close(STDOUT_FILENO);
   }
@@ -188,257 +194,286 @@ int main(int argc, char *argv[])
   }
 
   int exit_code;
-  do {
-    exit_code= EXIT_SUCCESS;
-    Framework *world= new Framework();
 
-    if (world == NULL)
-    {
-      Error << "Failed to create Framework()";
-      return EXIT_FAILURE;
-    }
+  try {
+    do {
+      exit_code= EXIT_SUCCESS;
+      Framework world;
 
-    assert(sigignore(SIGPIPE) == 0);
+      fatal_assert(sigignore(SIGPIPE) == 0);
 
-    libtest::SignalThread signal;
-    if (not signal.setup())
-    {
-      Error << "Failed to setup signals";
-      return EXIT_FAILURE;
-    }
-
-    Stats stats;
+      libtest::SignalThread signal;
+      if (signal.setup() == false)
+      {
+        Error << "Failed to setup signals";
+        return EXIT_FAILURE;
+      }
 
-    get_world(world);
+      Stats stats;
 
-    test_return_t error;
-    void *creators_ptr= world->create(error);
+      get_world(&world);
 
-    switch (error)
-    {
-    case TEST_SUCCESS:
-      break;
-
-    case TEST_SKIPPED:
-      Out << "SKIP " << argv[0];
-      delete world;
-      return EXIT_SUCCESS;
-
-    case TEST_FATAL:
-    case TEST_FAILURE:
-    case TEST_MEMORY_ALLOCATION_FAILURE:
-      delete world;
-      return EXIT_FAILURE;
-    }
+      test_return_t error;
+      void *creators_ptr= world.create(error);
 
-    if (getenv("TEST_COLLECTION"))
-    {
-      if (strlen(getenv("TEST_COLLECTION")))
+      switch (error)
       {
-        collection_to_run= getenv("TEST_COLLECTION");
-      }
-    }
-
-    if (collection_to_run.empty() == false)
-    {
-      Out << "Only testing " <<  collection_to_run;
-    }
+      case TEST_SUCCESS:
+        break;
 
-    char *wildcard= NULL;
-    if (argc == 3)
-    {
-      wildcard= argv[2];
-    }
+      case TEST_SKIPPED:
+        Out << "SKIP " << argv[0];
+        return EXIT_SUCCESS;
 
-    for (collection_st *next= world->collections; next and next->name and (not signal.is_shutdown()); next++)
-    {
-      bool failed= false;
-      bool skipped= false;
+      case TEST_FAILURE:
+        return EXIT_FAILURE;
+      }
 
-      if (collection_to_run.empty() == false and fnmatch(collection_to_run.c_str(), next->name, 0))
+      if (getenv("YATL_COLLECTION_TO_RUN"))
       {
-        continue;
+        if (strlen(getenv("YATL_COLLECTION_TO_RUN")))
+        {
+          collection_to_run= getenv("YATL_COLLECTION_TO_RUN");
+        }
       }
 
-      stats.collection_total++;
-
-      test_return_t collection_rc= world->startup(creators_ptr);
+      if (collection_to_run.compare("none") == 0)
+      {
+        return EXIT_SUCCESS;
+      }
 
-      if (collection_rc == TEST_SUCCESS and next->pre)
+      if (collection_to_run.empty() == false)
       {
-        collection_rc= world->runner()->pre(next->pre, creators_ptr);
+        Out << "Only testing " <<  collection_to_run;
       }
 
-      switch (collection_rc)
+      char *wildcard= NULL;
+      if (argc == 3)
       {
-      case TEST_SUCCESS:
-        break;
+        wildcard= argv[2];
+      }
 
-      case TEST_FATAL:
-      case TEST_FAILURE:
-        Out << next->name << " [ failed ]";
-        failed= true;
-        signal.set_shutdown(SHUTDOWN_GRACEFUL);
-        goto cleanup;
+      for (collection_st *next= world.collections; next and next->name and (not signal.is_shutdown()); next++)
+      {
+        bool failed= false;
+        bool skipped= false;
 
-      case TEST_SKIPPED:
-        Out << next->name << " [ skipping ]";
-        skipped= true;
-        goto cleanup;
+        if (collection_to_run.empty() == false and fnmatch(collection_to_run.c_str(), next->name, 0))
+        {
+          continue;
+        }
 
-      case TEST_MEMORY_ALLOCATION_FAILURE:
-        test_assert(0, "Allocation failure, or unknown return");
-      }
+        stats.collection_total++;
 
-      Out << "Collection: " << next->name;
+        test_return_t collection_rc= world.startup(creators_ptr);
 
-      for (test_st *run= next->tests; run->name; run++)
-      {
-        struct timeval start_time, end_time;
-        long int load_time= 0;
+        if (collection_rc == TEST_SUCCESS and next->pre)
+        {
+          collection_rc= world.runner()->pre(next->pre, creators_ptr);
+        }
 
-        if (wildcard && fnmatch(wildcard, run->name, 0))
+        switch (collection_rc)
         {
-          continue;
+        case TEST_SUCCESS:
+          break;
+
+        case TEST_FAILURE:
+          Out << next->name << " [ failed ]";
+          failed= true;
+          signal.set_shutdown(SHUTDOWN_GRACEFUL);
+          goto cleanup;
+
+        case TEST_SKIPPED:
+          Out << next->name << " [ skipping ]";
+          skipped= true;
+          goto cleanup;
+
+        default:
+          fatal_message("invalid return code");
         }
 
-        test_return_t return_code;
-        try {
-          if (test_success(return_code= world->item.startup(creators_ptr)))
+        Out << "Collection: " << next->name;
+
+        for (test_st *run= next->tests; run->name; run++)
+        {
+          struct timeval start_time, end_time;
+          long int load_time= 0;
+
+          if (wildcard && fnmatch(wildcard, run->name, 0))
           {
-            if (test_success(return_code= world->item.flush(creators_ptr, run)))
+            continue;
+          }
+
+          test_return_t return_code;
+          try {
+            if (test_success(return_code= world.item.startup(creators_ptr)))
             {
-              // @note pre will fail is SKIPPED is returned
-              if (test_success(return_code= world->item.pre(creators_ptr)))
+              if (test_success(return_code= world.item.flush(creators_ptr, run)))
               {
-                { // Runner Code
-                  gettimeofday(&start_time, NULL);
-                  assert(world->runner());
-                  assert(run->test_fn);
-                  return_code= world->runner()->run(run->test_fn, creators_ptr);
-                  gettimeofday(&end_time, NULL);
-                  load_time= timedif(end_time, start_time);
+                // @note pre will fail is SKIPPED is returned
+                if (test_success(return_code= world.item.pre(creators_ptr)))
+                {
+                  { // Runner Code
+                    gettimeofday(&start_time, NULL);
+                    assert(world.runner());
+                    assert(run->test_fn);
+                    try 
+                    {
+                      return_code= world.runner()->run(run->test_fn, creators_ptr);
+                    }
+                    // Special case where check for the testing of the exception
+                    // system.
+                    catch (libtest::fatal &e)
+                    {
+                      if (fatal::is_disabled())
+                      {
+                        fatal::increment_disabled_counter();
+                        return_code= TEST_SUCCESS;
+                      }
+                      else
+                      {
+                        throw;
+                      }
+                    }
+
+                    gettimeofday(&end_time, NULL);
+                    load_time= timedif(end_time, start_time);
+                  }
                 }
-              }
 
-              // @todo do something if post fails
-              (void)world->item.post(creators_ptr);
+                // @todo do something if post fails
+                (void)world.item.post(creators_ptr);
+              }
+              else if (return_code == TEST_SKIPPED)
+              { }
+              else if (return_code == TEST_FAILURE)
+              {
+                Error << " item.flush(failure)";
+                signal.set_shutdown(SHUTDOWN_GRACEFUL);
+              }
             }
             else if (return_code == TEST_SKIPPED)
             { }
             else if (return_code == TEST_FAILURE)
             {
-              Error << " item.flush(failure)";
+              Error << " item.startup(failure)";
               signal.set_shutdown(SHUTDOWN_GRACEFUL);
             }
           }
-          else if (return_code == TEST_SKIPPED)
-          { }
-          else if (return_code == TEST_FAILURE)
+
+          catch (libtest::fatal &e)
+          {
+            Error << "Fatal exception was thrown: " << e.what();
+            return_code= TEST_FAILURE;
+          }
+          catch (std::exception &e)
+          {
+            Error << "Exception was thrown: " << e.what();
+            return_code= TEST_FAILURE;
+          }
+          catch (...)
           {
-            Error << " item.startup(failure)";
+            Error << "Unknown exception occurred";
+            return_code= TEST_FAILURE;
+          }
+
+          stats.total++;
+
+          switch (return_code)
+          {
+          case TEST_SUCCESS:
+            Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << load_time / 1000 << "." << load_time % 1000 << "[ " << test_strerror(return_code) << " ]";
+            stats.success++;
+            break;
+
+          case TEST_FAILURE:
+            stats.failed++;
+            failed= true;
+            Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
+            break;
+
+          case TEST_SKIPPED:
+            stats.skipped++;
+            skipped= true;
+            Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
+            break;
+
+          default:
+            fatal_message("invalid return code");
+          }
+
+          if (test_failed(world.on_error(return_code, creators_ptr)))
+          {
+            Error << "Failed while running on_error()";
             signal.set_shutdown(SHUTDOWN_GRACEFUL);
+            break;
           }
         }
 
-        catch (std::exception &e)
-        {
-          Error << "Exception was thrown: " << e.what();
-          return_code= TEST_FAILURE;
-        }
-        catch (...)
+        (void) world.runner()->post(next->post, creators_ptr);
+
+cleanup:
+        if (failed == false and skipped == false)
         {
-          Error << "Unknown exception occurred";
-          return_code= TEST_FAILURE;
+          stats.collection_success++;
         }
 
-        stats.total++;
-
-        switch (return_code)
+        if (failed)
         {
-        case TEST_SUCCESS:
-          Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << load_time / 1000 << "." << load_time % 1000 << "[ " << test_strerror(return_code) << " ]";
-          stats.success++;
-          break;
-
-        case TEST_FATAL:
-        case TEST_FAILURE:
-          stats.failed++;
-          failed= true;
-          Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
-          break;
-
-        case TEST_SKIPPED:
-          stats.skipped++;
-          skipped= true;
-          Out << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
-          break;
-
-        case TEST_MEMORY_ALLOCATION_FAILURE:
-          test_assert(0, "Memory Allocation Error");
+          stats.collection_failed++;
         }
 
-        if (test_failed(world->on_error(return_code, creators_ptr)))
+        if (skipped)
         {
-          Error << "Failed while running on_error()";
-          signal.set_shutdown(SHUTDOWN_GRACEFUL);
-          break;
+          stats.collection_skipped++;
         }
-      }
 
-      (void) world->runner()->post(next->post, creators_ptr);
+        world.shutdown(creators_ptr);
+        Outn();
+      }
 
-cleanup:
-      if (failed == false and skipped == false)
+      if (not signal.is_shutdown())
       {
-        stats.collection_success++;
+        signal.set_shutdown(SHUTDOWN_GRACEFUL);
       }
 
-      if (failed)
+      shutdown_t status= signal.get_shutdown();
+      if (status == SHUTDOWN_FORCED)
       {
-        stats.collection_failed++;
+        Out << "Tests were aborted.";
+        exit_code= EXIT_FAILURE;
       }
-
-      if (skipped)
+      else if (stats.collection_failed)
       {
-        stats.collection_skipped++;
+        Out << "Some test failed.";
+        exit_code= EXIT_FAILURE;
+      }
+      else if (stats.collection_skipped and stats.collection_failed and stats.collection_success)
+      {
+        Out << "Some tests were skipped.";
+      }
+      else if (stats.collection_success and stats.collection_failed == 0)
+      {
+        Out << "All tests completed successfully.";
       }
 
-      world->shutdown(creators_ptr);
-      Outn();
-    }
-
-    if (not signal.is_shutdown())
-    {
-      signal.set_shutdown(SHUTDOWN_GRACEFUL);
-    }
-
-    shutdown_t status= signal.get_shutdown();
-    if (status == SHUTDOWN_FORCED)
-    {
-      Out << "Tests were aborted.";
-      exit_code= EXIT_FAILURE;
-    }
-    else if (stats.collection_failed)
-    {
-      Out << "Some test failed.";
-      exit_code= EXIT_FAILURE;
-    }
-    else if (stats.collection_skipped and stats.collection_failed and stats.collection_success)
-    {
-      Out << "Some tests were skipped.";
-    }
-    else if (stats.collection_success and stats.collection_failed == 0)
-    {
-      Out << "All tests completed successfully.";
-    }
-
-    stats_print(&stats);
-
-    delete world;
+      stats_print(&stats);
 
-    Outn(); // Generate a blank to break up the messages if make check/test has been run
-  } while (exit_code == EXIT_SUCCESS and opt_repeat);
+      Outn(); // Generate a blank to break up the messages if make check/test has been run
+    } while (exit_code == EXIT_SUCCESS and --opt_repeat);
+  }
+  catch (libtest::fatal& e)
+  {
+    std::cerr << e.what() << std::endl;
+  }
+  catch (std::exception& e)
+  {
+    std::cerr << e.what() << std::endl;
+  }
+  catch (...)
+  {
+    std::cerr << "Unknown exception halted execution." << std::endl;
+  }
 
   return exit_code;
 }