--- /dev/null
+/* 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 <libtest/common.h>
+#include <libtest/blobslap_worker.h>
+#include <libtest/killpid.h>
+
+using namespace libtest;
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <libgearman/gearman.h>
+
+#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 <sstream>
+
+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);
+}
+
+}
--- /dev/null
+/* 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);
+
+}
#include <libtest/cmdline.h>
+using namespace libtest;
+
#include <cstdlib>
#include <string>
#include <sstream>
arg_buffer << " -u root ";
}
+ arg_buffer << " --listen=127.0.0.1 ";
+
for (int x= 1 ; x < argc ; x++)
{
arg_buffer << " " << argv[x] << " ";
# 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
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 \
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
}
-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")))
{
}
}
}
+
+ 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;
}
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);
#ifdef HAVE_LIBGEARMAN
#include <libtest/gearmand.h>
+#include <libtest/blobslap_worker.h>
#endif
#ifdef HAVE_LIBMEMCACHED
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();
if (getenv("LIBTEST_LOG") and log_file_option())
{
if (not set_log_file())
+ {
return false;
+ }
arg_buffer << " " << log_file_option() << _log_file;
}
if (pid_file_option())
{
if (not set_pid_file())
+ {
return false;
+ }
arg_buffer << " " << pid_file_option() << pid_file();
}
if (_is_socket and socket_file_option())
{
if (not set_socket_file())
+ {
return false;
+ }
arg_buffer << " " << socket_file_option() << "\"" << _socket << "\"";
}
options+= arg_buffer.str();
if (not _extra_args.empty())
+ {
options+= _extra_args;
+ }
return true;
}
#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)
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);
+ }
}
}
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)
case SIGQUIT:
if (context->is_shutdown() == false)
{
- Error << "Signal handling thread got signal " << strsignal(sig);
context->set_shutdown(SHUTDOWN_FORCED);
}
break;
}
SignalThread::SignalThread() :
- magic_memory(MAGIC_MEMORY)
+ magic_memory(MAGIC_MEMORY),
+ thread(pthread_self())
{
pthread_mutex_init(&shutdown_mutex, NULL);
sigemptyset(&set);
return sigwait(&set, &sig);
}
- ~SignalThread()
- {
- sem_destroy(&lock);
- }
+ ~SignalThread();
void set_shutdown(shutdown_t arg);
bool is_shutdown();
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;
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;
}
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.";
}
#include <libtest/test.hpp>
#include <cstdlib>
+#include <unistd.h>
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;
{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 },
};
collection_st collection[] ={
+ {"environment", 0, 0, environment_tests},
{"return values", 0, 0, tests_log},
{"local", 0, 0, local_log},
{"gearmand", 0, 0, gearmand_tests},