From d1c9b695e9b3fbfcc94230a242b0290b43f27006 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 8 Sep 2020 13:44:03 +0200 Subject: [PATCH] flush --- testing/CMakeLists.txt | 28 +-- testing/lib/Cluster.cpp | 45 ++-- testing/lib/Cluster.hpp | 4 +- testing/lib/MemcachedCluster.cpp | 40 ++++ testing/lib/MemcachedCluster.hpp | 57 ++--- testing/lib/Retry.cpp | 4 +- testing/lib/Retry.hpp | 2 +- testing/lib/Server.cpp | 6 +- testing/lib/Server.hpp | 16 +- testing/lib/common.cpp | 39 ---- testing/lib/common.hpp | 37 ++-- testing/lib/random.cpp | 77 +++++++ testing/lib/random.hpp | 39 ++++ testing/memcached/basic.cpp | 28 --- testing/memcached/callbacks.cpp | 19 -- testing/memcached/servers.cpp | 40 ---- testing/{ => tests}/hashkit/basic.cpp | 2 +- testing/{ => tests}/lib.cpp | 8 +- testing/tests/memcached/append.cpp | 63 ++++++ testing/tests/memcached/basic.cpp | 33 +++ testing/tests/memcached/callbacks.cpp | 118 +++++++++++ testing/tests/memcached/cas.cpp | 41 ++++ testing/{ => tests}/memcached/dump.cpp | 4 +- .../{ => tests}/memcached/encoding_key.cpp | 4 +- testing/{ => tests}/memcached/exist.cpp | 4 +- testing/{ => tests}/memcached/haldenbrand.cpp | 4 +- testing/tests/memcached/inc_dec.cpp | 120 +++++++++++ testing/tests/memcached/ketama.cpp | 200 ++++++++++++++++++ testing/tests/memcached/ketama_test_cases.h | 118 +++++++++++ .../tests/memcached/ketama_test_cases_spy.h | 116 ++++++++++ testing/tests/memcached/prepend.cpp | 28 +++ .../memcached/regression/binary_block_add.cpp | 21 ++ testing/tests/memcached/servers.cpp | 119 +++++++++++ testing/tests/memcached/simple.cpp | 63 ++++++ testing/tests/noreply.cpp | 61 ++++++ tests/output_plus.res | 5 - 36 files changed, 1361 insertions(+), 252 deletions(-) create mode 100644 testing/lib/random.cpp create mode 100644 testing/lib/random.hpp delete mode 100644 testing/memcached/basic.cpp delete mode 100644 testing/memcached/callbacks.cpp delete mode 100644 testing/memcached/servers.cpp rename testing/{ => tests}/hashkit/basic.cpp (99%) rename testing/{ => tests}/lib.cpp (87%) create mode 100644 testing/tests/memcached/append.cpp create mode 100644 testing/tests/memcached/basic.cpp create mode 100644 testing/tests/memcached/callbacks.cpp create mode 100644 testing/tests/memcached/cas.cpp rename testing/{ => tests}/memcached/dump.cpp (93%) rename testing/{ => tests}/memcached/encoding_key.cpp (97%) rename testing/{ => tests}/memcached/exist.cpp (94%) rename testing/{ => tests}/memcached/haldenbrand.cpp (97%) create mode 100644 testing/tests/memcached/inc_dec.cpp create mode 100644 testing/tests/memcached/ketama.cpp create mode 100644 testing/tests/memcached/ketama_test_cases.h create mode 100644 testing/tests/memcached/ketama_test_cases_spy.h create mode 100644 testing/tests/memcached/prepend.cpp create mode 100644 testing/tests/memcached/regression/binary_block_add.cpp create mode 100644 testing/tests/memcached/servers.cpp create mode 100644 testing/tests/memcached/simple.cpp create mode 100644 testing/tests/noreply.cpp delete mode 100644 tests/output_plus.res diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index 5f1532f8..b019302e 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -1,28 +1,6 @@ -add_executable(catch_main - main.cpp - - lib/common.cpp - - lib/Cluster.cpp - lib/Connection.cpp - lib/ForkAndExec.cpp - lib/MemcachedCluster.cpp - lib/Server.cpp - lib/Retry.cpp - - lib.cpp - hashkit/basic.cpp - memcached/basic.cpp - memcached/callbacks.cpp - memcached/servers.cpp - memcached/dump.cpp - memcached/encoding_key.cpp - memcached/exist.cpp - memcached/haldenbrand.cpp - ) - -set_target_properties(catch_main PROPERTIES - CXX_STANDARD 17) +file(GLOB_RECURSE TESTING_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) +add_executable(catch_main ${TESTING_SRC}) +set_target_properties(catch_main PROPERTIES CXX_STANDARD 17) target_link_libraries(catch_main libhashkit libmemcached) diff --git a/testing/lib/Cluster.cpp b/testing/lib/Cluster.cpp index 5d2ab42a..4c6ea52c 100644 --- a/testing/lib/Cluster.cpp +++ b/testing/lib/Cluster.cpp @@ -1,10 +1,11 @@ #include "Cluster.hpp" +#include "Retry.hpp" #include -Cluster::Cluster(Server &&serv, uint16_t cnt) +Cluster::Cluster(Server serv, uint16_t cnt) : count{cnt} -, proto{forward(serv)} +, proto{move(serv)} { if (!cnt) { count = thread::hardware_concurrency()/2 ?: 4; @@ -33,10 +34,7 @@ bool Cluster::start() { bool started = true; for (auto &server : cluster) { - auto pid = server.start(); - if (pid.has_value()) { - pids[*pid] = &server; - } else { + if (!startServer(server)) { started = false; } } @@ -62,23 +60,39 @@ bool Cluster::isStopped() { bool Cluster::isListening() { for (auto &server : cluster) { - if (!server.isListening()) { - // zombie? - auto old_pid = server.getPid(); - if (server.tryWait()) { - pids.erase(old_pid); - auto pid = server.start(); - if (pid.has_value()) { - pids[*pid] = &server; + Retry server_is_listening{[&] { + if (!server.isListening()) { + // zombie? + auto old_pid = server.getPid(); + if (server.tryWait()) { + cerr << "zombie collected (old pid=" << old_pid << "): " << server << "\n"; + pids.erase(old_pid); + // restart + startServer(server); + } + if (!server.isListening()) { + return false; } } - return server.isListening(); + return true; + }}; + if (!server_is_listening()) { + return false; } } return true; } +bool Cluster::startServer(Server &server) { + auto pid = server.start(); + if (pid.has_value()) { + pids[*pid] = &server; + return true; + } + return false; +} + void Cluster::wait() { siginfo_t inf; @@ -94,4 +108,3 @@ void Cluster::wait() { } } } - diff --git a/testing/lib/Cluster.hpp b/testing/lib/Cluster.hpp index efc5eefd..1bbc9d22 100644 --- a/testing/lib/Cluster.hpp +++ b/testing/lib/Cluster.hpp @@ -6,7 +6,7 @@ class Cluster { public: explicit - Cluster(Server &&serv, uint16_t cnt = 0); + Cluster(Server serv, uint16_t cnt = 0); ~Cluster(); @@ -40,4 +40,6 @@ private: Server proto; vector cluster; map pids; + + bool startServer(Server &server); }; diff --git a/testing/lib/MemcachedCluster.cpp b/testing/lib/MemcachedCluster.cpp index 40f2a963..9da89a96 100644 --- a/testing/lib/MemcachedCluster.cpp +++ b/testing/lib/MemcachedCluster.cpp @@ -69,3 +69,43 @@ void MemcachedCluster::enableBinaryProto(bool enable) { REQUIRE(MEMCACHED_SUCCESS == memcached_behavior_set(&memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, enable)); } + +MemcachedCluster::MemcachedCluster(MemcachedCluster &&mc) + : cluster{Server{}} +{ + *this = move(mc); +} + +MemcachedCluster &MemcachedCluster::operator=(MemcachedCluster &&mc) { + cluster = move(mc.cluster); + memcached_clone(&memc, &mc.memc); + returns = ReturnMatcher{&memc}; + return *this; +} + +ReturnMatcher &ReturnMatcher::operator=(ReturnMatcher &&rm) { + memc = exchange(rm.memc, nullptr); + expected = rm.expected; + return *this; +} + +bool ReturnMatcher::match(const memcached_return_t &arg) const { + return arg == expected; +} + +ReturnMatcher ReturnMatcher::success() { + return ReturnMatcher{memc}; +} + +ReturnMatcher ReturnMatcher::operator()(memcached_return_t expected_) { + return ReturnMatcher{memc, expected_}; +} + +string ReturnMatcher::describe() const { + return "is " + to_string(expected) + + "\n actual: " + memcached_last_error_message(memc); +} + +ReturnMatcher::ReturnMatcher(ReturnMatcher &&rm) { + *this = move(rm); +} diff --git a/testing/lib/MemcachedCluster.hpp b/testing/lib/MemcachedCluster.hpp index 685cf6fb..7286e69f 100644 --- a/testing/lib/MemcachedCluster.hpp +++ b/testing/lib/MemcachedCluster.hpp @@ -13,39 +13,26 @@ public: 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_}; - } + ReturnMatcher(ReturnMatcher &&rm); + ReturnMatcher &operator = (ReturnMatcher &&rm); + + bool match(const memcached_return_t &arg) const override; + ReturnMatcher success(); + ReturnMatcher operator () (memcached_return_t expected_); protected: - string describe() const override { - return string{"is "} - + to_string(expected) - + " (" + memcached_strerror(memc, expected) + ") " - + "\n\tlast error: " - + memcached_last_error_message(memc); - } + string describe() const override; private: const memcached_st *memc; - memcached_return_t expected; + memcached_return_t expected{MEMCACHED_SUCCESS}; +}; + +class LoneReturnMatcher { +public: + ReturnMatcher returns; + explicit LoneReturnMatcher(const memcached_st *memc) : returns{memc} + {} }; class MemcachedCluster { @@ -62,18 +49,8 @@ public: 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; - } + MemcachedCluster(MemcachedCluster &&mc);; + MemcachedCluster &operator=(MemcachedCluster &&mc); void enableBinaryProto(bool enable = true); void flush(); diff --git a/testing/lib/Retry.cpp b/testing/lib/Retry.cpp index dd6b83c1..3630089f 100644 --- a/testing/lib/Retry.cpp +++ b/testing/lib/Retry.cpp @@ -1,9 +1,9 @@ #include "Retry.hpp" -Retry::Retry(predicate &&pred_, unsigned int max_, chrono::milliseconds sleep_for_) +Retry::Retry(predicate pred_, unsigned int max_, chrono::milliseconds sleep_for_) : max{max_} , sleep_for{sleep_for_} -, pred{forward(pred_)} +, pred{move(pred_)} {} bool Retry::operator()() { diff --git a/testing/lib/Retry.hpp b/testing/lib/Retry.hpp index 26924b3a..04c0466d 100644 --- a/testing/lib/Retry.hpp +++ b/testing/lib/Retry.hpp @@ -7,7 +7,7 @@ public: using predicate = function; - explicit Retry(predicate &&pred_, unsigned max_ = 10, chrono::milliseconds sleep_for_ = 20ms); + explicit Retry(predicate pred_, unsigned max_ = 10, chrono::milliseconds sleep_for_ = 100ms); bool operator () (); diff --git a/testing/lib/Server.cpp b/testing/lib/Server.cpp index b3d0118b..e5ef5ead 100644 --- a/testing/lib/Server.cpp +++ b/testing/lib/Server.cpp @@ -5,9 +5,9 @@ #include #include -Server::Server(string &&binary_, Server::argv_t &&args_) - : binary{forward(binary_)} - , args{forward(args_)} +Server::Server(string binary_, Server::argv_t args_) + : binary{move(binary_)} + , args{move(args_)} {} Server::~Server() { diff --git a/testing/lib/Server.hpp b/testing/lib/Server.hpp index 5891dea2..bb4bfa7f 100644 --- a/testing/lib/Server.hpp +++ b/testing/lib/Server.hpp @@ -15,7 +15,7 @@ public: using argv_t = vector>; explicit - Server(string &&binary_ = "false", argv_t && args_ = {}); + Server(string binary_ = "false", argv_t args_ = {}); ~Server(); @@ -65,3 +65,17 @@ private: vector createArgv(); optional handleArg(vector &arr, const string &arg, const arg_func_t &next_arg); }; + +inline ostream &operator << (ostream &out, const socket_or_port_t sop) { + if (holds_alternative(sop)) { + out << get(sop); + } else { + out << get(sop); + } + return out; +} + +inline ostream &operator << (ostream &out, const Server &server) { + out << "Server{binary=" << server.getBinary() << ",pid=" << server.getPid() << ",conn=" << server.getSocketOrPort() << "}"; + return out; +} diff --git a/testing/lib/common.cpp b/testing/lib/common.cpp index 16f5e186..04dd79d6 100644 --- a/testing/lib/common.cpp +++ b/testing/lib/common.cpp @@ -2,45 +2,6 @@ #include "Connection.hpp" #include -#include -#include - -unsigned random_num(unsigned min, unsigned max) { - unsigned p; - getrandom(&p, sizeof(p), 0); - return (p % (max - min + 1)) + min; -} - -unsigned random_port() { - retry: - int port = random_num(2<<9, 2<<15); - Connection conn(port); - - if (!conn.open()) { - return port; - } - if (!conn.isOpen()) { - return port; - } - goto retry; -} - -string random_socket() { - return "/tmp/libmc." + to_string(random_num(1, UINT32_MAX)) + "@" + to_string(getpid()) + ".sock"; -} - -string random_socket_or_port_string(const string &what) { - if (what == "-s") { - return random_socket(); - } - - return to_string(random_port()); -} - -string random_socket_or_port_flag(const string &binary) { - (void) binary; - return random_num(0, 1) ? "-p" : "-s"; -} const char *getenv_else(const char *var, const char *defval) { auto val = getenv(var); diff --git a/testing/lib/common.hpp b/testing/lib/common.hpp index 6daa357b..c1ef43ae 100644 --- a/testing/lib/common.hpp +++ b/testing/lib/common.hpp @@ -11,7 +11,8 @@ #include #include -#include "../lib/catch.hpp" +#include "testing/lib/catch.hpp" +#include "testing/lib/random.hpp" #include "libmemcached/memcached.h" @@ -22,29 +23,25 @@ using socket_or_port_t = variant; * Useful macros for testing */ #define S(s) (s),strlen(s) +#define DECLARE_STREQUAL static auto strequal = equal_to(); #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)) - +#define REQUIRE_SUCCESS(rc) do { \ + INFO("expected: SUCCESS"); \ + REQUIRE_THAT(rc, test.returns.success()); \ + } while(0) +#define REQUIRE_RC(rc, call) do { \ + INFO("expected: " << memcached_strerror(nullptr, rc)); \ + REQUIRE_THAT(call, test.returns(rc)); \ + } while(0) const char *getenv_else(const char *var, const char *defval); -unsigned random_num(unsigned min, unsigned max); -unsigned random_port(); -string random_socket(); -string random_socket_or_port_string(const string &what); -string random_socket_or_port_flag(const string &binary); - -inline auto random_socket_or_port_arg() { - return make_pair(&random_socket_or_port_flag, &random_socket_or_port_string); -} inline memcached_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned, memcached_return_t &rc) { keys_returned = 0; memcached_result_st *result = nullptr; - while ((result = memcached_fetch_result(memc, result, &rc))) - { + while ((result = memcached_fetch_result(memc, result, &rc))) { REQUIRE(MEMCACHED_SUCCESS == rc); keys_returned += 1; } @@ -78,16 +75,18 @@ public: } }; +template class Malloced { - void *ptr; + T *ptr; public: - Malloced(void *ptr_) + Malloced(T *ptr_) : ptr{ptr_} {} ~Malloced() { - free(ptr); + if(ptr) + free(ptr); } - void *operator *() { + auto operator *() { return ptr; } }; diff --git a/testing/lib/random.cpp b/testing/lib/random.cpp new file mode 100644 index 00000000..a238c743 --- /dev/null +++ b/testing/lib/random.cpp @@ -0,0 +1,77 @@ +#include "testing/lib/random.hpp" +#include "testing/lib/Connection.hpp" + +#include +#include + +#include // getpid() + + +template +enable_if_t, T> random_num(T min, T max) { + using namespace chrono; + using rnd = mt19937; + using dst = uniform_int_distribution; + + auto time = duration_cast(system_clock::now().time_since_epoch()); + auto seed = static_cast(time.count() % numeric_limits::max()); + auto rgen = rnd{seed}; + return dst(min, max)(rgen); +} + +unsigned random_port() { + retry: + auto port = random_num(2<<9, 2<<15); + Connection conn(port); + + if (!conn.open()) { + return port; + } + if (!conn.isOpen()) { + return port; + } + goto retry; +} + +string random_socket(const string &prefix) { + return prefix + to_string(random_num(1U, UINT32_MAX)) + "@" + to_string(getpid()) + ".sock"; +} + +string random_socket_or_port_string(const string &what) { + if (what == "-s") { + return random_socket(); + } + + return to_string(random_port()); +} + +string random_socket_or_port_flag(const string &binary) { + (void) binary; + return random_num(0, 1) ? "-p" : "-s"; +} + +char random_ascii(char min, char max) { + return static_cast(random_num(min, max)); +} + +string random_ascii_string(size_t len, char min, char max) { + string s; + s.reserve(len + 1); + + for (size_t rem = 0; rem < len; ++rem) { + s += random_ascii(min, max); + } + + s[len] = '\0'; + assert(strlen(s.c_str()) == s.size()); + + return s; +} + +pair random_ascii_pair(size_t minlen, size_t maxlen) { + return { + random_ascii_string(random_num(minlen, maxlen)), + random_ascii_string(random_num(minlen, maxlen)) + }; +} + diff --git a/testing/lib/random.hpp b/testing/lib/random.hpp new file mode 100644 index 00000000..208b09f4 --- /dev/null +++ b/testing/lib/random.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include + +using namespace std; + +using kv_pair = pair; + +template +enable_if_t, T> random_num(T min, T max); + +unsigned random_port(); + +char random_ascii(char min = '!', char max = '~'); +string random_ascii_string(size_t len, char min = '!', char max = '~'); +kv_pair random_ascii_pair(size_t minlen = 1<<2, size_t maxlen = 1<<10); + +template