Merge lp:~tangent-org/libmemcached/1.0-build/ Build: jenkins-Libmemcached-170
[awesomized/libmemcached] / tests / libmemcached-1.0 / replication.cc
index be1fd7e2bfb24d5dce52a6f2776e105598168e3a..1a22a2207b18abf411bd858b3ec88321401dc102 100644 (file)
  *
  */
 
-#include <config.h>
+#include <mem_config.h>
 #include <libtest/test.hpp>
 
 using namespace libtest;
 
-#include <libmemcached/memcached.h>
-#include <libmemcached/server_instance.h>
+#include <libmemcached-1.0/memcached.h>
+
+#include "libmemcached/server_instance.h"
+
 #include <tests/replication.h>
 #include <tests/debug.h>
 
+#include "tests/libmemcached-1.0/setup_and_teardowns.h"
+
+test_return_t check_replication_sanity_TEST(memcached_st *memc)
+{
+  test_true(memc);
+  test_compare(uint64_t(1), 
+               memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+
+  /*
+   * Make sure that we store the item on all servers
+   * (master + replicas == number of servers)
+ */
+  test_compare(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS), uint64_t(memcached_server_count(memc) - 1));
+
+  return TEST_SUCCESS;
+}
+
 test_return_t replication_set_test(memcached_st *memc)
 {
-  memcached_return_t rc;
   memcached_st *memc_clone= memcached_clone(NULL, memc);
-  memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0);
+  test_true(memc_clone);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0));
 
   test_compare(MEMCACHED_SUCCESS, 
                memcached_set(memc, "bubba", 5, "0", 1, 0, 0));
@@ -80,6 +100,7 @@ test_return_t replication_set_test(memcached_st *memc)
     const char key[2]= { (char)x, 0 };
     size_t len;
     uint32_t flags;
+    memcached_return_t rc;
     char *val= memcached_get_by_key(memc_clone, key, 1, "bubba", 5,
                                     &len, &flags, &rc);
     test_compare(MEMCACHED_SUCCESS, rc);
@@ -92,9 +113,10 @@ test_return_t replication_set_test(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+#include "libmemcached/instance.hpp"
+
 test_return_t replication_get_test(memcached_st *memc)
 {
-  memcached_return_t rc;
 
   /*
    * Don't do the following in your code. I am abusing the internal details
@@ -104,20 +126,20 @@ test_return_t replication_get_test(memcached_st *memc)
   for (uint32_t host= 0; host < memcached_server_count(memc); ++host)
   {
     memcached_st *memc_clone= memcached_clone(NULL, memc);
-    memcached_server_instance_st instance=
-      memcached_server_instance_by_position(memc_clone, host);
+    org::libmemcached::Instance* instance= (org::libmemcached::Instance*)memcached_server_instance_by_position(memc_clone, host);
 
-    ((memcached_server_write_instance_st)instance)->port= 0;
+    instance->port(0);
 
     for (int x= 'a'; x <= 'z'; ++x)
     {
       const char key[2]= { (char)x, 0 };
       size_t len;
       uint32_t flags;
+      memcached_return_t rc;
       char *val= memcached_get_by_key(memc_clone, key, 1, "bubba", 5,
                                       &len, &flags, &rc);
-      test_true(rc == MEMCACHED_SUCCESS);
-      test_true(val != NULL);
+      test_compare(MEMCACHED_SUCCESS, rc);
+      test_true(val);
       free(val);
     }
 
@@ -129,17 +151,17 @@ test_return_t replication_get_test(memcached_st *memc)
 
 test_return_t replication_mget_test(memcached_st *memc)
 {
-  memcached_return_t rc;
   memcached_st *memc_clone= memcached_clone(NULL, memc);
-  memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0);
+  test_true(memc_clone);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0));
 
   const char *keys[]= { "bubba", "key1", "key2", "key3" };
   size_t len[]= { 5, 4, 4, 4 };
 
   for (size_t x= 0; x< 4; ++x)
   {
-    rc= memcached_set(memc, keys[x], len[x], "0", 1, 0, 0);
-    test_true(rc == MEMCACHED_SUCCESS);
+    test_compare(MEMCACHED_SUCCESS, memcached_set(memc, keys[x], len[x], "0", 1, 0, 0));
   }
 
   /*
@@ -166,26 +188,26 @@ test_return_t replication_mget_test(memcached_st *memc)
   for (uint32_t host= 0; host < memcached_server_count(memc_clone); host++)
   {
     memcached_st *new_clone= memcached_clone(NULL, memc);
-    memcached_server_instance_st instance=
-      memcached_server_instance_by_position(new_clone, host);
-    ((memcached_server_write_instance_st)instance)->port= 0;
+    memcached_server_instance_st instance= memcached_server_instance_by_position(new_clone, host);
+    ((memcached_server_write_instance_st)instance)->port(0);
 
     for (int x= 'a'; x <= 'z'; ++x)
     {
       char key[2]= { (char)x, 0 };
 
-      rc= memcached_mget_by_key(new_clone, key, 1, keys, len, 4);
-      test_true(rc == MEMCACHED_SUCCESS);
+      test_compare(MEMCACHED_SUCCESS,
+                   memcached_mget_by_key(new_clone, key, 1, keys, len, 4));
 
       memcached_result_st *results= memcached_result_create(new_clone, &result_obj);
       test_true(results);
 
       int hits= 0;
+      memcached_return_t rc;
       while ((results= memcached_fetch_result(new_clone, &result_obj, &rc)) != NULL)
       {
         hits++;
       }
-      test_true(hits == 4);
+      test_compare(4, hits);
       memcached_result_free(&result_obj);
     }
 
@@ -200,7 +222,6 @@ test_return_t replication_mget_test(memcached_st *memc)
 test_return_t replication_randomize_mget_test(memcached_st *memc)
 {
   memcached_result_st result_obj;
-  memcached_return_t rc;
   memcached_st *memc_clone= memcached_clone(NULL, memc);
   memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 3);
   memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, 1);
@@ -210,8 +231,8 @@ test_return_t replication_randomize_mget_test(memcached_st *memc)
 
   for (size_t x= 0; x< 7; ++x)
   {
-    rc= memcached_set(memc, keys[x], len[x], "1", 1, 0, 0);
-    test_true(rc == MEMCACHED_SUCCESS);
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_set(memc, keys[x], len[x], "1", 1, 0, 0));
   }
 
   memcached_quit(memc);
@@ -227,6 +248,7 @@ test_return_t replication_randomize_mget_test(memcached_st *memc)
     test_true(results);
 
     int hits= 0;
+    memcached_return_t rc;
     while ((results= memcached_fetch_result(memc_clone, &result_obj, &rc)) != NULL)
     {
       ++hits;
@@ -235,6 +257,7 @@ test_return_t replication_randomize_mget_test(memcached_st *memc)
     memcached_result_free(&result_obj);
   }
   memcached_free(memc_clone);
+
   return TEST_SUCCESS;
 }
 
@@ -245,7 +268,7 @@ test_return_t replication_delete_test(memcached_st *memc_just_cloned)
   memcached_st *memc_replicated= memcached_clone(NULL, memc_just_cloned);
   const char *keys[]= { "bubba", "key1", "key2", "key3", "key4" };
 
-  test_true(memcached_behavior_get(memc_replicated, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
+  test_compare(uint64_t(1), memcached_behavior_get(memc_replicated, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
   test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc_replicated, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, false));
 
   // Make one copy
@@ -272,10 +295,15 @@ test_return_t replication_delete_test(memcached_st *memc_just_cloned)
   /* Delete the items from all of the servers except 1, we use the non replicated memc so that we know we deleted the keys */
   for (size_t x= 0; x < test_array_length(keys); ++x)
   {
-    test_compare(MEMCACHED_SUCCESS,
-                 memcached_delete(memc_replicated,
-                                  test_string_make_from_cstr(keys[x]), // Keys
-                                  0));
+    memcached_return_t del_rc= memcached_delete(memc_replicated,
+                                                test_string_make_from_cstr(keys[x]), // Keys
+                                                0);
+    if (del_rc == MEMCACHED_SUCCESS or del_rc == MEMCACHED_NOTFOUND)
+    { }
+    else 
+    {
+      test_compare(MEMCACHED_SUCCESS, del_rc);
+    }
   }
 
   test_compare(TEST_SUCCESS, confirm_keys_dont_exist(memc_replicated, keys, test_array_length(keys)));
@@ -309,17 +337,17 @@ test_return_t replication_randomize_mget_fail_test(memcached_st *memc)
   // We need to now cause a failure in one server, never do this in your own
   // code.
   close(memc_clone->servers[1].fd);
-  memc_clone->servers[1].port= 1;
+  memc_clone->servers[1].port(1);
   memc_clone->servers[1].address_info_next= NULL;
 
   for (int x= int(MEMCACHED_SUCCESS); x < int(MEMCACHED_MAXIMUM_RETURN); ++x)
   {
     const char *key= memcached_strerror(NULL, memcached_return_t(x));
-    memcached_return_t rc;
     uint32_t flags;
     size_t value_length;
+    memcached_return_t rc;
     char *value= memcached_get(memc_clone, key, strlen(key), &value_length, &flags, &rc);
-    test_true(rc == MEMCACHED_SUCCESS);
+    test_compare(MEMCACHED_SUCCESS, rc);
     test_compare(strlen(key), value_length);
     test_strcmp(key, value);
     free(value);
@@ -327,3 +355,92 @@ test_return_t replication_randomize_mget_fail_test(memcached_st *memc)
   memcached_free(memc_clone);
   return TEST_SUCCESS;
 }
+
+/* Test that single miss does not cause replica reads to fail */
+test_return_t replication_miss_test(memcached_st *memc)
+{
+  test_skip(true, false);
+
+  memcached_st *memc_repl= memcached_clone(NULL, memc);
+  test_true(memc_repl);
+  memcached_st *memc_single= memcached_clone(NULL, memc);
+  test_true(memc_single);
+
+  const char *value = "my_value";
+  size_t vlen;
+  uint32_t flags;
+
+  /* this test makes sense only with 2 or more servers */
+  test_true(memcached_server_count(memc_repl) > 1);
+
+  /* Consistent hash */
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_behavior_set_distribution(memc_repl, MEMCACHED_DISTRIBUTION_CONSISTENT));
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_behavior_set_distribution(memc_single, MEMCACHED_DISTRIBUTION_CONSISTENT));
+
+  /* The first clone writes to all servers */
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_behavior_set(memc_repl, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, true));
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_behavior_set(memc_repl, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 
+                                      memcached_server_count(memc_repl)));
+
+  /* Write to servers */
+  {
+    memcached_return_t rc= memcached_set(memc_repl,
+                                         test_literal_param(__func__),
+                                         value, strlen(value), 
+                                         time_t(1200), uint32_t(0));
+    test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+  }
+
+  /* Use the second clone to remove the key from primary server.
+    This should remove the key from only one server */
+  {
+    memcached_return_t rc= memcached_delete(memc_single, 
+                                            test_literal_param(__func__),
+                                            0);
+    test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+  }
+
+  /* Remove the server where the key was deleted */
+  {
+#if 0
+    memcached_return_t rc;
+    const memcached_server_st *instance= memcached_server_by_key(memc_single,
+                                                                 test_literal_param(__func__),
+                                                                 &rc);
+    test_compare(MEMCACHED_SUCCESS, rc);
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_server_remove(instance));
+#endif
+  }
+
+  /* Test that others still have it */
+  {
+    memcached_return_t rc;
+    char *get_value= memcached_get(memc_single,
+                                   test_literal_param(__func__),
+                                   &vlen, &flags, &rc);
+    test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
+    test_true(get_value and strcmp(get_value, value) == 0);
+    free(get_value);
+  }
+
+  /* This read should still return the value as we have it on other servers */
+  {
+    memcached_return_t rc;
+    char *get_value= memcached_get(memc_repl,
+                                   test_literal_param(__func__),
+                                   &vlen, &flags, &rc);
+    test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+    test_true(get_value and strcmp(get_value, value) == 0);
+    free(get_value);
+  }
+
+  memcached_free(memc_repl);
+  memcached_free(memc_single);
+
+  return TEST_SUCCESS;
+}