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
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"
--- /dev/null
+/* 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
+
--- /dev/null
+/* 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
+
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 {
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;
}
}
}
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)
{
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);
}
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);
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;
}
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
{
// 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);
}
}
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)
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);
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
_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);
+ }
+ }
}
}
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");
#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 {
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)
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;
}
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
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)
}
}
- 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++;
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)
{
--- /dev/null
+/* 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;
+}
#include <unistd.h>
+#pragma GCC diagnostic ignored "-Wundef"
+
#if defined(HAVE_SYS_SYSCTL_H) && HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
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);
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);
}
void fatal::disable()
{
+ _counter= 0;
_disabled= true;
}
void fatal::enable()
{
+ _counter= 0;
_disabled= false;
}
_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);
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()
{
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;
};
_total++;
- try
- {
+ try {
switch ((*iter)->exec())
{
case TEST_FAILURE:
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 (...)
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())))
{
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);
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;
}
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;
{
return true;
}
-#endif
}
+#endif
return false;
}
bool has_memcached()
{
+#if defined(HAVE_MEMCACHED_BINARY) && HAVE_MEMCACHED_BINARY
if (HAVE_MEMCACHED_BINARY)
{
std::stringstream arg_buffer;
return true;
}
}
+#endif
return false;
}
}
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)
#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)
#
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
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
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
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
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
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
}
}
- 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;
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;
return EXIT_SKIP;
case TEST_FAILURE:
- std::cerr << "frame->create()" << std::endl;
+ std::cerr << __FILE__ << ":" << __LINE__ << ": " << "frame->create()" << std::endl;
return EXIT_FAILURE;
}
}
}
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;
}
#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;
}
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;
}
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;
}
#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
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)
{
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;
}
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;
}
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,
Server::~Server()
{
+ kill();
}
bool Server::check()
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"))
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();
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 : "",
}
}
- 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;
break;
}
+ Error << "ping(" << _app.pid() << ") wait: " << this_wait << " " << hostname() << ":" << port() << " " << error();
+
this_wait= retry * retry / 3 + 1;
libtest::dream(this_wait, 0);
}
_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();
_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()
{
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.
*/
}
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 (...)
{
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)
#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" {
switch (sig)
{
+ case SIGVTALRM:
+ Error << "SIGVTALRM was called";
+ context->unblock();
+ raise(SIGVTALRM);
+
case SIGABRT:
case SIGUSR2:
case SIGINT:
sigaddset(&set, SIGABRT);
sigaddset(&set, SIGQUIT);
sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGVTALRM);
}
sigaddset(&set, SIGPIPE);
{
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.";
void test();
void post();
bool setup();
+ bool unblock();
int wait(int& sig)
{
#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>
#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>
# include <mach/clock.h>
# include <mach/mach.h>
#else
-# include <time.h>
# include <sys/time.h>
#endif
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
}
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"));
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;
}
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;
}
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;
}
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;
}
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();
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;
}
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;
}
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;
}
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;
}
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;
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());
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/");
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;
}
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;
}
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;
}
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 ));
return TEST_SUCCESS;
}
-static uint32_t fatal_calls= 0;
-
static test_return_t fatal_TEST(void *)
{
test_compare(fatal_calls++, fatal::disabled_counter());
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());
{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);
};
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 },
{"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}
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;
}
{"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},
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], [