add haldenbrand (nblock & tcp_nodelay) tests [ci skip]
authorMichael Wallner <mike@php.net>
Thu, 3 Sep 2020 13:18:15 +0000 (15:18 +0200)
committerMichael Wallner <mike@php.net>
Thu, 3 Sep 2020 13:18:15 +0000 (15:18 +0200)
testing/CMakeLists.txt
testing/lib/common.hpp
testing/memcached/exist.cpp
testing/memcached/haldenbrand.cpp [new file with mode: 0644]

index ab2f30e8adfa68880e7a86ff26d8952c3b1eea5b..5f1532f8c718bf3baf785ddc595488a9832fa3ed 100644 (file)
@@ -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
index 82c6156702853d21fb35e6e01506b645a4a7e557..6daa357beb07dbec1f2aa91478adb427d375db96 100644 (file)
@@ -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;
index 29c0f253a7db7e8dc0a28f638839dfd31fa23cbb..02ec0defb76a13807ae5b78a692f7f6ee64044f5 100644 (file)
@@ -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 (file)
index 0000000..44abf1e
--- /dev/null
@@ -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 <cstdlib>
+
+TEST_CASE("memcached haldenbrand nblock_tcp_ndelay") {
+  pair<string, MemcachedCluster> 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<size_t> key_lengths;
+    key_lengths.resize(HALDENBRAND_KEY_COUNT);
+    std::vector<char *> 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);
+    }
+  }
+}