From 9c7babba79ee747f7f549912ea01fd83c37f7e0c Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Fri, 30 Oct 2020 19:42:31 +0100 Subject: [PATCH] runtests --- test/CMakeLists.txt | 2 +- test/conf.h.in | 1 + test/lib/Cluster.cpp | 74 ++++++++++++++++----------------- test/lib/Cluster.hpp | 7 ++-- test/lib/MemcachedCluster.cpp | 6 +-- test/lib/MemcachedCluster.hpp | 1 - test/lib/Server.cpp | 12 ++++-- test/lib/Server.hpp | 2 +- test/setup.cpp | 24 ++++++++++- test/tests/lib.cpp | 17 ++++---- test/tests/memcached/errors.cpp | 2 +- 11 files changed, 83 insertions(+), 65 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d364ac31..bd865f36 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,10 +9,10 @@ if(NOT MEMCACHED_BINARY) set(ENV{INVALID_CONFIGURATION} 1) endif() - check_decl(pipe2 unistd.h) check_decl(SOCK_NONBLOCK sys/socket.h) check_decl(SOCK_CLOEXEC sys/socket.h) +check_header(execution) file(GLOB_RECURSE TESTING_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) set(TESTING_ROOT ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/test/conf.h.in b/test/conf.h.in index 22193bfb..b34f03a9 100644 --- a/test/conf.h.in +++ b/test/conf.h.in @@ -19,6 +19,7 @@ #cmakedefine HAVE_PIPE2 1 #cmakedefine HAVE_SOCK_NONBLOCK 1 #cmakedefine HAVE_SOCK_CLOEXEC 1 +#cmakedefine HAVE_EXECUTION 1 #cmakedefine TESTING_ROOT "@TESTING_ROOT@" #cmakedefine MEMCACHED_BINARY getenv_else("MEMCACHED_BINARY", "@MEMCACHED_BINARY@") diff --git a/test/lib/Cluster.cpp b/test/lib/Cluster.cpp index 3ecc6e9a..1186077b 100644 --- a/test/lib/Cluster.cpp +++ b/test/lib/Cluster.cpp @@ -1,16 +1,17 @@ #include "Cluster.hpp" #include "Retry.hpp" +#include #include -Cluster::Cluster(Server serv, uint16_t cnt) +Cluster::Cluster(Server serv, size_t cnt) : count{cnt} , proto{move(serv)} { if (!count) { count = 1; } - for (int i = 0; i < count; ++i) { + for (size_t i = 0; i < count; ++i) { cluster.push_back(proto); } } @@ -28,9 +29,11 @@ bool Cluster::start() { bool started = true; for (auto &server : cluster) { - if (!startServer(server)) { + if (!server.start()) { started = false; + continue; } + pids[server.getPid()] = &server; } return started; @@ -49,46 +52,43 @@ void Cluster::stop(bool graceful) { } bool Cluster::isStopped() { - for (auto &server : cluster) { - if (server.getPid() && !server.tryWait()) { - return false; - } - } - return true; + return none_of( +#if HAVE_EXECUTION + execution::par, +#endif + cluster.begin(), cluster.end(), [](Server &s) { + return s.getPid() && !s.tryWait(); + }); } -bool Cluster::isListening() { - for (auto &server : cluster) { - Retry server_is_listening{[&] { - if (!server.isListening()) { - // zombie? - auto old_pid = server.getPid(); - if (server.tryWait()) { - cerr << "Collected zombie " << server << "(old pid=" << old_pid << ")\n"; - pids.erase(old_pid); - // restart - startServer(server); - } - if (!server.isListening()) { - return false; - } - } - return true; - }}; - if (!server_is_listening()) { - return false; - } - } - - return true; +bool Cluster::isListening() const { + return all_of( +#if HAVE_EXECUTION + execution::par, +#endif + cluster.cbegin(), cluster.cend(), [](const Server &s) { + return s.isListening(); + }); } -bool Cluster::startServer(Server &server) { - if (server.start().has_value()) { +bool Cluster::ensureListening() { + if (!start()) { + return false; + } + auto listening = all_of( +#if HAVE_EXECUTION + execution::par, +#endif + cluster.begin(), cluster.end(), [](Server &s) { + return s.ensureListening(); + }); + + pids.clear(); + for (auto &server : cluster) { pids[server.getPid()] = &server; - return true; } - return false; + + return listening; } void Cluster::wait() { diff --git a/test/lib/Cluster.hpp b/test/lib/Cluster.hpp index d2b93b9c..ab20108c 100644 --- a/test/lib/Cluster.hpp +++ b/test/lib/Cluster.hpp @@ -20,7 +20,7 @@ class Cluster { public: - explicit Cluster(Server serv, uint16_t cnt = 3); + explicit Cluster(Server serv, size_t cnt = 3); ~Cluster(); Cluster(const Cluster &c) = delete; @@ -43,7 +43,8 @@ public: bool start(); void stop(bool graceful = false); bool isStopped(); - bool isListening(); + bool isListening() const; + bool ensureListening(); void wait(); bool restart(); @@ -52,6 +53,4 @@ private: Server proto; vector cluster; map pids; - - bool startServer(Server &server); }; diff --git a/test/lib/MemcachedCluster.cpp b/test/lib/MemcachedCluster.cpp index 521ff12c..a443360b 100644 --- a/test/lib/MemcachedCluster.cpp +++ b/test/lib/MemcachedCluster.cpp @@ -6,7 +6,7 @@ const memcached_st MemcachedCluster::empty_memc{}; void MemcachedCluster::init() { REQUIRE(cluster.start()); - while (!isListening()) { + while (!cluster.ensureListening()) { cluster.restart(); } @@ -146,7 +146,3 @@ void MemcachedCluster::killOneServer() const { const auto &victim = servers[random_num(0UL, servers.size() - 1)]; ::kill(victim.getPid(), SIGKILL); } - -bool MemcachedCluster::isListening() { - return Retry{[this]() {return cluster.isListening();}}(); -} diff --git a/test/lib/MemcachedCluster.hpp b/test/lib/MemcachedCluster.hpp index b2a692cd..dcda9ddd 100644 --- a/test/lib/MemcachedCluster.hpp +++ b/test/lib/MemcachedCluster.hpp @@ -42,7 +42,6 @@ public: void enableBuffering(bool enable = true); void enableReplication(); void flush(); - bool isListening(); static MemcachedCluster mixed(); static MemcachedCluster network(); diff --git a/test/lib/Server.cpp b/test/lib/Server.cpp index 2744f3e1..dddb68d9 100644 --- a/test/lib/Server.cpp +++ b/test/lib/Server.cpp @@ -117,7 +117,7 @@ optional Server::start() { return ChildProc{pid, pipe}; } -bool Server::isListening() { +bool Server::isListening() const { MemcachedPtr memc; if (holds_alternative(socket_or_port)) { @@ -149,11 +149,16 @@ bool Server::isListening() { } bool Server::ensureListening() { + if (!start()) { + return false; + } return Retry{[this] { again: start(); if (!isListening()) { - if (tryWait()){ + auto old = pid; + if (tryWait()) { + cerr << "Collected zombie " << *this << "(old pid=" << old << ")\n"; goto again; } } @@ -186,7 +191,8 @@ bool Server::check() { bool Server::wait(int flags) { if (pid && pid == waitpid(pid, &status, flags)) { - if (drain().length() && output != "Signal handled: Terminated.\n") { + if (drain().length() && + output.rfind("Signal handled: Terminated", 0) != 0) { cerr << "Output of " << *this << ":\n"; istringstream iss{output}; diff --git a/test/lib/Server.hpp b/test/lib/Server.hpp index 9b1d4a73..26acdc44 100644 --- a/test/lib/Server.hpp +++ b/test/lib/Server.hpp @@ -69,7 +69,7 @@ public: bool signal(int signo = SIGTERM); bool check(); - bool isListening(); + bool isListening() const; bool ensureListening(); bool wait(int flags = 0); diff --git a/test/setup.cpp b/test/setup.cpp index a0325af5..9e23ce2b 100644 --- a/test/setup.cpp +++ b/test/setup.cpp @@ -31,14 +31,17 @@ static void sigchld(int, siginfo_t *si, void *) { } static inline void setup_signals() { - struct sigaction sa; + cout << " - Setting up signals ... "; + struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_NOCLDSTOP | SA_RESTART | SA_SIGINFO | SA_NODEFER; sa.sa_sigaction = sigchld; if (0 > sigaction(SIGCHLD, &sa, nullptr)) { perror("sigaction(CHLD)"); + } else { + cout << "done\n"; } } @@ -59,11 +62,15 @@ static inline void setup_signals() { static inline void setup_asan(char **argv) { const auto set = getenv("ASAN_OPTIONS"); + cout << " - Setting up ASAN ... "; + if (!set || !*set) { SET_ENV_EX(asan, "ASAN_OPTIONS", ASAN_OPTIONS, 0); + cout << "re-exec\n"; execvp(argv[0], argv); perror("exec()"); } + cout << "done\n"; } #else # define setup_asan(a) (void) a @@ -71,17 +78,30 @@ static inline void setup_asan(char **argv) { #if LIBMEMCACHED_WITH_SASL_SUPPORT static inline void setup_sasl() { + cout << " - Setting up SASL ... "; + SET_ENV_EX(sasl_pwdb, "MEMCACHED_SASL_PWDB", LIBMEMCACHED_WITH_SASL_PWDB, 0); SET_ENV_EX(sasl_conf, "SASL_CONF_PATH", LIBMEMCACHED_WITH_SASL_CONF, 0); + + cout << "done\n"; } #else # define setup_sasl() #endif -int setup(int &, char ***argv) { +static inline void setup_random() { + cout << " - Setting up RNG ... "; + random_setup(); + cout << "done\n"; +} + +int setup(int &, char ***argv) { + cout << "Starting " << **argv << " (pid=" << getpid() << ") ... \n"; + setup_signals(); + setup_random(); setup_asan(*argv); setup_sasl(); diff --git a/test/tests/lib.cpp b/test/tests/lib.cpp index 76e6516e..2c3e0bd0 100644 --- a/test/tests/lib.cpp +++ b/test/tests/lib.cpp @@ -13,11 +13,9 @@ TEST_CASE("lib/Server") { SECTION("starts and listens") { REQUIRE(server.start().has_value()); - - Retry server_is_listening{[&server] { - return server.isListening(); - }}; - REQUIRE(server_is_listening()); + REQUIRE(server.ensureListening()); + REQUIRE(server.isListening()); + REQUIRE(server.check()); SECTION("stops") { @@ -30,6 +28,7 @@ TEST_CASE("lib/Server") { SECTION("stopped") { REQUIRE_FALSE(server.check()); + REQUIRE_FALSE(server.isListening()); } } } @@ -44,11 +43,8 @@ TEST_CASE("lib/Cluster") { SECTION("starts and listens") { REQUIRE(cluster.start()); - - Retry cluster_is_listening{[&cluster] { - return cluster.isListening(); - }}; - REQUIRE(cluster_is_listening()); + REQUIRE(cluster.ensureListening()); + REQUIRE(cluster.isListening()); SECTION("stops") { @@ -58,6 +54,7 @@ TEST_CASE("lib/Cluster") { SECTION("stopped") { REQUIRE(cluster.isStopped()); + REQUIRE_FALSE(cluster.isListening()); } } } diff --git a/test/tests/memcached/errors.cpp b/test/tests/memcached/errors.cpp index db557431..377e14d1 100644 --- a/test/tests/memcached/errors.cpp +++ b/test/tests/memcached/errors.cpp @@ -41,7 +41,7 @@ TEST_CASE("memcached_errors") { REQUIRE_RC(MEMCACHED_SERVER_TEMPORARILY_DISABLED, memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); REQUIRE(test.cluster.start()); - REQUIRE(test.isListening()); + REQUIRE(test.cluster.ensureListening()); Retry recovers{[memc]{ return MEMCACHED_SUCCESS == memcached_set(memc, S("foo"), nullptr, 0, 0, 0); -- 2.30.2