From cdff9052fb343b977fc63ae65a947958eedaab91 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 3 Sep 2020 15:18:15 +0200 Subject: [PATCH] add haldenbrand (nblock & tcp_nodelay) tests [ci skip] --- testing/CMakeLists.txt | 1 + testing/lib/common.hpp | 19 ++++++ testing/memcached/exist.cpp | 1 - testing/memcached/haldenbrand.cpp | 100 ++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 testing/memcached/haldenbrand.cpp diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index ab2f30e8..5f1532f8 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(catch_main memcached/dump.cpp memcached/encoding_key.cpp memcached/exist.cpp + memcached/haldenbrand.cpp ) set_target_properties(catch_main PROPERTIES diff --git a/testing/lib/common.hpp b/testing/lib/common.hpp index 82c61567..6daa357b 100644 --- a/testing/lib/common.hpp +++ b/testing/lib/common.hpp @@ -39,6 +39,25 @@ 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))) + { + REQUIRE(MEMCACHED_SUCCESS == rc); + keys_returned += 1; + } + memcached_result_free(result); + return MEMCACHED_SUCCESS; +} + +inline memcached_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned) { + memcached_return_t rc; + fetch_all_results(memc, keys_returned, rc); + return rc; +} + class MemcachedPtr { public: memcached_st memc; diff --git a/testing/memcached/exist.cpp b/testing/memcached/exist.cpp index 29c0f253..02ec0def 100644 --- a/testing/memcached/exist.cpp +++ b/testing/memcached/exist.cpp @@ -12,7 +12,6 @@ TEST_CASE("memcached exist") { LOOPED_SECTION(tests) { auto memc = &test.memc; - auto &returns = test.returns; SECTION("initial not found") { REQUIRE_RC(MEMCACHED_NOTFOUND,memcached_exist(memc, S("frog"))); diff --git a/testing/memcached/haldenbrand.cpp b/testing/memcached/haldenbrand.cpp new file mode 100644 index 00000000..44abf1ed --- /dev/null +++ b/testing/memcached/haldenbrand.cpp @@ -0,0 +1,100 @@ +#include "../lib/common.hpp" +#include "../lib/MemcachedCluster.hpp" + +/* Test case provided by Cal Haldenbrand */ + +#define HALDENBRAND_KEY_COUNT 3000U // * 1024576 +#define HALDENBRAND_FLAG_KEY 99 // * 1024576 + +#include + +TEST_CASE("memcached haldenbrand nblock_tcp_ndelay") { + pair tests[] = { + {"network", MemcachedCluster::network()}, + }; + + for (auto &[name, test] : tests) { + REQUIRE_SUCCESS(memcached_behavior_set(&test.memc, MEMCACHED_BEHAVIOR_NO_BLOCK, true)); + REQUIRE_SUCCESS(memcached_behavior_set(&test.memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, true)); + } + + LOOPED_SECTION(tests) { + auto memc = &test.memc; + + /* We just keep looking at the same values over and over */ + srandom(10); + + /* add key */ + unsigned long long total = 0; + for (uint32_t x = 0; total < 20 * 1024576; x++) { + uint32_t size = (uint32_t) (rand() % (5 * 1024)) + 400; + char randomstuff[6 * 1024]; + memset(randomstuff, 0, 6 * 1024); + REQUIRE(size < 6 * 1024); /* Being safe here */ + + for (uint32_t j = 0; j < size; j++) { + randomstuff[j] = (signed char) ((rand() % 26) + 97); + } + + total += size; + char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH + 1]; + int key_length = snprintf(key, sizeof(key), "%u", x); + REQUIRE_SUCCESS(memcached_set(memc, key, key_length, + randomstuff, strlen(randomstuff), + time_t(0), HALDENBRAND_FLAG_KEY + )); + } + REQUIRE(total > HALDENBRAND_KEY_COUNT); + + size_t total_value_length = 0; + for (uint32_t x = 0, errors = 0; total_value_length < 24576; x++) { + uint32_t flags = 0; + size_t val_len = 0; + + char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH + 1]; + int key_length = snprintf(key, sizeof(key), "%u", x); + + memcached_return_t rc; + char *getval = memcached_get(memc, key, key_length, &val_len, &flags, &rc); + if (memcached_failed(rc)) { + if (rc == MEMCACHED_NOTFOUND) { + errors++; + } else { + REQUIRE(rc); + } + + continue; + } + REQUIRE(uint32_t(HALDENBRAND_FLAG_KEY) == flags); + REQUIRE(getval); + + total_value_length += val_len; + errors = 0; + ::free(getval); + } + + + std::vector key_lengths; + key_lengths.resize(HALDENBRAND_KEY_COUNT); + std::vector keys; + keys.resize(key_lengths.size()); + for (uint32_t x = 0; x < key_lengths.size(); x++) { + char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH + 1]; + int key_length = snprintf(key, sizeof(key), "%u", x); + REQUIRE(key_length > 0); + REQUIRE(key_length < MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH + 1); + keys[x] = strdup(key); + key_lengths[x] = key_length; + } + + REQUIRE_SUCCESS(memcached_mget(memc, &keys[0], &key_lengths[0], key_lengths.size())); + + unsigned int keys_returned; + REQUIRE(memcached_success(fetch_all_results(memc, keys_returned))); + REQUIRE(HALDENBRAND_KEY_COUNT == keys_returned); + + for (auto key : keys) { + free(key); + } + } +} -- 2.30.2