*/Makefile.in
*TAGS
.deps
+.hg/
+.hgsub
+.hgignore
+.hgsubstate
INSTALL
Makefile
Makefile.in
configure
docs/*.[13]
docs/*.html
+docs/changes
docs/conf.py
docs/doctest/
docs/doctrees/
docs/html/
docs/linkcheck/
docs/man/*
+docs/text
example/memcached_light
libhashkit/configure.h
libmemcached-*.tar.gz
libmemcached/dtrace_probes.h
libmemcached/generated_probes.h
libmemcached/memcached_configure.h
+libtest/.hg/
+libtest/.hgignore
+libtest/unittest
+libtest/wait
libtool
libtool.m4
ltoptions.m4
support/libmemcached.spec
tags
tests/atomsmasher
+tests/cycle
tests/hash_plus
tests/hashplus
tests/memplus
tests/testudp
tests/var/
unittests/unittests
-libtest/wait
-docs/text
-docs/changes
-tests/cycle
-libtest/unittest
+++ /dev/null
-# Exact paths to config junk
-^INSTALL$
-^aclocal.m4$
-^configure$
-^config/(config.guess|config.sub|depcomp|install-sh|ltmain.sh|missing)$
-^config.(log|status)$
-^libtool$
-^autom4te.cache$
-^libmemcached/(libmemcached_config.h(.in)?|stamp-h1)$
-^libmemcached/libmemcached_config.h.in$
-^stamp-h1$
-^lib/libmemcachedPlus.la$
-^tests/testplus$
-
-# Don't bother with TAGS files
-TAGS
-clients/TAGS
-clients/memdump
-libmemcached/TAGS
-libmemcachedutil/TAGS
-tests/TAGS
-
-
-
-# Build artifacts
-^libmemcached/libmemcached.la$
-^libmemcachedutil/libmemcachedutil.la$
-^clients/mem(cat|cp|flush|rm|slap|stat|error)$
-^tests/testapp$
-.(deps|libs)/*$
-.cmp$
-autom4te.cache/*$
-.(gz|cmp|tar|rpm|srpm)$
-support/libmemcached.pc$
-support/libmemcached.spec$
-support/libmemcached-fc.spec$
-docs/pod2htmd.tmp
-docs/pod2htmi.tmp
-libmemcached/memcachedplus.loT
-tests/atomsmasher
-tests/startservers
-tests/stopservers
-tests/udptest
-^libmemcached/dtrace_probes.h$
-^tests/core$
-
-Makefile(.in)?$
-.(deps|libs)$
-\.l?o$
-
-# Generated man files
-\.1$
-\.3$
-
-# Merged files
-\.orig$
-
-#HTML files
-docs/libmemcached/default.css
-docs/libmemcached/memcached.html
-docs/libmemcached/memcached_auto.html
-docs/libmemcached/memcached_behavior.html
-docs/libmemcached/memcached_callback.html
-docs/libmemcached/memcached_create.html
-docs/libmemcached/memcached_delete.html
-docs/libmemcached/memcached_examples.html
-docs/libmemcached/memcached_flush.html
-docs/libmemcached/memcached_get.html
-docs/libmemcached/memcached_quit.html
-docs/libmemcached/memcached_result_st.html
-docs/libmemcached/memcached_server_st.html
-docs/libmemcached/memcached_servers.html
-docs/libmemcached/memcached_set.html
-docs/libmemcached/memcached_stats.html
-docs/libmemcached/memcached_strerror.html
-docs/libmemcached/memcached_verbosity.html
-docs/libmemcached/memcached_version.html
-docs/libmemcached/memcat.html
-docs/libmemcached/memcp.html
-docs/libmemcached/memerror.html
-docs/libmemcached/memflush.html
-docs/libmemcached/memrm.html
-docs/libmemcached/memslap.html
-docs/libmemcached/memstat.html
-
-# Backup files created by emacs
-.*~$
@cp ~/rpmbuild/RPMS/x86_64/libmemcached-$(VERSION)*.rpm .
@cp ~/rpmbuild/SRPMS/libmemcached-$(VERSION)*.rpm .
-generic:
+generic: support/libmemcached.spec
@rm -f ~/rpmbuild/RPMS/x86_64/libmemcached-$(VERSION)*.rpm
@rm -f ~/rpmbuild/SRPMS/libmemcached-$(VERSION)*.rpm
@cp libmemcached-$(VERSION).tar.gz ~/rpmbuild/SOURCES/
AC_INIT([libmemcached],[0.51],[http://libmemcached.org/])
AC_CONFIG_SRCDIR([libmemcached/memcached.cc])
AC_CONFIG_AUX_DIR(config)
+AC_CONFIG_MACRO_DIR(m4)
PANDORA_CANONICAL_TARGET(no-vc-changelog)
AC_CHECK_PROGS([YACC], ['bison'], [:])
HASHKIT_LIBRARY_VERSION=1:0:0
AC_SUBST(HASHKIT_LIBRARY_VERSION)
+AC_DEFINE([HAVE_LIBMEMCACHED], [ 1 ], [dummy rule for libtest])
+AC_SUBST(HAVE_LIBMEMCACHED, 1)
+AM_CONDITIONAL(HAVE_LIBMEMCACHED, true)
+
AH_TOP([
#ifndef CONFIG_H
#define CONFIG_H
PANDORA_HAVE_LIBINNODB
PANDORA_PRINT_CALLSTACK
PANDORA_HAVE_SASL
+WITH_LIBGEARMAN
dnl The sasl functions should only be visible if we build with sasl support
AS_IF([test "x$ac_cv_sasl" = "xyes"],
return self->number_of_hosts;
}
-const char *memcached_server_name(memcached_server_instance_st self)
+const char *memcached_server_name(const memcached_server_instance_st self)
{
WATCHPOINT_ASSERT(self);
if (not self)
return self->hostname;
}
-in_port_t memcached_server_port(memcached_server_instance_st self)
+in_port_t memcached_server_port(const memcached_server_instance_st self)
{
WATCHPOINT_ASSERT(self);
if (not self)
return self->port;
}
-uint32_t memcached_server_response_count(memcached_server_instance_st self)
+uint32_t memcached_server_response_count(const memcached_server_instance_st self)
{
WATCHPOINT_ASSERT(self);
if (not self)
return self->cursor_active;
}
-const char *memcached_server_type(memcached_server_instance_st ptr)
+const char *memcached_server_type(const memcached_server_instance_st ptr)
{
if (ptr)
{
Operations on Single Servers.
*/
LIBMEMCACHED_API
-uint32_t memcached_server_response_count(memcached_server_instance_st self);
+uint32_t memcached_server_response_count(const memcached_server_instance_st self);
LIBMEMCACHED_API
-const char *memcached_server_name(memcached_server_instance_st self);
+const char *memcached_server_name(const memcached_server_instance_st self);
LIBMEMCACHED_API
-in_port_t memcached_server_port(memcached_server_instance_st self);
+in_port_t memcached_server_port(const memcached_server_instance_st self);
LIBMEMCACHED_API
-const char *memcached_server_type(memcached_server_instance_st ptr);
+const char *memcached_server_type(const memcached_server_instance_st ptr);
LIBMEMCACHED_LOCAL
extern "C" {
#endif
-typedef void* (test_callback_create_fn)(enum test_return_t*);
+typedef void* (test_callback_create_fn)(libtest::server_startup_st&, test_return_t&);
+typedef bool test_callback_destroy_fn(void *);
typedef enum test_return_t (test_callback_fn)(void *);
typedef enum test_return_t (test_callback_runner_fn)(test_callback_fn*, void *);
-typedef enum test_return_t (test_callback_error_fn)(const enum test_return_t, void *);
+typedef enum test_return_t (test_callback_error_fn)(const test_return_t, void *);
#ifdef __cplusplus
}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * uTest
+ *
+ * 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/cmdline.h>
+
+#include <cstdlib>
+#include <string>
+#include <sstream>
+
+bool exec_cmdline(const std::string& executable, const char *args[])
+{
+ std::stringstream arg_buffer;
+
+ arg_buffer << "./libtool --mode=execute ";
+
+ arg_buffer << executable;
+ for (const char **ptr= args; *ptr; ++ptr)
+ {
+ arg_buffer << " " << *ptr;
+ }
+
+ arg_buffer << " > /dev/null 2>&1";
+ if (system(arg_buffer.str().c_str()) == -1)
+ {
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * uTest
+ *
+ * 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
+
+bool exec_cmdline(const std::string& executable, const char *args[]);
#include <cerrno>
#include <cassert>
+#include <sstream>
+#include <string>
#include <libtest/test.hpp>
-
-using namespace libtest;
#include <string>
#include <vector>
-struct failed_test_names_st
-{
- failed_test_names_st(const char *collection_arg, const char *test_arg) :
+namespace libtest {
+
+struct failed_st {
+ failed_st(const std::string collection_arg, const std::string test_arg) :
collection(collection_arg),
test(test_arg)
- {
- }
+ { }
std::string collection;
std::string test;
};
-typedef std::vector<failed_test_names_st> Failures;
-
-static Failures failures;
+typedef std::vector<failed_st> Failures;
-void push_failed_test(const char *collection, const char *test)
+class Failed
{
- failures.push_back(failed_test_names_st(collection, test));
-}
+private:
+ Failures failures;
-void print_failed_test(void)
-{
- for (Failures::iterator iter= failures.begin(); iter != failures.end(); iter++)
+public:
+ void push(const char *collection, const char *test)
{
- Error << "\t" << (*iter).collection << " " << (*iter).test;
+ failures.push_back(failed_st(collection, test));
}
-}
+ void print_failed_test(void)
+ {
+ for (Failures::iterator iter= failures.begin(); iter != failures.end(); iter++)
+ {
+ Error << "\t" << (*iter).collection << " " << (*iter).test;
+ }
+ }
+};
+
+} // namespace libtest
using namespace libtest;
-static test_return_t _runner_default(test_callback_fn func, void *p)
-{
- if (func)
- {
- return func(p);
- }
-
- return TEST_SUCCESS;
-}
-
-static Runner defualt_runners= {
- _runner_default,
- _runner_default,
- _runner_default
-};
-
static test_return_t _default_callback(void *p)
{
(void)p;
return TEST_SUCCESS;
}
+static Runner defualt_runners;
+
Framework::Framework() :
collections(NULL),
_create(NULL),
collection_startup(_default_callback),
collection_shutdown(_default_callback),
_on_error(NULL),
- runner(&defualt_runners),
+ _runner(NULL),
_creators_ptr(NULL)
{
}
Framework::~Framework()
{
- if (_destroy)
+ if (_destroy and _destroy(_creators_ptr))
{
- if (test_failed(_destroy(_creators_ptr)))
- {
- Error << "Failure in _destroy(), some resources may not have been cleaned up.";
- }
+ Error << "Failure in _destroy(), some resources may not have been cleaned up.";
}
+
+ _servers.shutdown();
+}
+
+test_return_t Framework::Item::pre(void *arg)
+{
+ if (pre_run)
+ {
+ return pre_run(arg);
+ }
+
+ return TEST_SUCCESS;
+}
+
+test_return_t Framework::Item::post(void *arg)
+{
+ if (post_run)
+ {
+ return post_run(arg);
+ }
+
+ return TEST_SUCCESS;
}
test_return_t Framework::Item::flush(void* arg, test_st* run)
return TEST_SUCCESS;
}
+libtest::Runner *Framework::runner()
+{
+ return _runner ? _runner : &defualt_runners;
+}
+
void* Framework::create(test_return_t& arg)
{
arg= TEST_SUCCESS;
if (_create)
{
- return _creators_ptr= _create(&arg);
+ return _creators_ptr= _create(_servers, arg);
}
return NULL;
get_world() in order to fill this structure.
*/
-struct Framework {
+class Framework {
+public:
collection_st *collections;
/* These methods are called outside of any collection call. */
test_callback_create_fn *_create;
- test_callback_fn *_destroy;
-
- void* create(test_return_t& arg);
+ test_callback_destroy_fn *_destroy;
/* This is called a the beginning of any collection run. */
test_callback_fn *collection_startup;
- test_return_t startup(void*);
-
/* This is called a the end of any collection run. */
test_callback_fn *collection_shutdown;
+ void set_collection_shutdown(test_callback_error_fn *arg)
+ {
+ _on_error= arg;
+ }
+
+public:
+ void* create(test_return_t& arg);
+
+ test_return_t startup(void*);
+
test_return_t shutdown(void* arg)
{
if (collection_shutdown)
These are run before/after the test. If implemented. Their execution is not controlled
by the test.
*/
- struct Item {
+ class Item {
+ public:
/* This is called a the beginning of any run. */
test_callback_fn *_startup;
*/
test_callback_fn *_flush;
+ private:
/*
Run before and after the runnner is executed.
*/
test_callback_fn *pre_run;
test_callback_fn *post_run;
+ public:
+
Item() :
_startup(NULL),
_flush(NULL),
post_run(NULL)
{ }
- test_return_t flush(void* arg, test_st* run);
-
- void set_pre(test_callback_fn *arg)
+ void set_startup(test_callback_fn *arg)
{
- pre_run= arg;
+ _startup= arg;
}
- void set_post(test_callback_fn *arg)
+ void set_collection(test_callback_fn *arg)
{
- pre_run= arg;
+ _flush= arg;
}
- test_return_t pre(void *arg)
+ void set_flush(test_callback_fn *arg)
{
- if (pre_run)
- {
- return pre_run(arg);
- }
-
- return TEST_SUCCESS;
+ _flush= arg;
}
- test_return_t post(void *arg)
+ void set_pre(test_callback_fn *arg)
{
- if (post_run)
- {
- return post_run(arg);
- }
+ pre_run= arg;
+ }
- return TEST_SUCCESS;
+ void set_post(test_callback_fn *arg)
+ {
+ pre_run= arg;
}
+ test_return_t pre(void *arg);
+ test_return_t flush(void* arg, test_st* run);
+ test_return_t post(void *arg);
+
} item;
/**
*/
test_callback_error_fn *_on_error;
+ void set_on_error(test_callback_error_fn *arg)
+ {
+ _on_error= arg;
+ }
+
test_return_t on_error(const enum test_return_t, void *);
/**
Runner represents the callers for the tests. If not implemented we will use
a set of default implementations.
*/
- Runner *runner;
+ libtest::Runner *_runner;
+
+ void set_runner(libtest::Runner *arg)
+ {
+ _runner= arg;
+ }
+
+ libtest::Runner *runner();
+
Framework();
private:
Framework& operator=(const Framework&);
+ libtest::server_startup_st _servers;
void *_creators_ptr;
};
--- /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/gearmand.h>
+
+#include "util/instance.h"
+#include "util/operation.h"
+
+using namespace gearman_util;
+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 <libtest/server.h>
+#include <libtest/wait.h>
+
+#include <libgearman/gearman.h>
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+class GetPid : public Instance::Finish
+{
+private:
+ pid_t _pid;
+
+public:
+ GetPid() :
+ _pid(-1)
+ { }
+
+ pid_t pid()
+ {
+ return _pid;
+ }
+
+
+ bool call(const bool success, const std::string &response)
+ {
+ _pid= -1;
+
+ if (success and response.size())
+ {
+ _pid= atoi(response.c_str());
+ }
+
+ if (_pid < 1)
+ {
+ _pid= -1;
+ return true;
+ }
+
+ return false;
+ }
+};
+
+using namespace libtest;
+
+class Gearmand : public Server
+{
+private:
+public:
+ Gearmand(const std::string& host_arg, in_port_t port_arg) :
+ Server(host_arg, port_arg)
+ { }
+
+ pid_t get_pid(bool error_is_ok)
+ {
+ GetPid *get_instance_pid;
+ Instance instance(hostname(), port());
+ instance.set_finish(get_instance_pid= new GetPid);
+
+ instance.push(new Operation(test_literal_param("getpid\r\n"), true));
+
+ if (not instance.run() and not error_is_ok)
+ {
+ Error << "Failed to obtain pid of server";
+ }
+
+ _pid= get_instance_pid->pid();
+
+ return _pid;
+ }
+
+ bool ping()
+ {
+ gearman_client_st *client= gearman_client_create(NULL);
+ if (not client)
+ {
+ Error << "Could not allocate memory for gearman_client_create()";
+ return false;
+ }
+ gearman_client_set_timeout(client, 1000);
+
+ if (gearman_success(gearman_client_add_server(client, hostname().c_str(), port())))
+ {
+ gearman_return_t rc= gearman_client_echo(client, gearman_literal_param("This is my echo test"));
+
+ if (gearman_success(rc))
+ {
+ gearman_client_free(client);
+ return true;
+ }
+ }
+
+ gearman_client_free(client);
+
+ return false;;
+ }
+
+ const char *name()
+ {
+ return "gearmand";
+ };
+
+ const char *executable()
+ {
+ return GEARMAND_BINARY;
+ }
+
+ const char *pid_file_option()
+ {
+ return "--pid-file=";
+ }
+
+ const char *daemon_file_option()
+ {
+ return "--daemon";
+ }
+
+ const char *log_file_option()
+ {
+ return "-vvvvv --log-file=";
+ }
+
+ const char *port_option()
+ {
+ return "--port=";
+ }
+
+ bool is_libtool()
+ {
+ return true;
+ }
+
+ bool build(int argc, const char *argv[]);
+};
+
+
+#include <sstream>
+
+bool Gearmand::build(int argc, const char *argv[])
+{
+ std::stringstream arg_buffer;
+
+ if (getuid() == 0 or geteuid() == 0)
+ {
+ arg_buffer << " -u root ";
+ }
+
+ for (int x= 1 ; x < argc ; x++)
+ {
+ arg_buffer << " " << argv[x] << " ";
+ }
+
+ set_extra_args(arg_buffer.str());
+
+ return true;
+}
+
+namespace libtest {
+
+Server *build_gearmand(const char *hostname, in_port_t try_port)
+{
+ return new Gearmand(hostname, 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_gearmand(const char *hostname, in_port_t try_port);
+
+}
#
# included from Top Level Makefile.am
# All paths should be given relative to the root
-#
+#
LIBUTEST_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
+DRD_COMMAND= $(LIBTOOL) --mode=execute valgrind --tool=drd
+GDB_COMMAND= $(LIBTOOL) --mode=execute gdb
CLEANFILES+= \
tests/var/log/* \
noinst_HEADERS+= \
libtest/callbacks.h \
+ libtest/cmdline.h \
libtest/collection.h \
libtest/common.h \
libtest/core.h \
libtest/error.h \
libtest/failed.h \
libtest/framework.h \
+ libtest/gearmand.h \
libtest/get.h \
libtest/killpid.h \
+ libtest/memcached.h \
libtest/runner.h \
libtest/server.h \
+ libtest/signal.h \
libtest/stats.h \
libtest/strerror.h \
libtest/test.h \
libtest/visibility.h \
libtest/wait.h
-noinst_LTLIBRARIES+= libtest/libserver.la
-libtest_libserver_la_SOURCES= \
- libtest/killpid.cc \
- libtest/memcached.cc \
- libtest/server.cc
-
noinst_LTLIBRARIES+= libtest/libtest.la
-libtest_libtest_la_SOURCES=\
- libtest/framework.cc \
- libtest/test.cc
+libtest_libtest_la_SOURCES= \
+ libtest/cmdline.cc \
+ libtest/framework.cc \
+ libtest/killpid.cc \
+ libtest/runner.cc \
+ libtest/server.cc \
+ libtest/signal.cc \
+ libtest/test.cc
+
libtest_libtest_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION} -DBUILDING_LIBTEST
libtest_libtest_la_CXXFLAGS= ${AM_CXXFLAGS} ${NO_CONVERSION} -DBUILDING_LIBTEST
+libtest_libtest_la_LIBADD=
+
+LIBTEST_LDADD= libtest/libtest.la
+
+if HAVE_LIBMEMCACHED
+LIBTEST_LDADD+= $(libmemcached_LIBS) -lmemcachedutil
+libtest_libtest_la_SOURCES+= libtest/memcached.cc
+endif
+
+if HAVE_LIBGEARMAN
+LIBTEST_LDADD+= libgearman/libgearman.la
+libtest_libtest_la_SOURCES+= libtest/gearmand.cc
+libtest_libtest_la_SOURCES+= util/instance.cc
+endif
clearn-var:
@rm -f tests/var/log/*
tests/var/run:
$(mkdir_p) tests/var/run
+
+libtest_unittest_CFLAGS=
libtest_unittest_LDADD= \
- libtest/libtest.la
-libtest_unittest_SOURCES= \
- libtest/unittest.cc
-noinst_PROGRAMS+= libtest/unittest
+ ${LIBTEST_LDADD} \
+ libtest/libtest.la
+libtest_unittest_SOURCES= libtest/unittest.cc
check_PROGRAMS+= libtest/unittest
+noinst_PROGRAMS+= libtest/unittest
+test-unittest: libtest/unittest
+ @libtest/unittest
+
+valgrind-unittest: libtest/unittest
+ @$(VALGRIND_COMMAND) libtest/unittest
+
+gdb-unittest: libtest/unittest
+ @$(GDB_COMMAND) libtest/unittest
+
+helgrind-unittest: libtest/unittest
+ @$(HELGRIND_COMMAND) libtest/unittest
+
+drd-unittest: libtest/unittest
+ @$(DRD_COMMAND) libtest/unittest
libtest_wait_SOURCES= libtest/wait.cc
noinst_PROGRAMS+= libtest/wait
+
#include <cstdlib>
#include <cstring>
#include <iostream>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
#include <libtest/killpid.h>
#include <libtest/stream.h>
bool kill_pid(pid_t pid_arg)
{
- if (pid_arg <= 1)
+ assert(pid_arg > 0);
+ if (pid_arg < 1)
+ {
+ Error << "Invalid pid:" << pid_arg;
return false;
+ }
if ((::kill(pid_arg, SIGTERM) == -1))
{
switch (errno)
{
case EPERM:
- perror(__func__);
- Error << __func__ << " -> Does someone else have a process running locally for " << int(pid_arg) << "?";
+ Error << "Does someone else have a process running locally for " << int(pid_arg) << "?";
return false;
case ESRCH:
- perror(__func__);
Error << "Process " << int(pid_arg) << " not found.";
return false;
default:
case EINVAL:
- perror(__func__);
+ Error << "kill() " << strerror(errno);
return false;
}
}
int status= 0;
- pid_t pid= waitpid(pid_arg, &status, 0);
- if (pid == -1)
+ if (waitpid(pid_arg, &status, 0) == -1)
{
switch (errno)
{
+ // Just means that the server has already gone away
case ECHILD:
- return true;
+ {
+ return true;
+ }
}
Error << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(pid_arg);
return false;
}
- if (WIFEXITED(status))
- return true;
-
- if (WCOREDUMP(status))
- return true;
-
- return false;
+ return true;
}
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * Libmemcached library
+ * libtest
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
*
*/
+#include <libtest/common.h>
-/*
- Startup, and shutdown the memcached servers.
-*/
-
-#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT+10
+#include <libmemcached/memcached.h>
+#include <libmemcached/util.h>
-#include <libtest/common.h>
+using namespace libtest;
+#include <cassert>
+#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
-#include <ctime>
-#include <limits.h>
+#include <iostream>
#include <signal.h>
-#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include <unistd.h>
-#include <iostream>
-
-#include <libmemcached/memcached.h>
-#include <libmemcached/util.h>
#include <libtest/server.h>
-#include <libtest/killpid.h>
#include <libtest/wait.h>
-#define SOCKET_FILE "/tmp/memcached.socket"
+#include <libtest/memcached.h>
-static pid_t __getpid(server_st& server)
-{
- memcached_return_t rc;
- pid_t pid= libmemcached_util_getpid(server.hostname(), server.port(), &rc);
- return pid;
-}
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
-static bool __ping(server_st& server)
-{
- memcached_return_t rc;
- bool ret= libmemcached_util_ping(server.hostname(), server.port(), &rc);
- return ret;
-}
+using namespace libtest;
-static bool cycle_server(server_st *server)
+class Memcached : public Server
{
- while (1)
+public:
+ Memcached(const std::string& host_arg, const in_port_t port_arg, const bool is_socket_arg) :
+ Server(host_arg, port_arg, is_socket_arg)
+ { }
+
+ pid_t get_pid(bool error_is_ok)
{
- if (libmemcached_util_ping(server->hostname(), server->port(), NULL))
+ // Memcached is slow to start, so we need to do this
+ if (not pid_file().empty())
{
- // First we try to kill it, and on fail of that we flush it.
- pid_t pid= libmemcached_util_getpid(server->hostname(), server->port(), NULL);
+ Wait wait(pid_file(), 0);
- if (pid > 0 and kill_pid(pid))
+ if (not wait.successful())
{
- Error << "Killed existing server," << *server << " with pid:" << pid;
- continue;
+ Error << "Pidfile was not found:" << pid_file();
+ return -1;
}
- else if (libmemcached_util_flush(server->hostname(), server->port(), NULL)) // If we can flush it, we will just use it
- {
- Error << "Found server on port " << int(server->port()) << ", flushed it!";
- server->set_used();
- return true;
- } // No idea what is wrong here, so we need to find a different port
- else
+ }
+
+ memcached_return_t rc;
+ if (has_socket())
+ {
+ _pid= libmemcached_util_getpid(socket().c_str(), port(), &rc);
+ }
+ else
+ {
+ _pid= libmemcached_util_getpid(hostname().c_str(), port(), &rc);
+ }
+
+ if ((memcached_failed(rc) or _pid < 1) and not error_is_ok)
+ {
+ Error << "libmemcached_util_getpid(" << memcached_strerror(NULL, rc) << ") pid: " << _pid << " for:" << *this;
+ }
+
+ return _pid;
+ }
+
+ bool ping()
+ {
+ // Memcached is slow to start, so we need to do this
+ if (not pid_file().empty())
+ {
+ Wait wait(pid_file(), 0);
+
+ if (not wait.successful())
{
- return false;
+ Error << "Pidfile was not found:" << pid_file();
+ return -1;
}
}
- break;
+ memcached_return_t rc;
+ bool ret;
+ if (has_socket())
+ {
+ ret= libmemcached_util_ping(socket().c_str(), 0, &rc);
+ }
+ else
+ {
+ ret= libmemcached_util_ping(hostname().c_str(), port(), &rc);
+ }
+
+ if (memcached_failed(rc) or not ret)
+ {
+ Error << "libmemcached_util_ping(" << memcached_strerror(NULL, rc) << ")";
+ }
+ return ret;
}
- return true;
-}
+ const char *name()
+ {
+ return "memcached";
+ };
-bool server_startup(server_startup_st *construct)
-{
- Logn();
+ const char *executable()
+ {
+ return MEMCACHED_BINARY;
+ }
- if (getenv(((char *)"MEMCACHED_SERVERS")))
+ const char *pid_file_option()
{
- construct->server_list= getenv(((char *)"MEMCACHED_SERVERS"));
- Log << "MEMCACHED_SERVERS " << construct->server_list;
- construct->count= 0;
+ return "-P ";
}
- else
+
+ const char *socket_file_option() const
{
- std::string server_config_string;
+ return "-s ";
+ }
- uint32_t port_base= 0;
- for (uint32_t x= 0; x < uint32_t(construct->count -1); x++)
- {
- server_st *server= NULL;
+ const char *daemon_file_option()
+ {
+ return "-d";
+ }
- {
- char *var;
- char variable_buffer[1024];
-
- snprintf(variable_buffer, sizeof(variable_buffer), "LIBMEMCACHED_PORT_%u", x);
-
- if ((var= getenv(variable_buffer)))
- {
- server= new server_st((in_port_t)atoi(var), __getpid, __ping);
- }
- else
- {
- server= new server_st(in_port_t(x +TEST_PORT_BASE +port_base), __getpid, __ping);
-
- while (not cycle_server(server))
- {
- Error << "Found server " << *server << ", could not flush it, so trying next port.";
- port_base++;
- server->set_port(in_port_t(x +TEST_PORT_BASE +port_base));
- }
- }
- }
+ const char *log_file_option()
+ {
+ return NULL;
+ }
- if (server->is_used())
- {
- Log << "Using server at : " << server;
- }
- else
- {
- char buffer[FILENAME_MAX];
- if (x == 0)
- {
- snprintf(buffer, sizeof(buffer), "%s -d -t 1 -p %u -U %u -m 128",
- MEMCACHED_BINARY, server->port(), server->port());
- }
- else
- {
- snprintf(buffer, sizeof(buffer), "%s -d -t 1 -p %u -U %u",
- MEMCACHED_BINARY, server->port(), server->port());
- }
- server->set_command(buffer);
-
- if (not server->start())
- {
- Error << "Failed system(" << buffer << ")";
- delete server;
- return false;
- }
- Log << "STARTING SERVER: " << buffer << " pid:" << server->pid();
- }
- construct->push_server(server);
+ const char *port_option()
+ {
+ return "-p ";
+ }
- if (x == 0)
- {
- assert(server->has_port());
- set_default_port(server->port());
- }
+ bool is_libtool()
+ {
+ return false;
+ }
- char port_str[NI_MAXSERV];
- snprintf(port_str, sizeof(port_str), "%u", int(server->port()));
+ // Memcached's pidfile is broken
+ bool broken_pid_file()
+ {
+ return true;
+ }
- server_config_string+= "--server=";
- server_config_string+= server->hostname();
- server_config_string+= ":";
- server_config_string+= port_str;
- server_config_string+= " ";
- }
+ bool build(int argc, const char *argv[]);
+};
- // Socket
- {
- std::string socket_file(SOCKET_FILE);
- char *var;
+#include <sstream>
- if ((var= getenv("LIBMEMCACHED_SOCKET")))
- {
- socket_file= var;
- }
+bool Memcached::build(int argc, const char *argv[])
+{
+ std::stringstream arg_buffer;
- server_st *server= new server_st(SOCKET_FILE, __getpid, __ping);
+ if (getuid() == 0 or geteuid() == 0)
+ {
+ arg_buffer << " -u root ";
+ }
- if (not cycle_server(server))
- {
- Error << "Found server " << server << ", could not flush it, failing since socket file is not available.";
- return false;
- }
+ for (int x= 1 ; x < argc ; x++)
+ {
+ arg_buffer << " " << argv[x] << " ";
+ }
- if (server->is_used())
- {
- Log << "Using server at : " << *server;
- }
- else
- {
- char buffer[FILENAME_MAX];
- snprintf(buffer, sizeof(buffer), "%s -d -t 1 -s %s", MEMCACHED_BINARY, SOCKET_FILE);
- server->set_command(buffer);
-
- if (not server->start())
- {
- Error << "Failed system(" << buffer << ")";
- delete server;
- return false;
- }
- Log << "STARTING SERVER: " << buffer << " pid:" << server->pid();
- }
- set_default_socket(server->hostname());
- construct->push_server(server);
+ set_extra_args(arg_buffer.str());
- {
- server_config_string+= "--socket=\"";
- server_config_string+= server->hostname();
- server_config_string+= "\" ";
- }
- }
+ return true;
+}
- server_config_string.resize(server_config_string.size() -1); // Remove final space
- construct->server_list= server_config_string;
- }
+namespace libtest {
- Logn();
+Server *build_memcached(const std::string& hostname, const in_port_t try_port)
+{
+ return new Memcached(hostname, try_port, false);
+}
- srandom((unsigned int)time(NULL));
+Server *build_memcached_socket(const std::string& hostname, const in_port_t try_port)
+{
+ return new Memcached(hostname, try_port, true);
+}
- return true;
}
+
--- /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 {
+
+LIBTEST_API
+Server *build_memcached(const std::string& hostname, const in_port_t try_port);
+
+LIBTEST_API
+Server *build_memcached_socket(const std::string& socket_file, const in_port_t try_port);
+
+}
+
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * uTest, 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>
+
+namespace libtest {
+
+Runner::Runner()
+{
+}
+
+test_return_t Runner::run(test_callback_fn* func, void *object)
+{
+ if (func)
+ {
+ return func(object);
+ }
+
+ return TEST_SUCCESS;
+}
+
+test_return_t Runner::pre(test_callback_fn* func, void *object)
+{
+ if (func)
+ {
+ return func(object);
+ }
+
+ return TEST_SUCCESS;
+}
+
+test_return_t Runner::post(test_callback_fn* func, void *object)
+{
+ if (func)
+ {
+ return func(object);
+ }
+
+ return TEST_SUCCESS;
+}
+
+} // namespace libtest
#pragma once
+namespace libtest {
+
/**
Structure which houses the actual callers for the test cases contained in
the collections.
*/
-struct Runner {
- test_callback_runner_fn *pre;
- test_callback_runner_fn *run;
- test_callback_runner_fn *post;
+class Runner {
+public:
+ virtual test_return_t run(test_callback_fn* func, void *object);
+ virtual test_return_t pre(test_callback_fn* func, void *object);
+ virtual test_return_t post(test_callback_fn* func, void *object);
+
+ Runner();
+
+ virtual ~Runner() { }
};
+} // namespace Runner
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * Libmemcached library
+ * Libtest library
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
*
*
*/
-#include <config.h>
-#include <iostream>
-#include <cstdlib>
+#include <libtest/common.h>
+
#include <cassert>
+#include <cerrno>
+#include <cstdlib>
+#include <iostream>
+
+#include <algorithm>
+#include <functional>
+#include <locale>
+
+// trim from end
+static inline std::string &rtrim(std::string &s)
+{
+ s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
+ return s;
+}
#include <libtest/server.h>
+#include <libtest/stream.h>
#include <libtest/killpid.h>
+#ifdef HAVE_LIBGEARMAN
+#include <libtest/gearmand.h>
+#endif
+
+#ifdef HAVE_LIBMEMCACHED
+#include <libtest/memcached.h>
+#endif
+
+namespace libtest {
-std::ostream& operator<<(std::ostream& output, const server_st &arg)
+std::ostream& operator<<(std::ostream& output, const Server &arg)
{
if (arg.is_socket())
{
{
output << arg.hostname() << ":" << arg.port();
}
+
+ if (arg.has_pid())
+ {
+ output << " Pid:" << arg.pid();
+ }
+
+ if (arg.has_socket())
+ {
+ output << " Socket:" << arg.socket();
+ }
+
+ if (not arg.running().empty())
+ {
+ output << " Exec:" << arg.running();
+ }
+
+
return output; // for multiple << operators
}
-static void global_sleep(void)
+void Server::nap(void)
{
- static struct timespec global_sleep_value= { 0, 50000 };
-
#ifdef WIN32
sleep(1);
#else
+ struct timespec global_sleep_value= { 0, 50000 };
nanosleep(&global_sleep_value, NULL);
#endif
}
-server_st::server_st(in_port_t port_arg, test_server_getpid *get_pid_arg, test_server_ping *ping_arg) :
- _used(false),
+Server::Server(const std::string& host_arg, const in_port_t port_arg, bool is_socket_arg) :
+ _is_socket(is_socket_arg),
_pid(-1),
_port(port_arg),
- __get_pid(get_pid_arg),
- __ping(ping_arg),
- _hostname("localhost")
+ _hostname(host_arg)
{
- pid_file[0]= 0;
}
-server_st::server_st(const std::string &socket_file, test_server_getpid *get_pid_arg, test_server_ping *ping_arg) :
- _used(false),
- _pid(-1),
- _port(0),
- __get_pid(get_pid_arg),
- __ping(ping_arg),
- _hostname(socket_file)
+Server::~Server()
{
- pid_file[0]= 0;
+ if (has_pid() and not kill())
+ {
+ Error << "Unable to kill:" << *this;
+ }
}
+std::string server_startup_st::option_string() const
+{
+ std::string temp= server_list;
+ rtrim(temp);
+ return temp;
+}
-server_st::~server_st()
+// If the server exists, kill it
+bool Server::cycle()
{
- if (has_pid())
+ uint32_t limit= 3;
+
+ // Try to ping, and kill the server #limit number of times
+ pid_t current_pid;
+ while (--limit and (current_pid= get_pid()) != -1)
{
- kill();
+ if (kill())
+ {
+ Log << "Killed existing server," << *this << " with pid:" << current_pid;
+ nap();
+ continue;
+ }
+ }
+
+ // For whatever reason we could not kill it, and we reached limit
+ if (limit == 0)
+ {
+ Error << "Reached limit, could not kill server pid:" << current_pid;
+ return false;
+ }
+
+ return true;
+}
+
+// Grab a one off command
+bool Server::command(std::string& command_arg)
+{
+ rebuild_base_command();
+
+ command_arg+= _base_command;
+
+ if (args(command_arg))
+ {
+ return true;
}
+
+ return false;
}
-bool server_st::start()
+bool Server::start()
{
- assert(not _command.empty());
+ // If we find that we already have a pid then kill it.
+ if (has_pid() and not kill())
+ {
+ Error << "Could not kill() existing server during start()";
+ return false;
+ }
assert(not has_pid());
- if (has_pid())
+ _running.clear();
+ if (not command(_running))
+ {
+ Error << "Could not build command()";
return false;
+ }
- if (system(_command.c_str()) == -1)
+ if (system(_running.c_str()) == -1)
+ {
+ Error << "system() failed:" << strerror(errno);
+ _running.clear();
return false;
+ }
- int count= 30;
+ if (pid_file_option() and not pid_file().empty())
+ {
+ Wait wait(pid_file());
+
+ if (not wait.successful())
+ {
+ Error << "Unable to open pidfile: " << pid_file();
+ }
+ }
+
+ int count= 5;
while (not ping() and --count)
{
- global_sleep();
+ nap();
}
if (count == 0)
{
+ Error << "Failed to ping() server once started:" << *this;
+ _running.clear();
return false;
}
- _pid= get_pid();
+ // A failing get_pid() at this point is considered an error
+ _pid= get_pid(false);
return has_pid();
}
-void server_st::reset_pid()
+void Server::reset_pid()
{
- pid_file[0]= 0;
+ _running.clear();
+ _pid_file.clear();
_pid= -1;
}
-pid_t server_st::pid()
+pid_t Server::pid()
+{
+ return _pid;
+}
+
+bool Server::set_socket_file()
{
- if (not has_pid())
+ char file_buffer[FILENAME_MAX];
+ file_buffer[0]= 0;
+
+ if (broken_pid_file())
+ {
+ snprintf(file_buffer, sizeof(file_buffer), "/tmp/%s.socketXXXXXX", name());
+ }
+ else
{
- _pid= get_pid();
+ snprintf(file_buffer, sizeof(file_buffer), "tests/var/run/%s.socketXXXXXX", name());
}
- return _pid;
+ int fd;
+ if ((fd= mkstemp(file_buffer)) == -1)
+ {
+ perror(file_buffer);
+ return false;
+ }
+ close(fd);
+ unlink(file_buffer);
+
+ _socket= file_buffer;
+
+ return true;
}
+bool Server::set_pid_file()
+{
+ char file_buffer[FILENAME_MAX];
+ file_buffer[0]= 0;
+
+ if (broken_pid_file())
+ {
+ snprintf(file_buffer, sizeof(file_buffer), "/tmp/%s.pidXXXXXX", name());
+ }
+ else
+ {
+ snprintf(file_buffer, sizeof(file_buffer), "tests/var/run/%s.pidXXXXXX", name());
+ }
+
+ int fd;
+ if ((fd= mkstemp(file_buffer)) == -1)
+ {
+ perror(file_buffer);
+ return false;
+ }
+ close(fd);
+ unlink(file_buffer);
+
+ _pid_file= file_buffer;
-bool server_st::kill()
+ return true;
+}
+
+bool Server::set_log_file()
{
- if (is_used())
+ char file_buffer[FILENAME_MAX];
+ file_buffer[0]= 0;
+
+ snprintf(file_buffer, sizeof(file_buffer), "tests/var/log/%s.logXXXXXX", name());
+ int fd;
+ if ((fd= mkstemp(file_buffer)) == -1)
+ {
+ perror(file_buffer);
return false;
+ }
+ close(fd);
+
+ _log_file= file_buffer;
+
+ return true;
+}
- if ((_pid= get_pid()))
+void Server::rebuild_base_command()
+{
+ _base_command.clear();
+ if (is_libtool())
{
- kill_pid(_pid);
- if (pid_file[0])
- {
- unlink(pid_file); // If this happens we may be dealing with a dead server that left its pid file.
- }
- reset_pid();
+ _base_command+= "./libtool --mode=execute ";
+ }
- return true;
+ if (is_debug())
+ {
+ _base_command+= "gdb ";
+ }
+ else if (is_valgrind())
+ {
+ _base_command+= "valgrind --log-file=tests/var/tmp/valgrind.out --leak-check=full --show-reachable=yes ";
+ }
+
+ _base_command+= executable();
+}
+
+void Server::set_extra_args(const std::string &arg)
+{
+ _extra_args= arg;
+}
+
+bool Server::args(std::string& options)
+{
+ std::stringstream arg_buffer;
+
+ // Set a log file if it was requested (and we can)
+ if (getenv("LIBTEST_LOG") and log_file_option())
+ {
+ if (not set_log_file())
+ return false;
+
+ arg_buffer << " " << log_file_option() << _log_file;
+ }
+
+ // Update pid_file
+ if (pid_file_option())
+ {
+ if (not set_pid_file())
+ return false;
+
+ arg_buffer << " " << pid_file_option() << pid_file();
+ }
+
+ assert(daemon_file_option());
+ if (daemon_file_option())
+ {
+ arg_buffer << " " << daemon_file_option();
+ }
+
+ if (_is_socket and socket_file_option())
+ {
+ if (not set_socket_file())
+ return false;
+
+ arg_buffer << " " << socket_file_option() << "\"" << _socket << "\"";
}
-#if 0
- else if (pid_file[0])
+
+ assert(port_option());
+ if (port_option() and _port > 0)
+ {
+ arg_buffer << " " << port_option() << _port;
+ }
+
+ options+= arg_buffer.str();
+
+ if (not _extra_args.empty())
+ options+= _extra_args;
+
+ return true;
+}
+
+bool Server::is_debug() const
+{
+ return bool(getenv("LIBTEST_MANUAL_GDB"));
+}
+
+bool Server::is_valgrind() const
+{
+ return bool(getenv("LIBTEST_MANUAL_VALGRIND"));
+}
+
+bool Server::kill()
+{
+ if (has_pid() and kill_pid(_pid)) // If we kill it, reset
{
- kill_file(pid_file);
+ if (broken_pid_file() and not pid_file().empty())
+ {
+ unlink(pid_file().c_str());
+ }
+
reset_pid();
return true;
}
-#endif
return false;
}
-void server_startup_st::push_server(server_st *arg)
+void server_startup_st::push_server(Server *arg)
{
servers.push_back(arg);
+
+ char port_str[NI_MAXSERV];
+ snprintf(port_str, sizeof(port_str), "%u", int(arg->port()));
+
+ std::string server_config_string;
+ if (arg->has_socket())
+ {
+ server_config_string+= "--socket=";
+ server_config_string+= '"';
+ server_config_string+= arg->socket();
+ server_config_string+= '"';
+ server_config_string+= " ";
+ }
+ else
+ {
+ server_config_string+= "--server=";
+ server_config_string+= arg->hostname();
+ server_config_string+= ":";
+ server_config_string+= port_str;
+ server_config_string+= " ";
+ }
+
+ server_list+= server_config_string;
+
}
-void server_startup_st::shutdown()
+Server* server_startup_st::pop_server()
{
- for (std::vector<server_st *>::iterator iter= servers.begin(); iter != servers.end(); iter++)
- {
- if ((*iter)->is_used())
- continue;
+ Server *tmp= servers.back();
+ servers.pop_back();
+ return tmp;
+}
- (*iter)->kill();
+void server_startup_st::shutdown(bool remove)
+{
+ if (remove)
+ {
+ for (std::vector<Server *>::iterator iter= servers.begin(); iter != servers.end(); iter++)
+ {
+ delete *iter;
+ }
+ servers.clear();
+ }
+ else
+ {
+ for (std::vector<Server *>::iterator iter= servers.begin(); iter != servers.end(); iter++)
+ {
+ if ((*iter)->has_pid() and not (*iter)->kill())
+ {
+ Error << "Unable to kill:" << *(*iter);
+ }
+ }
}
}
server_startup_st::~server_startup_st()
{
- for (std::vector<server_st *>::iterator iter= servers.begin(); iter != servers.end(); iter++)
+ shutdown(true);
+}
+
+bool server_startup_st::is_debug() const
+{
+ return bool(getenv("LIBTEST_MANUAL_GDB"));
+}
+
+bool server_startup_st::is_valgrind() const
+{
+ return bool(getenv("LIBTEST_MANUAL_VALGRIND"));
+}
+
+bool server_startup(server_startup_st& construct, const std::string& server_type, in_port_t try_port, int argc, const char *argv[])
+{
+ Logn();
+
+ // Look to see if we are being provided ports to use
+ {
+ char variable_buffer[1024];
+ snprintf(variable_buffer, sizeof(variable_buffer), "LIBTEST_PORT_%lu", (unsigned long)construct.count());
+
+ char *var;
+ if ((var= getenv(variable_buffer)))
+ {
+ in_port_t tmp= in_port_t(atoi(var));
+
+ if (tmp > 0)
+ try_port= tmp;
+ }
+ }
+
+ Server *server= NULL;
+ if (0)
+ { }
+ else if (server_type.compare("gearmand") == 0)
+ {
+#ifdef GEARMAND_BINARY
+ #ifdef HAVE_LIBGEARMAN
+ server= build_gearmand("localhost", try_port);
+ #else
+ Error << "Libgearman was not found";
+ #endif
+#else
+ Error << "No gearmand binary is available";
+#endif
+ }
+ else if (server_type.compare("memcached") == 0)
+ {
+#ifdef MEMCACHED_BINARY
+#ifdef HAVE_LIBMEMCACHED
+ server= build_memcached("localhost", try_port);
+#else
+ Error << "Libmemcached was not found";
+#endif
+#else
+ Error << "No memcached binary is available";
+#endif
+ }
+ else
+ {
+ Error << "Failed to start " << server_type << ", no support was found to be compiled in for it.";
+ }
+
+ if (server == NULL)
+ {
+ Error << "Failure occured while creating server: " << server_type;
+ return false;
+ }
+
+ /*
+ We will now cycle the server we have created.
+ */
+ if (not server->cycle())
+ {
+ Error << "Could not start up server " << *server;
+ delete server;
+ return false;
+ }
+
+ server->build(argc, argv);
+
+ if (construct.is_debug())
+ {
+ Log << "Pausing for startup, hit return when ready.";
+ std::string gdb_command= server->base_command();
+ std::string options;
+ Log << "run " << server->args(options);
+ getchar();
+ }
+ else if (not server->start())
+ {
+ Error << "Failed to start " << *server;
+ delete server;
+ return false;
+ }
+ else
+ {
+ Log << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
+ }
+
+ construct.push_server(server);
+
+ if (default_port() == 0)
{
- delete *iter;
+ assert(server->has_port());
+ set_default_port(server->port());
}
- servers.clear();
+
+ Logn();
+
+ return true;
}
-void server_shutdown(server_startup_st *construct)
+bool server_startup_st::start_socket_server(const std::string& server_type, const in_port_t try_port, int argc, const char *argv[])
{
- if (not construct)
- return;
+ Logn();
- construct->shutdown();
+ Server *server= NULL;
+ if (0)
+ { }
+ else if (server_type.compare("gearmand") == 0)
+ {
+ Error << "Socket files are not supported for gearmand yet";
+ }
+ else if (server_type.compare("memcached") == 0)
+ {
+#ifdef MEMCACHED_BINARY
+#ifdef HAVE_LIBMEMCACHED
+ server= build_memcached_socket("localhost", try_port);
+#else
+ Error << "Libmemcached was not found";
+#endif
+#else
+ Error << "No memcached binary is available";
+#endif
+ }
+ else
+ {
+ Error << "Failed to start " << server_type << ", no support was found to be compiled in for it.";
+ }
+
+ if (server == NULL)
+ {
+ Error << "Failure occured while creating server: " << server_type;
+ return false;
+ }
+
+ /*
+ We will now cycle the server we have created.
+ */
+ if (not server->cycle())
+ {
+ Error << "Could not start up server " << *server;
+ delete server;
+ return false;
+ }
+
+ server->build(argc, argv);
+
+ if (is_debug())
+ {
+ Log << "Pausing for startup, hit return when ready.";
+ std::string gdb_command= server->base_command();
+ std::string options;
+ Log << "run " << server->args(options);
+ getchar();
+ }
+ else if (not server->start())
+ {
+ Error << "Failed to start " << *server;
+ delete server;
+ return false;
+ }
+ else
+ {
+ Log << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
+ }
+
+ push_server(server);
+
+ set_default_socket(server->socket().c_str());
+
+ Logn();
+
+ return true;
}
+
+} // namespace libtest
#pragma once
+#include <cassert>
+#include <cstdio>
#include <cstring>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <vector>
-#define SERVERS_TO_CREATE 5
+namespace libtest {
-struct server_st;
-
-typedef pid_t (test_server_getpid)(server_st &);
-typedef bool (test_server_ping)(server_st &);
-
-struct server_st {
+struct Server {
private:
- bool _used;
+ bool _is_socket;
+ std::string _socket;
+ std::string _pid_file;
+ std::string _log_file;
+ std::string _base_command; // executable command which include libtool, valgrind, gdb, etc
+ std::string _running; // Current string being used for system()
+
+protected:
pid_t _pid;
in_port_t _port;
- char pid_file[FILENAME_MAX]; // Did we start it, or was it just sitting there?
- std::string _command;
- test_server_getpid *__get_pid;
- test_server_ping *__ping;
std::string _hostname;
+ std::string _extra_args;
public:
- server_st(in_port_t port_arg, test_server_getpid *, test_server_ping *);
+ Server(const std::string& hostname, const in_port_t port_arg, const bool is_socket_arg= false);
+
+ virtual ~Server();
- server_st(const std::string &socket_file, test_server_getpid *, test_server_ping *);
+ virtual const char *name()= 0;
+ virtual const char *executable()= 0;
+ virtual const char *port_option()= 0;
+ virtual const char *pid_file_option()= 0;
+ virtual const char *daemon_file_option()= 0;
+ virtual const char *log_file_option()= 0;
+ virtual bool is_libtool()= 0;
- void set_methods(test_server_getpid *get_pid_arg, test_server_ping *ping_arg)
+ virtual const char *socket_file_option() const
{
- __get_pid= get_pid_arg;
- __ping= ping_arg;
+ return NULL;
}
- const char *hostname() const
+ virtual bool broken_pid_file()
{
- if (_hostname.empty())
- return "";
+ return false;
+ }
- return _hostname.c_str();
+ const std::string& pid_file() const
+ {
+ return _pid_file;
}
- bool ping()
+ const std::string& base_command() const
{
- if (__ping)
- return __ping(*this);
+ return _base_command;
+ }
- return false;
+ const std::string& log_file() const
+ {
+ return _log_file;
}
- pid_t get_pid()
+ const std::string& hostname() const
{
- if (__get_pid)
- return _pid= __get_pid(*this);
+ return _hostname;
+ }
- return -1;
+ const std::string& socket() const
+ {
+ return _socket;
}
- void set_port(in_port_t arg)
+ bool has_socket() const
{
- _port= arg;
+ return _is_socket;
}
+ bool cycle();
+
+ virtual bool ping()= 0;
+
+ virtual pid_t get_pid(bool error_is_ok= true)= 0;
+
+ virtual bool build(int argc, const char *argv[])= 0;
+
in_port_t port() const
{
return _port;
return (_port != 0);
}
- void set_command(const char *arg)
+ // Reset a server if another process has killed the server
+ void reset()
{
- _command= arg;
+ _pid= -1;
+ _pid_file.clear();
+ _log_file.clear();
}
- void set_used()
- {
- _used= true;
- }
+ void set_extra_args(const std::string &arg);
+
+ bool args(std::string& options);
pid_t pid();
- bool is_used() const
+ pid_t pid() const
{
- return _used;
+ return _pid;
}
- ~server_st();
-
- bool has_pid()
+ bool has_pid() const
{
return (_pid > 1);
}
return _hostname[0] == '/';
}
+ const std::string running() const
+ {
+ return _running;
+ }
+
+ std::string log_and_pid();
+
bool kill();
bool start();
+ bool command(std::string& command_arg);
+
+protected:
+ void nap();
private:
+ bool is_valgrind() const;
+ bool is_debug() const;
+ bool set_log_file();
+ bool set_pid_file();
+ bool set_socket_file();
+ void rebuild_base_command();
void reset_pid();
};
-std::ostream& operator<<(std::ostream& output, const server_st &arg);
+std::ostream& operator<<(std::ostream& output, const libtest::Server &arg);
-struct server_startup_st
+class server_startup_st
{
- uint32_t count;
- uint8_t udp;
+private:
std::string server_list;
- std::vector<server_st *> servers;
+
+public:
+
+ uint8_t udp;
+ std::vector<Server *> servers;
server_startup_st() :
- count(SERVERS_TO_CREATE),
udp(0)
{ }
- void shutdown();
- void push_server(server_st *);
+ bool start_socket_server(const std::string& server_type, const in_port_t try_port, int argc, const char *argv[]);
+
+ std::string option_string() const;
+
+ size_t count() const
+ {
+ return servers.size();
+ }
+
+ bool is_debug() const;
+ bool is_valgrind() const;
+
+ void shutdown(bool remove= false);
+ void push_server(Server *);
+ Server *pop_server();
~server_startup_st();
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+bool server_startup(server_startup_st&, const std::string&, in_port_t try_port, int argc, const char *argv[]);
+} // namespace libtest
-bool server_startup(server_startup_st *construct);
-void server_shutdown(server_startup_st *construct);
-#ifdef __cplusplus
-}
-#endif
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * uTest, 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 <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+
+#include <libtest/signal.h>
+
+using namespace libtest;
+
+struct context_st {
+ sigset_t set;
+ sem_t lock;
+
+ context_st()
+ {
+ sigemptyset(&set);
+ sigaddset(&set, SIGABRT);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGUSR2);
+
+ sem_init(&lock, 0, 0);
+ }
+
+ void test()
+ {
+ assert(sigismember(&set, SIGABRT));
+ assert(sigismember(&set, SIGINT));
+ assert(sigismember(&set, SIGUSR2));
+ }
+
+ int wait(int& sig)
+ {
+ return sigwait(&set, &sig);
+ }
+
+ ~context_st()
+ {
+ sem_destroy(&lock);
+ }
+};
+
+static volatile shutdown_t __shutdown;
+static pthread_mutex_t shutdown_mutex;
+static pthread_t thread;
+
+bool is_shutdown()
+{
+ bool ret;
+ pthread_mutex_lock(&shutdown_mutex);
+ ret= bool(__shutdown != SHUTDOWN_RUNNING);
+ pthread_mutex_unlock(&shutdown_mutex);
+
+ return ret;
+}
+
+void set_shutdown(shutdown_t arg)
+{
+ pthread_mutex_lock(&shutdown_mutex);
+ __shutdown= arg;
+ pthread_mutex_unlock(&shutdown_mutex);
+
+ if (arg == SHUTDOWN_GRACEFUL)
+ {
+ pthread_kill(thread, SIGUSR2);
+
+ void *retval;
+ pthread_join(thread, &retval);
+ }
+}
+
+shutdown_t get_shutdown()
+{
+ shutdown_t local;
+ pthread_mutex_lock(&shutdown_mutex);
+ local= __shutdown;
+ pthread_mutex_unlock(&shutdown_mutex);
+
+ return local;
+}
+
+extern "C" {
+
+static void *sig_thread(void *arg)
+{
+ context_st *context= (context_st*)arg;
+ assert(context);
+
+ context->test();
+ sem_post(&context->lock);
+
+ while (get_shutdown() == SHUTDOWN_RUNNING)
+ {
+ int sig;
+
+ if (context->wait(sig) == -1)
+ {
+ Error << "sigwait() returned errno:" << strerror(errno);
+ continue;
+ }
+
+ switch (sig)
+ {
+ case SIGABRT:
+ case SIGINT:
+ Error << "Signal handling thread got signal " << strsignal(sig);
+ set_shutdown(SHUTDOWN_FORCED);
+ break;
+
+ // Signal thread is being told that a graceful shutdown is occuring
+ case SIGUSR2:
+ break;
+
+ default:
+ Error << "Signal handling thread got unexpected signal " << strsignal(sig);
+ break;
+ }
+ }
+
+ delete context;
+
+ return NULL;
+}
+
+}
+
+void setup_signals()
+{
+ pthread_mutex_init(&shutdown_mutex, NULL);
+ set_shutdown(SHUTDOWN_RUNNING);
+
+ context_st *context= new context_st;
+
+ assert(context);
+
+ int error;
+ if ((error= pthread_sigmask(SIG_BLOCK, &context->set, NULL)) != 0)
+ {
+ Error << "pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")";
+ exit(EXIT_FAILURE);
+ }
+
+ if ((error= pthread_create(&thread, NULL, &sig_thread, (void *) &context->set)) != 0)
+ {
+ Error << "pthread_create() died during pthread_create(" << strerror(error) << ")";
+ exit(EXIT_FAILURE);
+ }
+
+ sem_wait(&context->lock);
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * uTest, 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
+
+enum shutdown_t {
+ SHUTDOWN_RUNNING,
+ SHUTDOWN_GRACEFUL,
+ SHUTDOWN_FORCED
+};
+
+LIBTEST_INTERNAL_API
+bool is_shutdown();
+
+LIBTEST_INTERNAL_API
+shutdown_t get_shutdown();
+
+LIBTEST_INTERNAL_API
+void set_shutdown(shutdown_t arg);
+
+LIBTEST_INTERNAL_API
+void setup_signals(void);
class cerr {
private:
+ public:
+ typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
+
+ public:
+ void operator()(const stream_buffer &s)
+ {
+ std::cerr << s.str() << std::endl;
+ }
+ };
+
+template<class Ch, class Tr, class A>
+ class make_cerr {
+ private:
+
public:
typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
public:
void operator()(const stream_buffer &s)
{
- std::cerr << s.str() << std::endl;
+ std::cerr<< s.str() << std::endl;
}
};
typedef OutputPolicy<Ch, Tr, A> output_policy;
const char *_filename;
int _line_number;
+ const char *_func;
public:
log() :
_line_number(0)
{ }
- void set_filename(const char *filename, int line_number)
+ void set_filename(const char *filename, int line_number, const char *func)
{
_filename= filename;
_line_number= line_number;
+ _func= func;
}
~log()
{
if (_filename)
{
- arg << __FILE__ << ":" << __LINE__ << " ";
+ arg << _filename << ":" << _line_number << ": in " << _func << "() ";
_filename= NULL;
}
arg << x;
};
}
+class make_cerr : public detail::log<detail::make_cerr> {
+public:
+ make_cerr(const char *filename, int line_number, const char *func)
+ {
+ set_filename(filename, line_number, func);
+ }
+};
+
class cerr : public detail::log<detail::cerr> {
public:
- cerr(const char *filename, int line_number)
+ cerr(const char *filename, int line_number, const char *func)
{
- set_filename(filename, line_number);
+ set_filename(filename, line_number, func);
}
};
class clog : public detail::log<detail::clog> {
public:
- clog(const char *, int)
+ clog(const char *, int, const char*)
{ }
};
class cout : public detail::log<detail::cout> {
public:
- cout(const char *, int)
+ cout(const char *, int, const char *)
{ }
};
} // namespace stream
-#define Error stream::cerr(__FILE__, __LINE__)
+#define Error stream::cerr(__FILE__, __LINE__, __func__)
-#define Out stream::cout(NULL, __LINE__)
+#define Out stream::cout(NULL, __LINE__, __func__)
-#define Log stream::clog(NULL, __LINE__)
+#define Log stream::clog(NULL, __LINE__, __func__)
-#define Logn() stream::clog(NULL, __LINE__) << " "
+#define Logn() stream::clog(NULL, __LINE__, __func__) << " "
} // namespace libtest
*
*/
-
-
-
#include <libtest/common.h>
#include <cassert>
#include <signal.h>
#include <libtest/stats.h>
+#include <libtest/signal.h>
#ifndef __INTEL_COMPILER
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif
+using namespace libtest;
+
static in_port_t global_port= 0;
static char global_socket[1024];
in_port_t default_port()
{
- assert(global_port);
return global_port;
}
void set_default_socket(const char *socket)
{
- strncpy(global_socket, socket, strlen(socket));
+ if (socket)
+ {
+ strncpy(global_socket, socket, strlen(socket));
+ }
}
static void stats_print(Stats *stats)
{
- std::cout << "\tTotal Collections\t\t\t\t" << stats->collection_total << std::endl;
- std::cout << "\tFailed Collections\t\t\t\t" << stats->collection_failed << std::endl;
- std::cout << "\tSkipped Collections\t\t\t\t" << stats->collection_skipped << std::endl;
- std::cout << "\tSucceeded Collections\t\t\t\t" << stats->collection_success << std::endl;
- std::cout << std::endl;
- std::cout << "Total\t\t\t\t" << stats->total << std::endl;
- std::cout << "\tFailed\t\t\t" << stats->failed << std::endl;
- std::cout << "\tSkipped\t\t\t" << stats->skipped << std::endl;
- std::cout << "\tSucceeded\t\t" << stats->success << std::endl;
+ Log << "\tTotal Collections\t\t\t\t" << stats->collection_total;
+ Log << "\tFailed Collections\t\t\t\t" << stats->collection_failed;
+ Log << "\tSkipped Collections\t\t\t\t" << stats->collection_skipped;
+ Log << "\tSucceeded Collections\t\t\t\t" << stats->collection_success;
+ Logn();
+ Log << "Total\t\t\t\t" << stats->total;
+ Log << "\tFailed\t\t\t" << stats->failed;
+ Log << "\tSkipped\t\t\t" << stats->skipped;
+ Log << "\tSucceeded\t\t" << stats->success;
}
static long int timedif(struct timeval a, struct timeval b)
}
}
-enum shutdown_t {
- SHUTDOWN_RUNNING,
- SHUTDOWN_GRACEFUL,
- SHUTDOWN_FORCED
-};
-
static Framework *world= NULL;
-static volatile shutdown_t __shutdown= SHUTDOWN_RUNNING;
-pthread_mutex_t shutdown_mutex= PTHREAD_MUTEX_INITIALIZER;
-
-static bool is_shutdown()
-{
- bool ret;
- pthread_mutex_lock(&shutdown_mutex);
- ret= bool(__shutdown != SHUTDOWN_RUNNING);
- pthread_mutex_unlock(&shutdown_mutex);
-
- return ret;
-}
-
-static void set_shutdown(shutdown_t arg)
-{
- pthread_mutex_lock(&shutdown_mutex);
- __shutdown= arg;
- pthread_mutex_unlock(&shutdown_mutex);
-}
-
-static void *sig_thread(void *arg)
-{
- sigset_t *set= (sigset_t *) arg;
-
- while (is_shutdown())
- {
- int sig;
- int error;
- while ((error= sigwait(set, &sig)) == EINTR) ;
-
- switch (sig)
- {
- case SIGSEGV:
- case SIGINT:
- case SIGABRT:
- Error << "Signal handling thread got signal " << strsignal(sig);
- set_shutdown(SHUTDOWN_FORCED);
- break;
-
- default:
- Error << "Signal handling thread got unexpected signal " << strsignal(sig);
- case SIGUSR1:
- break;
- }
- }
-
- return NULL;
-}
-
-
-static void setup_signals(pthread_t& thread)
-{
- sigset_t set;
-
- sigemptyset(&set);
- sigaddset(&set, SIGSEGV);
- sigaddset(&set, SIGABRT);
- sigaddset(&set, SIGINT);
- sigaddset(&set, SIGUSR1);
-
- int error;
- if ((error= pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
- {
- Error << " died during pthread_sigmask(" << strerror(error) << ")";
- exit(EXIT_FAILURE);
- }
-
- if ((error= pthread_create(&thread, NULL, &sig_thread, (void *) &set)) != 0)
- {
- Error << " died during pthread_create(" << strerror(error) << ")";
- exit(EXIT_FAILURE);
- }
-}
-
-
int main(int argc, char *argv[])
{
+ srandom((unsigned int)time(NULL));
+
world= new Framework();
if (not world)
return EXIT_FAILURE;
}
- pthread_t thread;
- setup_signals(thread);
+ setup_signals();
Stats stats;
if (test_failed(error))
{
Error << "create() failed";
+ delete world;
return EXIT_FAILURE;
}
if (collection_to_run)
{
- std::cout << "Only testing " << collection_to_run << std::endl;
+ Log << "Only testing " << collection_to_run;
}
char *wildcard= NULL;
if (collection_rc == TEST_SUCCESS and next->pre)
{
- collection_rc= world->runner->pre(next->pre, creators_ptr);
+ collection_rc= world->runner()->pre(next->pre, creators_ptr);
}
switch (collection_rc)
case TEST_FATAL:
case TEST_FAILURE:
Error << next->name << " [ failed ]";
- stats.collection_failed++;
+ failed= true;
+ set_shutdown(SHUTDOWN_GRACEFUL);
goto cleanup;
case TEST_SKIPPED:
Log << next->name << " [ skipping ]";
- stats.collection_skipped++;
+ skipped= true;
goto cleanup;
case TEST_MEMORY_ALLOCATION_FAILURE:
{
{ // Runner Code
gettimeofday(&start_time, NULL);
- return_code= world->runner->run(run->test_fn, creators_ptr);
+ assert(world->runner());
+ assert(run->test_fn);
+ return_code= world->runner()->run(run->test_fn, creators_ptr);
gettimeofday(&end_time, NULL);
load_time= timedif(end_time, start_time);
}
// @todo do something if post fails
(void)world->item.post(creators_ptr);
}
- else
+ else if (return_code == TEST_SKIPPED)
+ { }
+ else if (return_code == TEST_FAILURE)
{
Error << " item.flush(failure)";
+ set_shutdown(SHUTDOWN_GRACEFUL);
}
}
- else
+ else if (return_code == TEST_SKIPPED)
+ { }
+ else if (return_code == TEST_FAILURE)
{
Error << " item.startup(failure)";
+ set_shutdown(SHUTDOWN_GRACEFUL);
}
stats.total++;
case TEST_FAILURE:
stats.failed++;
failed= true;
- Error << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
+ Log << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
break;
case TEST_SKIPPED:
if (test_failed(world->on_error(return_code, creators_ptr)))
{
Error << "Failed while running on_error()";
+ set_shutdown(SHUTDOWN_GRACEFUL);
break;
}
}
- if (next->post and world->runner->post)
+ (void) world->runner()->post(next->post, creators_ptr);
+
+cleanup:
+ if (failed == false and skipped == false)
{
- (void) world->runner->post(next->post, creators_ptr);
+ stats.collection_success++;
}
- if (failed == 0 and skipped == 0)
+ if (failed)
{
- stats.collection_success++;
+ stats.collection_failed++;
+ }
+
+ if (skipped)
+ {
+ stats.collection_skipped++;
}
-cleanup:
world->shutdown(creators_ptr);
Logn();
if (not is_shutdown())
{
set_shutdown(SHUTDOWN_GRACEFUL);
- pthread_kill(thread, SIGUSR1);
}
- if (__shutdown == SHUTDOWN_FORCED)
+ int exit_code= EXIT_SUCCESS;
+ shutdown_t status= get_shutdown();
+ if (status == SHUTDOWN_FORCED)
{
- Error << "Tests were aborted.";
+ Log << "Tests were aborted.";
+ exit_code= EXIT_FAILURE;
}
- else if (stats.collection_failed or stats.collection_skipped)
+ else if (stats.collection_failed)
{
- Error << "Some test failures and/or skipped test occurred.";
+ Log << "Some test failed.";
+ exit_code= EXIT_FAILURE;
+ }
+ else if (stats.collection_skipped)
+ {
+ Log << "Some tests were skipped.";
}
else
{
stats_print(&stats);
- void *retval;
- pthread_join(thread, &retval);
-
delete world;
- return stats.failed == 0 and __shutdown == SHUTDOWN_GRACEFUL ? EXIT_SUCCESS : EXIT_FAILURE;
+ Logn(); // Generate a blank to break up the messages if make check/test has been run
+
+ return exit_code;
}
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif
+#include <libtest/stream.h>
+
+LIBTEST_API
+const char* default_socket();
+
+LIBTEST_API
+void set_default_socket(const char *socket);
+
+
/**
A structure describing the test case.
*/
} \
} while (0)
-#define test_true_got(A,B) \
+template <class T_comparable, class T_hint>
+bool _true_hint(const char *file, int line, const char *func, T_comparable __expected, const char *assertation_label, T_hint __hint)
+{
+ if (__expected == false)
+ {
+ libtest::stream::make_cerr(file, line, func) << "Assertation \"" << assertation_label << "\" failed, hint: " << __hint;
+ return false;
+ }
+
+ return true;
+}
+
+#define test_true_got(__expected, __hint) \
do \
{ \
- if (! (A)) { \
- fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, received \"%s\"\n", __FILE__, __LINE__, #A, (B));\
+ if (not _true_hint(__FILE__, __LINE__, __func__, ((__expected)), #__expected, ((__hint)))) \
+ { \
create_core(); \
return TEST_FAILURE; \
} \
} \
} while (0)
+template <class T_comparable>
+bool _compare(const char *file, int line, const char *func, T_comparable __expected, T_comparable __actual)
+{
+ if (__expected != __actual)
+ {
+ libtest::stream::make_cerr(file, line, func) << "Expected \"" << __expected << "\" got \"" << __actual << "\"";
+ return false;
+ }
+
+ return true;
+}
+
+template <class T_comparable>
+bool _compare_zero(const char *file, int line, const char *func, T_comparable __actual)
+{
+ if (T_comparable(0) != __actual)
+ {
+ libtest::stream::make_cerr(file, line, func) << "Expected 0 got \"" << __actual << "\"";
+ return false;
+ }
+
+ return true;
+}
+
+template <class T_comparable, class T_hint>
+bool _compare_hint(const char *file, int line, const char *func, T_comparable __expected, T_comparable __actual, T_hint __hint)
+{
+ if (__expected != __actual)
+ {
+ libtest::stream::make_cerr(file, line, func) << "Expected \"" << __expected << "\" got \"" << __actual << "\" Additionally: \"" << __hint << "\"";
+
+ return false;
+ }
+
+ return true;
+}
+
+#define test_compare(__expected, __actual) \
+do \
+{ \
+ if (not _compare(__FILE__, __LINE__, __func__, ((__expected)), ((__actual)))) \
+ { \
+ create_core(); \
+ return TEST_FAILURE; \
+ } \
+} while (0)
-#define test_compare(A,B) \
+#define test_zero(__actual) \
do \
{ \
- if ((A) != (B)) \
+ if (not _compare_zero(__FILE__, __LINE__, __func__, ((__actual)))) \
{ \
- fprintf(stderr, "\n%s:%d: Expected %s, got %lu\n", __FILE__, __LINE__, #A, (unsigned long)(B)); \
create_core(); \
return TEST_FAILURE; \
} \
} while (0)
-#define test_compare_got(A,B,C) \
+#define test_compare_got(__expected, __actual, __hint) \
do \
{ \
- if ((A) != (B)) \
+ if (not _compare_hint(__FILE__, __LINE__, __func__, (__expected), (__actual), (__hint))) \
{ \
- fprintf(stderr, "\n%s:%d: Expected %s, got %s\n", __FILE__, __LINE__, #A, (C)); \
create_core(); \
return TEST_FAILURE; \
} \
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * uTest, libtest
+ * libtest
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
#include <libtest/visibility.h>
#include <libtest/error.h>
+#include <libtest/server.h>
+#include <libtest/wait.h>
#include <libtest/callbacks.h>
#include <libtest/test.h>
#include <libtest/strerror.h>
#include <libtest/framework.h>
#include <libtest/get.h>
#include <libtest/stream.h>
+#include <libtest/cmdline.h>
#pragma once
#endif
#define test_string_make_from_cstr(X) (X), ((X) ? strlen(X) : 0)
+
+#define test_array_length(__array) sizeof(__array)/sizeof(&__array)
*/
#include <config.h>
+
#include <libtest/test.hpp>
+#include <cstdlib>
+
+using namespace libtest;
+
static test_return_t test_success_test(void *)
{
return TEST_SUCCESS;
}
-static test_return_t local_test(void *)
+static test_return_t test_failure_test(void *)
{
- char buffer[sizeof("LIBTEST_LOCAL=1")];
+ return TEST_SKIPPED; // Only run this when debugging
- snprintf(buffer, sizeof(buffer), "%s", "LIBTEST_LOCAL=1");
- test_compare(0, putenv(buffer));
+ test_compare(1, 2);
+ return TEST_SUCCESS;
+}
- test_true(test_is_local());
+static test_return_t local_test(void *)
+{
+ if (getenv("LIBTEST_LOCAL"))
+ {
+ test_true(test_is_local());
+ }
+ else
+ {
+ test_false(test_is_local());
+ }
return TEST_SUCCESS;
}
static test_return_t local_not_test(void *)
{
- test_compare(0, unsetenv("LIBTEST_LOCAL"));
+ return TEST_SKIPPED;
+ std::string temp;
+
+ const char *ptr;
+ if ((ptr= getenv("LIBTEST_LOCAL")) == NULL)
+ {
+ temp.append(ptr);
+ }
+
+ // unsetenv() will cause issues with valgrind
+ _compare(__FILE__, __LINE__, __func__, 0, unsetenv("LIBTEST_LOCAL"));
+ test_compare(0, unsetenv("LIBTEST_LOCAL"));
test_false(test_is_local());
+ test_compare(0, setenv("LIBTEST_LOCAL", "1", 1));
+ test_true(test_is_local());
+
+ if (temp.empty())
+ {
+ test_compare(0, unsetenv("LIBTEST_LOCAL"));
+ }
+ else
+ {
+ char *old_string= strdup(temp.c_str());
+ test_compare(0, setenv("LIBTEST_LOCAL", old_string, 1));
+ }
+
+ return TEST_SUCCESS;
+}
+
+#if 0
+static test_return_t pause_test(void *)
+{
+ (void)getchar();
return TEST_SUCCESS;
}
+#endif
+
+
+static test_return_t gearmand_cycle_test(void *object)
+{
+ server_startup_st *servers= (server_startup_st*)object;
+ test_true(servers);
+
+#ifndef HAVE_LIBGEARMAN
+ return TEST_SKIPPED;
+#endif
+
+ const char *argv[1]= { "cycle_gearmand" };
+ test_true(server_startup(*servers, "gearmand", 9999, 1, argv));
+
+ return TEST_SUCCESS;
+}
+
+static test_return_t memcached_cycle_test(void *object)
+{
+ server_startup_st *servers= (server_startup_st*)object;
+ test_true(servers);
+
+#if !defined(MEMCACHED_BINARY) && !defined(HAVE_LIBMEMCACHED)
+ return TEST_SKIPPED;
+#endif
+
+ const char *argv[1]= { "cycle_memcached" };
+ test_true(server_startup(*servers, "memcached", 9998, 1, argv));
+
+ return TEST_SUCCESS;
+}
+
+static test_return_t memcached_socket_cycle_test(void *object)
+{
+ server_startup_st *servers= (server_startup_st*)object;
+ test_true(servers);
+
+#if !defined(MEMCACHED_BINARY) && !defined(HAVE_LIBMEMCACHED)
+ return TEST_SKIPPED;
+#endif
+
+ const char *argv[1]= { "cycle_memcached" };
+ test_true(servers->start_socket_server("memcached", 9997, 1, argv));
+
+ return TEST_SUCCESS;
+}
+
+test_st gearmand_tests[] ={
+#if 0
+ {"pause", 0, pause_test },
+#endif
+ {"gearmand startup-shutdown", 0, gearmand_cycle_test },
+ {0, 0, 0}
+};
+
+test_st memcached_tests[] ={
+ {"memcached startup-shutdown", 0, memcached_cycle_test },
+ {"memcached(socket file) startup-shutdown", 0, memcached_socket_cycle_test },
+ {0, 0, 0}
+};
test_st tests_log[] ={
{"TEST_SUCCESS", 0, test_success_test },
+ {"TEST_FAILURE", 0, test_failure_test },
{0, 0, 0}
};
collection_st collection[] ={
{"return values", 0, 0, tests_log},
{"local", 0, 0, local_log},
+ {"gearmand", 0, 0, gearmand_tests},
+ {"memcached", 0, 0, memcached_tests},
{0, 0, 0, 0}
};
-void get_world(Framework *arg)
+static void *world_create(server_startup_st& servers, test_return_t&)
+{
+ return &servers;
+}
+
+void get_world(Framework *world)
{
- arg->collections= collection;
+ world->collections= collection;
+ world->_create= world_create;
}
for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
{
- if ((not access(filename.c_str(), R_OK)) or (waited >= timeout))
+ if (access(filename.c_str(), R_OK) == 0)
{
_successful= true;
break;
}
+ else if (waited >= timeout)
+ {
+ break;
+ }
this_wait= retry * retry / 3 + 1;
sleep(this_wait);
+#ifdef WIN32
+ sleep(this_wait);
+#else
+ struct timespec global_sleep_value= { this_wait, 0 };
+ nanosleep(&global_sleep_value, NULL);
+#endif
}
}
--- /dev/null
+AC_DEFUN([_WITH_LIBGEARMAN],
+ [ AC_ARG_ENABLE([libgearman],
+ [AS_HELP_STRING([--disable-libgearman],
+ [Build with libgearman support @<:@default=on@:>@])],
+ [ac_enable_libgearman="$enableval"],
+ [ac_enable_libgearman="yes"])
+
+ AS_IF([test "x$ac_enable_libgearman" = "xyes"],
+ [ PKG_CHECK_MODULES([libgearman], [ libgearman >= 0.24 ],
+ [AC_DEFINE([HAVE_LIBGEARMAN], [ 1 ], [Enable libgearman support])],
+ [ac_enable_libgearman="no"] )])
+
+ AM_CONDITIONAL(HAVE_LIBGEARMAN, test "x${ac_enable_libgearman}" = "xyes")
+ ])
+
+AC_DEFUN([WITH_LIBGEARMAN], [ AC_REQUIRE([_WITH_LIBGEARMAN]) ])
+++ /dev/null
-dnl Copyright (C) 2009 Sun Microsystems, Inc.
-dnl This file is free software; Sun Microsystems, Inc.
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([_PANDORA_SEARCH_LIBGEARMAN],[
- AC_REQUIRE([AC_LIB_PREFIX])
-
- dnl --------------------------------------------------------------------
- dnl Check for libgearman
- dnl --------------------------------------------------------------------
-
- AC_ARG_ENABLE([libgearman],
- [AS_HELP_STRING([--disable-libgearman],
- [Build with libgearman support @<:@default=on@:>@])],
- [ac_enable_libgearman="$enableval"],
- [ac_enable_libgearman="yes"])
-
- AS_IF([test "x$ac_enable_libgearman" = "xyes"],[
- AC_LIB_HAVE_LINKFLAGS(gearman,,[
- #include <libgearman/gearman.h>
- ],[
- gearman_client_st gearman_client;
- gearman_client_context(&gearman_client);
- ])
- ],[
- ac_cv_libgearman="no"
- ])
-
- AM_CONDITIONAL(HAVE_LIBGEARMAN, [test "x${ac_cv_libgearman}" = "xyes"])
-])
-
-AC_DEFUN([PANDORA_HAVE_LIBGEARMAN],[
- AC_REQUIRE([_PANDORA_SEARCH_LIBGEARMAN])
-])
-
-AC_DEFUN([PANDORA_REQUIRE_LIBGEARMAN],[
- AC_REQUIRE([PANDORA_HAVE_LIBGEARMAN])
- AS_IF([test "x${ac_cv_libgearman}" = "xno"],
- AC_MSG_ERROR([At least version 0.10 of libgearman is required for ${PACKAGE}]))
-])
%setup -q
%{__mkdir} examples
-%{__cp} tests/*.{c,cc,cpp,h} examples/
+%{__cp} tests/*.{cc,cpp,h} examples/
%build
/*
Sample test application.
*/
-#include <libtest/common.h>
+#include <config.h>
+
+#include <libtest/test.hpp>
#include <libmemcached/memcached.h>
#include <libmemcached/watchpoint.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdio>
+#include <cstdlib>
#include <stdint.h>
-#include <string.h>
+#include <cstring>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <time.h>
+#include <ctime>
#include <clients/generator.h>
#include <clients/execute.h>
#include <libtest/server.h>
+using namespace libtest;
+
/* Number of items generated for tests */
#define GLOBAL_COUNT 100000
world->collections= collection;
world->_create= (test_callback_create_fn*)world_create;
- world->_destroy= (test_callback_fn*)world_destroy;
+ world->_destroy= (test_callback_destroy_fn*)world_destroy;
world->item._startup= (test_callback_fn*)world_test_startup;
world->item._flush= (test_callback_fn*)world_flush;
world->collection_startup= (test_callback_fn*)world_container_startup;
world->collection_shutdown= (test_callback_fn*)world_container_shutdown;
- world->runner= &defualt_libmemcached_runner;
+ world->set_runner(&defualt_libmemcached_runner);
}
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
#include <libmemcached/memcached.h>
#include <libmemcached/is.h>
Test that we are cycling the servers we are creating during testing.
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
#include <libmemcached/common.h>
#include <libmemcached/is.h>
#include <libtest/server.h>
+using namespace libtest;
+
#define SERVERS_TO_CREATE 5
#ifndef __INTEL_COMPILER
{0, 0, 0, 0}
};
-#if 0
-static server_startup_st *world_create(test_return_t *error)
-{
- server_startup_st *servers= new server_startup_st();
-
- server_startup(servers);
-
- *error= TEST_SUCCESS;
-
- return servers;
-}
-
-static test_return_t world_destroy(server_startup_st *servers)
-{
- server_shutdown(servers);
- delete servers;
-
- return TEST_SUCCESS;
-}
-#endif
-
#include "tests/libmemcached_world.h"
world->collections= collection;
world->_create= (test_callback_create_fn*)world_create;
- world->_destroy= (test_callback_fn*)world_destroy;
+ world->_destroy= (test_callback_destroy_fn*)world_destroy;
- world->item._startup= (test_callback_fn*)world_test_startup;
+ world->item.set_startup((test_callback_fn*)world_test_startup);
world->item.set_pre((test_callback_fn*)world_pre_run);
world->item.set_post((test_callback_fn*)world_post_run);
- world->_on_error= (test_callback_error_fn*)world_on_error;
+
+ world->set_on_error((test_callback_error_fn*)world_on_error);
world->collection_startup= (test_callback_fn*)world_container_startup;
world->collection_shutdown= (test_callback_fn*)world_container_shutdown;
- world->runner= &defualt_libmemcached_runner;
+ world->set_runner(&defualt_libmemcached_runner);
}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached client and server library.
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * 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/test.hpp>
+#include <climits>
+
+using namespace libtest;
+
+#include <libmemcached/memcached.h>
+#include <tests/debug.h>
+
+/* Dump each server's keys */
+static memcached_return_t print_keys_callback(const memcached_st *,
+ const char *key,
+ size_t key_length,
+ void *)
+{
+
+ Out << "\t" << key << " (" << key_length << ")";
+
+
+ return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t server_wrapper_for_dump_callback(const memcached_st *,
+ memcached_server_instance_st server,
+ void *)
+{
+ memcached_st *memc= memcached_create(NULL);
+
+ if (server->type == MEMCACHED_CONNECTION_UNIX_SOCKET)
+ {
+ if (memcached_failed(memcached_server_add_unix_socket(memc, memcached_server_name(server))))
+ {
+ return MEMCACHED_FAILURE;
+ }
+ }
+ else
+ {
+ if (memcached_failed(memcached_server_add(memc, memcached_server_name(server), memcached_server_port(server))))
+ {
+ return MEMCACHED_FAILURE;
+ }
+ }
+
+ memcached_dump_fn callbacks[1];
+
+ callbacks[0]= &print_keys_callback;
+
+ Out << memcached_server_name(server) << ":" << memcached_server_port(server);
+
+ if (memcached_failed(memcached_dump(memc, callbacks, NULL, 1)))
+ {
+ return MEMCACHED_FAILURE;
+ }
+
+ memcached_free(memc);
+
+ return MEMCACHED_SUCCESS;
+}
+
+
+test_return_t confirm_keys_exist(memcached_st *memc, const char * const *keys, const size_t number_of_keys, bool key_matches_value)
+{
+ for (size_t x= 0; x < number_of_keys; ++x)
+ {
+ memcached_return_t rc;
+ size_t value_length;
+ char *value= memcached_get(memc,
+ test_string_make_from_cstr(keys[x]), // Keys
+ &value_length,
+ 0, &rc);
+ test_true_got(value, keys[x]);
+ if (key_matches_value)
+ {
+ test_strcmp(keys[x], value);
+ }
+ free(value);
+ }
+
+ return TEST_SUCCESS;
+}
+
+test_return_t confirm_keys_dont_exist(memcached_st *memc, const char * const *keys, const size_t number_of_keys)
+{
+ for (size_t x= 0; x < number_of_keys; ++x)
+ {
+ memcached_return_t rc;
+ size_t value_length;
+ char *value= memcached_get(memc,
+ test_string_make_from_cstr(keys[x]), // Keys
+ &value_length,
+ 0, &rc);
+ test_false(value);
+ test_compare(MEMCACHED_NOTFOUND, rc);
+ }
+
+ return TEST_SUCCESS;
+}
+
+
+test_return_t print_keys_by_server(memcached_st *memc)
+{
+ memcached_server_fn callback[]= { server_wrapper_for_dump_callback };
+ test_compare(MEMCACHED_SUCCESS, memcached_server_cursor(memc, callback, NULL, test_array_length(callback)));
+
+ return TEST_SUCCESS;
+}
+
+static memcached_return_t callback_dump_counter(const memcached_st *ptr,
+ const char *key,
+ size_t key_length,
+ void *context)
+{
+ (void)ptr; (void)key; (void)key_length;
+ size_t *counter= (size_t *)context;
+
+ *counter= *counter + 1;
+
+ return MEMCACHED_SUCCESS;
+}
+
+size_t confirm_key_count(memcached_st *memc)
+{
+ memcached_st *clone= memcached_clone(NULL, memc);
+ if (memcached_failed(memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, false)))
+ {
+ memcached_free(clone);
+ return ULONG_MAX;
+ }
+
+ memcached_dump_fn callbacks[1];
+
+ callbacks[0]= &callback_dump_counter;
+
+ size_t count= 0;
+ if (memcached_failed(memcached_dump(clone, callbacks, (void *)&count, 1)))
+ {
+ memcached_free(clone);
+ return ULONG_MAX;
+ }
+
+ memcached_free(clone);
+ return count;
+}
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached client and server library.
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * 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
+
+test_return_t confirm_keys_exist(memcached_st *memc, const char * const *keys, const size_t number_of_keys, bool key_matches_value= false);
+
+test_return_t confirm_keys_dont_exist(memcached_st *memc, const char * const *keys, const size_t number_of_keys);
+
+test_return_t print_keys_by_server(memcached_st *memc);
+
+size_t confirm_key_count(memcached_st *memc);
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
#include <cassert>
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
#define BUILDING_LIBMEMCACHED
C++ to libhashkit
*/
-#include <libtest/common.h>
+#include <config.h>
+
+#include <libtest/test.hpp>
#include <cstdio>
#include <cstdlib>
#include <libhashkit/hashkit.hpp>
+using namespace libtest;
+
#include "hash_results.h"
static test_return_t exists_test(void *obj)
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+using namespace libtest;
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <libhashkit/hashkit.h>
{0, 0, 0, 0}
};
-/* Prototypes for functions we will pass to test framework */
-void *world_create(test_return_t *error);
-test_return_t world_destroy(hashkit_st *hashk);
-
-void *world_create(test_return_t *error)
+static void *world_create(libtest::server_startup_st&, test_return_t& error)
{
hashkit_st *hashk_ptr= hashkit_create(&global_hashk);
if (hashk_ptr != &global_hashk)
{
- *error= TEST_FAILURE;
+ error= TEST_FAILURE;
return NULL;
}
if (hashkit_is_allocated(hashk_ptr) == true)
{
- *error= TEST_FAILURE;
+ error= TEST_FAILURE;
return NULL;
}
- *error= TEST_SUCCESS;
-
return hashk_ptr;
}
-test_return_t world_destroy(hashkit_st *hashk)
+static bool world_destroy(void *object)
{
+ hashkit_st *hashk= (hashkit_st *)object;
// Did we get back what we expected?
- assert(hashkit_is_allocated(hashk) == false);
+ test_true(hashkit_is_allocated(hashk) == false);
hashkit_free(&global_hashk);
return TEST_SUCCESS;
void get_world(Framework *world)
{
world->collections= collection;
- world->_create= (test_callback_create_fn*)world_create;
- world->_destroy= (test_callback_fn*)world_destroy;
+ world->_create= world_create;
+ world->_destroy= world_destroy;
}
TESTS_LDADDS= \
libmemcached/libmemcached.la \
- libtest/libserver.la \
libtest/libtest.la
DEBUG_COMMAND= $(LIBTOOL) --mode=execute gdb
noinst_HEADERS+= \
tests/basic.h \
+ tests/debug.h \
tests/error_conditions.h \
tests/hash_results.h \
tests/ketama_test_cases.h \
tests_testapp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
tests_testapp_SOURCES= \
tests/basic.cc \
+ tests/debug.cc \
tests/deprecated.cc \
tests/error_conditions.cc \
tests/mem_functions.cc \
check_PROGRAMS+= tests/testudp
tests_testhashkit_SOURCES = tests/hashkit_functions.cc
-tests_testhashkit_DEPENDENCIES = libtest/libtest.la libhashkit/libhashkit.la
+tests_testhashkit_DEPENDENCIES = libtest/libtest.la libhashkit/libhashkit.la $(TESTS_LDADDS)
tests_testhashkit_LDADD = $(tests_testhashkit_DEPENDENCIES)
check_PROGRAMS+= tests/testhashkit
tests_hash_plus_SOURCES= tests/hash_plus.cc
tests_hash_plus_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-tests_hash_plus_DEPENDENCIES= $(tests_testhashkit_DEPENDENCIES)
+tests_hash_plus_DEPENDENCIES= $(tests_testhashkit_DEPENDENCIES) $(TESTS_LDADDS)
tests_hash_plus_LDADD= $(tests_testhashkit_DEPENDENCIES)
check_PROGRAMS+= tests/hash_plus
-MEMSLAP_COMMAND= clients/memslap $(COLLECTION) $(SUITE)
+MEMSLAP_COMMAND= clients/memslap
-MEM_COMMAND= tests/testapp $(COLLECTION) $(SUITE)
+MEM_COMMAND= tests/testapp
-TESTPLUS_COMMAND= tests/testplus $(COLLECTION) $(SUITE)
+TESTPLUS_COMMAND= tests/testplus
-HASHPLUS_COMMAND= tests/hashplus $(COLLECTION) $(SUITE)
+HASHPLUS_COMMAND= tests/hashplus
-CYCLE_COMMAND= tests/cycle $(COLLECTION) $(SUITE)
+CYCLE_COMMAND= tests/cycle
-ATOM_COMMAND= tests/atomsmasher $(COLLECTION) $(SUITE)
+ATOM_COMMAND= tests/atomsmasher
-UDP_COMMAND= tests/testudp $(COLLECTION) $(SUITE)
+UDP_COMMAND= tests/testudp
-HASH_COMMAND= tests/testhashkit $(COLLECTION) $(SUITE)
+HASH_COMMAND= tests/testhashkit
test-mem: tests/var tests/testapp
$(MEM_COMMAND)
/* The structure we use for the test system */
struct libmemcached_test_container_st
{
- server_startup_st construct;
+ server_startup_st& construct;
memcached_st *parent;
memcached_st *memc;
- libmemcached_test_container_st() :
+ libmemcached_test_container_st(server_startup_st &construct_arg) :
+ construct(construct_arg),
parent(NULL),
memc(NULL)
{ }
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+#define SERVERS_TO_CREATE 5
+#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10
-/* Prototypes for functions we will pass to test framework */
-libmemcached_test_container_st *world_create(test_return_t *error);
-test_return_t world_test_startup(libmemcached_test_container_st *);
-test_return_t world_flush(libmemcached_test_container_st *container);
-test_return_t world_pre_run(libmemcached_test_container_st *);
+static void *world_create(server_startup_st& servers, test_return_t& error)
+{
+ in_port_t max_port;
+ for (uint32_t x= 0; x < SERVERS_TO_CREATE; x++)
+ {
+ in_port_t port;
+
+ char variable_buffer[1024];
+ snprintf(variable_buffer, sizeof(variable_buffer), "LIBMEMCACHED_PORT_%u", x);
+
+ char *var;
+ if ((var= getenv(variable_buffer)))
+ {
+ port= in_port_t(atoi(var));
+ }
+ else
+ {
+ port= in_port_t(TEST_PORT_BASE +x);
+ }
+
+ max_port= port;
+ const char *argv[1]= { "memcached" };
+ if (not server_startup(servers, "memcached", port, 1, argv))
+ {
+ error= TEST_FAILURE;
+ return NULL;
+ }
+ }
-test_return_t world_post_run(libmemcached_test_container_st *);
-test_return_t world_on_error(test_return_t, libmemcached_test_container_st *);
-test_return_t world_destroy(libmemcached_test_container_st *);
+ const char *argv[1]= { "memcached" };
+ if (not servers.start_socket_server("memcached", max_port +1, 1, argv))
+ {
+ error= TEST_FAILURE;
+ return NULL;
+ }
-/**
- @note generic shutdown/startup for libmemcached tests.
-*/
-test_return_t world_container_startup(libmemcached_test_container_st *container);
-test_return_t world_container_shutdown(libmemcached_test_container_st *container);
-libmemcached_test_container_st *world_create(test_return_t *error)
-{
- libmemcached_test_container_st *global_container= new libmemcached_test_container_st();
- if (not server_startup(&global_container->construct))
+ libmemcached_test_container_st *global_container= new libmemcached_test_container_st(servers);
+ if (global_container == NULL)
{
- *error= TEST_FAILURE;
+ error= TEST_MEMORY_ALLOCATION_FAILURE;
return NULL;
}
- *error= TEST_SUCCESS;
+ error= TEST_SUCCESS;
return global_container;
}
-test_return_t world_container_startup(libmemcached_test_container_st *container)
+static test_return_t world_container_startup(libmemcached_test_container_st *container)
{
char buffer[BUFSIZ];
test_compare_got(MEMCACHED_SUCCESS,
- libmemcached_check_configuration(container->construct.server_list.c_str(), container->construct.server_list.size(),
+ libmemcached_check_configuration(container->construct.option_string().c_str(), container->construct.option_string().size(),
buffer, sizeof(buffer)),
- buffer);
+ container->construct.option_string().c_str());
- assert(not container->parent);
- container->parent= memcached(container->construct.server_list.c_str(), container->construct.server_list.size());
+ test_true(not container->parent);
+ container->parent= memcached(container->construct.option_string().c_str(), container->construct.option_string().size());
test_true(container->parent);
+ for (uint32_t host= 0; host < memcached_server_count(container->parent); ++host)
+ {
+ memcached_server_instance_st instance=
+ memcached_server_instance_by_position(container->parent, host);
+
+ if (instance->type == MEMCACHED_CONNECTION_TCP)
+ {
+ test_true_got(memcached_server_port(instance) >= TEST_PORT_BASE, memcached_server_port(instance));
+ }
+ }
+
return TEST_SUCCESS;
}
-test_return_t world_container_shutdown(libmemcached_test_container_st *container)
+static test_return_t world_container_shutdown(libmemcached_test_container_st *container)
{
memcached_free(container->parent);
container->parent= NULL;
return TEST_SUCCESS;
}
-test_return_t world_test_startup(libmemcached_test_container_st *container)
+static test_return_t world_test_startup(libmemcached_test_container_st *container)
{
- assert(container);
- assert(not container->memc);
- assert(container->parent);
+ test_true(container);
+ test_true(not container->memc);
+ test_true(container->parent);
container->memc= memcached_clone(NULL, container->parent);
test_true(container->memc);
return TEST_SUCCESS;
}
+test_return_t world_flush(libmemcached_test_container_st *container);
test_return_t world_flush(libmemcached_test_container_st *container)
{
- assert(container->memc);
+ test_true(container->memc);
memcached_flush(container->memc, 0);
memcached_quit(container->memc);
return TEST_SUCCESS;
}
-test_return_t world_pre_run(libmemcached_test_container_st *container)
+static test_return_t world_pre_run(libmemcached_test_container_st *container)
{
- assert(container->memc);
+ test_true(container->memc);
for (uint32_t loop= 0; loop < memcached_server_list_count(container->memc->servers); loop++)
{
memcached_server_instance_st instance=
memcached_server_instance_by_position(container->memc, loop);
test_compare(-1, instance->fd);
- test_compare(0, instance->cursor_active);
+ test_compare(0U, instance->cursor_active);
}
return TEST_SUCCESS;
}
-test_return_t world_post_run(libmemcached_test_container_st *container)
+static test_return_t world_post_run(libmemcached_test_container_st *container)
{
test_true(container->memc);
return TEST_SUCCESS;
}
-test_return_t world_on_error(test_return_t test_state, libmemcached_test_container_st *container)
+static test_return_t world_on_error(test_return_t test_state, libmemcached_test_container_st *container)
{
(void)test_state;
- assert(container->memc);
+ test_true(container->memc);
memcached_free(container->memc);
container->memc= NULL;
return TEST_SUCCESS;
}
-test_return_t world_destroy(libmemcached_test_container_st *container)
+static bool world_destroy(void *object)
{
- server_startup_st *construct= &container->construct;
-
- server_shutdown(construct);
-
+ libmemcached_test_container_st *container= (libmemcached_test_container_st *)object;
#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
sasl_done();
#endif
}
typedef test_return_t (*libmemcached_test_callback_fn)(memcached_st *);
+
static test_return_t _runner_default(libmemcached_test_callback_fn func, libmemcached_test_container_st *container)
{
if (func)
{
- assert(container);
- assert(container->memc);
+ test_true(container);
+ test_true(container->memc);
return func(container->memc);
}
- else
- {
- return TEST_SUCCESS;
- }
+
+ return TEST_SUCCESS;
}
static test_return_t _pre_runner_default(libmemcached_test_callback_fn func, libmemcached_test_container_st *container)
{
return func(container->parent);
}
- else
- {
- return TEST_SUCCESS;
- }
+
+ return TEST_SUCCESS;
}
static test_return_t _post_runner_default(libmemcached_test_callback_fn func, libmemcached_test_container_st *container)
{
return func(container->parent);
}
- else
- {
- return TEST_SUCCESS;
- }
-}
-#ifdef __cplusplus
+ return TEST_SUCCESS;
}
-#endif
-
-#ifdef __cplusplus
-static Runner defualt_libmemcached_runner= {
- reinterpret_cast<test_callback_runner_fn*>(_pre_runner_default),
- reinterpret_cast<test_callback_runner_fn*>(_runner_default),
- reinterpret_cast<test_callback_runner_fn*>(_post_runner_default)
-};
+class LibmemcachedRunner : public Runner {
+public:
+ test_return_t run(test_callback_fn* func, void *object)
+ {
+ return _runner_default(libmemcached_test_callback_fn(func), (libmemcached_test_container_st*)object);
+ }
-#else
+ test_return_t pre(test_callback_fn* func, void *object)
+ {
+ return _pre_runner_default(libmemcached_test_callback_fn(func), (libmemcached_test_container_st*)object);
+ }
-static Runner defualt_libmemcached_runner= {
- (test_callback_runner_fn)_pre_runner_default,
- (test_callback_runner_fn)_runner_default,
- (test_callback_runner_fn)_post_runner_default
+ test_return_t post(test_callback_fn* func, void *object)
+ {
+ return _post_runner_default(libmemcached_test_callback_fn(func), (libmemcached_test_container_st*)object);
+ }
};
-#endif
+static LibmemcachedRunner defualt_libmemcached_runner;
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
/*
Test cases
#include "tests/namespace.h"
#include "tests/string.h"
#include "tests/replication.h"
+#include "tests/debug.h"
#include "tests/basic.h"
#include "tests/error_conditions.h"
#include "tests/print.h"
#include "tests/virtual_buckets.h"
+using namespace libtest;
#ifdef HAVE_LIBMEMCACHEDUTIL
#include <pthread.h>
test_true(local_memc);
memcached_behavior_set(local_memc, MEMCACHED_BEHAVIOR_SORT_HOSTS, 1);
- for (size_t x= 0; x < TEST_PORT_COUNT; x++)
+ for (uint32_t x= 0; x < TEST_PORT_COUNT; x++)
{
test_ports[x]= (in_port_t)random() % 64000;
rc= memcached_server_add_with_weight(local_memc, "localhost", test_ports[x], 0);
test_compare(MEMCACHED_SUCCESS,
memcached_server_add_with_weight(local_memc, "MEMCACHED_BEHAVIOR_SORT_HOSTS", 43043, 0));
instance= memcached_server_instance_by_position(local_memc, 0);
- test_compare(43043, memcached_server_port(instance));
+ test_compare(in_port_t(43043), memcached_server_port(instance));
test_compare(MEMCACHED_SUCCESS,
memcached_server_add_with_weight(local_memc, "MEMCACHED_BEHAVIOR_SORT_HOSTS", 43042, 0));
instance= memcached_server_instance_by_position(local_memc, 0);
- test_compare(43042, memcached_server_port(instance));
+ test_compare(in_port_t(43042), memcached_server_port(instance));
instance= memcached_server_instance_by_position(local_memc, 1);
- test_compare(43043, memcached_server_port(instance));
+ test_compare(in_port_t(43043), memcached_server_port(instance));
callbacks[0]= server_display_function;
memcached_server_cursor(local_memc, callbacks, (void *)&bigger, 1);
const char *server_string= "--server=localhost:4444 --server=localhost:4445 --server=localhost:4446 --server=localhost:4447 --server=localhost --server=memcache1.memcache.bk.sapo.pt:11211 --server=memcache1.memcache.bk.sapo.pt:11212 --server=memcache1.memcache.bk.sapo.pt:11213 --server=memcache1.memcache.bk.sapo.pt:11214 --server=memcache2.memcache.bk.sapo.pt:11211 --server=memcache2.memcache.bk.sapo.pt:11212 --server=memcache2.memcache.bk.sapo.pt:11213 --server=memcache2.memcache.bk.sapo.pt:11214";
char buffer[BUFSIZ];
- memcached_return_t rc;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= libmemcached_check_configuration(server_string, strlen(server_string), buffer, sizeof(buffer)),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ libmemcached_check_configuration(server_string, strlen(server_string), buffer, sizeof(buffer)));
memcached_st *memc= memcached(server_string, strlen(server_string));
test_true(memc);
local_memc= memcached_create(NULL);
test_true(local_memc);
- for (size_t x= 0; x < TEST_PORT_COUNT; x++)
+ for (uint32_t x= 0; x < TEST_PORT_COUNT; x++)
{
test_ports[x]= (in_port_t)(random() % 64000);
test_compare(MEMCACHED_SUCCESS,
{
test_true(libmemcached_string_behavior(memcached_behavior_t(x)));
}
- test_compare(36, MEMCACHED_BEHAVIOR_MAX);
+ test_compare(36, int(MEMCACHED_BEHAVIOR_MAX));
return TEST_SUCCESS;
}
{
test_true(libmemcached_string_distribution(memcached_server_distribution_t(x)));
}
- test_compare(7, MEMCACHED_DISTRIBUTION_CONSISTENT_MAX);
+ test_compare(7, int(MEMCACHED_DISTRIBUTION_CONSISTENT_MAX));
return TEST_SUCCESS;
}
}
test_compare(values[rc], hash_val);
}
- test_compare(MEMCACHED_MAXIMUM_RETURN, 47);
+ test_compare(47, int(MEMCACHED_MAXIMUM_RETURN));
return TEST_SUCCESS;
}
test_compare(MEMCACHED_SUCCESS, rc);
out_value= memcached_get(memc, key, strlen(key),
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_memcmp(out_value, "we the people", strlen("we the people"));
test_compare(strlen("we the people"), value_length);
test_compare(MEMCACHED_SUCCESS, rc);
}
value= (uint32_t *)memcached_get(memc, key, strlen(key),
- &value_length, &flags, &rc);
+ &value_length, &flags, &rc);
test_compare(value_length, sizeof(uint32_t) * x);
test_compare(MEMCACHED_SUCCESS, rc);
string= memcached_get(memc_clone, key, strlen(key),
&string_length, &flags, &rc);
test_compare(MEMCACHED_BAD_KEY_PROVIDED, rc);
- test_compare(0, string_length);
+ test_zero(string_length);
test_false(string);
set= 0;
string= memcached_get(memc_clone, key, strlen(key),
&string_length, &flags, &rc);
test_compare_got(MEMCACHED_NOTFOUND, rc, memcached_strerror(NULL, rc));
- test_compare(0, string_length);
+ test_zero(string_length);
test_false(string);
/* Test multi key for bad keys */
string= memcached_get(memc_clone, longkey, max_keylen,
&string_length, &flags, &rc);
test_compare(MEMCACHED_NOTFOUND, rc);
- test_compare(0, string_length);
+ test_zero(string_length);
test_false(string);
string= memcached_get(memc_clone, longkey, max_keylen + 1,
&string_length, &flags, &rc);
test_compare(MEMCACHED_BAD_KEY_PROVIDED, rc);
- test_compare(0, string_length);
+ test_zero(string_length);
test_false(string);
free(longkey);
string= memcached_get(memc_clone, key, 0,
&string_length, &flags, &rc);
test_compare(MEMCACHED_BAD_KEY_PROVIDED, rc);
- test_compare(0, string_length);
+ test_zero(string_length);
test_false(string);
memcached_free(memc_clone);
memcached_return_t rc= memcached_set(memc, keys[0], lengths[0],
keys[0], lengths[0], 0, 0);
- test_compare(MEMCACHED_SUCCESS, rc);
- rc= memcached_mget(memc, keys, lengths, 2);
+ test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, keys, lengths, test_array_length(keys)));
memcached_result_st results_obj;
- memcached_result_st *results;
- results=memcached_result_create(memc, &results_obj);
+ memcached_result_st *results= memcached_result_create(memc, &results_obj);
test_true(results);
- results=memcached_fetch_result(memc, &results_obj, &rc);
+
+ results= memcached_fetch_result(memc, &results_obj, &rc);
test_true(results);
+
memcached_result_free(&results_obj);
/* Don't read out the second result, but issue a set instead.. */
- rc= memcached_set(memc, keys[0], lengths[0], keys[0], lengths[0], 0, 0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys[0], lengths[0], keys[0], lengths[0], 0, 0));
char *val= memcached_get_by_key(memc, keys[0], lengths[0], "yek", 3,
&rlen, &flags, &rc);
memcached_return_t rc;
// Set foo and foo2
- for (int i= 0; i < 2; i++)
+ for (size_t x= 0; x < test_array_length(keys); x++)
{
- rc= memcached_set(memc, keys[i], lengths[i], values[i], strlen(values[i]),
- (time_t)0, (uint32_t)0);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys[x], lengths[x], values[x], strlen(values[x]), (time_t)0, (uint32_t)0));
}
char *string;
uint32_t flags;
// retrieve both via mget
- rc= memcached_mget(memc, keys, lengths, 2);
- test_compare(MEMCACHED_SUCCESS, rc);
+ test_compare(MEMCACHED_SUCCESS, memcached_mget(memc, keys, lengths, test_array_length(keys)));
char key[MEMCACHED_MAX_KEY];
size_t key_length;
// this should get both
- for (int i = 0; i < 2; i++)
+ for (size_t x= 0; x < test_array_length(keys); x++)
{
string= memcached_fetch(memc, key, &key_length, &string_length,
&flags, &rc);
test_literal_param("0"),
(time_t)0, (uint32_t)0));
- memcached_return_t rc;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= memcached_increment(memc,
- test_literal_param("number"),
- 1, &new_number),
- memcached_strerror(NULL, rc));
- test_compare(1, new_number);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_increment(memc, test_literal_param("number"), 1, &new_number));
+ test_compare(uint64_t(1), new_number);
test_compare(MEMCACHED_SUCCESS,
- memcached_increment(memc,
- test_literal_param("number"),
- 1, &new_number));
- test_compare(2, new_number);
+ memcached_increment(memc, test_literal_param("number"), 1, &new_number));
+ test_compare(uint64_t(2), new_number);
return TEST_SUCCESS;
}
test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
- memcached_return_t rc;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= memcached_increment_with_initial(memc,
- test_literal_param("number"),
- 1, initial, 0, &new_number),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_increment_with_initial(memc, test_literal_param("number"), 1, initial, 0, &new_number));
test_compare(new_number, initial);
test_compare(MEMCACHED_SUCCESS,
- memcached_increment_with_initial(memc,
- test_literal_param("number"),
- 1, initial, 0, &new_number));
- test_compare(new_number, (initial + 1));
+ memcached_increment_with_initial(memc, test_literal_param("number"), 1, initial, 0, &new_number));
+ test_compare(new_number, (initial +1));
return TEST_SUCCESS;
}
test_literal_param("number"),
value, strlen(value),
(time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
test_compare(MEMCACHED_SUCCESS,
memcached_decrement(memc,
test_literal_param("number"),
1, &new_number));
- test_compare(new_number, 2);
+ test_compare(uint64_t(2), new_number);
test_compare(MEMCACHED_SUCCESS,
memcached_decrement(memc,
test_literal_param("number"),
1, &new_number));
- test_compare(new_number, 1);
+ test_compare(uint64_t(1), new_number);
return TEST_SUCCESS;
}
test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
test_compare(MEMCACHED_SUCCESS,
- memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key),
- 1, &new_number));
- test_compare(new_number, 1);
+ memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), 1, &new_number));
+ test_compare(uint64_t(1), new_number);
test_compare(MEMCACHED_SUCCESS,
- memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key),
- 1, &new_number));
- test_compare(new_number, 2);
+ memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key), 1, &new_number));
+ test_compare(uint64_t(2), new_number);
return TEST_SUCCESS;
}
key, strlen(key),
1, initial, 0, &new_number);
test_compare(MEMCACHED_SUCCESS, rc);
- test_true(new_number == initial);
+ test_compare(new_number, initial);
rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
key, strlen(key),
1, initial, 0, &new_number);
test_compare(MEMCACHED_SUCCESS, rc);
- test_true(new_number == (initial + 1));
+ test_compare(new_number, (initial +1));
return TEST_SUCCESS;
}
test_literal_param("number"),
value, strlen(value),
(time_t)0, (uint32_t)0);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
test_compare(MEMCACHED_SUCCESS,
memcached_decrement_by_key(memc,
test_literal_param("foo"),
test_literal_param("number"),
1, &new_number));
- test_compare(new_number, 2);
+ test_compare(uint64_t(2), new_number);
test_compare(MEMCACHED_SUCCESS,
memcached_decrement_by_key(memc,
test_literal_param("foo"),
test_literal_param("number"),
1, &new_number));
- test_compare(new_number, 1);
+ test_compare(uint64_t(1), new_number);
return TEST_SUCCESS;
}
rc= memcached_set(memc, key, strlen(key),
value, strlen(value),
(time_t)10, (uint32_t)3);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
memcached_quit(memc);
rc= memcached_set(memc, key, strlen(key),
value, strlen(value),
(time_t)50, (uint32_t)9);
- test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
return TEST_SUCCESS;
}
callbacks[0]= &callback_counter;
counter= 0;
- memcached_return_t rc;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_fetch_execute(memc, callbacks, (void *)&counter, 1));
- test_compare(counter, 3);
+ test_compare(size_t(3), counter);
return TEST_SUCCESS;
}
test_true(return_value);
}
test_false(return_value);
- test_compare(0, return_value_length);
- test_compare_got(MEMCACHED_NOTFOUND, rc, memcached_strerror(NULL, rc));
+ test_zero(return_value_length);
+ test_compare(MEMCACHED_NOTFOUND, rc);
for (uint32_t x= 0; x < 3; x++)
{
return TEST_SUCCESS;
}
-static test_return_t fetch_all_results(memcached_st *memc, size_t &keys_returned, const memcached_return_t expect)
+static test_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned, const memcached_return_t expect)
{
memcached_return_t rc;
char return_key[MEMCACHED_MAX_KEY];
{
return TEST_SUCCESS;
}
- fprintf(stderr, "\n%s:%u %s(#%lu)\n", __FILE__, __LINE__, memcached_strerror(NULL, rc), (unsigned long)(keys_returned));
+ fprintf(stderr, "\n%s:%u %s(#%u)\n", __FILE__, __LINE__, memcached_strerror(NULL, rc), keys_returned);
return TEST_FAILURE;
}
/* Test case provided by Cal Haldenbrand */
-#define HALDENBRAND_KEY_COUNT 3000 // * 1024576
+#define HALDENBRAND_KEY_COUNT 3000U // * 1024576
#define HALDENBRAND_FLAG_KEY 99 // * 1024576
static test_return_t user_supplied_bug1(memcached_st *memc)
{
total+= size;
char key[22];
int key_length= snprintf(key, sizeof(key), "%u", x);
- memcached_return_t rc;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= memcached_set(memc, key, key_length, randomstuff, strlen(randomstuff), time_t(0), HALDENBRAND_FLAG_KEY),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc, key, key_length, randomstuff, strlen(randomstuff), time_t(0), HALDENBRAND_FLAG_KEY));
}
test_true(total > HALDENBRAND_KEY_COUNT);
continue;
}
- test_compare(HALDENBRAND_FLAG_KEY, flags);
+ test_compare(uint32_t(HALDENBRAND_FLAG_KEY), flags);
total_value_length+= val_len;
errors= 0;
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, (const char **)keys, key_lengths, HALDENBRAND_KEY_COUNT));
- test_return_t foo;
- size_t keys_returned;
- test_compare_got(TEST_SUCCESS, foo= fetch_all_results(memc, keys_returned, MEMCACHED_SUCCESS), test_strerror(foo));
+ unsigned int keys_returned;
+ test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, MEMCACHED_SUCCESS));
test_compare(HALDENBRAND_KEY_COUNT, keys_returned);
for (uint32_t x= 0; x < HALDENBRAND_KEY_COUNT; x++)
test_compare(MEMCACHED_NO_SERVERS,
memcached_mget(memc, keys, key_length, 3));
- size_t keys_returned;
+ unsigned int keys_returned;
test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, MEMCACHED_NOTFOUND));
- test_compare(0, keys_returned);
+ test_zero(keys_returned);
for (uint32_t x= 0; x < 3; x++)
{
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, key_length, 4));
- size_t count;
+ unsigned int count;
test_compare(TEST_SUCCESS, fetch_all_results(memc, count, MEMCACHED_NOTFOUND));
- test_compare(0, count);
+ test_zero(count);
for (uint32_t x= 0; x < 4; x++)
{
memcached_mget(memc, keys, key_length, 4));
test_compare(TEST_SUCCESS, fetch_all_results(memc, count, MEMCACHED_SUCCESS));
- test_compare(4, count);
+ test_compare(4U, count);
}
delete [] insert_data;
insert_data[x]= (signed char)rand();
}
- test_compare(MEMCACHED_SUCCESS,
- memcached_flush(memc, 0));
+ test_compare(MEMCACHED_SUCCESS, memcached_flush(memc, 0));
- memcached_return_t rc;
- value= memcached_get(memc, keys[0], key_length[0],
- &value_length, &flags, &rc);
- test_false(value);
- test_compare(MEMCACHED_NOTFOUND, rc);
+ test_compare(TEST_SUCCESS, confirm_keys_dont_exist(memc, keys, test_array_length(keys)));
+ // We will now confirm that memcached_mget() returns success, but we will
+ // then check to make sure that no actual keys are returned.
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, key_length, 4));
+ memcached_return_t rc;
uint32_t count= 0;
while ((value= memcached_fetch(memc, return_key, &return_key_length,
&value_length, &flags, &rc)))
{
count++;
}
- test_compare(0, count);
+ test_zero(count);
test_compare_got(MEMCACHED_NOTFOUND, rc, memcached_strerror(NULL, rc));
- for (uint32_t x= 0; x < 4; x++)
+ for (uint32_t x= 0; x < test_array_length(keys); x++)
{
test_compare(MEMCACHED_SUCCESS,
memcached_set(memc, keys[x], key_length[x],
insert_data, VALUE_SIZE_BUG5,
(time_t)0, (uint32_t)0));
}
+ test_compare(TEST_SUCCESS, confirm_keys_exist(memc, keys, test_array_length(keys)));
for (uint32_t x= 0; x < 2; x++)
{
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, keys, key_length, 4));
- count= 3;
/* We test for purge of partial complete fetches */
for (count= 3; count; count--)
{
flags= 0;
value= memcached_fetch(memc, return_key, &return_key_length,
&value_length, &flags, &rc);
- test_compare(245, flags);
+ test_compare(uint32_t(245), flags);
test_true(value);
free(value);
delete [] insert_data;
free(return_value);
count++;
}
- test_compare(3, count);
+ test_compare(3U, count);
return TEST_SUCCESS;
}
test_false(return_value); // There are no keys to fetch, so the value should never be returned
}
test_compare(MEMCACHED_NOTFOUND, rc);
- test_compare(0, return_value_length);
- test_compare(0, return_key_length);
+ test_zero(return_value_length);
+ test_zero(return_key_length);
test_false(return_key[0]);
test_false(return_value);
{
unsigned int check_execute= execute_set(memc, global_pairs, global_count);
- test_true(check_execute == global_count);
+ test_compare(check_execute, global_count);
return TEST_SUCCESS;
}
test_skip(true, bool(libmemcached_util_version_check(memc, 1, 4, 4)));
- memcached_return_t rc;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= memcached_mget(memc, global_keys, global_keys_length, global_count),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_mget(memc, global_keys, global_keys_length, global_count));
// Go fetch the keys and test to see if all of them were returned
{
- size_t keys_returned;
+ unsigned int keys_returned;
test_compare(TEST_SUCCESS, fetch_all_results(memc, keys_returned, MEMCACHED_SUCCESS));
test_true(keys_returned > 0);
- char buffer[30];
- snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)keys_returned);
- test_compare_got(global_count, keys_returned, buffer);
+ test_compare(global_count, keys_returned);
}
return TEST_SUCCESS;
memcached_server_st *servers= memcached_server_list_append_with_weight(NULL, servername, 400, 0, &rc);
test_true(servers);
- test_compare(1, memcached_server_list_count(servers));
+ test_compare(1U, memcached_server_list_count(servers));
- for (size_t x= 2; x < 20; x++)
+ for (uint32_t x= 2; x < 20; x++)
{
char buffer[SMALL_STRING_LEN];
* Make sure that we store the item on all servers
* (master + replicas == number of servers)
*/
- memcached_return_t rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS,
- memcached_server_count(memc) - 1);
- test_compare(MEMCACHED_SUCCESS, rc);
- test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS) == memcached_server_count(memc) - 1);
+ test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, memcached_server_count(memc) - 1));
+ test_compare(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS), uint64_t(memcached_server_count(memc) - 1));
- return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED;
+ return TEST_SUCCESS;
}
memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, long_key));
/* Test for a bad prefix, but with a short key */
- test_compare_got(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? MEMCACHED_INVALID_ARGUMENTS : MEMCACHED_SUCCESS,
- rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1),
- memcached_strerror(NULL, rc));
+ test_compare(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? MEMCACHED_INVALID_ARGUMENTS : MEMCACHED_SUCCESS,
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1));
test_compare(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? MEMCACHED_SUCCESS : MEMCACHED_BAD_KEY_PROVIDED,
memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, "dog cat"));
static test_return_t poll_timeout(memcached_st *memc)
{
- size_t timeout= 100; // Not using, just checking that it sets
+ const uint64_t timeout= 100; // Not using, just checking that it sets
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, timeout);
- timeout= (size_t)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT);
- test_compare(100, timeout);
+ test_compare(timeout, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT));
return TEST_SUCCESS;
}
}
/* Count the objects */
-static memcached_return_t callback_dump_counter(const memcached_st *ptr,
- const char *key,
- size_t key_length,
- void *context)
-{
- (void)ptr; (void)key; (void)key_length;
- size_t *counter= (size_t *)context;
-
- *counter= *counter + 1;
-
- return MEMCACHED_SUCCESS;
-}
static test_return_t dump_test(memcached_st *memc)
{
- size_t counter= 0;
- memcached_dump_fn callbacks[1];
-
- callbacks[0]= &callback_dump_counter;
-
/* No support for Binary protocol yet */
test_skip(false, memc->flags.binary_protocol);
test_compare(TEST_SUCCESS, set_test3(memc));
- test_compare(MEMCACHED_SUCCESS,
- memcached_dump(memc, callbacks, (void *)&counter, 1));
+ // confirm_key_count() call dump
+ size_t counter= confirm_key_count(memc);
/* We may have more then 32 if our previous flush has not completed */
test_true(counter >= 32);
mmc[1]= memcached_pool_pop(pool, false, &rc);
test_true(mmc[1]);
- test_compare(9999, memcached_behavior_get(mmc[1], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK));
+ test_compare(UINT64_C(9999), memcached_behavior_get(mmc[1], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK));
test_compare(MEMCACHED_SUCCESS, memcached_pool_push(pool, mmc[1]));
test_compare(MEMCACHED_SUCCESS, memcached_pool_push(pool, mmc[0]));
mmc[0]= memcached_pool_pop(pool, false, &rc);
- test_compare(9999, memcached_behavior_get(mmc[0], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK));
+ test_compare(UINT64_C(9999), memcached_behavior_get(mmc[0], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK));
test_compare(MEMCACHED_SUCCESS, memcached_pool_push(pool, mmc[0]));
test_true(memcached_pool_destroy(pool) == memc);
return TEST_SUCCESS;
}
-static test_return_t one_at_a_time_run (memcached_st *memc)
+static test_return_t one_at_a_time_run (memcached_st *)
{
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
return TEST_SUCCESS;
}
-static test_return_t md5_run (memcached_st *memc)
+static test_return_t md5_run (memcached_st *)
{
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
return TEST_SUCCESS;
}
-static test_return_t crc_run (memcached_st *memc)
+static test_return_t crc_run (memcached_st *)
{
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
return TEST_SUCCESS;
}
-static test_return_t fnv1_64_run (memcached_st *memc)
+static test_return_t fnv1_64_run (memcached_st *)
{
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
return TEST_SUCCESS;
}
-static test_return_t fnv1a_64_run (memcached_st *memc)
+static test_return_t fnv1a_64_run (memcached_st *)
{
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
return TEST_SUCCESS;
}
-static test_return_t fnv1_32_run (memcached_st *memc)
+static test_return_t fnv1_32_run (memcached_st *)
{
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
return TEST_SUCCESS;
}
-static test_return_t fnv1a_32_run (memcached_st *memc)
+static test_return_t fnv1a_32_run (memcached_st *)
{
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
return TEST_SUCCESS;
}
-static test_return_t hsieh_run (memcached_st *memc)
+static test_return_t hsieh_run (memcached_st *)
{
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
return TEST_SUCCESS;
}
-static test_return_t murmur_run (memcached_st *memc)
+static test_return_t murmur_run (memcached_st *)
{
#ifdef WORDS_BIGENDIAN
(void)murmur_values;
#else
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
#endif
}
-static test_return_t jenkins_run (memcached_st *memc)
+static test_return_t jenkins_run (memcached_st *)
{
uint32_t x;
const char **ptr;
- (void)memc;
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
{
return libhashkit_crc32(string, string_length);
}
-static test_return_t memcached_get_hashkit_test (memcached_st *memc)
+static test_return_t memcached_get_hashkit_test (memcached_st *)
{
uint32_t x;
const char **ptr;
- const hashkit_st *kit;
hashkit_st new_kit;
- hashkit_return_t hash_rc;
+
+ memcached_st *memc= memcached(test_literal_param("--server=localhost:1 --server=localhost:2 --server=localhost:3 --server=localhost:4 --server=localhost5"));
uint32_t md5_hosts[]= {4U, 1U, 0U, 1U, 4U, 2U, 0U, 3U, 0U, 0U, 3U, 1U, 0U, 0U, 1U, 3U, 0U, 0U, 0U, 3U, 1U, 0U, 4U, 4U, 3U};
uint32_t crc_hosts[]= {2U, 4U, 1U, 0U, 2U, 4U, 4U, 4U, 1U, 2U, 3U, 4U, 3U, 4U, 1U, 3U, 3U, 2U, 0U, 0U, 0U, 1U, 2U, 4U, 0U};
- kit= memcached_get_hashkit(memc);
+ const hashkit_st *kit= memcached_get_hashkit(memc);
hashkit_clone(&new_kit, kit);
- hash_rc= hashkit_set_custom_function(&new_kit, hash_md5_test_function, NULL);
- test_true(hash_rc == HASHKIT_SUCCESS);
+ test_compare(HASHKIT_SUCCESS, hashkit_set_custom_function(&new_kit, hash_md5_test_function, NULL));
memcached_set_hashkit(memc, &new_kit);
uint32_t hash_val;
hash_val= hashkit_digest(kit, *ptr, strlen(*ptr));
- test_true(md5_values[x] == hash_val);
+ test_compare_got(md5_values[x], hash_val, *ptr);
}
uint32_t hash_val;
hash_val= memcached_generate_hash(memc, *ptr, strlen(*ptr));
- test_true(md5_hosts[x] == hash_val);
+ test_compare_got(md5_hosts[x], hash_val, *ptr);
}
- hash_rc= hashkit_set_custom_function(&new_kit, hash_crc_test_function, NULL);
- test_true(hash_rc == HASHKIT_SUCCESS);
+ test_compare(HASHKIT_SUCCESS, hashkit_set_custom_function(&new_kit, hash_crc_test_function, NULL));
memcached_set_hashkit(memc, &new_kit);
uint32_t hash_val;
hash_val= memcached_generate_hash(memc, *ptr, strlen(*ptr));
- test_true(crc_hosts[x] == hash_val);
+ test_compare(crc_hosts[x], hash_val);
}
+ memcached_free(memc);
+
return TEST_SUCCESS;
}
char *value= memcached_get(tl_memc_h, key, strlen(key), &len, &flags, &rc);
test_false(value);
- test_compare(0, len);
+ test_zero(len);
test_true(memcached_failed(rc));
memcached_free(tl_memc_h);
value= memcached_get(memc, key, strlen(key), &len, &flags, &rc);
test_false(value);
- test_compare(0, len);
+ test_zero(len);
test_compare(MEMCACHED_NOTFOUND, rc);
return TEST_SUCCESS;
value= memcached_get_by_key(tl_memc_h, key, strlen(key), key, strlen(key), &len, &flags, &rc);
test_false(value);
- test_compare(0, len);
+ test_zero(len);
test_true(memcached_failed(rc));
memcached_free(tl_memc_h);
value= memcached_get_by_key(memc, key, strlen(key), key, strlen(key), &len, &flags, &rc);
test_false(value);
- test_compare(0, len);
+ test_zero(len);
test_compare(MEMCACHED_NOTFOUND, rc);
return TEST_SUCCESS;
test_compare(MEMCACHED_SUCCESS,
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, 1));
- uint64_t value;
- test_compare(1, value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED));
+ test_compare(1UL, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED));
test_compare(MEMCACHED_SUCCESS, memcached_behavior_set_distribution(memc, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA));
test_compare(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA, memcached_behavior_get_distribution(memc));
-
memcached_server_st *server_pool= memcached_servers_parse("10.0.1.1:11211 600,10.0.1.2:11211 300,10.0.1.3:11211 200,10.0.1.4:11211 350,10.0.1.5:11211 1000,10.0.1.6:11211 800,10.0.1.7:11211 950,10.0.1.8:11211 100");
memcached_server_push(memc, server_pool);
/* verify that the server list was parsed okay. */
- test_compare(8, memcached_server_count(memc));
+ test_compare(8U, memcached_server_count(memc));
test_strcmp(server_pool[0].hostname, "10.0.1.1");
- test_compare(11211, server_pool[0].port);
- test_compare(600, server_pool[0].weight);
+ test_compare(in_port_t(11211), server_pool[0].port);
+ test_compare(600U, server_pool[0].weight);
test_strcmp(server_pool[2].hostname, "10.0.1.3");
- test_compare(11211, server_pool[2].port);
- test_compare(200, server_pool[2].weight);
+ test_compare(in_port_t(11211), server_pool[2].port);
+ test_compare(200U, server_pool[2].weight);
test_strcmp(server_pool[7].hostname, "10.0.1.8");
- test_compare(11211, server_pool[7].port);
- test_compare(100, server_pool[7].weight);
+ test_compare(in_port_t(11211), server_pool[7].port);
+ test_compare(100U, server_pool[7].weight);
/* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
* us test the boundary wraparound.
static test_return_t ketama_compatibility_spymemcached(memcached_st *)
{
- uint64_t value;
-
memcached_st *memc= memcached_create(NULL);
test_true(memc);
test_compare(MEMCACHED_SUCCESS,
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, 1));
- test_compare(1, value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED));
+ test_compare(UINT64_C(1), memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED));
test_compare(MEMCACHED_SUCCESS, memcached_behavior_set_distribution(memc, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY));
test_compare(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY, memcached_behavior_get_distribution(memc));
memcached_server_push(memc, server_pool);
/* verify that the server list was parsed okay. */
- test_compare(8, memcached_server_count(memc));
+ test_compare(8U, memcached_server_count(memc));
test_strcmp(server_pool[0].hostname, "10.0.1.1");
- test_compare(11211, server_pool[0].port);
- test_compare(600, server_pool[0].weight);
+ test_compare(in_port_t(11211), server_pool[0].port);
+ test_compare(600U, server_pool[0].weight);
test_strcmp(server_pool[2].hostname, "10.0.1.3");
- test_compare(11211, server_pool[2].port);
- test_compare(200, server_pool[2].weight);
+ test_compare(in_port_t(11211), server_pool[2].port);
+ test_compare(200U, server_pool[2].weight);
test_strcmp(server_pool[7].hostname, "10.0.1.8");
- test_compare(11211, server_pool[7].port);
- test_compare(100, server_pool[7].weight);
+ test_compare(in_port_t(11211), server_pool[7].port);
+ test_compare(100U, server_pool[7].weight);
/* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
* us test the boundary wraparound.
test_compare(MEMCACHED_SUCCESS,
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 2));
- const size_t max_keys= 100;
+ const unsigned int max_keys= 100;
char **keys= (char**)calloc(max_keys, sizeof(char*));
size_t *key_length= (size_t *)calloc(max_keys, sizeof(size_t));
- for (size_t x= 0; x < max_keys; ++x)
+ for (unsigned int x= 0; x < max_keys; ++x)
{
char k[251];
test_compare(MEMCACHED_SUCCESS,
memcached_mget(memc, (const char* const *)keys, key_length, max_keys));
- size_t counter= 0;
+ unsigned int counter= 0;
memcached_execute_fn callbacks[]= { &callback_counter };
- memcached_return_t rc;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_fetch_execute(memc, callbacks, (void *)&counter, 1));
/* Verify that we received all of the key/value pairs */
test_compare(counter, max_keys);
memcached_mget(memc, (const char* const *)keys, key_length, max_keys));
counter= 0;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_fetch_execute(memc, callbacks, (void *)&counter, 1));
test_compare(counter, (unsigned int)(max_keys >> 1));
/* Release allocated resources */
disconnected_server= memcached_server_get_last_disconnect(mine);
test_true_got(disconnected_server, memcached_strerror(mine, rc));
- test_compare(9, memcached_server_port(disconnected_server));
+ test_compare(in_port_t(9), memcached_server_port(disconnected_server));
test_false(strncmp(memcached_server_name(disconnected_server),"localhost",9));
memcached_quit(mine);
const char *server_string= "--server=localhost:8888 --server=localhost:8889 --server=localhost:8890 --server=localhost:8891 --server=localhost:8892";
char buffer[BUFSIZ];
- memcached_return_t rc;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= libmemcached_check_configuration(server_string, strlen(server_string), buffer, sizeof(buffer)),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ libmemcached_check_configuration(server_string, strlen(server_string), buffer, sizeof(buffer)));
memcached_st *memc= memcached(server_string, strlen(server_string));
test_true(memc);
memcached_behavior_set(local_memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 2);
uint32_t server_count= memcached_server_count(local_memc);
- test_compare(1, server_count);
+ test_compare(1U, server_count);
// Disable the server
instance= memcached_server_instance_by_position(local_memc, 0);
memcached_last_error_message(local_memc));
((memcached_server_write_instance_st)instance)->server_failure_counter= 0;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= memcached_set(local_memc, "foo", strlen("foo"), NULL, 0, (time_t)0, (uint32_t)0),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(local_memc, "foo", strlen("foo"), NULL, 0, (time_t)0, (uint32_t)0));
#if 0
- memcached_last_error_message(local_memc));
+ memcached_last_error_message(local_memc));
#endif
* Please note that this isn't bullet proof, because an error could
* occur...
*/
- test_compare(0, instance->server_failure_counter);
+ test_zero(instance->server_failure_counter);
/* restore the instance */
memc->number_of_hosts= number_of_hosts;
const char *value= memcached_get(memc, "dsf", 3, &length, &flags, &rc);
test_false(value);
- test_compare(0, length);
+ test_zero(length);
test_compare_got(MEMCACHED_TIMEOUT, rc, memcached_strerror(memc, rc));
if (rc == MEMCACHED_NOTFOUND)
{
test_false(value);
- test_compare(0, value_length);
+ test_zero(value_length);
continue;
}
test_compare(MEMCACHED_SUCCESS, rc);
test_true(value);
- test_compare(100, value_length);
+ test_compare(100UL, value_length);
free(value);
}
test_true(key_length[x]);
}
- memcached_return_t rc;
- test_compare_got(MEMCACHED_SUCCESS,
- rc= memcached_mget(clone, (const char* const *)keys, key_length, regression_bug_655423_COUNT),
- memcached_strerror(NULL, rc));
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_mget(clone, (const char* const *)keys, key_length, regression_bug_655423_COUNT));
uint32_t count= 0;
memcached_result_st *result= NULL;
while ((result= memcached_fetch_result(clone, result, NULL)))
{
- test_compare(100, memcached_result_length(result));
+ test_compare(size_t(100), memcached_result_length(result));
count++;
}
{"set", 1, (test_callback_fn*)replication_set_test },
{"get", 0, (test_callback_fn*)replication_get_test },
{"mget", 0, (test_callback_fn*)replication_mget_test },
- {"delete", 0, (test_callback_fn*)replication_delete_test },
+ {"delete", true, (test_callback_fn*)replication_delete_test },
{"rand_mget", 0, (test_callback_fn*)replication_randomize_mget_test },
{"fail", 0, (test_callback_fn*)replication_randomize_mget_fail_test },
{0, 0, (test_callback_fn*)0}
world->collections= collection;
world->_create= (test_callback_create_fn*)world_create;
- world->_destroy= (test_callback_fn*)world_destroy;
+ world->_destroy= (test_callback_destroy_fn*)world_destroy;
world->item._startup= (test_callback_fn*)world_test_startup;
- world->item._flush= (test_callback_fn*)world_flush;
world->item.set_pre((test_callback_fn*)world_pre_run);
+ world->item.set_flush((test_callback_fn*)world_flush);
world->item.set_post((test_callback_fn*)world_post_run);
world->_on_error= (test_callback_error_fn*)world_on_error;
world->collection_startup= (test_callback_fn*)world_container_startup;
world->collection_shutdown= (test_callback_fn*)world_container_shutdown;
- world->runner= &defualt_libmemcached_runner;
+ world->set_runner(&defualt_libmemcached_runner);
}
Sample test application.
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
#include <libmemcached/common.h>
world->collections= collection;
world->_create= (test_callback_create_fn*)world_create;
- world->_destroy= (test_callback_fn*)world_destroy;
+ world->_destroy= (test_callback_destroy_fn*)world_destroy;
world->item._startup= (test_callback_fn*)world_test_startup;
world->item._flush= (test_callback_fn*)world_flush;
world->collection_startup= (test_callback_fn*)world_container_startup;
world->collection_shutdown= (test_callback_fn*)world_container_shutdown;
- world->runner= &defualt_libmemcached_runner;
+ world->set_runner(&defualt_libmemcached_runner);
}
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
+
#include <libmemcached/memcached.h>
+
#include <tests/namespace.h>
test_return_t memcached_increment_namespace(memcached_st *memc)
memcached_increment(memc,
test_literal_param("number"),
1, &new_number));
- test_compare(1, new_number);
+ test_compare(1UL, new_number);
test_compare(MEMCACHED_SUCCESS,
memcached_increment(memc,
test_literal_param("number"),
1, &new_number));
- test_compare(2, new_number);
+ test_compare(2UL, new_number);
memcached_st *clone= memcached_clone(NULL, memc);
test_literal_param("number"),
0, 0, 0);
test_true(value);
- test_compare(2, strlen(value));
+ test_compare(2UL, strlen(value));
test_strcmp("10", value);
free(value);
memcached_increment(clone,
test_literal_param("number"),
1, &new_number));
- test_compare(11, new_number);
+ test_compare(11UL, new_number);
test_compare(MEMCACHED_SUCCESS,
memcached_increment(memc,
test_literal_param("number"),
1, &new_number));
- test_compare(3, new_number);
+ test_compare(3UL, new_number);
memcached_free(clone);
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
#include <vector>
#include <iostream>
for (scanner_variable_t *ptr= scanner; ptr->type != NIL; ptr++)
{
memcached_st *memc= memcached(ptr->option.c_str, ptr->option.size);
- if (test_true_opt)
+
+ // The case that it should have parsed, but it didn't. We will inspect
+ // for an error with libmemcached_check_configuration()
+ if (not memc and test_true_opt)
{
char buffer[2048];
- if (not memc)
- {
- libmemcached_check_configuration(ptr->option.c_str, ptr->option.size, buffer, sizeof(buffer));
- }
+ bool success= libmemcached_check_configuration(ptr->option.c_str, ptr->option.size, buffer, sizeof(buffer));
std::string temp(buffer);
temp+= " with option string:";
temp+= ptr->option.c_str;
+ test_true_got(success, temp.c_str());
- test_true_got(memc, temp.c_str());
+ return TEST_FAILURE; // The line above should fail since memc should be null
+ }
+ if (test_true_opt)
+ {
if (ptr->check_func)
{
test_return_t test_rc= (*ptr->check_func)(memc, ptr->result);
const char *server_string= "--server=localhost:8888/?2 --server=localhost:8889/?3 --server=localhost:8890/?4 --server=localhost:8891/?5 --server=localhost:8892/?3";
char buffer[BUFSIZ];
- memcached_return_t rc;
test_compare_got(MEMCACHED_SUCCESS,
- rc= libmemcached_check_configuration(server_string, strlen(server_string), buffer, sizeof(buffer)),
- memcached_strerror(NULL, rc));
+ libmemcached_check_configuration(server_string, strlen(server_string), buffer, sizeof(buffer)), buffer);
memcached_st *memc= memcached(server_string, strlen(server_string));
test_true(memc);
{ // Test the connect-timeout, on a bad host we should get MEMCACHED_CONNECTION_FAILURE
memcached_st *memc= memcached(memcached_literal_param("--SERVER=10.0.2.252 --CONNECT-TIMEOUT=0"));
test_true(memc);
- test_compare(0, memc->connect_timeout);
+ test_zero(memc->connect_timeout);
test_compare(MEMCACHED_DEFAULT_TIMEOUT, memc->poll_timeout);
memcached_return_t rc;
size_t value_len;
char *value= memcached_get(memc, memcached_literal_param("test"), &value_len, NULL, &rc);
test_false(value);
- test_compare(0, value_len);
+ test_zero(value_len);
test_compare_got(MEMCACHED_TIMEOUT, rc, memcached_strerror(NULL, rc));
memcached_free(memc);
memcached_st *memc= memcached(memcached_literal_param("--SERVER=10.0.2.252 --POLL-TIMEOUT=0"));
test_true(memc);
test_compare(MEMCACHED_DEFAULT_CONNECT_TIMEOUT, memc->connect_timeout);
- test_compare(0, memc->poll_timeout);
+ test_zero(memc->poll_timeout);
memcached_return_t rc;
size_t value_len;
char *value= memcached_get(memc, memcached_literal_param("test"), &value_len, NULL, &rc);
test_false(value);
- test_compare(0, value_len);
+ test_zero(value_len);
test_compare_got(MEMCACHED_TIMEOUT, rc, memcached_strerror(NULL, rc));
memcached_free(memc);
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ * 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>
+
/*
C++ interface test
*/
#include <libmemcached/memcached.hpp>
+#include <libtest/test.hpp>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <ctime>
-#include <libtest/server.h>
-
-#include <libtest/test.hpp>
-
#include <string>
#include <iostream>
using namespace std;
using namespace memcache;
+using namespace libtest;
extern "C" {
test_return_t basic_test(memcached_st *memc);
test_compare(int_inc_value, int_ret_value);
test_true(mcach.increment(key, 1, &int_ret_value));
- test_compare(2, int_ret_value);
+ test_compare(2UL, int_ret_value);
test_true(mcach.increment(key, 1, &int_ret_value));
- test_compare(3, int_ret_value);
+ test_compare(3UL, int_ret_value);
test_true(mcach.increment(key, 5, &int_ret_value));
- test_compare(8, int_ret_value);
+ test_compare(8UL, int_ret_value);
return TEST_SUCCESS;
}
test_value.clear();
+#if 0
test_false(foo.getByKey(master_key_b, key, test_value));
- test_compare(0, test_value.size());
+ test_zero(test_value.size());
+#endif
return TEST_SUCCESS;
}
{
world->collections= collection;
- world->_create= reinterpret_cast<test_callback_create_fn*>(world_create);
- world->_destroy= reinterpret_cast<test_callback_fn*>(world_destroy);
+ world->_create= world_create;
+ world->_destroy= world_destroy;
world->item._startup= reinterpret_cast<test_callback_fn*>(world_test_startup);
world->item._flush= reinterpret_cast<test_callback_fn*>(world_flush);
world->collection_startup= reinterpret_cast<test_callback_fn*>(world_container_startup);
world->collection_shutdown= reinterpret_cast<test_callback_fn*>(world_container_shutdown);
- world->runner= &defualt_libmemcached_runner;
+ world->set_runner(&defualt_libmemcached_runner);
}
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
#include <vector>
#include <iostream>
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * Gearmand client and server library.
+ * Libmemcached client and server library.
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
* All rights reserved.
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
+
#include <iostream>
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * Gearmand client and server library.
+ * Libmemcached client and server library.
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
* All rights reserved.
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * Gearmand client and server library.
+ * Libmemcached client and server library.
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
* All rights reserved.
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
#include <libmemcached/common.h>
#include <tests/replication.h>
+#include <tests/debug.h>
test_return_t replication_set_test(memcached_st *memc)
{
memcached_st *memc_clone= memcached_clone(NULL, memc);
memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0);
- rc= memcached_set(memc, "bubba", 5, "0", 1, 0, 0);
- test_true(rc == MEMCACHED_SUCCESS);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc, "bubba", 5, "0", 1, 0, 0));
/*
** We are using the quiet commands to store the replicas, so we need
uint32_t flags;
char *val= memcached_get_by_key(memc_clone, key, 1, "bubba", 5,
&len, &flags, &rc);
- test_true(rc == MEMCACHED_SUCCESS);
- test_true(val != NULL);
+ test_compare(MEMCACHED_SUCCESS, rc);
+ test_true(val);
free(val);
}
* This is to verify correct behavior in the library
*/
memcached_result_st result_obj;
- for (uint32_t host= 0; host < memc_clone->number_of_hosts; host++)
+ for (uint32_t host= 0; host < memcached_server_count(memc_clone); host++)
{
memcached_st *new_clone= memcached_clone(NULL, memc);
memcached_server_instance_st instance=
{
const char key[2]= { (char)x, 0 };
- rc= memcached_mget_by_key(memc_clone, key, 1, keys, len, 7);
- test_true(rc == MEMCACHED_SUCCESS);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_mget_by_key(memc_clone, key, 1, keys, len, 7));
memcached_result_st *results= memcached_result_create(memc_clone, &result_obj);
test_true(results);
{
++hits;
}
- test_true(hits == 7);
+ test_compare(hits, 7);
memcached_result_free(&result_obj);
}
memcached_free(memc_clone);
return TEST_SUCCESS;
}
-test_return_t replication_delete_test(memcached_st *memc)
+test_return_t replication_delete_test(memcached_st *memc_just_cloned)
{
- memcached_return_t rc;
- memcached_st *memc_clone= memcached_clone(NULL, memc);
- /* Delete the items from all of the servers except 1 */
- uint64_t repl= memcached_behavior_get(memc,
- MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS);
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, --repl);
+ memcached_flush(memc_just_cloned, 0);
+ memcached_st *memc_not_replicate= memcached_clone(NULL, memc_just_cloned);
+ memcached_st *memc_replicated= memcached_clone(NULL, memc_just_cloned);
+ const char *keys[]= { "bubba", "key1", "key2", "key3", "key4" };
- const char *keys[]= { "bubba", "key1", "key2", "key3" };
- size_t len[]= { 5, 4, 4, 4 };
+ test_true(memcached_behavior_get(memc_replicated, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+ test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc_replicated, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, false));
- for (size_t x= 0; x< 4; ++x)
+ // Make one copy
+ test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc_replicated, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 1UL));
+ test_compare(1UL, memcached_behavior_get(memc_replicated, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS));
+
+ test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc_not_replicate, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0UL));
+ test_compare(0UL, memcached_behavior_get(memc_not_replicate, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS));
+
+ for (size_t x= 0; x < test_array_length(keys); ++x)
{
- rc= memcached_delete_by_key(memc, keys[0], len[0], keys[x], len[x], 0);
- test_true(rc == MEMCACHED_SUCCESS);
+ memcached_set(memc_replicated,
+ test_string_make_from_cstr(keys[x]), // Keys
+ test_string_make_from_cstr(keys[x]), // We use the keys as values
+ 0, 0);
}
- /*
- * Don't do the following in your code. I am abusing the internal details
- * within the library, and this is not a supported interface.
- * This is to verify correct behavior in the library
- */
- uint32_t hash= memcached_generate_hash(memc, keys[0], len[0]);
- for (uint32_t x= 0; x < (repl + 1); ++x)
- {
- memcached_server_instance_st instance=
- memcached_server_instance_by_position(memc_clone, x);
+ memcached_flush_buffers(memc_replicated);
- ((memcached_server_write_instance_st)instance)->port= 0;
- if (++hash == memc_clone->number_of_hosts)
- hash= 0;
- }
+ // Confirm keys with replication read
+ test_compare(TEST_SUCCESS, confirm_keys_exist(memc_replicated, keys, test_array_length(keys), true));
+ test_compare(TEST_SUCCESS, confirm_keys_exist(memc_not_replicate, keys, test_array_length(keys), true));
- memcached_result_st result_obj;
- for (uint32_t host= 0; host < memc_clone->number_of_hosts; ++host)
+ /* Delete the items from all of the servers except 1, we use the non replicated memc so that we know we deleted the keys */
+ for (size_t x= 0; x < test_array_length(keys); ++x)
{
- for (size_t x= 'a'; x <= 'z'; ++x)
- {
- const char key[2]= { (char)x, 0 };
-
- rc= memcached_mget_by_key(memc_clone, key, 1, keys, len, 4);
- test_true(rc == MEMCACHED_SUCCESS);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_delete(memc_replicated,
+ test_string_make_from_cstr(keys[x]), // Keys
+ 0));
+ }
- memcached_result_st *results= memcached_result_create(memc_clone, &result_obj);
- test_true(results);
+ test_compare(TEST_SUCCESS, confirm_keys_dont_exist(memc_replicated, keys, test_array_length(keys)));
+ test_compare(TEST_SUCCESS, confirm_keys_dont_exist(memc_not_replicate, keys, test_array_length(keys)));
+#if 0
+ test_zero(confirm_key_count(memc_not_replicate));
+#endif
- int hits= 0;
- while ((results= memcached_fetch_result(memc_clone, &result_obj, &rc)) != NULL)
- {
- ++hits;
- }
- test_true(hits == 4);
- memcached_result_free(&result_obj);
- }
- }
- memcached_free(memc_clone);
+ memcached_free(memc_not_replicate);
+ memcached_free(memc_replicated);
return TEST_SUCCESS;
}
for (int x= int(MEMCACHED_SUCCESS); x < int(MEMCACHED_MAXIMUM_RETURN); ++x)
{
const char *key= memcached_strerror(NULL, memcached_return_t(x));
- memcached_return_t rc= memcached_set(memc,
- key, strlen(key),
- key, strlen(key), 0, 0);
- test_true(rc == MEMCACHED_SUCCESS);
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_set(memc,
+ key, strlen(key),
+ key, strlen(key), 0, 0));
}
memcached_flush_buffers(memc);
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * Gearmand client and server library.
+ * Libmemcached client and server library.
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
* All rights reserved.
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * Gearmand client and server library.
+ * Libmemcached client and server library.
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
* All rights reserved.
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
*
- * Gearmand client and server library.
+ * Libmemcached client and server library.
*
* Copyright (C) 2011 Data Differential, http://datadifferential.com/
* All rights reserved.
*
*/
-#include <libtest/common.h>
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
#include <tests/virtual_buckets.h>