X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=test%2Ftests%2Fmemcached%2Ferrors.cpp;h=75ba019aba085c1adf457a64a715b3e29aa97888;hb=2c43b7ea471c819c8e726eefccc39a469f6b9ae6;hp=16ac61a7e62eb815d453c8a51942b4dab84c039a;hpb=45ea55c5fec4ea1da25bca47b5ed2c77c0e41689;p=awesomized%2Flibmemcached diff --git a/test/tests/memcached/errors.cpp b/test/tests/memcached/errors.cpp index 16ac61a7..75ba019a 100644 --- a/test/tests/memcached/errors.cpp +++ b/test/tests/memcached/errors.cpp @@ -1,4 +1,6 @@ #include "test/lib/common.hpp" +#include "test/lib/MemcachedCluster.hpp" +#include "test/lib/Retry.hpp" TEST_CASE("memcached_errors") { SECTION("NO_SERVERS") { @@ -13,4 +15,64 @@ TEST_CASE("memcached_errors") { REQUIRE(MEMCACHED_NO_SERVERS == rc); REQUIRE(MEMCACHED_NO_SERVERS == memcached_mget(*memc, &key, &len, 1)); } + + SECTION("dead servers") { + MemcachedCluster test{Cluster{vector{Server{MEMCACHED_BINARY, {"-p", random_port_string("-p")}}}}}; + auto memc = &test.memc; + + REQUIRE_SUCCESS(memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); + memcached_quit(memc); + + test.cluster.stop(); + Retry cluster_is_stopped{[&cluster = test.cluster]{ + return cluster.isStopped(); + }}; + REQUIRE(cluster_is_stopped()); + + SECTION("TEMPORARILY_DISABLED") { + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 3)); + REQUIRE_RC(MEMCACHED_CONNECTION_FAILURE, memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); + REQUIRE_RC(MEMCACHED_SERVER_TEMPORARILY_DISABLED, memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); + } + + SECTION("recovers from TEMPORARILY_DISABLED") { + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 1)); + REQUIRE_RC(MEMCACHED_CONNECTION_FAILURE, memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); + REQUIRE_RC(MEMCACHED_SERVER_TEMPORARILY_DISABLED, memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); + + REQUIRE(test.cluster.start()); + Retry cluster_is_listening{[&cluster = test.cluster] { + return cluster.isListening(); + }}; + REQUIRE(cluster_is_listening()); + + Retry recovers{[memc]{ + return MEMCACHED_SUCCESS == memcached_set(memc, S("foo"), nullptr, 0, 0, 0); + }, 50, 100ms}; + REQUIRE(recovers()); + } + + SECTION("MARKED_DEAD") { + SECTION("immediately") { + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, true)); + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 1)); + + REQUIRE_RC(MEMCACHED_CONNECTION_FAILURE, memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); + REQUIRE_RC(MEMCACHED_SERVER_MARKED_DEAD, memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); + } + SECTION("with retry") { + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, true)); + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 2)); + REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 1)); + + REQUIRE_RC(MEMCACHED_CONNECTION_FAILURE, memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); + REQUIRE_RC(MEMCACHED_SERVER_TEMPORARILY_DISABLED, memcached_set(memc, S("foo"), nullptr, 0, 0, 0)); + + Retry server_is_marked_dead{[memc] { + return MEMCACHED_SERVER_MARKED_DEAD == memcached_set(memc, S("foo"), nullptr, 0, 0, 0); + },50, 100ms}; + REQUIRE(server_is_marked_dead()); + } + } + } }