}
SECTION("can digest default") {
- REQUIRE(2297466611U == stack.digest(LITERAL("apple")));
- REQUIRE(2297466611U == hashkit_digest(&st, LITERAL("apple")));
+ REQUIRE(2297466611U == stack.digest(S("apple")));
+ REQUIRE(2297466611U == hashkit_digest(&st, S("apple")));
}
SECTION("can set hash function") {
auto n = 0;
for (auto i : input) {
- CHECK(output[f][n] == stack.digest(LITERAL(i)));
- CHECK(output[f][n] == hashkit_digest(&st, LITERAL(i)));
- CHECK(output[f][n] == libhashkit_digest(LITERAL(i), h));
+ CHECK(output[f][n] == stack.digest(S(i)));
+ CHECK(output[f][n] == hashkit_digest(&st, S(i)));
+ CHECK(output[f][n] == libhashkit_digest(S(i), h));
++n;
}
}
Cluster(const Cluster &c) = delete;
Cluster &operator = (const Cluster &c) = delete;
- Cluster(Cluster &&c) = default;
- Cluster &operator = (Cluster &&c) = default;
+ Cluster(Cluster &&c)
+ : proto{}
+ {
+ *this = move(c);
+ };
+ Cluster &operator = (Cluster &&c) {
+ count = exchange(c.count, 0);
+ proto = exchange(c.proto, Server{});
+ cluster = exchange(c.cluster, {});
+ pids = exchange(c.pids, {});
+ return *this;
+ }
const vector<Server> &getServers() const;
#include "MemcachedCluster.hpp"
#include "Retry.hpp"
+const memcached_st MemcachedCluster::empty_memc{};
+
void MemcachedCluster::init() {
REQUIRE(cluster.start());
}
MemcachedCluster::~MemcachedCluster() {
- memcached_free(&memc);
+ if (memcmp(&memc, &empty_memc, sizeof(memc))) {
+ memcached_free(&memc);
+ }
}
void MemcachedCluster::flush() {
}
MemcachedCluster::MemcachedCluster()
-: cluster{Server{getenv_else("MEMCACHED_BINARY", "memcached"), {random_socket_or_port_arg()}}}
+: cluster{Server{
+ getenv_else("MEMCACHED_BINARY", "memcached"),
+ {random_socket_or_port_arg()}
+}}
{
init();
}
return MemcachedCluster{};
}
-MemcachedCluster MemcachedCluster::net() {
- return MemcachedCluster{Cluster{Server{getenv_else("MEMCACHED_BINARY", "memcached"), {"-p", random_socket_or_port_string}}}};
+MemcachedCluster MemcachedCluster::network() {
+ return MemcachedCluster{Cluster{Server{
+ getenv_else("MEMCACHED_BINARY", "memcached"),
+ {"-p", random_socket_or_port_string}
+ }}};
}
MemcachedCluster MemcachedCluster::socket() {
- return MemcachedCluster{Cluster{Server{getenv_else("MEMCACHED_BINARY", "memcached"), {"-s", random_socket_or_port_string}}}};
+ return MemcachedCluster{Cluster{Server{
+ getenv_else("MEMCACHED_BINARY", "memcached"),
+ {"-s", random_socket_or_port_string}
+ }}};
}
-void MemcachedCluster::enableBinary(bool enable) {
- REQUIRE(MEMCACHED_SUCCESS == memcached_behavior_set(&memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, enable));
+void MemcachedCluster::enableBinaryProto(bool enable) {
+ REQUIRE(MEMCACHED_SUCCESS == memcached_behavior_set(&memc,
+ MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, enable));
}
#include "common.hpp"
#include "Cluster.hpp"
+class ReturnMatcher : public Catch::MatcherBase<memcached_return_t> {
+public:
+ explicit ReturnMatcher(const memcached_st *memc_, memcached_return_t expected_ = MEMCACHED_SUCCESS)
+ : memc{memc_}
+ , expected{expected_}
+ {}
+
+ ReturnMatcher(const ReturnMatcher &) = default;
+ ReturnMatcher &operator = (const ReturnMatcher &) = default;
+
+ ReturnMatcher(ReturnMatcher &&rm) {
+ *this = move(rm);
+ }
+ ReturnMatcher &operator = (ReturnMatcher &&rm) {
+ memc = exchange(rm.memc, nullptr);
+ expected = rm.expected;
+ return *this;
+ }
+
+ bool match(const memcached_return_t &arg) const override {
+ return arg == expected;
+ }
+
+ ReturnMatcher success() {
+ return ReturnMatcher{memc};
+ }
+
+ ReturnMatcher operator () (memcached_return_t expected_) {
+ return ReturnMatcher{memc, expected_};
+ }
+
+protected:
+ string describe() const override {
+ return string{"is "}
+ + to_string(expected)
+ + " (" + memcached_strerror(memc, expected) + ") "
+ + "\n\tlast error: "
+ + memcached_last_error_message(memc);
+ }
+
+private:
+ const memcached_st *memc;
+ memcached_return_t expected;
+};
+
class MemcachedCluster {
public:
Cluster cluster;
- memcached_st memc;
+ memcached_st memc{empty_memc};
+ ReturnMatcher returns{&memc};
MemcachedCluster();
explicit
MemcachedCluster(Cluster &&cluster);
~MemcachedCluster();
- void enableBinary(bool enable = true);
+ MemcachedCluster(const MemcachedCluster &) = delete;
+ MemcachedCluster &operator=(const MemcachedCluster &) = delete;
+
+ MemcachedCluster(MemcachedCluster &&mc)
+ : cluster{Server{}}
+ {
+ *this = move(mc);
+ };
+ MemcachedCluster &operator=(MemcachedCluster &&mc)
+ {
+ cluster = move(mc.cluster);
+ memcached_clone(&memc, &mc.memc);
+ returns = ReturnMatcher{&memc};
+ return *this;
+ }
+
+ void enableBinaryProto(bool enable = true);
void flush();
static MemcachedCluster mixed();
- static MemcachedCluster net();
+ static MemcachedCluster network();
static MemcachedCluster socket();
private:
+ static const memcached_st empty_memc;
+
void init();
};
using argv_t = vector<variant<arg_t, arg_pair_t>>;
explicit
- Server(string &&binary_, argv_t && args_ = {});
+ Server(string &&binary_ = "false", argv_t && args_ = {});
~Server();
Server(const Server &s);
Server &operator = (const Server &s);
- Server &operator = (Server &&s) = default;
- Server(Server &&s) = default;
+ Server(Server &&s) {
+ *this = move(s);
+ };
+ Server &operator = (Server &&s) {
+ binary = exchange(s.binary, "false");
+ args = exchange(s.args, {});
+ pid = exchange(s.pid, 0);
+ status = exchange(s.status, 0);
+ signalled = exchange(s.signalled, {});
+ socket_or_port = exchange(s.socket_or_port, {});
+ return *this;
+ };
pid_t getPid() const;
#include "libmemcached/memcached.h"
-#define LITERAL(s) (s),strlen(s)
-#define LOOPED_SECTION(tests) \
- auto i_=0; \
- for (auto &&test : tests) DYNAMIC_SECTION("test" << i_++)
-
using namespace std;
-
using socket_or_port_t = variant<string, int>;
+/**
+ * Useful macros for testing
+ */
+#define S(s) (s),strlen(s)
+#define LOOPED_SECTION(tests) \
+ for (auto &[name, test] : tests) DYNAMIC_SECTION("test " << name)
+#define REQUIRE_SUCCESS(rc) REQUIRE_THAT(rc, test.returns.success())
+#define REQUIRE_RC(rc, call) REQUIRE_THAT(call, test.returns(rc))
+
+
const char *getenv_else(const char *var, const char *defval);
unsigned random_num(unsigned min, unsigned max);
unsigned random_port();
#include "../lib/MemcachedCluster.hpp"
memcached_return_t dump_cb(const memcached_st *, const char *, size_t, void *ctx) {
- size_t *c = reinterpret_cast<size_t *>(ctx);
+ auto *c = reinterpret_cast<size_t *>(ctx);
++(*c);
return MEMCACHED_SUCCESS;
}
TEST_CASE("memcached dump") {
- MemcachedCluster tests[]{
- MemcachedCluster::mixed(),
- MemcachedCluster::net(),
- MemcachedCluster::socket()
+ pair<string, MemcachedCluster> tests[]{
+ {"mixed", MemcachedCluster::mixed()},
+ {"network", MemcachedCluster::network()},
+ {"socket", MemcachedCluster::socket()}
};
LOOPED_SECTION(tests) {
int len = snprintf(key, sizeof(key) - 1, "k_%d", i);
CHECKED_IF(len) {
- auto rc = memcached_set(memc, key, len, key, len, 0, 0);
- INFO("last error: " << memcached_last_error(memc));
- REQUIRE(MEMCACHED_SUCCESS == rc);
+ REQUIRE_SUCCESS(memcached_set(memc, key, len, key, len, 0, 0));
}
}
size_t counter = 0;
memcached_dump_fn fn[] = {dump_cb};
- REQUIRE(MEMCACHED_SUCCESS == memcached_dump(memc, fn, &counter, 1));
+ REQUIRE_SUCCESS(memcached_dump(memc, fn, &counter, 1));
REQUIRE(counter == 64);
}
}
#include "../lib/common.hpp"
#include "../lib/MemcachedCluster.hpp"
-#define TEST_KEY LITERAL("test")
-#define INITIAL_VAL LITERAL("initial")
-#define REPLACED_VAL LITERAL("replaced")
+#define TEST_KEY S("test")
+#define INITIAL_VAL S("initial")
+#define REPLACED_VAL S("replaced")
static inline void check(memcached_st *enc, memcached_st *raw, const char *val, size_t len) {
memcached_return_t enc_rc, raw_rc;
}
TEST_CASE("memcached encoding_key") {
- MemcachedCluster tests[]{
- MemcachedCluster::mixed(),
- MemcachedCluster::net(),
- MemcachedCluster::socket()
+ pair<string, MemcachedCluster> tests[]{
+ {"network", MemcachedCluster::network()},
+ {"socket", MemcachedCluster::socket()}
};
LOOPED_SECTION(tests) {
SECTION("accepts encoding key") {
MemcachedPtr copy(memc);
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_set_encoding_key(memc, LITERAL(__func__)));
+ REQUIRE_SUCCESS(memcached_set_encoding_key(memc, S(__func__)));
SECTION("sets encoded value") {
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_set(memc, TEST_KEY, INITIAL_VAL, 0, 0));
+ REQUIRE_SUCCESS(memcached_set(memc, TEST_KEY, INITIAL_VAL, 0, 0));
SECTION("gets encoded value") {
check(memc, ©.memc, INITIAL_VAL);
SECTION("adds encoded value") {
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_set(memc, TEST_KEY, INITIAL_VAL, 0, 0));
- REQUIRE(MEMCACHED_NOTSTORED ==
- memcached_add(memc, TEST_KEY, REPLACED_VAL, 0, 0));
+ REQUIRE_SUCCESS(memcached_set(memc, TEST_KEY, INITIAL_VAL, 0, 0));
+ REQUIRE_RC(MEMCACHED_NOTSTORED, memcached_add(memc, TEST_KEY, REPLACED_VAL, 0, 0));
check(memc, ©.memc, INITIAL_VAL);
test.flush();
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_add(memc, TEST_KEY, REPLACED_VAL, 0, 0));
+ REQUIRE_SUCCESS(memcached_add(memc, TEST_KEY, REPLACED_VAL, 0, 0));
SECTION("gets encoded value") {
check(memc, ©.memc, REPLACED_VAL);
}
SECTION("replaces encoded value") {
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_set(memc, TEST_KEY, INITIAL_VAL, 0, 0));
+ REQUIRE_SUCCESS(memcached_set(memc, TEST_KEY, INITIAL_VAL, 0, 0));
check(memc, ©.memc, INITIAL_VAL);
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_replace(memc, TEST_KEY, REPLACED_VAL, 0, 0));
+ REQUIRE_SUCCESS(memcached_replace(memc, TEST_KEY, REPLACED_VAL, 0, 0));
SECTION("gets encoded value") {
check(memc, ©.memc, REPLACED_VAL);
}
SECTION("unsupported") {
- REQUIRE(MEMCACHED_NOT_SUPPORTED ==
- memcached_increment(memc, TEST_KEY, 0, nullptr));
- REQUIRE(MEMCACHED_NOT_SUPPORTED ==
- memcached_decrement(memc, TEST_KEY, 0, nullptr));
- REQUIRE(MEMCACHED_NOT_SUPPORTED ==
- memcached_increment_with_initial(memc, TEST_KEY, 0, 0,
- 0, nullptr));
- REQUIRE(MEMCACHED_NOT_SUPPORTED ==
- memcached_decrement_with_initial(memc, TEST_KEY, 0, 0,
- 0, nullptr));
- REQUIRE(MEMCACHED_NOT_SUPPORTED ==
- memcached_append(memc, TEST_KEY, REPLACED_VAL, 0, 0));
- REQUIRE(MEMCACHED_NOT_SUPPORTED ==
- memcached_prepend(memc, TEST_KEY, REPLACED_VAL, 0, 0));
+ REQUIRE_RC(MEMCACHED_NOT_SUPPORTED, memcached_increment(memc, TEST_KEY, 0, nullptr));
+ REQUIRE_RC(MEMCACHED_NOT_SUPPORTED, memcached_decrement(memc, TEST_KEY, 0, nullptr));
+ REQUIRE_RC(MEMCACHED_NOT_SUPPORTED, memcached_increment_with_initial(memc, TEST_KEY, 0, 0, 0, nullptr));
+ REQUIRE_RC(MEMCACHED_NOT_SUPPORTED, memcached_decrement_with_initial(memc, TEST_KEY, 0, 0, 0, nullptr));
+ REQUIRE_RC(MEMCACHED_NOT_SUPPORTED, memcached_append(memc, TEST_KEY, REPLACED_VAL, 0, 0));
+ REQUIRE_RC(MEMCACHED_NOT_SUPPORTED, memcached_prepend(memc, TEST_KEY, REPLACED_VAL, 0, 0));
}
}
}
#include "../lib/MemcachedCluster.hpp"
TEST_CASE("memcached exist") {
- MemcachedCluster tests[]{
- MemcachedCluster::mixed(),
- MemcachedCluster::net(),
- MemcachedCluster::socket()
+ pair<string, MemcachedCluster> tests[]{
+ {"bin_mixed", MemcachedCluster::mixed()},
+ {"network", MemcachedCluster::network()},
+ {"socket", MemcachedCluster::socket()}
};
- tests[0].enableBinary();
+ tests[0].second.enableBinaryProto();
LOOPED_SECTION(tests) {
auto memc = &test.memc;
+ auto &returns = test.returns;
SECTION("initial not found") {
- REQUIRE(
- MEMCACHED_NOTFOUND == memcached_exist(memc, LITERAL("frog")));
+ REQUIRE_RC(MEMCACHED_NOTFOUND,memcached_exist(memc, S("frog")));
}
SECTION("set found") {
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_set(memc, LITERAL("frog"), LITERAL("frog"), 0,
- 0));
- REQUIRE(
- MEMCACHED_SUCCESS == memcached_exist(memc, LITERAL("frog")));
-
- SECTION("deleted not found") {
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_delete(memc, LITERAL("frog"), 0));
- REQUIRE(MEMCACHED_NOTFOUND ==
- memcached_exist(memc, LITERAL("frog")));
- }
+ REQUIRE_SUCCESS(memcached_set(memc, S("frog"), S("frog"), 0, 0));
+ REQUIRE_SUCCESS(memcached_exist(memc, S("frog")));
+
+ SECTION("deleted not found") {
+ REQUIRE_SUCCESS(memcached_delete(memc, S("frog"), 0));
+ REQUIRE_RC(MEMCACHED_NOTFOUND, memcached_exist(memc, S("frog")));
+ }
}
SECTION("by key") {
SECTION("initial not found") {
- REQUIRE(MEMCACHED_NOTFOUND ==
- memcached_exist_by_key(memc, LITERAL("master"),
- LITERAL("frog")));
+ REQUIRE_RC(MEMCACHED_NOTFOUND, memcached_exist_by_key(memc, S("master"), S("frog")));
}
SECTION("set found") {
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_set_by_key(memc, LITERAL("master"),
- LITERAL("frog"), LITERAL("frog"), 0, 0));
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_exist_by_key(memc, LITERAL("master"),
- LITERAL("frog")));
+ REQUIRE_SUCCESS(memcached_set_by_key(memc, S("master"), S("frog"), S("frog"), 0, 0));
+ REQUIRE_SUCCESS(memcached_exist_by_key(memc, S("master"), S("frog")));
SECTION("deleted not found") {
- REQUIRE(MEMCACHED_SUCCESS ==
- memcached_delete_by_key(memc, LITERAL("master"),
- LITERAL("frog"), 0));
- REQUIRE(MEMCACHED_NOTFOUND ==
- memcached_exist_by_key(memc, LITERAL("master"),
- LITERAL("frog")));
+ REQUIRE_SUCCESS(memcached_delete_by_key(memc, S("master"), S("frog"), 0));
+ REQUIRE_RC(MEMCACHED_NOTFOUND, memcached_exist_by_key(memc, S("master"), S("frog")));
}
}
}
}
+
}
SECTION("no configured servers") {
MemcachedPtr memc;
- REQUIRE(MEMCACHED_NO_SERVERS == memcached_increment(*memc, LITERAL("key"), 1, nullptr));
+ REQUIRE(MEMCACHED_NO_SERVERS == memcached_increment(*memc, S("key"), 1, nullptr));
}
}