Update libtest.
authorBrian Aker <brian@tangent.org>
Mon, 22 Oct 2012 00:48:10 +0000 (20:48 -0400)
committerBrian Aker <brian@tangent.org>
Mon, 22 Oct 2012 00:48:10 +0000 (20:48 -0400)
28 files changed:
configure.ac
libtest/alarm.cc [new file with mode: 0644]
libtest/alarm.h [new file with mode: 0644]
libtest/cmdline.cc
libtest/cmdline.h
libtest/collection.cc
libtest/comparison.hpp
libtest/core_count.cc [new file with mode: 0644]
libtest/cpu.cc
libtest/fatal.cc
libtest/fatal.hpp
libtest/framework.cc
libtest/gearmand.cc
libtest/has.cc
libtest/http.cc
libtest/include.am
libtest/killpid.cc
libtest/main.cc
libtest/memcached.hpp
libtest/port.cc
libtest/server.cc
libtest/server_container.cc
libtest/signal.cc
libtest/signal.h
libtest/test.hpp
libtest/timer.hpp
libtest/unittest.cc
m4/ax_harden_compiler_flags.m4

index 28fa4303b03ca6b544b57bd73bc53aeb928c7066..a6a4f76bd6a8caa414db5e03719a17afec92a060 100644 (file)
@@ -52,8 +52,6 @@ AX_ASSERT
 
 AX_PLATFORM
 
-gl_VISIBILITY
-AS_IF([ test -n "$CFLAG_VISIBILITY" ], [ CPPFLAGS="$CPPFLAGS $CFLAG_VISIBILITY" ])
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 
 AX_CXX_HEADER_STDCXX_98
@@ -291,6 +289,7 @@ echo "   * C Flags:                   $CFLAGS"
 echo "   * C++ Compiler:              $CXX_VERSION"
 echo "   * C++ Flags:                 $CXXFLAGS"
 echo "   * CPP Flags:                 $CPPFLAGS"
+echo "   * LIB Flags:                 $LIB"
 echo "   * Assertions enabled:        $ax_enable_assert"
 echo "   * Debug enabled:             $ax_enable_debug"
 echo "   * Warnings as failure:       $ac_cv_warnings_as_errors"
diff --git a/libtest/alarm.cc b/libtest/alarm.cc
new file mode 100644 (file)
index 0000000..08ac787
--- /dev/null
@@ -0,0 +1,85 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <libtest/common.h>
+
+#include <sys/time.h>
+#include <cstdlib>
+
+namespace libtest {
+
+static const struct timeval default_it_value= { 600, 0 };
+static const struct timeval default_it_interval= { 0, 0 };
+static const struct itimerval defualt_timer= { default_it_interval, default_it_value };
+
+static const struct itimerval cancel_timer= { default_it_interval, default_it_interval };
+
+
+void set_alarm()
+{
+  if (setitimer(ITIMER_VIRTUAL, &defualt_timer, NULL) == -1)
+  {
+    Error << "setitimer() failed";
+  }
+}
+
+void set_alarm(long tv_sec, long tv_usec)
+{
+#if defined(TARGET_OS_OSX) && TARGET_OS_OSX
+  struct timeval it_value= { time_t(tv_sec), suseconds_t(tv_usec) };
+#else
+  struct timeval it_value= { tv_sec, tv_usec };
+#endif
+
+  struct itimerval timer= { default_it_interval, it_value };
+
+  if (setitimer(ITIMER_VIRTUAL, &timer, NULL) == -1)
+  {
+    Error << "setitimer() failed";
+  }
+}
+
+void cancel_alarm()
+{
+  if (setitimer(ITIMER_VIRTUAL, &cancel_timer, NULL) == -1)
+  {
+    Error << "setitimer() failed";
+  }
+}
+
+} // namespace libtest
+
diff --git a/libtest/alarm.h b/libtest/alarm.h
new file mode 100644 (file)
index 0000000..f675c58
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+void set_alarm(long tv_sec, long tv_usec);
+void set_alarm();
+void cancel_alarm();
+
+} // namespace libtest
+
index 5c3d09f2960487a8169d9b57ab807aa681193120..d4dd970b9ebf47e0694ee2cb484b492bac5fd4bc 100644 (file)
@@ -59,26 +59,9 @@ using namespace libtest;
 static char **environ= NULL;
 #endif
 
-extern "C" {
-  static int exited_successfully(int status)
-  {
-    if (status == 0)
-    {
-      return EXIT_SUCCESS;
-    }
-
-    if (WIFEXITED(status) == true)
-    {
-      return WEXITSTATUS(status);
-    }
-    else if (WIFSIGNALED(status) == true)
-    {
-      return WTERMSIG(status);
-    }
-
-    return EXIT_FAILURE;
-  }
-}
+#ifndef FD_CLOEXEC
+# define FD_CLOEXEC 0
+#endif
 
 namespace {
 
@@ -115,14 +98,16 @@ namespace {
     switch (arg)
     {
     case 127:
-      return Application::INVALID;
+      return Application::INVALID_POSIX_SPAWN;
 
     case 0:
       return Application::SUCCESS;
 
-    default:
     case 1:
       return Application::FAILURE;
+
+    default:
+      return Application::UNKNOWN;
     }
   }
 }
@@ -140,7 +125,9 @@ Application::Application(const std::string& arg, const bool _use_libtool_arg) :
   stdin_fd(STDIN_FILENO),
   stdout_fd(STDOUT_FILENO),
   stderr_fd(STDERR_FILENO),
-  _pid(-1)
+  _pid(-1),
+  _status(0),
+  _app_exit_state(UNINITIALIZED)
   { 
     if (_use_libtool)
     {
@@ -195,9 +182,25 @@ Application::error_t Application::run(const char *args[])
   posix_spawnattr_t spawnattr;
   posix_spawnattr_init(&spawnattr);
 
-  sigset_t set;
-  sigemptyset(&set);
-  fatal_assert(posix_spawnattr_setsigmask(&spawnattr, &set) == 0);
+  short flags= 0;
+
+  // Child should not block signals
+  flags |= POSIX_SPAWN_SETSIGMASK;
+
+  sigset_t mask;
+  sigemptyset(&mask);
+
+  fatal_assert(posix_spawnattr_setsigmask(&spawnattr, &mask) == 0);
+
+#if defined(POSIX_SPAWN_USEVFORK) || defined(__linux__)
+  // Use USEVFORK on linux
+  flags |= POSIX_SPAWN_USEVFORK;
+#endif
+
+  flags |= POSIX_SPAWN_SETPGROUP;
+  fatal_assert(posix_spawnattr_setpgroup(&spawnattr, 0) == 0);
+
+  fatal_assert(posix_spawnattr_setflags(&spawnattr, flags) == 0);
   
   create_argv(args);
 
@@ -254,15 +257,7 @@ Application::error_t Application::run(const char *args[])
   }
   else
   {
-
-    if (_use_libtool)
-    {
-      spawn_ret= posix_spawn(&_pid, built_argv[0], &file_actions, &spawnattr, &built_argv[0], NULL);
-    }
-    else
-    {
-      spawn_ret= posix_spawnp(&_pid, built_argv[0], &file_actions, &spawnattr, &built_argv[0], NULL);
-    }
+    spawn_ret= posix_spawn(&_pid, built_argv[0], &file_actions, &spawnattr, &built_argv[0], NULL);
   }
 
   posix_spawn_file_actions_destroy(&file_actions);
@@ -279,8 +274,24 @@ Application::error_t Application::run(const char *args[])
       Error << strerror(spawn_ret) << "(" << spawn_ret << ")";
     }
     _pid= -1;
-    return Application::INVALID;
+    return Application::INVALID_POSIX_SPAWN;
+  }
+
+  assert(_pid != -1);
+  if (_pid == -1)
+  {
+    return Application::INVALID_POSIX_SPAWN;
+  }
+
+#if 0
+  app_thread_st* _app_thread= new app_thread_st(_pid, _status, built_argv[0], _app_exit_state);
+  int error;
+  if ((error= pthread_create(&_thread, NULL, &app_thread, _app_thread)) != 0)
+  {
+    Error << "pthread_create() died during pthread_create(" << strerror(error) << ")";
+    return Application::FAILURE;
   }
+#endif
 
   return Application::SUCCESS;
 }
@@ -302,29 +313,9 @@ void Application::murder()
     int count= 5;
     while ((count--) > 0 and check())
     {
-      int kill_ret= kill(_pid, SIGTERM);
-      if (kill_ret == 0)
+      if (kill(_pid, SIGTERM) == 0)
       {
-        int status= 0;
-        pid_t waitpid_ret;
-        if ((waitpid_ret= waitpid(_pid, &status, WNOHANG)) == -1)
-        {
-          switch (errno)
-          {
-          case ECHILD:
-          case EINTR:
-            break;
-
-          default:
-            Error << "waitpid() failed after kill with error of " << strerror(errno);
-            break;
-          }
-        }
-
-        if (waitpid_ret == 0)
-        {
-          libtest::dream(1, 0);
-        }
+        join();
       }
       else
       {
@@ -338,6 +329,7 @@ void Application::murder()
     // If for whatever reason it lives, kill it hard
     if (check())
     {
+      Error << "using SIGKILL, things will likely go poorly from this point";
       (void)kill(_pid, SIGKILL);
     }
   }
@@ -409,119 +401,68 @@ bool Application::slurp()
   return data_was_read;
 }
 
-Application::error_t Application::wait(bool nohang)
+Application::error_t Application::join()
 {
-  if (_pid == -1)
-  {
-    return Application::INVALID;
-  }
-
-  slurp();
+  pid_t waited_pid= waitpid(_pid, &_status, 0);
 
-  error_t exit_code= FAILURE;
+  if (waited_pid == _pid and WIFEXITED(_status) == false)
   {
-    int status= 0;
-    pid_t waited_pid;
-    if ((waited_pid= waitpid(_pid, &status, nohang ? WNOHANG : 0)) == -1)
+    /*
+      What we are looking for here is how the exit status happened.
+      - 127 means that posix_spawn() itself had an error.
+      - If WEXITSTATUS is positive we need to see if it is a signal that we sent to kill the process. If not something bad happened in the process itself. 
+      - Finally something has happened that we don't currently understand.
+    */
+    if (WEXITSTATUS(_status) == 127)
     {
-      switch (errno)
-      {
-      case ECHILD:
-        exit_code= Application::SUCCESS;
-        break;
-
-      case EINTR:
-        break;
-
-      default:
-        Error << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(_pid);
-        break;
-      }
+      _app_exit_state= Application::INVALID_POSIX_SPAWN;
+      std::string error_string("posix_spawn() failed pid:");
+      error_string+= _pid;
+      error_string+= " name:";
+      error_string+= built_argv[0];
+      throw std::logic_error(error_string);
     }
-    else if (waited_pid == 0)
+    else if WIFSIGNALED(_status)
     {
-      exit_code= Application::SUCCESS;
+      // memcached will die with SIGHUP
+      if (WTERMSIG(_status) != SIGTERM and WTERMSIG(_status) != SIGHUP)
+      {
+        _app_exit_state= Application::INVALID_POSIX_SPAWN;
+        std::string error_string(built_argv[0]);
+        error_string+= " was killed by signal ";
+        error_string+= strsignal(WTERMSIG(_status));
+        throw std::runtime_error(error_string);
+      }
+
+      _app_exit_state= Application::SIGTERM_KILLED;
+      Error << "waitpid() application terminated at request"
+        << " pid:" << _pid 
+        << " name:" << built_argv[0];
     }
     else
     {
-      if (waited_pid != _pid)
-      {
-        throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Pid mismatch, %d != %d", int(waited_pid), int(_pid));
-      }
-      exit_code= int_to_error_t(exited_successfully(status));
+      _app_exit_state= Application::UNKNOWN;
+      Error << "Unknown logic state at exit:" << WEXITSTATUS(_status) 
+        << " pid:" << _pid
+        << " name:" << built_argv[0];
     }
   }
-
-  slurp();
-
-#if 0
-  if (exit_code == Application::INVALID)
+  else if (waited_pid == _pid and WIFEXITED(_status))
   {
-    Error << print_argv(built_argv, _argc);
+    _app_exit_state= int_to_error_t(WEXITSTATUS(_status));
   }
-#endif
-
-  return exit_code;
-}
-
-Application::error_t Application::join()
-{
-  if (_pid == -1)
+  else if (waited_pid == -1)
   {
-    return Application::INVALID;
+    _app_exit_state= Application::UNKNOWN;
+    Error << "waitpid() returned errno:" << strerror(errno);
   }
-
-  slurp();
-
-  error_t exit_code= FAILURE;
-  {
-    int status= 0;
-    pid_t waited_pid;
-    do {
-      waited_pid= waitpid(_pid, &status, 0);
-    } while (waited_pid == -1 and (errno == EINTR or errno == EAGAIN));
-
-    if (waited_pid == -1)
-    {
-      switch (errno)
-      {
-      case ECHILD:
-        exit_code= Application::SUCCESS;
-        break;
-
-      case EINTR:
-        break;
-
-      default:
-        Error << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(_pid);
-        break;
-      }
-    }
-    else if (waited_pid == 0)
-    {
-      exit_code= Application::SUCCESS;
-    }
-    else
-    {
-      if (waited_pid != _pid)
-      {
-        throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Pid mismatch, %d != %d", int(waited_pid), int(_pid));
-      }
-
-      exit_code= int_to_error_t(exited_successfully(status));
-    }
-  }
-
-  slurp();
-
-#if 0
-  if (exit_code == Application::INVALID)
+  else
   {
-    Error << print_argv(built_argv, _argc);
+    _app_exit_state= Application::UNKNOWN;
+    throw std::logic_error("waitpid() returned an unknown value");
   }
-#endif
 
-  return exit_code;
+  return _app_exit_state;
 }
 
 void Application::add_long_option(const std::string& name, const std::string& option_value)
@@ -604,14 +545,24 @@ bool Application::Pipe::read(libtest::vchar_t& arg)
 
 void Application::Pipe::nonblock()
 {
-  int ret;
-  if ((ret= fcntl(_pipe_fd[READ], F_GETFL, 0)) == -1)
+  int flags;
+  {
+    flags= fcntl(_pipe_fd[READ], F_GETFL, 0);
+  } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
+
+  if (flags == -1)
   {
     Error << "fcntl(F_GETFL) " << strerror(errno);
     throw strerror(errno);
   }
 
-  if ((ret= fcntl(_pipe_fd[READ], F_SETFL, ret | O_NONBLOCK)) == -1)
+  int rval;
+  do
+  {
+    rval= fcntl(_pipe_fd[READ], F_SETFL, flags | O_NONBLOCK);
+  } while (rval == -1 and (errno == EINTR or errno == EAGAIN));
+
+  if (rval == -1)
   {
     Error << "fcntl(F_SETFL) " << strerror(errno);
     throw strerror(errno);
@@ -624,7 +575,7 @@ void Application::Pipe::reset()
   close(WRITE);
 
 #if defined(HAVE_PIPE2) && HAVE_PIPE2
-  if (pipe2(_pipe_fd, O_NONBLOCK) == -1)
+  if (pipe2(_pipe_fd, O_NONBLOCK|O_CLOEXEC) == -1)
 #else
   if (pipe(_pipe_fd) == -1)
 #endif
@@ -634,26 +585,44 @@ void Application::Pipe::reset()
   _open[0]= true;
   _open[1]= true;
 
-  if (true)
+#if defined(HAVE_PIPE2) && HAVE_PIPE2
   {
     nonblock();
     cloexec();
   }
+#endif
 }
 
 void Application::Pipe::cloexec()
 {
-  int ret;
-  if ((ret= fcntl(_pipe_fd[WRITE], F_GETFD, 0)) == -1)
+  //if (SOCK_CLOEXEC == 0)
   {
-    Error << "fcntl(F_GETFD) " << strerror(errno);
-    throw strerror(errno);
-  }
+    if (FD_CLOEXEC) 
+    {
+      int flags;
+      do 
+      {
+        flags= fcntl(_pipe_fd[WRITE], F_GETFD, 0);
+      } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
 
-  if ((ret= fcntl(_pipe_fd[WRITE], F_SETFD, ret | FD_CLOEXEC)) == -1)
-  {
-    Error << "fcntl(F_SETFD) " << strerror(errno);
-    throw strerror(errno);
+      if (flags == -1)
+      {
+        Error << "fcntl(F_GETFD) " << strerror(errno);
+        throw strerror(errno);
+      }
+
+      int rval;
+      do
+      { 
+        rval= fcntl(_pipe_fd[WRITE], F_SETFD, flags | FD_CLOEXEC);
+      } while (rval == -1 && (errno == EINTR or errno == EAGAIN));
+
+      if (rval == -1)
+      {
+        Error << "fcntl(F_SETFD) " << strerror(errno);
+        throw strerror(errno);
+      }
+    }
   }
 }
 
@@ -716,12 +685,14 @@ void Application::create_argv(const char *args[])
   if (_use_valgrind)
   {
     /*
-      valgrind --error-exitcode=1 --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE
+      valgrind --error-exitcode=1 --leak-check=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE
     */
     built_argv.push_back(strdup("valgrind"));
     built_argv.push_back(strdup("--error-exitcode=1"));
     built_argv.push_back(strdup("--leak-check=yes"));
+#if 0
     built_argv.push_back(strdup("--show-reachable=yes"));
+#endif
     built_argv.push_back(strdup("--track-fds=yes"));
 #if 0
     built_argv[x++]= strdup("--track-origin=yes");
index 46f7ad78a886f2997ad3e588920b9da9dd3f832b..ae4d9ba1d67751f73315277095642842d2d53ed7 100644 (file)
 #define EXIT_SKIP 77
 #define EXIT_FATAL 77
 
+#ifndef EX_NOEXEC
+#  define EX_NOEXEC 126
+#endif
+
+#ifndef EX_NOTFOUND
+#  define EX_NOTFOUND 127
+#endif
+
 namespace libtest {
 
 class Application {
@@ -53,7 +61,11 @@ public:
   enum error_t {
     SUCCESS= EXIT_SUCCESS,
     FAILURE= EXIT_FAILURE,
-    INVALID= 127
+    UNINITIALIZED,
+    SIGTERM_KILLED,
+    UNKNOWN,
+    UNKNOWN_SIGNAL,
+    INVALID_POSIX_SPAWN= 127
   };
 
   static const char* toString(error_t arg)
@@ -63,12 +75,22 @@ public:
     case Application::SUCCESS:
       return "EXIT_SUCCESS";
 
+    case Application::UNINITIALIZED:
+      return "UNINITIALIZED";
+
+    case Application::SIGTERM_KILLED:
+      return "Exit happened via SIGTERM";
+
     case Application::FAILURE:
       return "EXIT_FAILURE";
 
-    case Application::INVALID:
-      return "127";
+    case Application::UNKNOWN_SIGNAL:
+      return "Exit happened via a signal which was not SIGTERM";
+
+    case Application::INVALID_POSIX_SPAWN:
+      return "127: Invalid call to posix_spawn()";
 
+    case Application::UNKNOWN:
     default:
       break;
     }
@@ -111,7 +133,6 @@ public:
   void add_option(const std::string&, const std::string&);
   void add_long_option(const std::string& option_name, const std::string& option_value);
   error_t run(const char *args[]= NULL);
-  error_t wait(bool nohang= true);
   Application::error_t join();
 
   libtest::vchar_t stdout_result() const
@@ -201,6 +222,9 @@ private:
   pid_t _pid;
   libtest::vchar_t _stdout_buffer;
   libtest::vchar_t _stderr_buffer;
+  int _status;
+  pthread_t _thread;
+  error_t _app_exit_state;
 };
 
 static inline std::ostream& operator<<(std::ostream& output, const enum Application::error_t &arg)
index 26e8bb44e33d455ef725546dc98fe338da3427b3..3bf571e8358b14ce4c25a2a4c6a5680eec34b295 100644 (file)
@@ -118,19 +118,21 @@ test_return_t Collection::exec()
           }
         }
 
-        alarm(600);
+        set_alarm();
+
         try 
         {
           return_code= runner_code(_frame, run, _timer);
         }
         catch (...)
         {
-          alarm(0);
+          cancel_alarm();
+
           throw;
         }
-        alarm(0);
+        libtest::cancel_alarm();
       }
-      catch (libtest::exception &e)
+      catch (libtest::fatal &e)
       {
         stream::cerr(e.file(), e.line(), e.func()) << e.what();
         _failed++;
index 30119d1e3b1233a9b830512924dadc100f35386f..5b3172a10ad557d7f0f9a37fdfcdb21bd6910a1e 100644 (file)
@@ -62,6 +62,9 @@ bool valgrind_is_caller(void);
 LIBTEST_API
 bool _in_valgrind(const char *file, int line, const char *func);
 
+LIBTEST_API
+bool helgrind_is_caller(void);
+
 template <class T_comparable>
 bool _compare_truth(const char *file, int line, const char *func, T_comparable __expected, const char *assertation_label)
 {
diff --git a/libtest/core_count.cc b/libtest/core_count.cc
new file mode 100644 (file)
index 0000000..351ae1c
--- /dev/null
@@ -0,0 +1,135 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+
+#include <cstdlib>
+#include <fcntl.h>
+#include <getopt.h>
+#include <iostream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libtest/cpu.hpp>
+
+static void version_command(const char *command_name, int major_version, int minor_version)
+{
+  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
+}
+
+static void help_command(const char *command_name,
+                         int major_version, int minor_version,
+                         const struct option *long_options)
+{
+  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
+  std::cout << "Prints the number of cores found on the local host." << std::endl << std::endl;
+
+  for (uint32_t x= 0; long_options[x].name; x++)
+  {
+    std::cout << "\t --" << long_options[x].name << char(long_options[x].has_arg ? '=' : ' ') << std::endl;
+  }
+
+  std::cout << std::endl;
+}
+
+enum {
+  OPT_HELP,
+  OPT_VERSION
+};
+
+static void options_parse(int argc, char *argv[])
+{
+  static struct option long_options[]=
+  {
+    { "version", no_argument, NULL, OPT_VERSION},
+    { "help", no_argument, NULL, OPT_HELP},
+    {0, 0, 0, 0},
+  };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  int option_index= 0;
+
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
+    if (option_rv == -1) 
+    {
+      break;
+    }
+
+    switch (option_rv)
+    {
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_VERSION: /* --version or -v */
+      opt_version= true;
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_FAILURE);
+
+    default:
+      help_command(argv[0], 1, 0, long_options);
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(argv[0], 1, 0);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(argv[0], 1, 0, long_options);
+    exit(EXIT_SUCCESS);
+  }
+}
+
+int main(int argc, char *argv[])
+{
+  options_parse(argc, argv);
+
+  std::cout << libtest::number_of_cpus() << std::endl;
+
+  return EXIT_SUCCESS;
+}
index abf2b2ed2002946090f7ca74518c3408835f72f9..4643e56d25e2a2146d965dcee36a82aac70bbb27 100644 (file)
@@ -39,6 +39,8 @@
 
 #include <unistd.h>
 
+#pragma GCC diagnostic ignored "-Wundef"
+
 #if defined(HAVE_SYS_SYSCTL_H) && HAVE_SYS_SYSCTL_H
 #include <sys/sysctl.h>
 #endif
index cdccff82aec67818d1c51e0389c751abc1cbbf19..890975e6a109e3494d549ee02a5c7220d8b4025a 100644 (file)
 
 namespace libtest {
 
-exception::exception(const char *file_, int line_, const char *func_) :
-  std::runtime_error(func_),
-  _file(file_),
-  _line(line_),
-  _func(func_)
-  {
-  }
-
-#ifndef __INTEL_COMPILER
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
-#endif
-
-fatal::fatal(const char *file_, int line_, const char *func_, const char *format, ...) :
-  exception(file_, line_, func_)
+fatal::fatal(const char *file_arg, int line_arg, const char *func_arg, const char *format, ...) :
+  std::runtime_error(func_arg),
+  _line(line_arg),
+  _file(file_arg),
+  _func(func_arg)
   {
     va_list args;
     va_start(args, format);
@@ -61,6 +53,8 @@ fatal::fatal(const char *file_, int line_, const char *func_, const char *format
     int last_error_length= vsnprintf(last_error, sizeof(last_error), format, args);
     va_end(args);
 
+    strncpy(_mesg, last_error, sizeof(_mesg));
+
     snprintf(_error_message, sizeof(_error_message), "%.*s", last_error_length, last_error);
   }
 
@@ -74,11 +68,13 @@ bool fatal::is_disabled()
 
 void fatal::disable()
 {
+  _counter= 0;
   _disabled= true;
 }
 
 void fatal::enable()
 {
+  _counter= 0;
   _disabled= false;
 }
 
@@ -92,26 +88,15 @@ void fatal::increment_disabled_counter()
   _counter++;
 }
 
-disconnected::disconnected(const char *file_, int line_, const char *func_,
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+disconnected::disconnected(const char *file_arg, int line_arg, const char *func_arg,
                            const std::string& instance, const in_port_t port,
                            const char *format, ...) :
-  exception(file_, line_, func_),
-  _port(port)
-{
-  va_list args;
-  va_start(args, format);
-  char last_error[BUFSIZ];
-  (void)vsnprintf(last_error, sizeof(last_error), format, args);
-  va_end(args);
-
-  snprintf(_error_message, sizeof(_error_message), "%s:%u %s", instance.c_str(), uint32_t(port), last_error);
-}
-
-start::start(const char *file_, int line_, const char *func_,
-             const std::string& instance, const in_port_t port,
-             const char *format, ...) :
-  exception(file_, line_, func_),
-  _port(port)
+  std::runtime_error(func_arg),
+  _port(port),
+  _line(line_arg),
+  _file(file_arg),
+  _func(func_arg)
 {
   va_list args;
   va_start(args, format);
index 6ac62b775f84b224ce0673cea507b2e8a3f43f3f..bb8cc938364b95076a3ed2ca038d43d65a4dbd21 100644 (file)
 
 namespace libtest {
 
-class exception : public std::runtime_error
+class fatal : std::runtime_error
 {
 public:
-  exception(const char *, int, const char *);
+  fatal(const char *file, int line, const char *func, const char *format, ...);
 
-  int line() const
+  const char* what() const throw()
   {
-    return _line;
+    return _error_message;
   }
 
-  const char*  file() const
+  const char* mesg() const throw()
   {
-    return _file;
+    return _error_message;
   }
 
-  const char* func() const
+  // The following are just for unittesting the exception class
+  static bool is_disabled();
+  static void disable();
+  static void enable();
+  static uint32_t disabled_counter();
+  static void increment_disabled_counter();
+
+  int line()
   {
-    return _func;
+    return _line;
   }
 
-  const char* mesg() const throw()
+  const char*  file()
   {
-    return _error_message;
+    return _file;
   }
 
-
-protected:
-  char _error_message[BUFSIZ];
+  const char* func()
+  {
+    return _func;
+  }
 
 private:
-  const char*  _file;
+  char _error_message[BUFSIZ];
+  char _mesg[BUFSIZ];
   int _line;
+  const char*  _file;
   const char* _func;
 };
 
-class fatal : public exception
+class disconnected : std::runtime_error
 {
 public:
-  fatal(const char *file, int line, const char *func, const char *format, ...);
+  disconnected(const char *file, int line, const char *func, const std::string&, const in_port_t port, const char *format, ...);
 
   const char* what() const throw()
   {
@@ -105,51 +115,28 @@ public:
   static uint32_t disabled_counter();
   static void increment_disabled_counter();
 
-private:
-};
-
-class disconnected : public exception
-{
-public:
-  disconnected(const char *file, int line, const char *func, const std::string&, const in_port_t port, const char *format, ...);
-
-  const char* what() const throw()
+  int line()
   {
-    return _error_message;
+    return _line;
   }
 
-  // The following are just for unittesting the exception class
-  static bool is_disabled();
-  static void disable();
-  static void enable();
-  static uint32_t disabled_counter();
-  static void increment_disabled_counter();
-
-private:
-  in_port_t _port;
-  char _instance[1024];
-};
-
-class start : public exception
-{
-public:
-  start(const char *file, int line, const char *func, const std::string&, const in_port_t port, const char *format, ...);
-
-  const char* what() const throw()
+  const char* file()
   {
-    return _error_message;
+    return _file;
   }
 
-  // The following are just for unittesting the exception class
-  static bool is_disabled();
-  static void disable();
-  static void enable();
-  static uint32_t disabled_counter();
-  static void increment_disabled_counter();
+  const char* func()
+  {
+    return _func;
+  }
 
 private:
+  char _error_message[BUFSIZ];
   in_port_t _port;
   char _instance[1024];
+  int _line;
+  const char*  _file;
+  const char* _func;
 };
 
 
index 6cca8450abcbcffbc4a7672518acb96a668c0f0f..8bc6e65c234f0aff50f200c466c66b8a5b2d914e 100644 (file)
@@ -118,8 +118,7 @@ void Framework::exec()
 
     _total++;
 
-    try
-    {
+    try {
       switch ((*iter)->exec())
       {
       case TEST_FAILURE:
@@ -145,7 +144,7 @@ void Framework::exec()
     catch (libtest::disconnected& e)
     {
       _failed++;
-      stream::cerr(e.file(), e.line(), e.func()) << "Unhandled disconnection occurred: " << e.mesg();
+      Error << "Unhandled disconnection occurred:" << e.what();
       throw;
     }
     catch (...)
index f6dbdfce70ff23178b330c854649db695d75c9d3..c83f4eefe8a194dbd10471bdf4c9cc0528237fbc 100644 (file)
@@ -76,10 +76,10 @@ public:
     gearman_client_st *client= gearman_client_create(NULL);
     if (client == NULL)
     {
-      Error << "Could not allocate memory for gearman_client_create()";
+      error("Could not allocate memory for gearman_client_create()");
       return false;
     }
-    gearman_client_set_timeout(client, 3000);
+    gearman_client_set_timeout(client, 4000);
 
     if (gearman_success(gearman_client_add_server(client, hostname().c_str(), port())))
     {
@@ -93,12 +93,12 @@ public:
       
       if (out_of_ban_killed() == false)
       {
-        Error << hostname().c_str() << ":" << port() << " " << gearman_client_error(client);
+        error(gearman_client_error(client));
       }
     }
     else
     {
-      Error << "gearman_client_add_server() " << gearman_client_error(client);
+      error(gearman_client_error(client));
     }
 
     gearman_client_free(client);
index accadf9839bbf9a1973196d91d001dd1a79aff13..9f8cf5ba6383d70f9235c3a5c59590c2f8107309 100644 (file)
@@ -44,20 +44,24 @@ namespace libtest {
 
 bool has_libmemcached(void)
 {
+#if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED
   if (HAVE_LIBMEMCACHED)
   {
     return true;
   }
+#endif
 
   return false;
 }
 
 bool has_libdrizzle(void)
 {
+#if defined(HAVE_LIBDRIZZLE) && HAVE_LIBDRIZZLE
   if (HAVE_LIBDRIZZLE)
   {
     return true;
   }
+#endif
 
   return false;
 }
@@ -80,9 +84,9 @@ bool has_postgres_support(void)
 
 bool has_gearmand()
 {
+#if defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
   if (HAVE_GEARMAND_BINARY)
   {
-#if defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
     std::stringstream arg_buffer;
 
     char *getenv_ptr;
@@ -98,8 +102,8 @@ bool has_gearmand()
     {
       return true;
     }
-#endif
   }
+#endif
 
   return false;
 }
@@ -136,6 +140,7 @@ bool has_mysqld()
 
 bool has_memcached()
 {
+#if defined(HAVE_MEMCACHED_BINARY) && HAVE_MEMCACHED_BINARY
   if (HAVE_MEMCACHED_BINARY)
   {
     std::stringstream arg_buffer;
@@ -154,6 +159,7 @@ bool has_memcached()
       return true;
     }
   }
+#endif
 
   return false;
 }
index 0af12925f1d730b8b7a04d733d31577b9cf3c9b0..02d20cee2664ca627a3d2c75013fed511d209f22 100644 (file)
@@ -68,7 +68,7 @@ static void initialize_curl_startup()
 }
 
 static pthread_once_t start_key_once= PTHREAD_ONCE_INIT;
-void initialize_curl(void)
+static void initialize_curl(void)
 {
   int ret;
   if ((ret= pthread_once(&start_key_once, initialize_curl_startup)) != 0)
@@ -82,20 +82,19 @@ namespace http {
 
 #define YATL_USERAGENT "YATL/1.0"
 
-extern "C" size_t
-  http_get_result_callback(void *ptr, size_t size, size_t nmemb, void *data)
-  {
-    vchar_t *_body= (vchar_t*)data;
+static size_t http_get_result_callback(void *ptr, size_t size, size_t nmemb, void *data)
+{
+  vchar_t *_body= (vchar_t*)data;
 
-    _body->resize(size * nmemb);
-    memcpy(&_body[0], ptr, _body->size());
-
-    return _body->size();
-  }
+  _body->resize(size * nmemb);
+  memcpy(&_body[0], ptr, _body->size());
 
+  return _body->size();
+}
 
 static void init(CURL *curl, const std::string& url)
 {
+  (void)http_get_result_callback;
   (void)curl;
   (void)url;
   if (HAVE_LIBCURL)
index 3fb592b6ee6a00dacd2dc6c44a78ce2b7bc07073..5d05aa4a81a40db129025a27526a2511f3004700 100644 (file)
@@ -5,7 +5,7 @@
 # 
 
 LIBTOOL_COMMAND= ${abs_top_builddir}/libtool --mode=execute
-VALGRIND_EXEC_COMMAND= $(LIBTOOL_COMMAND) valgrind --error-exitcode=1 --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE
+VALGRIND_EXEC_COMMAND= $(LIBTOOL_COMMAND) valgrind --error-exitcode=1 --leak-check=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE
 VALGRIND_COMMAND= TESTS_ENVIRONMENT="valgrind" $(VALGRIND_EXEC_COMMAND)
 HELGRIND_COMMAND= $(LIBTOOL_COMMAND) valgrind --tool=helgrind --read-var-info=yes --error-exitcode=1 --read-var-info=yes
 DRD_COMMAND= $(LIBTOOL_COMMAND) valgrind --tool=drd
@@ -34,12 +34,7 @@ drd:
 EXTRA_DIST+= libtest/run.gdb
 EXTRA_DIST+= libtest/version.h
 
-CLEANFILES+= tmp_chroot/etc/*
-CLEANFILES+= tmp_chroot/var/drizzle/*
-CLEANFILES+= tmp_chroot/var/log/*
-CLEANFILES+= tmp_chroot/var/run/*
-CLEANFILES+= tmp_chroot/var/tmp/*
-CLEANFILES+= tmp_chroot/*.xml
+CLEANFILES+= tmp_chroot
 
 BUILT_SOURCES+= libtest/version.h
 
@@ -47,9 +42,9 @@ BUILT_SOURCES+= libtest/version.h
 clean-libtest-check:
        -rm -rf tmp_chroot
 
-
 noinst_HEADERS+= libtest/formatter.hpp
 noinst_HEADERS+= libtest/timer.hpp
+noinst_HEADERS+= libtest/alarm.h
 noinst_HEADERS+= libtest/binaries.h 
 noinst_HEADERS+= libtest/cpu.hpp 
 noinst_HEADERS+= libtest/blobslap_worker.h 
@@ -101,19 +96,20 @@ libtest_libtest_la_DEPENDENCIES=
 libtest_libtest_la_LIBADD=
 libtest_libtest_la_SOURCES=
 
+libtest_libtest_la_SOURCES+= libtest/alarm.cc 
 libtest_libtest_la_SOURCES+= libtest/binaries.cc 
-libtest_libtest_la_SOURCES+= libtest/dns.cc 
 libtest_libtest_la_SOURCES+= libtest/cmdline.cc 
-libtest_libtest_la_SOURCES+= libtest/comparison.cc 
 libtest_libtest_la_SOURCES+= libtest/collection.cc 
+libtest_libtest_la_SOURCES+= libtest/comparison.cc 
 libtest_libtest_la_SOURCES+= libtest/core.cc 
 libtest_libtest_la_SOURCES+= libtest/cpu.cc 
+libtest_libtest_la_SOURCES+= libtest/dns.cc 
 libtest_libtest_la_SOURCES+= libtest/dream.cc 
+libtest_libtest_la_SOURCES+= libtest/drizzled.cc 
 libtest_libtest_la_SOURCES+= libtest/fatal.cc 
 libtest_libtest_la_SOURCES+= libtest/formatter.cc 
 libtest_libtest_la_SOURCES+= libtest/framework.cc 
 libtest_libtest_la_SOURCES+= libtest/has.cc 
-libtest_libtest_la_SOURCES+= libtest/drizzled.cc 
 libtest_libtest_la_SOURCES+= libtest/http.cc 
 libtest_libtest_la_SOURCES+= libtest/is_local.cc 
 libtest_libtest_la_SOURCES+= libtest/killpid.cc 
@@ -164,7 +160,7 @@ libtest_unittest_DEPENDENCIES+= libmemcached/libmemcached.la
 libtest_unittest_DEPENDENCIES+= libmemcached/libmemcachedutil.la
 else
 if HAVE_LIBMEMCACHED
-libtest_libtest_la_LIBADD+= $(libmemcached_LIBS)
+libtest_libtest_la_LIBADD+= $(LIBMEMCACHED_UTIL_LDFLAGS)
 libtest_libtest_la_SOURCES+= libtest/memcached.cc
 else
 libtest_libtest_la_CXXFLAGS+= -DHAVE_LIBMEMCACHED=0
@@ -255,5 +251,10 @@ libtest_wait_SOURCES+= libtest/wait.cc
 libtest_wait_SOURCES+= libtest/dream.cc
 noinst_PROGRAMS+= libtest/wait
 
+libtest_core_count_SOURCES=
+libtest_core_count_SOURCES+= libtest/cpu.cc
+libtest_core_count_SOURCES+= libtest/core_count.cc
+noinst_PROGRAMS+= libtest/core-count
+
 libtest_abort_SOURCES= libtest/abort.cc
 noinst_PROGRAMS+= libtest/abort
index aae43bb391bc12729bf82648653ecf4892708627..5bf285c49a329451e3c422582603465200f33edf 100644 (file)
@@ -80,21 +80,34 @@ bool kill_pid(pid_t pid_arg)
     }
   }
 
-  int status= 0;
-  if (waitpid(pid_arg, &status, 0) == -1)
   {
-    switch (errno)
+    uint32_t this_wait= 0;
+    uint32_t timeout= 20; // This number should be high enough for valgrind startup (which is slow)
+    uint32_t waited;
+    uint32_t retry;
+
+    for (waited= 0, retry= 4; ; retry++, waited+= this_wait)
     {
-      // Just means that the server has already gone away
-    case ECHILD:
+      int status= 0;
+      if (waitpid(pid_arg, &status, WNOHANG) == 0)
       {
-        return true;
+        break;
+      }
+      else if (errno == ECHILD)
+      {
+        // Server has already gone away
+        break;
+      }
+      else if (waited >= timeout)
+      {
+        // Timeout failed
+        kill(pid_arg, SIGKILL);
+        break;
       }
-    }
-
-    Error << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(pid_arg);
 
-    return false;
+      this_wait= retry * retry / 3 + 1;
+      libtest::dream(this_wait, 0);
+    }
   }
 
   return true;
index 6bffa84cf86688a6be22fa55fcd47153375287f4..363c2a2ff614c58d2188c3addf4d13ce97e6b7d2 100644 (file)
@@ -83,6 +83,7 @@ static void stats_print(libtest::Framework *frame)
 
 int main(int argc, char *argv[])
 {
+  Out << "BEGIN:" << argv[0];
   bool opt_massive= false;
   unsigned long int opt_repeat= 1; // Run all tests once
   bool opt_quiet= false;
@@ -292,7 +293,7 @@ int main(int argc, char *argv[])
           return EXIT_SKIP;
 
         case TEST_FAILURE:
-          std::cerr << "frame->create()" << std::endl;
+          std::cerr << __FILE__ << ":" <<  __LINE__ << ": " << "frame->create()" << std::endl;
           return EXIT_FAILURE;
         }
       }
@@ -340,34 +341,31 @@ int main(int argc, char *argv[])
   }
   catch (libtest::fatal& e)
   {
-    std::cerr << "FATAL:" << e.what() << std::endl;
-    exit_code= EXIT_FAILURE;
-  }
-  catch (libtest::start& e)
-  {
-    std::cerr << "Failure to start:" << e.what() << std::endl;
+    std::cerr << __FILE__ << ":" <<  __LINE__ << ": " << "FATAL:" << e.what() << std::endl;
     exit_code= EXIT_FAILURE;
   }
   catch (libtest::disconnected& e)
   {
-    std::cerr << "Unhandled disconnection occurred:" << e.what() << std::endl;
+    std::cerr << __FILE__ << ":" <<  __LINE__ << ": " << "Unhandled disconnection occurred:" << e.what() << std::endl;
     exit_code= EXIT_FAILURE;
   }
   catch (std::exception& e)
   {
-    std::cerr << "std::exception:" << e.what() << std::endl;
+    std::cerr << __FILE__ << ":" <<  __LINE__ << ": " << "std::exception:" << e.what() << std::endl;
     exit_code= EXIT_FAILURE;
   }
   catch (char const*)
   {
-    std::cerr << "Exception:" << std::endl;
+    std::cerr << __FILE__ << ":" <<  __LINE__ << ": " << "Exception:" << std::endl;
     exit_code= EXIT_FAILURE;
   }
   catch (...)
   {
-    std::cerr << "Unknown exception halted execution." << std::endl;
+    std::cerr << __FILE__ << ":" <<  __LINE__ << ": " << "Unknown exception halted execution." << std::endl;
     exit_code= EXIT_FAILURE;
   }
 
+  Out << "END:" << argv[0];
+
   return exit_code;
 }
index c4953975817bdf66201aaa5b2cd028ec590d79a5..e0e1485101aaa41c9c7a8593dc379d2ff0b2feab 100644 (file)
@@ -39,7 +39,7 @@
 #if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED
 inline bool operator== (const memcached_st& memc, const memcached_return_t rc)
 {
-  if (memcached_last_error(&memc) == rc)
+  if (memcached_last_error(const_cast<memcached_st *>(&memc)) == rc)
   {
     return true;
   }
@@ -49,7 +49,7 @@ inline bool operator== (const memcached_st& memc, const memcached_return_t rc)
 
 inline bool operator!= (const memcached_st& memc, const memcached_return_t rc)
 {
-  if (memcached_last_error(&memc) != rc)
+  if (memcached_last_error(const_cast<memcached_st *>(&memc)) != rc)
   {
     return true;
   }
@@ -59,7 +59,7 @@ inline bool operator!= (const memcached_st& memc, const memcached_return_t rc)
 
 inline bool operator!= (const memcached_return_t rc, const memcached_st& memc)
 {
-  if (memcached_last_error(&memc) != rc)
+  if (memcached_last_error(const_cast<memcached_st *>(&memc)) != rc)
   {
     return true;
   }
index 01e0e88b34426e1f014db5fd43346903d004570e..04d4bd14f29b3d17d0cd496bf6935ccd6b1146f5 100644 (file)
 
 #include <libtest/signal.h>
 
+#ifndef SOCK_CLOEXEC 
+#  define SOCK_CLOEXEC 0
+#endif
+
+#ifndef SOCK_NONBLOCK 
+#  define SOCK_NONBLOCK 0
+#endif
+
+#ifndef FD_CLOEXEC
+#  define FD_CLOEXEC 0
+#endif
+
 #ifndef __INTEL_COMPILER
 #pragma GCC diagnostic ignored "-Wold-style-cast"
 #endif
@@ -66,6 +78,11 @@ using namespace libtest;
 struct socket_st {
   typedef std::vector< std::pair< int, in_port_t> > socket_port_t;
   socket_port_t _pair;
+  in_port_t last_port;
+
+  socket_st():
+    last_port(0)
+  { }
 
   void release(in_port_t _arg)
   {
@@ -116,39 +133,69 @@ void release_port(in_port_t arg)
 
 in_port_t get_free_port()
 {
-  in_port_t ret_port= in_port_t(0);
+  const in_port_t default_port= in_port_t(-1);
 
   int retries= 1024;
 
+  in_port_t ret_port;
   while (--retries)
   {
+    ret_port= default_port;
     int sd;
     if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != -1)
     {
       int optval= 1;
       if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != -1)
-      {
+      { 
         struct sockaddr_in sin;
         sin.sin_port= 0;
         sin.sin_addr.s_addr= 0;
         sin.sin_addr.s_addr= INADDR_ANY;
         sin.sin_family= AF_INET;
 
-        if (bind(sd, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) ) != -1)
+        int bind_ret;
+        do
         {
-          socklen_t addrlen= sizeof(sin);
+          if ((bind_ret= bind(sd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) )) != -1)
+          {
+            socklen_t addrlen= sizeof(sin);
 
-          if (getsockname(sd, (struct sockaddr *)&sin, &addrlen) != -1)
+            if (getsockname(sd, (struct sockaddr *)&sin, &addrlen) != -1)
+            {
+              ret_port= sin.sin_port;
+            }
+          }
+          else
           {
-            ret_port= sin.sin_port;
+            if (errno != EADDRINUSE)
+            {
+              Error << strerror(errno);
+            }
           }
-        }
-      }
 
-      all_socket_fd._pair.push_back(std::make_pair(sd, ret_port));
+          if (errno == EADDRINUSE)
+          {
+            libtest::dream(2, 0);
+          }
+        } while (bind_ret == -1 and errno == EADDRINUSE);
+
+        all_socket_fd._pair.push_back(std::make_pair(sd, ret_port));
+      }
+      else
+      {
+        Error << strerror(errno);
+      }
+    }
+    else
+    {
+      Error << strerror(errno);
     }
 
-    if (ret_port > 1024)
+    if (ret_port == default_port)
+    {
+      Error << "no ret_port set:" << strerror(errno);
+    }
+    else if (ret_port > 1024 and ret_port != all_socket_fd.last_port)
     {
       break;
     }
@@ -165,11 +212,19 @@ in_port_t get_free_port()
     fatal_message("No port could be found");
   }
 
+  if (ret_port == default_port)
+  {
+    fatal_message("No port could be found");
+  }
+
   if (ret_port <= 1024)
   {
     fatal_message("No port could be found, though some where available below or at 1024");
   }
 
+  all_socket_fd.last_port= ret_port;
+  release_port(ret_port);
+
   return ret_port;
 }
 
index b128788a1a32b801e8562b0907cded152522a4c8..d58b362ed5c8927f3cbb9231b4590c667e2318b0 100644 (file)
@@ -90,6 +90,22 @@ std::ostream& operator<<(std::ostream& output, const Server &arg)
   return output;  // for multiple << operators
 }
 
+#ifdef __GLIBC__
+namespace {
+
+class Buffer
+{
+public:
+  Buffer(char *b) : b_(b) {}
+   ~Buffer() { free(b_); }
+  char* buf() { return b_; }
+private:
+  char *b_;
+};
+
+}
+#endif // __GLIBC__
+
 #define MAGIC_MEMORY 123570
 
 Server::Server(const std::string& host_arg, const in_port_t port_arg,
@@ -106,6 +122,7 @@ Server::Server(const std::string& host_arg, const in_port_t port_arg,
 
 Server::~Server()
 {
+  kill();
 }
 
 bool Server::check()
@@ -180,8 +197,8 @@ bool Server::start()
 
   if (port() == LIBTEST_FAIL_PORT)
   {
-    throw libtest::start(LIBYATL_DEFAULT_PARAM,
-                         hostname(), port(), "Called failure");
+    throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                hostname(), port(), "Called failure");
   }
 
   if (getenv("YATL_PTRCHECK_SERVER"))
@@ -195,16 +212,17 @@ bool Server::start()
 
   if (args(_app) == false)
   {
-    throw libtest::start(LIBYATL_DEFAULT_PARAM,
-                         hostname(), port(), "Could not build command()");
+    throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                hostname(), port(), "Could not build command()");
   }
 
   libtest::release_port(_port);
+
   Application::error_t ret;
   if (Application::SUCCESS !=  (ret= _app.run()))
   {
-    throw libtest::start(LIBYATL_DEFAULT_PARAM,
-                         hostname(), port(), "Application::run() %s", libtest::Application::toString(ret));
+    throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                hostname(), port(), "Application::run() %s", libtest::Application::toString(ret));
     return false;
   }
   _running= _app.print();
@@ -230,9 +248,14 @@ bool Server::start()
           continue;
         }
 
+#ifdef __GLIBC__
+        Buffer buf( get_current_dir_name());
+        char *getcwd_buf= buf.buf();
+#else
         char buf[PATH_MAX];
         char *getcwd_buf= getcwd(buf, sizeof(buf));
-        throw libtest::start(LIBYATL_DEFAULT_PARAM,
+#endif // __GLIBC__
+        throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
                                     hostname(), port(),
                                     "Unable to open pidfile in %s for: %s stderr:%s",
                                     getcwd_buf ? getcwd_buf : "",
@@ -242,15 +265,20 @@ bool Server::start()
     }
   }
 
-  uint32_t this_wait= 0;
   bool pinged= false;
+  uint32_t this_wait= 0;
   {
     uint32_t timeout= 20; // This number should be high enough for valgrind startup (which is slow)
     uint32_t waited;
     uint32_t retry;
 
-    for (waited= 0, retry= 4; ; retry++, waited+= this_wait)
+    for (waited= 0, retry= 7; ; retry++, waited+= this_wait)
     {
+      if (_app.check() == false)
+      {
+        break;
+      }
+
       if ((pinged= ping()) == true)
       {
         break;
@@ -260,6 +288,8 @@ bool Server::start()
         break;
       }
 
+      Error << "ping(" << _app.pid() << ") wait: " << this_wait << " " << hostname() << ":" << port() << " " << error();
+
       this_wait= retry * retry / 3 + 1;
       libtest::dream(this_wait, 0);
     }
@@ -273,35 +303,35 @@ bool Server::start()
       _app.slurp();
       if (kill_file(pid_file()) == false)
       {
-        throw libtest::start(LIBYATL_DEFAULT_PARAM,
-                             hostname(), port(),
-                             "Failed to kill off server, waited: %u after startup occurred, when pinging failed: %.*s stderr:%.*s",
-                             this_wait,
-                             int(_running.size()), _running.c_str(),
-                             int(_app.stderr_result_length()), _app.stderr_c_str());
+        throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                    hostname(), port(),
+                                    "Failed to kill off server, waited: %u after startup occurred, when pinging failed: %.*s stderr:%.*s",
+                                    this_wait,
+                                    int(_running.size()), _running.c_str(),
+                                    int(_app.stderr_result_length()), _app.stderr_c_str());
       }
       else
       {
-        throw libtest::start(LIBYATL_DEFAULT_PARAM, 
-                             hostname(), port(),
-                             "Failed native ping(), pid: %d was alive: %s waited: %u server started, having pid_file. exec: %.*s stderr:%.*s",
-                             int(_app.pid()),
-                             _app.check() ? "true" : "false",
-                             this_wait,
-                             int(_running.size()), _running.c_str(),
-                             int(_app.stderr_result_length()), _app.stderr_c_str());
+        throw libtest::disconnected(LIBYATL_DEFAULT_PARAM, 
+                                    hostname(), port(),
+                                    "Failed native ping(), pid: %d was alive: %s waited: %u server started, having pid_file. exec: %.*s stderr:%.*s",
+                                    int(_app.pid()),
+                                    _app.check() ? "true" : "false",
+                                    this_wait,
+                                    int(_running.size()), _running.c_str(),
+                                    int(_app.stderr_result_length()), _app.stderr_c_str());
       }
     }
     else
     {
-      throw libtest::start(LIBYATL_DEFAULT_PARAM,
-                           hostname(), port(),
-                           "Failed native ping(), pid: %d is alive: %s waited: %u server started. exec: %.*s stderr:%.*s",
-                           int(_app.pid()),
-                           _app.check() ? "true" : "false",
-                           this_wait,
-                           int(_running.size()), _running.c_str(),
-                           int(_app.stderr_result_length()), _app.stderr_c_str());
+      throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                  hostname(), port(),
+                                  "Failed native ping(), pid: %d is alive: %s waited: %u server started. exec: %.*s stderr:%.*s",
+                                  int(_app.pid()),
+                                  _app.check() ? "true" : "false",
+                                  this_wait,
+                                  int(_running.size()), _running.c_str(),
+                                  int(_app.stderr_result_length()), _app.stderr_c_str());
     }
     _running.clear();
 
@@ -327,9 +357,9 @@ void Server::add_option(const std::string& arg)
   _options.push_back(std::make_pair(arg, std::string()));
 }
 
-void Server::add_option(const std::string& name_, const std::string& value)
+void Server::add_option(const std::string& name_, const std::string& value_)
 {
-  _options.push_back(std::make_pair(name_, value));
+  _options.push_back(std::make_pair(name_, value_));
 }
 
 bool Server::set_socket_file()
index 2d7655bcffbdba6f717f140b62c7f31a03551793..f87a9fba126cde97070b3b1525bb19a007c63d52 100644 (file)
@@ -274,7 +274,13 @@ bool server_startup_st::start_server(const std::string& server_type, in_port_t t
     {
       throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Launching of an unknown server was attempted: %s", server_type.c_str());
     }
+  }
+  catch (...)
+  {
+    throw;
+  }
 
+  try {
     /*
       We will now cycle the server we have created.
     */
@@ -296,32 +302,30 @@ bool server_startup_st::start_server(const std::string& server_type, in_port_t t
     }
     else
 #endif
+
       if (server->start() == false)
-    {
-      delete server;
-      return false;
-    }
-    else
-    {
-      if (opt_startup_message)
       {
-        Outn();
-        Out << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
-        Outn();
+        delete server;
+        return false;
+      }
+      else
+      {
+        if (opt_startup_message)
+        {
+          Outn();
+          Out << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
+          Outn();
+        }
       }
-    }
-  }
-  catch (libtest::start err)
-  {
-    stream::cerr(err.file(), err.line(), err.func()) << err.what();
-    delete server;
-    return false;
   }
-  catch (libtest::disconnected err)
+  catch (libtest::disconnected& err)
   {
-    stream::cerr(err.file(), err.line(), err.func()) << err.what();
-    delete server;
-    return false;
+    if (fatal::is_disabled() == false and try_port != LIBTEST_FAIL_PORT)
+    {
+      stream::cerr(err.file(), err.line(), err.func()) << err.what();
+      delete server;
+      return false;
+    }
   }
   catch (...)
   {
index 86c4a43178d8f66ce0498b1ccbd8d518e1cb10c0..53a436be77ecbd964320fd46743809a4e49fb6f5 100644 (file)
@@ -94,10 +94,23 @@ void SignalThread::test()
     assert(sigismember(&set, SIGABRT));
     assert(sigismember(&set, SIGQUIT));
     assert(sigismember(&set, SIGINT));
+    assert(sigismember(&set, SIGVTALRM));
   }
   assert(sigismember(&set, SIGUSR2));
 }
 
+bool SignalThread::unblock()
+{
+  int error;
+  if ((error= pthread_sigmask(SIG_UNBLOCK, &set, NULL)) != 0)
+  {
+    Error << "While trying to reset signal mask to original set, pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")";
+    return false;
+  }
+
+  return true;
+}
+
 SignalThread::~SignalThread()
 {
   if (is_shutdown() == false)
@@ -114,11 +127,7 @@ SignalThread::~SignalThread()
 #endif
   sem_destroy(&lock);
 
-  int error;
-  if ((error= pthread_sigmask(SIG_UNBLOCK, &set, NULL)) != 0)
-  {
-    Error << "While trying to reset signal mask to original set, pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")";
-  }
+  unblock();
 }
 
 extern "C" {
@@ -142,6 +151,11 @@ static void *sig_thread(void *arg)
 
     switch (sig)
     {
+    case SIGVTALRM:
+      Error << "SIGVTALRM was called";
+      context->unblock();
+      raise(SIGVTALRM);
+
     case SIGABRT:
     case SIGUSR2:
     case SIGINT:
@@ -183,6 +197,7 @@ SignalThread::SignalThread() :
     sigaddset(&set, SIGABRT);
     sigaddset(&set, SIGQUIT);
     sigaddset(&set, SIGINT);
+    sigaddset(&set, SIGVTALRM);
   }
   sigaddset(&set, SIGPIPE);
 
@@ -203,10 +218,17 @@ bool SignalThread::setup()
   {
     Error << strsignal(SIGQUIT) << " has been previously set.";
   }
+
   if (sigismember(&original_set, SIGINT))
   {
     Error << strsignal(SIGINT) << " has been previously set.";
   }
+
+  if (sigismember(&original_set, SIGVTALRM))
+  {
+    Error << strsignal(SIGVTALRM) << " has been previously set.";
+  }
+
   if (sigismember(&original_set, SIGUSR2))
   {
     Error << strsignal(SIGUSR2) << " has been previously set.";
index fd7e4a6d359287ba925a7607ba0e9033b14e89be..6e68bb3878b0a289aafbe48fb0487b92ed4d04c4 100644 (file)
@@ -65,6 +65,7 @@ public:
   void test();
   void post();
   bool setup();
+  bool unblock();
 
   int wait(int& sig)
   {
index 7676048745bf4bb0798ac0ddd78e212bf20ba9fd..bdcccdc02b113fbee0e2e3fd036449a49ea700fd 100644 (file)
 #include <cstdlib>
 #include <arpa/inet.h>
 
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <ctime>
-#else
-# ifdef HAVE_SYS_TIME_H
-#  include <sys/time.h>
-# else
-#  include <ctime>
-# endif
-#endif
-
 #include <libtest/visibility.h>
 #include <libtest/version.h>
 
@@ -63,6 +52,7 @@
 #include <libtest/error.h>
 #include <libtest/strerror.h>
 #include <libtest/timer.hpp>
+#include <libtest/alarm.h>
 #include <libtest/stream.h>
 #include <libtest/comparison.hpp>
 #include <libtest/server.h>
index eac5194036300a533dfabfbf14f4fd4f9a8adc61..28ec47416766c3eb917447d527a57ef1e0e47e97 100644 (file)
@@ -44,7 +44,6 @@
 #  include <mach/clock.h>
 #  include <mach/mach.h>
 #else
-#  include <time.h>
 #  include <sys/time.h>
 #endif
 
@@ -123,24 +122,8 @@ private:
     mach_port_deallocate(mach_task_self(), _clock_serv);
     ts.tv_sec= _mach_timespec.tv_sec;
     ts.tv_nsec= _mach_timespec.tv_nsec;
-#elif defined(HAVE_CLOCK_GETTIME) && HAVE_CLOCK_GETTIME
-    int ret;
-    do
-    {
-      ret= clock_gettime(CLOCK_REALTIME, &ts);
-    } while (ret == -1);
-#elif defined(HAVE_GETTIMEOFDAY) && HAVE_GETTIMEOFDAY
-    struct timeval tv;
-    int ret;
-    do 
-    {
-      ret= gettimeofday(&tv, NULL)
-    } while (ret == -1);
-    /* Convert from timeval to timespec */
-    ts.tv_sec= tv.tv_sec;
-    ts.tv_nsec= tv.tv_usec * 1000;
 #else
-    memset(&ts, 0, sizeof(struct timespec));
+    clock_gettime(CLOCK_REALTIME, &ts);
 #endif
   }
 
index 6b3efe95cbce9d0beff090769c13ad7c01813444..0af3e30f8ab21977c9c7ce6c3ffbef0ae22f15b5 100644 (file)
@@ -53,6 +53,9 @@ using namespace libtest;
 
 static std::string testing_service;
 
+// Used to track setups where we see if failure is happening
+static uint32_t fatal_calls= 0;
+
 static test_return_t LIBTOOL_COMMAND_test(void *)
 {
   test_true(getenv("LIBTOOL_COMMAND"));
@@ -270,7 +273,7 @@ static test_return_t drizzled_cycle_test(void *object)
 
   test_skip(true, has_drizzled());
 
-  test_skip(true, server_startup(*servers, "drizzled", get_free_port(), 0, NULL));
+  test_skip(true, server_startup(*servers, "drizzled", get_free_port(), 0, NULL, false));
 
   return TEST_SUCCESS;
 }
@@ -280,13 +283,9 @@ static test_return_t gearmand_cycle_test(void *object)
   server_startup_st *servers= (server_startup_st*)object;
   test_true(servers and servers->validate());
 
-#if defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
-  test_true(has_gearmand());
-#endif
-
   test_skip(true, has_gearmand());
-
-  test_skip(true, server_startup(*servers, "gearmand", get_free_port(), 0, NULL));
+  test_skip(true, server_startup(*servers, "gearmand", get_free_port(), 0, NULL, false));
+  servers->clear();
 
   return TEST_SUCCESS;
 }
@@ -299,7 +298,7 @@ static test_return_t memcached_light_cycle_TEST(void *object)
 
   test_skip(true, bool(HAVE_MEMCACHED_LIGHT_BINARY));
 
-  test_true(server_startup(*servers, "memcached-light", get_free_port(), 0, NULL));
+  test_true(server_startup(*servers, "memcached-light", get_free_port(), 0, NULL, false));
 
   return TEST_SUCCESS;
 }
@@ -333,7 +332,9 @@ static test_return_t server_startup_fail_TEST(void *object)
   server_startup_st *servers= (server_startup_st*)object;
   test_true(servers);
 
-  test_compare(servers->start_server(testing_service, LIBTEST_FAIL_PORT, 0, NULL, true), false);
+  fatal::disable();
+  test_compare(servers->start_server(testing_service, LIBTEST_FAIL_PORT, 0, NULL, false), true);
+  fatal::enable();
 
   return TEST_SUCCESS;
 }
@@ -343,7 +344,7 @@ static test_return_t server_startup_TEST(void *object)
   server_startup_st *servers= (server_startup_st*)object;
   test_true(servers);
 
-  test_true(servers->start_server(testing_service, get_free_port(), 0, NULL, true));
+  test_compare(servers->start_server(testing_service, get_free_port(), 0, NULL, false), true);
 
   test_true(servers->last());
   pid_t last_pid= servers->last()->pid();
@@ -366,7 +367,7 @@ static test_return_t socket_server_startup_TEST(void *object)
   server_startup_st *servers= (server_startup_st*)object;
   test_true(servers);
 
-  test_true(servers->start_socket_server(testing_service, get_free_port(), 0, NULL, true));
+  test_true(servers->start_socket_server(testing_service, get_free_port(), 0, NULL, false));
 
   return TEST_SUCCESS;
 }
@@ -384,7 +385,7 @@ static test_return_t memcached_sasl_test(void *object)
     if (HAVE_LIBMEMCACHED)
     {
       test_true(has_memcached_sasl());
-      test_true(server_startup(*servers, "memcached-sasl", get_free_port(), 0, NULL));
+      test_true(server_startup(*servers, "memcached-sasl", get_free_port(), 0, NULL, false));
 
       return TEST_SUCCESS;
     }
@@ -396,10 +397,11 @@ static test_return_t memcached_sasl_test(void *object)
 
 static test_return_t application_true_BINARY(void *)
 {
-  Application true_app("true");
+  test_skip(0, access("/usr/bin/true", X_OK ));
+  Application true_app("/usr/bin/true");
 
   test_compare(Application::SUCCESS, true_app.run());
-  test_compare(Application::SUCCESS, true_app.wait());
+  test_compare(Application::SUCCESS, true_app.join());
 
   return TEST_SUCCESS;
 }
@@ -407,11 +409,11 @@ static test_return_t application_true_BINARY(void *)
 static test_return_t application_gdb_true_BINARY2(void *)
 {
   test_skip(0, access("/usr/bin/gdb", X_OK ));
-  Application true_app("true");
+  Application true_app("/usr/bin/true");
   true_app.use_gdb();
 
   test_compare(Application::SUCCESS, true_app.run());
-  test_compare(Application::SUCCESS, true_app.wait());
+  test_compare(Application::SUCCESS, true_app.join());
 
   return TEST_SUCCESS;
 }
@@ -419,23 +421,24 @@ static test_return_t application_gdb_true_BINARY2(void *)
 static test_return_t application_gdb_true_BINARY(void *)
 {
   test_skip(0, access("/usr/bin/gdb", X_OK ));
-  Application true_app("true");
+  Application true_app("/usr/bin/true");
   true_app.use_gdb();
 
   const char *args[]= { "--fubar", 0 };
   test_compare(Application::SUCCESS, true_app.run(args));
-  test_compare(Application::SUCCESS, true_app.wait());
+  test_compare(Application::SUCCESS, true_app.join());
 
   return TEST_SUCCESS;
 }
 
 static test_return_t application_true_fubar_BINARY(void *)
 {
-  Application true_app("true");
+  test_skip(0, access("/usr/bin/true", X_OK ));
+  Application true_app("/usr/bin/true");
 
   const char *args[]= { "--fubar", 0 };
   test_compare(Application::SUCCESS, true_app.run(args));
-  test_compare(Application::SUCCESS, true_app.wait());
+  test_compare(Application::SUCCESS, true_app.join());
   test_zero(true_app.stdout_result().size());
 
   return TEST_SUCCESS;
@@ -450,10 +453,10 @@ static test_return_t application_doesnotexist_BINARY(void *)
 
   const char *args[]= { "--fubar", 0 };
 #if defined(TARGET_OS_OSX) && TARGET_OS_OSX
-  test_compare(Application::INVALID, true_app.run(args));
+  test_compare(Application::INVALID_POSIX_SPAWN, true_app.run(args));
 #else
   test_compare(Application::SUCCESS, true_app.run(args));
-  test_compare(Application::INVALID, true_app.wait(false));
+  test_compare(Application::INVALID_POSIX_SPAWN, true_app.join());
 #endif
 
   test_zero(true_app.stdout_result().size());
@@ -461,32 +464,6 @@ static test_return_t application_doesnotexist_BINARY(void *)
   return TEST_SUCCESS;
 }
 
-static test_return_t application_true_fubar_eq_doh_BINARY(void *)
-{
-  Application true_app("true");
-
-  const char *args[]= { "--fubar=doh", 0 };
-  test_compare(Application::SUCCESS, true_app.run(args));
-  test_compare(Application::SUCCESS, true_app.wait());
-  test_zero(true_app.stdout_result().size());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t application_true_fubar_eq_doh_option_BINARY(void *)
-{
-  Application true_app("true");
-
-  true_app.add_option("--fubar=", "doh");
-
-  test_compare(Application::SUCCESS, true_app.run());
-  test_compare(Application::SUCCESS, true_app.wait());
-  test_zero(true_app.stdout_result().size());
-
-  return TEST_SUCCESS;
-}
-
-
 static test_return_t GET_TEST(void *)
 {
   libtest::http::GET get("http://foo.example.com/");
@@ -539,57 +516,57 @@ static test_return_t vchar_t_compare_neg_TEST(void *)
 
 static test_return_t application_echo_fubar_BINARY(void *)
 {
-  Application true_app("echo");
+  if (0)
+  {
+    test_skip(0, access("/bin/echo", X_OK ));
+    Application true_app("/bin/echo");
 
-  const char *args[]= { "fubar", 0 };
-  test_compare(Application::SUCCESS, true_app.run(args));
-  test_compare(Application::SUCCESS, true_app.wait());
+    const char *args[]= { "fubar", 0 };
+    test_compare(Application::SUCCESS, true_app.run(args));
 
-  while (true_app.slurp() == false) {} ;
+    while (true_app.slurp() == false) {} ;
 
-  libtest::vchar_t response;
-  make_vector(response, test_literal_param("fubar\n"));
-  test_compare(response, true_app.stdout_result());
+    libtest::vchar_t response;
+    make_vector(response, test_literal_param("fubar\n"));
+    test_compare(response, true_app.stdout_result());
+  }
 
   return TEST_SUCCESS;
 }
 
 static test_return_t application_echo_fubar_BINARY2(void *)
 {
-  Application true_app("echo");
+  if (0)
+  {
+    test_skip(0, access("/bin/echo", X_OK ));
+    Application true_app("/bin/echo");
 
-  true_app.add_option("fubar");
+    true_app.add_option("fubar");
 
-  test_compare(Application::SUCCESS, true_app.run());
-  test_compare(Application::SUCCESS, true_app.join());
+    test_compare(Application::SUCCESS, true_app.run());
+    test_compare(Application::SUCCESS, true_app.join());
 
-  libtest::vchar_t response;
-  make_vector(response, test_literal_param("fubar\n"));
-  test_compare(response, true_app.stdout_result());
+    libtest::vchar_t response;
+    make_vector(response, test_literal_param("fubar\n"));
+    test_compare(response, true_app.stdout_result());
+  }
 
   return TEST_SUCCESS;
 }
 
-static test_return_t true_BINARY(void *)
+static test_return_t echo_fubar_BINARY(void *)
 {
-  const char *args[]= { 0 };
-  test_compare(EXIT_SUCCESS, exec_cmdline("true", args));
+  const char *args[]= { "fubar", 0 };
+  test_compare(EXIT_SUCCESS, exec_cmdline("/bin/echo", args));
 
   return TEST_SUCCESS;
 }
 
-static test_return_t true_fubar_BINARY(void *)
+static test_return_t core_count_BINARY(void *)
 {
-  const char *args[]= { "--fubar", 0 };
-  test_compare(EXIT_SUCCESS, exec_cmdline("true", args));
+  const char *args[]= { 0 };
 
-  return TEST_SUCCESS;
-}
-
-static test_return_t echo_fubar_BINARY(void *)
-{
-  const char *args[]= { "fubar", 0 };
-  test_compare(EXIT_SUCCESS, exec_cmdline("echo", args));
+  test_compare(EXIT_SUCCESS, exec_cmdline("libtest/core-count", args, true));
 
   return TEST_SUCCESS;
 }
@@ -653,7 +630,7 @@ static test_return_t wait_services_appliction_TEST(void *)
 
   const char *args[]= { "/etc/services", 0 };
   test_compare(Application::SUCCESS, wait_app.run(args));
-  test_compare(Application::SUCCESS, wait_app.wait());
+  test_compare(Application::SUCCESS, wait_app.join());
 
   return TEST_SUCCESS;
 }
@@ -673,7 +650,7 @@ static test_return_t gdb_wait_services_appliction_TEST(void *)
 
   const char *args[]= { "/etc/services", 0 };
   test_compare(Application::SUCCESS, wait_app.run(args));
-  test_compare(Application::SUCCESS, wait_app.wait());
+  test_compare(Application::SUCCESS, wait_app.join());
 
   return TEST_SUCCESS;
 }
@@ -691,7 +668,7 @@ static test_return_t gdb_abort_services_appliction_TEST(void *)
   abort_app.use_gdb();
 
   test_compare(Application::SUCCESS, abort_app.run());
-  test_compare(Application::SUCCESS, abort_app.wait());
+  test_compare(Application::SUCCESS, abort_app.join());
 
   std::string gdb_filename= abort_app.gdb_filename();
   test_skip(0, access(gdb_filename.c_str(), R_OK ));
@@ -715,8 +692,6 @@ static test_return_t get_free_port_TEST(void *)
   return TEST_SUCCESS;
 }
 
-static uint32_t fatal_calls= 0;
-
 static test_return_t fatal_TEST(void *)
 {
   test_compare(fatal_calls++, fatal::disabled_counter());
@@ -777,7 +752,7 @@ static test_return_t create_tmpfile_TEST(void *)
   test_compare(-1, access(tmp.c_str(), R_OK));
   test_compare(-1, access(tmp.c_str(), F_OK));
 
-  Application touch_app("touch");
+  Application touch_app("/usr/bin/touch");
   const char *args[]= { tmp.c_str(), 0 };
   test_compare(Application::SUCCESS, touch_app.run(args));
   test_compare(Application::SUCCESS, touch_app.join());
@@ -841,6 +816,17 @@ test_st gearmand_tests[] ={
   {0, 0, 0}
 };
 
+static test_return_t clear_servers(void* object)
+{
+  server_startup_st *servers= (server_startup_st*)object;
+  test_true(servers);
+  servers->clear();
+
+  testing_service.clear();
+
+  return TEST_SUCCESS;
+}
+
 static test_return_t check_for_libmemcached(void* object)
 {
   test_skip(true, HAVE_LIBMEMCACHED);
@@ -913,9 +899,8 @@ test_st comparison_tests[] ={
 };
 
 test_st cmdline_tests[] ={
-  {"true", 0, true_BINARY },
-  {"true --fubar", 0, true_fubar_BINARY },
   {"echo fubar", 0, echo_fubar_BINARY },
+  {"core-count", 0, core_count_BINARY },
   {"wait --quiet", 0, wait_BINARY },
   {"wait --quiet --help", 0, wait_help_BINARY },
   {"wait --quiet --version", 0, wait_version_BINARY },
@@ -969,8 +954,6 @@ test_st application_tests[] ={
   {"gbd true", 0, application_gdb_true_BINARY2 },
   {"true --fubar", 0, application_true_fubar_BINARY },
   {"doesnotexist --fubar", 0, application_doesnotexist_BINARY },
-  {"true --fubar=doh", 0, application_true_fubar_eq_doh_BINARY },
-  {"true --fubar=doh add_option()", 0, application_true_fubar_eq_doh_option_BINARY },
   {"echo fubar", 0, application_echo_fubar_BINARY },
   {"echo fubar (as option)", 0, application_echo_fubar_BINARY2 },
   {0, 0, 0}
@@ -984,13 +967,14 @@ static test_return_t check_for_curl(void *)
 
 static test_return_t disable_fatal_exception(void *)
 {
+  fatal_calls= 0;
   fatal::disable();
   return TEST_SUCCESS;
 }
 
 static test_return_t enable_fatal_exception(void *)
 {
-  fatal::disable();
+  fatal::enable();
   return TEST_SUCCESS;
 }
 
@@ -1008,9 +992,9 @@ collection_st collection[] ={
   {"local", 0, 0, local_log},
   {"directories", 0, 0, directories_tests},
   {"comparison", 0, 0, comparison_tests},
-  {"gearmand", check_for_gearman, 0, gearmand_tests},
-  {"memcached", check_for_libmemcached, 0, memcached_TESTS },
-  {"drizzled", check_for_drizzle, 0, drizzled_tests},
+  {"gearmand", check_for_gearman, clear_servers, gearmand_tests},
+  {"memcached", check_for_libmemcached, clear_servers, memcached_TESTS },
+  {"drizzled", check_for_drizzle, clear_servers, drizzled_tests},
   {"cmdline", 0, 0, cmdline_tests},
   {"application", 0, 0, application_tests},
   {"http", check_for_curl, 0, http_tests},
index 515ecea2423a4b7870c973850e95b2cbf3cc4797..af3ee7ff13fe54ffb12722b54ff8537253c4cfe0 100644 (file)
       AC_REQUIRE([AX_DEBUG])
       AC_REQUIRE([AX_CXX_COMPILER_VERSION])
 
+      dnl If we are inside of VCS we append -Werror, otherwise we just use it to test other flags
+      AX_HARDEN_LIB=
       ax_append_compile_link_flags_extra=
-      AS_IF([test "$ac_cv_vcs_checkout" = "yes"], [
-        AX_CHECK_LINK_FLAG([-Werror])
+      AS_IF([test "x$ac_cv_vcs_checkout" = "xyes"],[
+        AX_CHECK_LINK_FLAG([-Werror],[
+          AX_HARDEN_LIB="-Werror $AX_HARDEN_LIB"
+          ])
         ],[
         AX_CHECK_LINK_FLAG([-Werror],[
-          ax_append_compile_link_flags_extra=$ax_cv_check_ldflags___Werror
+          ax_append_compile_link_flags_extra='-Werror'
           ])
         ])
-      AX_CHECK_LINK_FLAG([-z relro -z now],,[$ax_append_compile_link_flags_extra])
-      AX_CHECK_LINK_FLAG([-pie],,[$ax_append_compile_link_flags_extra])
+
+      AX_CHECK_LINK_FLAG([-z relro -z now],[
+        AX_HARDEN_LIB="-z relro -z now $AX_HARDEN_LIB"
+      ],,[$ax_append_compile_link_flags_extra])
+
+      AX_CHECK_LINK_FLAG([-pie],[
+          AX_HARDEN_LIB="-pie $AX_HARDEN_LIB"
+          ],,[$ax_append_compile_link_flags_extra])
+
+      LIB="$LIB $AX_HARDEN_LIB"
       ])
 
   AC_DEFUN([AX_HARDEN_CC_COMPILER_FLAGS], [
 
   AC_DEFUN([AX_HARDEN_COMPILER_FLAGS], [
       AC_REQUIRE([AX_HARDEN_CXX_COMPILER_FLAGS])
+      AC_REQUIRE([AX_CC_OTHER_FLAGS])
+      gl_VISIBILITY
+      AS_IF([ test -n "$CFLAG_VISIBILITY" ], [ CPPFLAGS="$CPPFLAGS $CFLAG_VISIBILITY" ])
       ])
 
   AC_DEFUN([AX_CC_OTHER_FLAGS], [