Merge in additions to the scanner.
[awesomized/libmemcached] / tests / mem_functions.c
index 48b254dbfcf921de08f853e0af9cd2d303e04961..ccd4b95b3ac000978d0edde406f6dd5070234ca8 100644 (file)
 
 #include "libmemcached/common.h"
 
-#include "server.h"
+#include <libtest/server.h>
+
 #include "clients/generator.h"
 #include "clients/execute.h"
 
 #define SMALL_STRING_LEN 1024
 
-#include "test.h"
+#include <libtest/test.h>
+#include "tests/parser.h"
+#include "tests/replication.h"
+#include "tests/print.h"
 
 
 #ifdef HAVE_LIBMEMCACHEDUTIL
@@ -188,21 +192,6 @@ static test_return_t server_sort2_test(memcached_st *ptr)
   return TEST_SUCCESS;
 }
 
-static memcached_return_t server_print_callback(const memcached_st *ptr,
-                                                const memcached_server_st *server,
-                                                void *context)
-{
-  (void)server; // Just in case we aren't printing.
-  (void)ptr;
-  (void)context;
-
-#if 0
-  fprintf(stderr, "%s(%d)", memcached_server_name(server), memcached_server_port(server));
-#endif
-
-  return MEMCACHED_SUCCESS;
-}
-
 static test_return_t memcached_server_remove_test(memcached_st *ptr)
 {
   memcached_return_t rc;
@@ -3695,9 +3684,13 @@ static test_return_t pre_nonblock_binary(memcached_st *memc)
 
 static test_return_t pre_murmur(memcached_st *memc)
 {
+#ifdef HAVE_MURMUR_HASH
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, (uint64_t)MEMCACHED_HASH_MURMUR);
-
   return TEST_SUCCESS;
+#else
+  (void) memc;
+  return TEST_SKIPPED;
+#endif
 }
 
 static test_return_t pre_jenkins(memcached_st *memc)
@@ -4569,259 +4562,6 @@ static test_return_t ping_test(memcached_st *memc)
 }
 #endif
 
-static 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);
-
-  rc= memcached_set(memc, "bubba", 5, "0", 1, 0, 0);
-  test_true(rc == MEMCACHED_SUCCESS);
-
-  /*
-  ** We are using the quiet commands to store the replicas, so we need
-  ** to ensure that all of them are processed before we can continue.
-  ** In the test we go directly from storing the object to trying to
-  ** receive the object from all of the different servers, so we
-  ** could end up in a race condition (the memcached server hasn't yet
-  ** processed the quiet command from the replication set when it process
-  ** the request from the other client (created by the clone)). As a
-  ** workaround for that we call memcached_quit to send the quit command
-  ** to the server and wait for the response ;-) If you use the test code
-  ** as an example for your own code, please note that you shouldn't need
-  ** to do this ;-)
-  */
-  memcached_quit(memc);
-
-  /*
-  ** "bubba" should now be stored on all of our servers. We don't have an
-  ** easy to use API to address each individual server, so I'll just iterate
-  ** through a bunch of "master keys" and I should most likely hit all of the
-  ** servers...
-  */
-  for (int x= 'a'; x <= 'z'; ++x)
-  {
-    char key[2]= { [0]= (char)x };
-    size_t len;
-    uint32_t flags;
-    char *val= memcached_get_by_key(memc_clone, key, 1, "bubba", 5,
-                                    &len, &flags, &rc);
-    test_true(rc == MEMCACHED_SUCCESS);
-    test_true(val != NULL);
-    free(val);
-  }
-
-  memcached_free(memc_clone);
-
-  return TEST_SUCCESS;
-}
-
-static 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
-   * within the library, and this is not a supported interface.
-   * This is to verify correct behavior in the library
-   */
-  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);
-
-    ((memcached_server_write_instance_st)instance)->port= 0;
-
-    for (int x= 'a'; x <= 'z'; ++x)
-    {
-      char key[2]= { [0]= (char)x };
-      size_t len;
-      uint32_t flags;
-      char *val= memcached_get_by_key(memc_clone, key, 1, "bubba", 5,
-                                      &len, &flags, &rc);
-      test_true(rc == MEMCACHED_SUCCESS);
-      test_true(val != NULL);
-      free(val);
-    }
-
-    memcached_free(memc_clone);
-  }
-
-  return TEST_SUCCESS;
-}
-
-static 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);
-
-  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);
-  }
-
-  /*
-  ** We are using the quiet commands to store the replicas, so we need
-  ** to ensure that all of them are processed before we can continue.
-  ** In the test we go directly from storing the object to trying to
-  ** receive the object from all of the different servers, so we
-  ** could end up in a race condition (the memcached server hasn't yet
-  ** processed the quiet command from the replication set when it process
-  ** the request from the other client (created by the clone)). As a
-  ** workaround for that we call memcached_quit to send the quit command
-  ** to the server and wait for the response ;-) If you use the test code
-  ** as an example for your own code, please note that you shouldn't need
-  ** to do this ;-)
-  */
-  memcached_quit(memc);
-
-  /*
-   * Don't do the following in your code. I am abusing the internal details
-   * within the library, and this is not a supported interface.
-   * This is to verify correct behavior in the library
-   */
-  memcached_result_st result_obj;
-  for (uint32_t host= 0; host < memc_clone->number_of_hosts; 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;
-
-    for (int x= 'a'; x <= 'z'; ++x)
-    {
-      char key[2]= { [0]= (char)x, [1]= 0 };
-
-      rc= memcached_mget_by_key(new_clone, key, 1, keys, len, 4);
-      test_true(rc == MEMCACHED_SUCCESS);
-
-      memcached_result_st *results= memcached_result_create(new_clone, &result_obj);
-      test_true(results);
-
-      int hits= 0;
-      while ((results= memcached_fetch_result(new_clone, &result_obj, &rc)) != NULL)
-      {
-        hits++;
-      }
-      test_true(hits == 4);
-      memcached_result_free(&result_obj);
-    }
-
-    memcached_free(new_clone);
-  }
-
-  memcached_free(memc_clone);
-
-  return TEST_SUCCESS;
-}
-
-static 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);
-
-  const char *keys[]= { "key1", "key2", "key3", "key4", "key5", "key6", "key7" };
-  size_t len[]= { 4, 4, 4, 4, 4, 4, 4 };
-
-  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);
-  }
-
-  memcached_quit(memc);
-
-  for (size_t x= 0; x< 7; ++x)
-  {
-    const char key[2]= { [0]= (const char)x };
-
-    rc= memcached_mget_by_key(memc_clone, key, 1, keys, len, 7);
-    test_true(rc == MEMCACHED_SUCCESS);
-
-    memcached_result_st *results= memcached_result_create(memc_clone, &result_obj);
-    test_true(results);
-
-    int hits= 0;
-    while ((results= memcached_fetch_result(memc_clone, &result_obj, &rc)) != NULL)
-    {
-      ++hits;
-    }
-    test_true(hits == 7);
-    memcached_result_free(&result_obj);
-  }
-  memcached_free(memc_clone);
-  return TEST_SUCCESS;
-}
-
-static test_return_t replication_delete_test(memcached_st *memc)
-{
-  memcached_return_t rc;
-  memcached_st *memc_clone= memcached_clone(NULL, memc);
-  /* Delete the items from all of the servers except 1 */
-  uint64_t repl= memcached_behavior_get(memc,
-                                        MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, --repl);
-
-  const char *keys[]= { "bubba", "key1", "key2", "key3" };
-  size_t len[]= { 5, 4, 4, 4 };
-
-  for (size_t x= 0; x< 4; ++x)
-  {
-    rc= memcached_delete_by_key(memc, keys[0], len[0], keys[x], len[x], 0);
-    test_true(rc == MEMCACHED_SUCCESS);
-  }
-
-  /*
-   * Don't do the following in your code. I am abusing the internal details
-   * within the library, and this is not a supported interface.
-   * This is to verify correct behavior in the library
-   */
-  uint32_t hash= memcached_generate_hash(memc, keys[0], len[0]);
-  for (uint32_t x= 0; x < (repl + 1); ++x)
-  {
-    memcached_server_instance_st instance=
-      memcached_server_instance_by_position(memc_clone, x);
-
-    ((memcached_server_write_instance_st)instance)->port= 0;
-    if (++hash == memc_clone->number_of_hosts)
-      hash= 0;
-  }
-
-  memcached_result_st result_obj;
-  for (uint32_t host= 0; host < memc_clone->number_of_hosts; ++host)
-  {
-    for (size_t x= 'a'; x <= 'z'; ++x)
-    {
-      const char key[2]= { [0]= (const char)x };
-
-      rc= memcached_mget_by_key(memc_clone, key, 1, keys, len, 4);
-      test_true(rc == MEMCACHED_SUCCESS);
-
-      memcached_result_st *results= memcached_result_create(memc_clone, &result_obj);
-      test_true(results);
-
-      int hits= 0;
-      while ((results= memcached_fetch_result(memc_clone, &result_obj, &rc)) != NULL)
-      {
-        ++hits;
-      }
-      test_true(hits == 4);
-      memcached_result_free(&result_obj);
-    }
-  }
-  memcached_free(memc_clone);
-
-  return TEST_SUCCESS;
-}
 
 #if 0
 static test_return_t hash_sanity_test (memcached_st *memc)
@@ -4859,6 +4599,19 @@ static test_return_t hsieh_avaibility_test (memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+static test_return_t murmur_avaibility_test (memcached_st *memc)
+{
+  memcached_return_t expected_rc= MEMCACHED_FAILURE;
+#ifdef HAVE_MURMUR_HASH
+  expected_rc= MEMCACHED_SUCCESS;
+#endif
+  memcached_return_t rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH,
+                                                (uint64_t)MEMCACHED_HASH_MURMUR);
+  test_true(rc == expected_rc);
+
+  return TEST_SUCCESS;
+}
+
 static test_return_t one_at_a_time_run (memcached_st *memc)
 {
   uint32_t x;
@@ -4998,6 +4751,7 @@ static test_return_t hsieh_run (memcached_st *memc)
 static test_return_t murmur_run (memcached_st *memc)
 {
 #ifdef WORDS_BIGENDIAN
+  (void)murmur_values;
   return TEST_SKIPPED;
 #else
   uint32_t x;
@@ -5920,6 +5674,53 @@ static test_return_t wrong_failure_counter_test(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+/*
+ * This tests ensures expected disconnections (for some behavior changes
+ * for instance) do not wrongly increase failure counter
+ */
+static test_return_t wrong_failure_counter_two_test(memcached_st *memc)
+{
+  memcached_return rc;
+
+  memcached_st *memc_clone;
+  memc_clone= memcached_clone(NULL, memc);
+  test_true(memc_clone);
+
+  /* Set value to force connection to the server */
+  const char *key= "marmotte";
+  const char *value= "milka";
+  char *string = NULL;
+  size_t string_length;
+  uint32_t flags;
+
+  rc= memcached_set(memc_clone, key, strlen(key),
+                    value, strlen(value),
+                    (time_t)0, (uint32_t)0);
+  test_true_got(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
+
+
+  /* put failure limit to 1 */
+  rc= memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 1);
+  assert(rc == MEMCACHED_SUCCESS);
+  /* Put a retry timeout to effectively activate failure_limit effect */
+  rc= memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 1);
+  assert(rc == MEMCACHED_SUCCESS);
+  /* change behavior that triggers memcached_quit()*/
+  rc= memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1);
+  assert(rc == MEMCACHED_SUCCESS);
+
+
+  /* Check if we still are connected */
+  string= memcached_get(memc_clone, key, strlen(key),
+                        &string_length, &flags, &rc);
+
+  test_true_got(rc == MEMCACHED_SUCCESS, memcached_strerror(NULL, rc));
+  test_true(string);
+  free(string);
+
+  return TEST_SUCCESS;
+}
+
 
 
 
@@ -6057,6 +5858,30 @@ static test_return_t regression_bug_583031(memcached_st *unused)
     return TEST_SUCCESS;
 }
 
+// Look for memory leak
+static test_return_t regression_bug_728286(memcached_st *unused)
+{
+  (void)unused;
+  memcached_server_st *servers = memcached_servers_parse("1.2.3.4:99");
+  memcached_server_free(servers);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t regression_bug_581030(memcached_st *unused)
+{
+  (void)unused;
+
+#ifndef DEBUG
+  memcached_stat_st *local_stat= memcached_stat(NULL, NULL, NULL);
+  test_false(local_stat);
+
+  memcached_stat_free(NULL, NULL);
+#endif
+
+  return TEST_SUCCESS;
+}
+
 static void memcached_die(memcached_st* mc, memcached_return error, const char* what, uint32_t it)
 {
   fprintf(stderr, "Iteration #%u: ", it);
@@ -6344,6 +6169,7 @@ test_st user_tests[] ={
   {"user_supplied_bug20", 1, (test_callback_fn)user_supplied_bug20 },
   {"user_supplied_bug21", 1, (test_callback_fn)user_supplied_bug21 },
   {"wrong_failure_counter_test", 1, (test_callback_fn)wrong_failure_counter_test},
+  {"wrong_failure_counter_two_test", 1, (test_callback_fn)wrong_failure_counter_two_test},
   {0, 0, (test_callback_fn)0}
 };
 
@@ -6373,6 +6199,8 @@ test_st regression_tests[]= {
   {"lp:490486", 1, (test_callback_fn)regression_bug_490486 },
   {"lp:583031", 1, (test_callback_fn)regression_bug_583031 },
   {"lp:?", 1, (test_callback_fn)regression_bug_ },
+  {"lp:728286", 1, (test_callback_fn)regression_bug_728286 },
+  {"lp:581030", 1, (test_callback_fn)regression_bug_581030 },
   {0, 0, (test_callback_fn)0}
 };
 
@@ -6427,6 +6255,11 @@ test_st hsieh_availability[] ={
   {0, 0, (test_callback_fn)0}
 };
 
+test_st murmur_availability[] ={
+  {"murmur_avaibility_test", 0, (test_callback_fn)murmur_avaibility_test},
+  {0, 0, (test_callback_fn)0}
+};
+
 #if 0
 test_st hash_sanity[] ={
   {"hash sanity", 0, (test_callback_fn)hash_sanity_test},
@@ -6463,11 +6296,22 @@ test_st error_conditions[] ={
   {0, 0, (test_callback_fn)0}
 };
 
+
+test_st parser_tests[] ={
+  {"behavior", 0, (test_callback_fn)behavior_parser_test },
+  {"distribtions", 0, (test_callback_fn)parser_distribution_test },
+  {"hash", 0, (test_callback_fn)parser_hash_test },
+  {"server", 0, (test_callback_fn)server_test },
+  {"servers", 0, (test_callback_fn)servers_test },
+  {0, 0, (test_callback_fn)0}
+};
+
 collection_st collection[] ={
 #if 0
   {"hash_sanity", 0, 0, hash_sanity},
 #endif
   {"hsieh_availability", 0, 0, hsieh_availability},
+  {"murmur_availability", 0, 0, murmur_availability},
   {"block", 0, 0, tests},
   {"binary", (test_callback_fn)pre_binary, 0, tests},
   {"nonblock", (test_callback_fn)pre_nonblock, 0, tests},
@@ -6524,6 +6368,7 @@ collection_st collection[] ={
   {"behaviors", 0, 0, behavior_tests},
   {"regression_binary_vs_block", (test_callback_fn)key_setup, (test_callback_fn)key_teardown, regression_binary_vs_block},
   {"error_conditions", 0, 0, error_conditions},
+  {"parser", 0, 0, parser_tests},
   {0, 0, 0, 0}
 };