From a0a194ba0789e0650329d81a5ed12620360789eb Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Sun, 21 Oct 2012 20:48:10 -0400 Subject: [PATCH] Update libtest. --- configure.ac | 3 +- libtest/alarm.cc | 85 +++++++++ libtest/alarm.h | 46 +++++ libtest/cmdline.cc | 307 +++++++++++++++------------------ libtest/cmdline.h | 32 +++- libtest/collection.cc | 10 +- libtest/comparison.hpp | 3 + libtest/core_count.cc | 135 +++++++++++++++ libtest/cpu.cc | 2 + libtest/fatal.cc | 47 ++--- libtest/fatal.hpp | 89 ++++------ libtest/framework.cc | 5 +- libtest/gearmand.cc | 8 +- libtest/has.cc | 10 +- libtest/http.cc | 19 +- libtest/include.am | 25 +-- libtest/killpid.cc | 33 ++-- libtest/main.cc | 20 +-- libtest/memcached.hpp | 6 +- libtest/port.cc | 75 ++++++-- libtest/server.cc | 96 +++++++---- libtest/server_container.cc | 46 ++--- libtest/signal.cc | 32 +++- libtest/signal.h | 1 + libtest/test.hpp | 12 +- libtest/timer.hpp | 19 +- libtest/unittest.cc | 164 ++++++++---------- m4/ax_harden_compiler_flags.m4 | 25 ++- 28 files changed, 847 insertions(+), 508 deletions(-) create mode 100644 libtest/alarm.cc create mode 100644 libtest/alarm.h create mode 100644 libtest/core_count.cc diff --git a/configure.ac b/configure.ac index 28fa4303..a6a4f76b 100644 --- a/configure.ac +++ b/configure.ac @@ -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 index 00000000..08ac787c --- /dev/null +++ b/libtest/alarm.cc @@ -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 +#include + +#include +#include + +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 index 00000000..f675c580 --- /dev/null +++ b/libtest/alarm.h @@ -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 + diff --git a/libtest/cmdline.cc b/libtest/cmdline.cc index 5c3d09f2..d4dd970b 100644 --- a/libtest/cmdline.cc +++ b/libtest/cmdline.cc @@ -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"); diff --git a/libtest/cmdline.h b/libtest/cmdline.h index 46f7ad78..ae4d9ba1 100644 --- a/libtest/cmdline.h +++ b/libtest/cmdline.h @@ -42,6 +42,14 @@ #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) diff --git a/libtest/collection.cc b/libtest/collection.cc index 26e8bb44..3bf571e8 100644 --- a/libtest/collection.cc +++ b/libtest/collection.cc @@ -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++; diff --git a/libtest/comparison.hpp b/libtest/comparison.hpp index 30119d1e..5b3172a1 100644 --- a/libtest/comparison.hpp +++ b/libtest/comparison.hpp @@ -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 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 index 00000000..351ae1c0 --- /dev/null +++ b/libtest/core_count.cc @@ -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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +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; +} diff --git a/libtest/cpu.cc b/libtest/cpu.cc index abf2b2ed..4643e56d 100644 --- a/libtest/cpu.cc +++ b/libtest/cpu.cc @@ -39,6 +39,8 @@ #include +#pragma GCC diagnostic ignored "-Wundef" + #if defined(HAVE_SYS_SYSCTL_H) && HAVE_SYS_SYSCTL_H #include #endif diff --git a/libtest/fatal.cc b/libtest/fatal.cc index cdccff82..890975e6 100644 --- a/libtest/fatal.cc +++ b/libtest/fatal.cc @@ -40,20 +40,12 @@ 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); diff --git a/libtest/fatal.hpp b/libtest/fatal.hpp index 6ac62b77..bb8cc938 100644 --- a/libtest/fatal.hpp +++ b/libtest/fatal.hpp @@ -53,45 +53,55 @@ 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; }; diff --git a/libtest/framework.cc b/libtest/framework.cc index 6cca8450..8bc6e65c 100644 --- a/libtest/framework.cc +++ b/libtest/framework.cc @@ -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 (...) diff --git a/libtest/gearmand.cc b/libtest/gearmand.cc index f6dbdfce..c83f4eef 100644 --- a/libtest/gearmand.cc +++ b/libtest/gearmand.cc @@ -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); diff --git a/libtest/has.cc b/libtest/has.cc index accadf98..9f8cf5ba 100644 --- a/libtest/has.cc +++ b/libtest/has.cc @@ -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; } diff --git a/libtest/http.cc b/libtest/http.cc index 0af12925..02d20cee 100644 --- a/libtest/http.cc +++ b/libtest/http.cc @@ -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) diff --git a/libtest/include.am b/libtest/include.am index 3fb592b6..5d05aa4a 100644 --- a/libtest/include.am +++ b/libtest/include.am @@ -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 diff --git a/libtest/killpid.cc b/libtest/killpid.cc index aae43bb3..5bf285c4 100644 --- a/libtest/killpid.cc +++ b/libtest/killpid.cc @@ -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; diff --git a/libtest/main.cc b/libtest/main.cc index 6bffa84c..363c2a2f 100644 --- a/libtest/main.cc +++ b/libtest/main.cc @@ -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; } diff --git a/libtest/memcached.hpp b/libtest/memcached.hpp index c4953975..e0e14851 100644 --- a/libtest/memcached.hpp +++ b/libtest/memcached.hpp @@ -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(&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(&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(&memc)) != rc) { return true; } diff --git a/libtest/port.cc b/libtest/port.cc index 01e0e88b..04d4bd14 100644 --- a/libtest/port.cc +++ b/libtest/port.cc @@ -57,6 +57,18 @@ #include +#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; } diff --git a/libtest/server.cc b/libtest/server.cc index b128788a..d58b362e 100644 --- a/libtest/server.cc +++ b/libtest/server.cc @@ -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() diff --git a/libtest/server_container.cc b/libtest/server_container.cc index 2d7655bc..f87a9fba 100644 --- a/libtest/server_container.cc +++ b/libtest/server_container.cc @@ -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 (...) { diff --git a/libtest/signal.cc b/libtest/signal.cc index 86c4a431..53a436be 100644 --- a/libtest/signal.cc +++ b/libtest/signal.cc @@ -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."; diff --git a/libtest/signal.h b/libtest/signal.h index fd7e4a6d..6e68bb38 100644 --- a/libtest/signal.h +++ b/libtest/signal.h @@ -65,6 +65,7 @@ public: void test(); void post(); bool setup(); + bool unblock(); int wait(int& sig) { diff --git a/libtest/test.hpp b/libtest/test.hpp index 76760487..bdcccdc0 100644 --- a/libtest/test.hpp +++ b/libtest/test.hpp @@ -42,17 +42,6 @@ #include #include -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else -# ifdef HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - #include #include @@ -63,6 +52,7 @@ #include #include #include +#include #include #include #include diff --git a/libtest/timer.hpp b/libtest/timer.hpp index eac51940..28ec4741 100644 --- a/libtest/timer.hpp +++ b/libtest/timer.hpp @@ -44,7 +44,6 @@ # include # include #else -# include # include #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 } diff --git a/libtest/unittest.cc b/libtest/unittest.cc index 6b3efe95..0af3e30f 100644 --- a/libtest/unittest.cc +++ b/libtest/unittest.cc @@ -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}, diff --git a/m4/ax_harden_compiler_flags.m4 b/m4/ax_harden_compiler_flags.m4 index 515ecea2..af3ee7ff 100644 --- a/m4/ax_harden_compiler_flags.m4 +++ b/m4/ax_harden_compiler_flags.m4 @@ -64,16 +64,28 @@ 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], [ @@ -212,6 +224,9 @@ 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], [ -- 2.30.2