From: Michael Wallner Date: Tue, 8 Sep 2020 11:44:03 +0000 (+0200) Subject: flush X-Git-Tag: 1.1.0-beta1~236^2~80 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=d1c9b695e9b3fbfcc94230a242b0290b43f27006;p=awesomized%2Flibmemcached flush --- 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/hashkit/basic.cpp b/testing/hashkit/basic.cpp deleted file mode 100644 index 8393266f..00000000 --- a/testing/hashkit/basic.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include "../lib/common.hpp" - -#include "libhashkit-1.0/hashkit.hpp" - -static const char *input[] = { - "apple", - "beat", - "carrot", - "daikon", - "eggplant", - "flower", - "green", - "hide", - "ick", - "jack", - "kick", - "lime", - "mushrooms", - "nectarine", - "orange", - "peach", - "quant", - "ripen", - "strawberry", - "tang", - "up", - "volumne", - "when", - "yellow", - "zip", -}; - -static const uint32_t output[][sizeof(input)/sizeof(*input)] = { - // one_at_a_time - { 2297466611U, 3902465932U, 469785835U, 1937308741U, - 261917617U, 3785641677U, 1439605128U, 1649152283U, - 1493851484U, 1246520657U, 2221159044U, 1973511823U, - 384136800U, 214358653U, 2379473940U, 4269788650U, - 2864377005U, 2638630052U, 427683330U, 990491717U, - 1747111141U, 792127364U, 2599214128U, 2553037199U, - 2509838425U }, - - // md5 - { 3195025439U, 2556848621U, 3724893440U, 3332385401U, - 245758794U, 2550894432U, 121710495U, 3053817768U, - 1250994555U, 1862072655U, 2631955953U, 2951528551U, - 1451250070U, 2820856945U, 2060845566U, 3646985608U, - 2138080750U, 217675895U, 2230934345U, 1234361223U, - 3968582726U, 2455685270U, 1293568479U, 199067604U, - 2042482093U }, - - // crc - { 10542U, 22009U, 14526U, 19510U, 19432U, 10199U, 20634U, - 9369U, 11511U, 10362U, 7893U, 31289U, 11313U, 9354U, - 7621U, 30628U, 15218U, 25967U, 2695U, 9380U, - 17300U, 28156U, 9192U, 20484U, 16925U }, - - // fnv1_64 - { 473199127U, 4148981457U, 3971873300U, 3257986707U, - 1722477987U, 2991193800U, 4147007314U, 3633179701U, - 1805162104U, 3503289120U, 3395702895U, 3325073042U, - 2345265314U, 3340346032U, 2722964135U, 1173398992U, - 2815549194U, 2562818319U, 224996066U, 2680194749U, - 3035305390U, 246890365U, 2395624193U, 4145193337U, - 1801941682U }, - - // fnv1a_64 - { 1488911807U, 2500855813U, 1510099634U, 1390325195U, - 3647689787U, 3241528582U, 1669328060U, 2604311949U, - 734810122U, 1516407546U, 560948863U, 1767346780U, - 561034892U, 4156330026U, 3716417003U, 3475297030U, - 1518272172U, 227211583U, 3938128828U, 126112909U, - 3043416448U, 3131561933U, 1328739897U, 2455664041U, - 2272238452U }, - - // fnv1_32 - { 67176023U, 1190179409U, 2043204404U, 3221866419U, - 2567703427U, 3787535528U, 4147287986U, 3500475733U, - 344481048U, 3865235296U, 2181839183U, 119581266U, - 510234242U, 4248244304U, 1362796839U, 103389328U, - 1449620010U, 182962511U, 3554262370U, 3206747549U, - 1551306158U, 4127558461U, 1889140833U, 2774173721U, - 1180552018U }, - - // fnv1a_32 - { 280767167U, 2421315013U, 3072375666U, 855001899U, - 459261019U, 3521085446U, 18738364U, 1625305005U, - 2162232970U, 777243802U, 3323728671U, 132336572U, - 3654473228U, 260679466U, 1169454059U, 2698319462U, - 1062177260U, 235516991U, 2218399068U, 405302637U, - 1128467232U, 3579622413U, 2138539289U, 96429129U, - 2877453236U }, - - // hsieh -#ifdef HAVE_HSIEH_HASH - { 3738850110U, 3636226060U, 3821074029U, 3489929160U, 3485772682U, 80540287U, - 1805464076U, 1895033657U, 409795758U, 979934958U, 3634096985U, 1284445480U, - 2265380744U, 707972988U, 353823508U, 1549198350U, 1327930172U, 9304163U, - 4220749037U, 2493964934U, 2777873870U, 2057831732U, 1510213931U, 2027828987U, - 3395453351U }, -#else - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, -#endif - - // murmur -#ifdef HAVE_MURMUR_HASH - // murmur - { 4142305122U, 734504955U, 3802834688U, 4076891445U, - 387802650U, 560515427U, 3274673488U, 3150339524U, - 1527441970U, 2728642900U, 3613992239U, 2938419259U, - 2321988328U, 1145154116U, 4038540960U, 2224541613U, - 264013145U, 3995512858U, 2400956718U, 2346666219U, - 926327338U, 442757446U, 1770805201U, 560483147U, - 3902279934U }, - // murmur3 - { 1120212521U, 1448785489U, 4186307405U, 2686268514U, - 444808887U, 221750260U, 3074673162U, 1946933257U, - 2826416675U, 2430719166U, 3200429559U, 297894347U, - 732888124U, 4050076964U, 3298336176U, 1336207361U, - 810553576U, 3748182674U, 3860119212U, 3439537197U, - 3044240981U, 1464271804U, 3896193724U, 2915115798U, - 1702843840U }, -#else - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, -#endif - - // jenkins - { 1442444624U, 4253821186U, 1885058256U, 2120131735U, - 3261968576U, 3515188778U, 4232909173U, 4288625128U, - 1812047395U, 3689182164U, 2502979932U, 1214050606U, - 2415988847U, 1494268927U, 1025545760U, 3920481083U, - 4153263658U, 3824871822U, 3072759809U, 798622255U, - 3065432577U, 1453328165U, 2691550971U, 3408888387U, - 2629893356U } -}; - -TEST_CASE("hashkit") { - hashkit_st st, *hp = hashkit_create(nullptr); - Hashkit stack; - Hashkit *heap = new Hashkit; - - REQUIRE(hashkit_create(&st)); - REQUIRE(hp); - - SECTION("can copy") { - Hashkit stack_copy(stack); - Hashkit *heap_copy(heap); - hashkit_st st_copy, *st_ptr; - - (void) stack_copy; - (void) heap_copy; - - st_ptr = hashkit_clone(&st_copy, &st); - REQUIRE(st_ptr == &st_copy); - REQUIRE(hashkit_compare(st_ptr, &st_copy)); - - SUCCEED("OK"); - } - - SECTION("can assign") { - Hashkit stack_copy; - - stack_copy = stack; - (void) stack_copy; - - SUCCEED("OK"); - } - - SECTION("can digest default") { - REQUIRE(2297466611U == stack.digest(S("apple"))); - REQUIRE(2297466611U == hashkit_digest(&st, S("apple"))); - } - - SECTION("can set hash function") { - for (int f = HASHKIT_HASH_DEFAULT; f < HASHKIT_HASH_MAX; ++f) { - auto h = static_cast(f); - - if (h == HASHKIT_HASH_CUSTOM) { - continue; - } - if (!libhashkit_has_algorithm(h)) { - WARN("hashkit algorithm not enabled: " << libhashkit_string_hash(h) << " (" << f << ")"); - continue; - } - - REQUIRE(HASHKIT_SUCCESS == stack.set_function(h)); - REQUIRE(HASHKIT_SUCCESS == hashkit_set_function(&st, h)); - - SECTION("can digest set hash function") { - auto n = 0; - - for (auto i : input) { - 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; - } - } - } - } - - SECTION("is comparable") { - REQUIRE(*heap == stack); - REQUIRE(hashkit_compare(&st, hp)); - - stack.set_function(HASHKIT_HASH_MD5); - hashkit_set_function(&st, HASHKIT_HASH_MD5); - - REQUIRE_FALSE(*heap == stack); - REQUIRE_FALSE(hashkit_compare(&st, hp)); - } - - delete heap; - hashkit_free(&st); - hashkit_free(hp); -} diff --git a/testing/lib.cpp b/testing/lib.cpp deleted file mode 100644 index 571b56bf..00000000 --- a/testing/lib.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "lib/common.hpp" -#include "lib/Cluster.hpp" -#include "lib/Retry.hpp" -#include "lib/Server.hpp" - -TEST_CASE("lib/Server") { - Server server{"memcached"}; - - SECTION("starts and listens") { - - REQUIRE(server.start().has_value()); - - Retry server_is_listening{[&server] { - return server.isListening(); - }}; - REQUIRE(server_is_listening()); - - SECTION("stops") { - - REQUIRE(server.stop()); - - SECTION("is waitable") { - - REQUIRE(server.wait()); - - SECTION("stopped") { - - REQUIRE_FALSE(server.check()); - } - } - } - } -} - -TEST_CASE("lib/Cluster") { - Cluster cluster{Server{"memcached", { - random_socket_or_port_arg(), - }}}; - - SECTION("starts and listens") { - - REQUIRE(cluster.start()); - - Retry cluster_is_listening{[&cluster] { - return cluster.isListening(); - }}; - REQUIRE(cluster_is_listening()); - - SECTION("stops") { - - cluster.stop(); - cluster.wait(); - - SECTION("stopped") { - - REQUIRE(cluster.isStopped()); - } - } - } -} 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