From 582b47ae25f9fecc459204592f23491297488cd8 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Wed, 27 Jul 2011 09:56:41 -0700 Subject: [PATCH] Merge in libtest updates. --- libtest/blobslap_worker.cc | 179 +++++++++++++++++++++++++++++++++++++ libtest/blobslap_worker.h | 43 +++++++++ libtest/cmdline.cc | 2 + libtest/gearmand.cc | 2 + libtest/include.am | 43 +++++---- libtest/killpid.cc | 38 +++++++- libtest/killpid.h | 4 +- libtest/server.cc | 42 +++++++-- libtest/signal.cc | 23 +++-- libtest/signal.h | 5 +- libtest/test.cc | 25 +++++- libtest/unittest.cc | 34 +++++++ 12 files changed, 398 insertions(+), 42 deletions(-) create mode 100644 libtest/blobslap_worker.cc create mode 100644 libtest/blobslap_worker.h diff --git a/libtest/blobslap_worker.cc b/libtest/blobslap_worker.cc new file mode 100644 index 00000000..2ac07d68 --- /dev/null +++ b/libtest/blobslap_worker.cc @@ -0,0 +1,179 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * libtest + * + * Copyright (C) 2011 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 + +using namespace libtest; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef __INTEL_COMPILER +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +using namespace libtest; + +class BlobslapWorker : public Server +{ +private: +public: + BlobslapWorker(in_port_t port_arg) : + Server("localhost", port_arg) + { } + + pid_t get_pid(bool error_is_ok) + { + if (not pid_file().empty()) + { + Wait wait(pid_file(), 0); + + if (error_is_ok and not wait.successful()) + { + Error << "Pidfile was not found:" << pid_file(); + return -1; + + return get_pid_from_file(pid_file()); + } + } + + return -1; + } + + bool ping() + { + if (pid_file().empty()) + { + Error << "No pid file available"; + return false; + } + + Wait wait(pid_file(), 0); + if (not wait.successful()) + { + Error << "Pidfile was not found:" << pid_file(); + return false; + } + + pid_t local_pid= get_pid_from_file(pid_file()); + if (local_pid <= 0) + { + return false; + } + + if (::kill(local_pid, 0) == 0) + { + return true; + } + + return false; + } + + const char *name() + { + return "blobslap_worker"; + }; + + const char *executable() + { + return GEARMAND_BLOBSLAP_WORKER; + } + + const char *pid_file_option() + { + return "--pid-file="; + } + + const char *daemon_file_option() + { + return "--daemon"; + } + + const char *log_file_option() + { + return NULL; + } + + const char *port_option() + { + return "--port="; + } + + bool is_libtool() + { + return true; + } + + bool build(int argc, const char *argv[]); +}; + + +#include + +bool BlobslapWorker::build(int argc, const char *argv[]) +{ + std::stringstream arg_buffer; + + for (int x= 1 ; x < argc ; x++) + { + arg_buffer << " " << argv[x] << " "; + } + + set_extra_args(arg_buffer.str()); + + return true; +} + +namespace libtest { + +Server *build_blobslap_worker(in_port_t try_port) +{ + return new BlobslapWorker(try_port); +} + +} diff --git a/libtest/blobslap_worker.h b/libtest/blobslap_worker.h new file mode 100644 index 00000000..96eb4267 --- /dev/null +++ b/libtest/blobslap_worker.h @@ -0,0 +1,43 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * libtest + * + * Copyright (C) 2011 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 { + +Server *build_blobslap_worker(in_port_t try_port); + +} diff --git a/libtest/cmdline.cc b/libtest/cmdline.cc index d7bed820..afd560b2 100644 --- a/libtest/cmdline.cc +++ b/libtest/cmdline.cc @@ -38,6 +38,8 @@ #include +using namespace libtest; + #include #include #include diff --git a/libtest/gearmand.cc b/libtest/gearmand.cc index f526e015..bd9bd14d 100644 --- a/libtest/gearmand.cc +++ b/libtest/gearmand.cc @@ -208,6 +208,8 @@ bool Gearmand::build(int argc, const char *argv[]) arg_buffer << " -u root "; } + arg_buffer << " --listen=127.0.0.1 "; + for (int x= 1 ; x < argc ; x++) { arg_buffer << " " << argv[x] << " "; diff --git a/libtest/include.am b/libtest/include.am index 7cda0f9b..57d579ba 100644 --- a/libtest/include.am +++ b/libtest/include.am @@ -9,12 +9,19 @@ # All paths should be given relative to the root # -LIBUTEST_TMP = ${abs_top_builddir}/tests/var/tmp/ +LIBTEST_TMP = ${abs_top_builddir}/tests/var/tmp/ -VALGRIND_COMMAND= $(LIBTOOL) --mode=execute valgrind --error-exitcode=1 --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE -HELGRIND_COMMAND= $(LIBTOOL) --mode=execute valgrind --tool=helgrind --read-var-info=yes --error-exitcode=1 -v -DRD_COMMAND= $(LIBTOOL) --mode=execute valgrind --tool=drd -GDB_COMMAND= $(LIBTOOL) --mode=execute gdb -f -x libtest/run.gdb +LIBTOOL_COMMAND=$(LIBTOOL) --mode=execute +VALGRIND_COMMAND= $(LIBTOOL_COMMAND) valgrind --error-exitcode=1 --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE +HELGRIND_COMMAND= $(LIBTOOL_COMMAND) valgrind --tool=helgrind --read-var-info=yes --error-exitcode=1 +DRD_COMMAND= $(LIBTOOL_COMMAND) valgrind --tool=drd +GDB_COMMAND= $(LIBTOOL_COMMAND) gdb -f -x libtest/run.gdb + +export LIBTOOL_COMMAND +export VALGRIND_COMMAND +export HELGRIND_COMMAND +export DRD_COMMAND +export GDB_COMMAND EXTRA_DIST+= libtest/run.gdb @@ -24,11 +31,12 @@ CLEANFILES+= \ tests/var/tmp/* noinst_HEADERS+= \ + libtest/blobslap_worker.h \ libtest/callbacks.h \ libtest/cmdline.h \ libtest/collection.h \ - libtest/comparison.hpp \ libtest/common.h \ + libtest/comparison.hpp \ libtest/core.h \ libtest/error.h \ libtest/failed.h \ @@ -77,34 +85,37 @@ endif if HAVE_LIBGEARMAN LIBTEST_LDADD+= libgearman/libgearman.la +libtest_libtest_la_SOURCES+= libtest/blobslap_worker.cc libtest_libtest_la_SOURCES+= libtest/gearmand.cc libtest_libtest_la_SOURCES+= util/instance.cc +libtest_libtest_la_SOURCES+= util/operation.cc endif +libtest_tmp_dir: tests/var/log tests/var/tmp tests/var/run clearn-var + clearn-var: @rm -f tests/var/log/* @rm -f tests/var/run/* @rm -f tests/var/tmp/* +tests/var: + @$(mkdir_p) tests/var -tests/var: tests/var/log tests/var/tmp tests/var/run clearn-var - $(mkdir_p) tests/var - -tests/var/log: - $(mkdir_p) tests/var/log +tests/var/log: tests/var + @$(mkdir_p) tests/var/log -tests/var/tmp: - $(mkdir_p) tests/var/tmp +tests/var/tmp: tests/var + @$(mkdir_p) tests/var/tmp -tests/var/run: - $(mkdir_p) tests/var/run +tests/var/run: tests/var + @$(mkdir_p) tests/var/run .PHONY+= tests/var libtest_unittest_CFLAGS= libtest_unittest_LDADD= ${LIBTEST_LDADD} -libtest_unittest_DEPENDENCIES= ${LIBTEST_LDADD} +libtest_unittest_DEPENDENCIES= ${LIBTEST_LDADD} libtest_tmp_dir libtest_unittest_SOURCES= libtest/unittest.cc check_PROGRAMS+= libtest/unittest noinst_PROGRAMS+= libtest/unittest diff --git a/libtest/killpid.cc b/libtest/killpid.cc index bc9a5594..1d5992db 100644 --- a/libtest/killpid.cc +++ b/libtest/killpid.cc @@ -99,12 +99,13 @@ bool kill_pid(pid_t pid_arg) } -void kill_file(const std::string &filename) +pid_t kill_file(const std::string &filename) { + pid_t ret= -1; FILE *fp; if (filename.empty()) - return; + return ret; if ((fp= fopen(filename.c_str(), "r"))) { @@ -123,4 +124,37 @@ void kill_file(const std::string &filename) } } } + + return ret; +} + +pid_t get_pid_from_file(const std::string &filename) +{ + pid_t ret= -1; + FILE *fp; + + if (filename.empty()) + { + Error << "empty pid file"; + return ret; + } + + if ((fp= fopen(filename.c_str(), "r"))) + { + char pid_buffer[1024]; + + char *ptr= fgets(pid_buffer, sizeof(pid_buffer), fp); + fclose(fp); + + if (ptr) + { + ret= (pid_t)atoi(pid_buffer); + if (ret <= 0) + { + return ret; + } + } + } + + return ret; } diff --git a/libtest/killpid.h b/libtest/killpid.h index d67ec94b..12c438e5 100644 --- a/libtest/killpid.h +++ b/libtest/killpid.h @@ -39,4 +39,6 @@ bool kill_pid(pid_t pid_arg); -void kill_file(const std::string &filename); +pid_t kill_file(const std::string &filename); + +pid_t get_pid_from_file(const std::string &filename); diff --git a/libtest/server.cc b/libtest/server.cc index d5329b11..bf962e42 100644 --- a/libtest/server.cc +++ b/libtest/server.cc @@ -58,6 +58,7 @@ static inline std::string &rtrim(std::string &s) #ifdef HAVE_LIBGEARMAN #include +#include #endif #ifdef HAVE_LIBMEMCACHED @@ -324,23 +325,26 @@ bool Server::set_log_file() void Server::rebuild_base_command() { _base_command.clear(); - if (is_libtool()) + if (is_libtool() and getenv("LIBTOOL_COMMAND")) { - _base_command+= "./libtool --mode=execute "; + _base_command+= getenv("LIBTOOL_COMMAND"); + _base_command+= " "; } - if (is_debug()) + if (is_debug() and getenv("GDB_COMMAND")) { - _base_command+= "gdb "; + _base_command+= getenv("GDB_COMMAND"); + _base_command+= " "; } - else if (is_valgrind()) + else if (is_valgrind() and getenv("VALGRIND_COMMAND")) { - _base_command+= "valgrind --log-file=tests/var/tmp/valgrind.out --error-exitcode=1 --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE "; - + _base_command+= getenv("VALGRIND_COMMAND"); + _base_command+= " "; } - else if (is_helgrind()) + else if (is_helgrind() and getenv("HELGRIND_COMMAND")) { - _base_command+= "valgrind --log-file=tests/var/tmp/helgrind.out --tool=helgrind --read-var-info=yes --error-exitcode=1 -v "; + _base_command+= getenv("HELGRIND_COMMAND"); + _base_command+= " "; } _base_command+= executable(); @@ -359,7 +363,9 @@ bool Server::args(std::string& options) if (getenv("LIBTEST_LOG") and log_file_option()) { if (not set_log_file()) + { return false; + } arg_buffer << " " << log_file_option() << _log_file; } @@ -368,7 +374,9 @@ bool Server::args(std::string& options) if (pid_file_option()) { if (not set_pid_file()) + { return false; + } arg_buffer << " " << pid_file_option() << pid_file(); } @@ -382,7 +390,9 @@ bool Server::args(std::string& options) if (_is_socket and socket_file_option()) { if (not set_socket_file()) + { return false; + } arg_buffer << " " << socket_file_option() << "\"" << _socket << "\""; } @@ -396,7 +406,9 @@ bool Server::args(std::string& options) options+= arg_buffer.str(); if (not _extra_args.empty()) + { options+= _extra_args; + } return true; } @@ -544,6 +556,18 @@ bool server_startup(server_startup_st& construct, const std::string& server_type #endif #else Error << "No gearmand binary is available"; +#endif + } + else if (server_type.compare("blobslap_worker") == 0) + { +#ifdef GEARMAND_BINARY + #ifdef HAVE_LIBGEARMAN + server= build_blobslap_worker(try_port); + #else + Error << "Libgearman was not found"; + #endif +#else + Error << "No gearmand binary is available"; #endif } else if (server_type.compare("memcached") == 0) diff --git a/libtest/signal.cc b/libtest/signal.cc index 45d0fd9e..263d183a 100644 --- a/libtest/signal.cc +++ b/libtest/signal.cc @@ -62,10 +62,11 @@ void SignalThread::set_shutdown(shutdown_t arg) if (arg == SHUTDOWN_GRACEFUL) { - pthread_kill(thread, SIGUSR2); - - void *retval; - pthread_join(thread, &retval); + if (pthread_kill(thread, SIGUSR2) == 0) + { + void *retval; + pthread_join(thread, &retval); + } } } @@ -96,6 +97,16 @@ void SignalThread::test() assert(sigismember(&set, SIGUSR2)); } +SignalThread::~SignalThread() +{ + if (pthread_equal(thread, pthread_self()) != 0 and (pthread_kill(thread, 0) == ESRCH) == true) + { + void *retval; + pthread_join(thread, &retval); + } + sem_destroy(&lock); +} + extern "C" { static void *sig_thread(void *arg) @@ -123,7 +134,6 @@ static void *sig_thread(void *arg) case SIGQUIT: if (context->is_shutdown() == false) { - Error << "Signal handling thread got signal " << strsignal(sig); context->set_shutdown(SHUTDOWN_FORCED); } break; @@ -140,7 +150,8 @@ static void *sig_thread(void *arg) } SignalThread::SignalThread() : - magic_memory(MAGIC_MEMORY) + magic_memory(MAGIC_MEMORY), + thread(pthread_self()) { pthread_mutex_init(&shutdown_mutex, NULL); sigemptyset(&set); diff --git a/libtest/signal.h b/libtest/signal.h index eb092825..d87d4f4e 100644 --- a/libtest/signal.h +++ b/libtest/signal.h @@ -69,10 +69,7 @@ public: return sigwait(&set, &sig); } - ~SignalThread() - { - sem_destroy(&lock); - } + ~SignalThread(); void set_shutdown(shutdown_t arg); bool is_shutdown(); diff --git a/libtest/test.cc b/libtest/test.cc index d71057d3..d113740f 100644 --- a/libtest/test.cc +++ b/libtest/test.cc @@ -94,6 +94,11 @@ void set_default_socket(const char *socket) static void stats_print(Stats *stats) { + if (stats->collection_failed == 0 and stats->collection_success == 0) + { + return; + } + Out << "\tTotal Collections\t\t\t\t" << stats->collection_total; Out << "\tFailed Collections\t\t\t\t" << stats->collection_failed; Out << "\tSkipped Collections\t\t\t\t" << stats->collection_skipped; @@ -179,9 +184,21 @@ int main(int argc, char *argv[]) test_return_t error; void *creators_ptr= world->create(error); - if (test_failed(error)) + + switch (error) { - Error << "create() failed"; + case TEST_SUCCESS: + break; + + case TEST_SKIPPED: + Out << "SKIP " << argv[0]; + delete world; + return EXIT_SUCCESS; + + case TEST_FATAL: + case TEST_FAILURE: + case TEST_MEMORY_ALLOCATION_FAILURE: + Error << argv[0] << "create() failed"; delete world; return EXIT_FAILURE; } @@ -368,11 +385,11 @@ cleanup: Out << "Some test failed."; exit_code= EXIT_FAILURE; } - else if (stats.collection_skipped) + else if (stats.collection_skipped and stats.collection_failed and stats.collection_success) { Out << "Some tests were skipped."; } - else + else if (stats.collection_success and stats.collection_failed == 0) { Out << "All tests completed successfully."; } diff --git a/libtest/unittest.cc b/libtest/unittest.cc index 1528106b..6902d001 100644 --- a/libtest/unittest.cc +++ b/libtest/unittest.cc @@ -40,9 +40,34 @@ #include #include +#include using namespace libtest; +static test_return_t LIBTOOL_COMMAND_test(void *) +{ + test_true(getenv("LIBTOOL_COMMAND")); + return TEST_SUCCESS; +} + +static test_return_t VALGRIND_COMMAND_test(void *) +{ + test_true(getenv("VALGRIND_COMMAND")); + return TEST_SUCCESS; +} + +static test_return_t HELGRIND_COMMAND_test(void *) +{ + test_true(getenv("HELGRIND_COMMAND")); + return TEST_SUCCESS; +} + +static test_return_t GDB_COMMAND_test(void *) +{ + test_true(getenv("GDB_COMMAND")); + return TEST_SUCCESS; +} + static test_return_t test_success_test(void *) { return TEST_SUCCESS; @@ -171,6 +196,14 @@ test_st memcached_tests[] ={ {0, 0, 0} }; +test_st environment_tests[] ={ + {"LIBTOOL_COMMAND", 0, LIBTOOL_COMMAND_test }, + {"VALGRIND_COMMAND", 0, VALGRIND_COMMAND_test }, + {"HELGRIND_COMMAND", 0, HELGRIND_COMMAND_test }, + {"GDB_COMMAND", 0, GDB_COMMAND_test }, + {0, 0, 0} +}; + test_st tests_log[] ={ {"TEST_SUCCESS", 0, test_success_test }, {"TEST_FAILURE", 0, test_failure_test }, @@ -184,6 +217,7 @@ test_st local_log[] ={ }; collection_st collection[] ={ + {"environment", 0, 0, environment_tests}, {"return values", 0, 0, tests_log}, {"local", 0, 0, local_log}, {"gearmand", 0, 0, gearmand_tests}, -- 2.30.2