Fixed distcheck issue.
[awesomized/libmemcached] / tests / mem_functions.c
index db4126f131b3ffc0a494437a5abcefd1bd2307e7..9bd9334e6cb297a1caf3772ea853c164c9d88af3 100644 (file)
@@ -52,6 +52,10 @@ static pairs_st *global_pairs;
 static const char *global_keys[GLOBAL_COUNT];
 static size_t global_keys_length[GLOBAL_COUNT];
 
+// Prototype
+static test_return_t pre_binary(memcached_st *memc);
+
+
 static test_return_t init_test(memcached_st *not_used __attribute__((unused)))
 {
   memcached_st memc;
@@ -1667,7 +1671,7 @@ static test_return_t mget_execute(memcached_st *memc)
   uint32_t number_of_hosts= memc->number_of_hosts;
   memc->number_of_hosts= 1;
 
-  size_t max_keys= binary ? 20480 : 1;
+  size_t max_keys= 20480;
 
 
   char **keys= calloc(max_keys, sizeof(char*));
@@ -1676,6 +1680,7 @@ static test_return_t mget_execute(memcached_st *memc)
   /* First add all of the items.. */
   char blob[1024] = {0};
   memcached_return_t rc;
+
   for (size_t x= 0; x < max_keys; ++x)
   {
     char k[251];
@@ -1693,21 +1698,23 @@ static test_return_t mget_execute(memcached_st *memc)
   rc= memcached_mget_execute(memc, (const char**)keys, key_length,
                              max_keys, callbacks, &counter, 1);
 
-  if (binary)
+  if (rc == MEMCACHED_SUCCESS)
   {
-    test_true(rc == MEMCACHED_SUCCESS);
-
+    test_true(binary);
     rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1);
     test_true(rc == MEMCACHED_END);
 
     /* Verify that we got all of the items */
     test_true(counter == max_keys);
   }
-  else
+  else if (rc == MEMCACHED_NOT_SUPPORTED)
   {
-    test_true(rc == MEMCACHED_NOT_SUPPORTED);
     test_true(counter == 0);
   }
+  else
+  {
+    test_fail("note: this test functions differently when in binary mode");
+  }
 
   /* Release all allocated resources */
   for (size_t x= 0; x < max_keys; ++x)
@@ -1721,6 +1728,51 @@ static test_return_t mget_execute(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+#define REGRESSION_BINARY_VS_BLOCK_COUNT  20480
+
+static test_return_t key_setup(memcached_st *memc)
+{
+  (void)memc;
+
+  if (pre_binary(memc) != TEST_SUCCESS)
+    return TEST_SKIPPED;
+
+  global_pairs= pairs_generate(REGRESSION_BINARY_VS_BLOCK_COUNT, 0);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t key_teardown(memcached_st *memc)
+{
+  (void)memc;
+  pairs_free(global_pairs);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t block_add_regression(memcached_st *memc)
+{
+  /* First add all of the items.. */
+  for (size_t x= 0; x < REGRESSION_BINARY_VS_BLOCK_COUNT; ++x)
+  {
+    memcached_return_t rc;
+    char blob[1024] = {0};
+
+    rc= memcached_add_by_key(memc, "bob", 3, global_pairs[x].key, global_pairs[x].key_length, blob, sizeof(blob), 0, 0);
+    test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+  }
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t binary_add_regression(memcached_st *memc)
+{
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
+  test_return_t rc= block_add_regression(memc);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 0);
+  return rc;
+}
+
 static test_return_t get_stats_keys(memcached_st *memc)
 {
  char **stat_list;
@@ -2945,8 +2997,6 @@ static test_return_t _user_supplied_bug21(memcached_st* memc, size_t key_count)
   return TEST_SUCCESS;
 }
 
-static test_return_t pre_binary(memcached_st *memc);
-
 static test_return_t user_supplied_bug21(memcached_st *memc)
 {
   test_return_t test_rc;
@@ -3095,6 +3145,8 @@ static test_return_t output_ketama_weighted_keys(memcached_st *trash)
     char *hostname = memc->hosts[server_idx].hostname;
     in_port_t port = memc->hosts[server_idx].port;
     fprintf(fp, "key %s is on host /%s:%u\n", key, hostname, port);
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc, host_index);
   }
   fclose(fp);
 #endif
@@ -4373,6 +4425,24 @@ static test_return_t connection_pool_test(memcached_st *memc)
   test_true(memcached_pool_destroy(pool) == memc);
   return TEST_SUCCESS;
 }
+
+static test_return_t ping_test(memcached_st *memc)
+{
+  memcached_return_t rc;
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc, 0);
+
+  // Test both the version that returns a code, and the one that does not.
+  test_true(libmemcached_ping(memcached_server_name(instance),
+                              memcached_server_port(instance), NULL));
+
+  test_true(libmemcached_ping(memcached_server_name(instance),
+                              memcached_server_port(instance), &rc));
+
+  test_true(rc == MEMCACHED_SUCCESS);
+
+  return TEST_SUCCESS;
+}
 #endif
 
 static test_return_t replication_set_test(memcached_st *memc)
@@ -4912,6 +4982,136 @@ static test_return_t memcached_get_hashkit_test (memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+/*
+  Test case adapted from John Gorman <johngorman2@gmail.com> 
+
+  We are testing the error condition when we connect to a server via memcached_get() 
+  but find that the server is not available.
+*/
+static test_return_t memcached_get_MEMCACHED_SOME_ERRORS(memcached_st *memc)
+{
+  (void)memc;
+  memcached_st *tl_memc_h;
+  memcached_server_st *servers;
+
+  const char *key= "MemcachedLives";
+  size_t len;
+  uint32_t flags;
+  memcached_return rc;
+  char *value;
+
+  // Create a handle.
+  tl_memc_h= memcached_create(NULL);
+  servers= memcached_servers_parse("localhost:9898"); // This server should not exist
+  memcached_server_push(tl_memc_h, servers);
+  memcached_server_list_free(servers);
+
+  // See if memcached is reachable.
+  value= memcached_get(tl_memc_h, key, strlen(key), &len, &flags, &rc);
+
+  if (value)
+  {
+    free(value);
+    test_true(value); // Pointer won't be zero so this is fine.
+  }
+
+  test_true(len == 0);
+  test_true(rc == MEMCACHED_SOME_ERRORS);
+
+  return TEST_SUCCESS;
+}
+
+/* 
+  We connect to a server which exists, but search for a key that does not exist.
+*/
+static test_return_t memcached_get_MEMCACHED_NOTFOUND(memcached_st *memc)
+{
+  const char *key= "MemcachedKeyNotEXIST";
+  size_t len;
+  uint32_t flags;
+  memcached_return rc;
+  char *value;
+
+  // See if memcached is reachable.
+  value= memcached_get(memc, key, strlen(key), &len, &flags, &rc);
+
+  if (value)
+  {
+    free(value);
+    test_true(value); // Pointer won't be zero so this is fine.
+  }
+
+  test_true(len == 0);
+  test_true(rc == MEMCACHED_NOTFOUND);
+
+  return TEST_SUCCESS;
+}
+
+/*
+  Test case adapted from John Gorman <johngorman2@gmail.com> 
+
+  We are testing the error condition when we connect to a server via memcached_get_by_key() 
+  but find that the server is not available.
+*/
+static test_return_t memcached_get_by_key_MEMCACHED_SOME_ERRORS(memcached_st *memc)
+{
+  (void)memc;
+  memcached_st *tl_memc_h;
+  memcached_server_st *servers;
+
+  const char *key= "MemcachedLives";
+  size_t len;
+  uint32_t flags;
+  memcached_return rc;
+  char *value;
+
+  // Create a handle.
+  tl_memc_h= memcached_create(NULL);
+  servers= memcached_servers_parse("localhost:9898"); // This server should not exist
+  memcached_server_push(tl_memc_h, servers);
+  memcached_server_list_free(servers);
+
+  // See if memcached is reachable.
+  value= memcached_get_by_key(tl_memc_h, key, strlen(key), key, strlen(key), &len, &flags, &rc);
+
+  if (value)
+  {
+    free(value);
+    test_true(value); // Pointer won't be zero so this is fine.
+  }
+
+  test_true(len == 0);
+  test_true(rc == MEMCACHED_SOME_ERRORS);
+
+  return TEST_SUCCESS;
+}
+
+/* 
+  We connect to a server which exists, but search for a key that does not exist.
+*/
+static test_return_t memcached_get_by_key_MEMCACHED_NOTFOUND(memcached_st *memc)
+{
+  const char *key= "MemcachedKeyNotEXIST";
+  size_t len;
+  uint32_t flags;
+  memcached_return rc;
+  char *value;
+
+  // See if memcached is reachable.
+  value= memcached_get_by_key(memc, key, strlen(key), key, strlen(key), &len, &flags, &rc);
+
+  if (value)
+  {
+    free(value);
+    test_true(value); // Pointer won't be zero so this is fine.
+  }
+
+  test_true(len == 0);
+  test_true(rc == MEMCACHED_NOTFOUND);
+
+  return TEST_SUCCESS;
+}
+
 
 static test_return_t ketama_compatibility_libmemcached(memcached_st *trash)
 {
@@ -5417,6 +5617,7 @@ static test_return_t test_get_last_disconnect(memcached_st *memc)
   const char *key= "marmotte";
   const char *value= "milka";
 
+  memcached_reset_last_disconnected_server(memc);
   rc= memcached_set(memc, key, strlen(key),
                     value, strlen(value),
                     (time_t)0, (uint32_t)0);
@@ -5444,7 +5645,12 @@ static test_return_t test_get_last_disconnect(memcached_st *memc)
                     (time_t)0, (uint32_t)0);
   test_true(rc != MEMCACHED_SUCCESS);
 
-  disconnected_server = memcached_server_get_last_disconnect(mine);
+  disconnected_server= memcached_server_get_last_disconnect(mine);
+  if (disconnected_server == NULL)
+  {
+    fprintf(stderr, "RC %s\n", memcached_strerror(mine, rc));
+    abort();
+  }
   test_true(disconnected_server != NULL);
   test_true(memcached_server_port(disconnected_server)== 9);
   test_true(strncmp(memcached_server_name(disconnected_server),"localhost",9) == 0);
@@ -5579,6 +5785,10 @@ static test_return_t regression_bug_490486(memcached_st *memc)
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 1);
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 3600);
 
+#ifdef __APPLE__
+  return TEST_SKIPPED; // My MAC can't handle this test
+#endif
+
   /*
    * I only want to hit _one_ server so I know the number of requests I'm
    * sending in the pipeline.
@@ -5592,6 +5802,7 @@ static test_return_t regression_bug_490486(memcached_st *memc)
   size_t *key_length=calloc(max_keys, sizeof(size_t));
 
   /* First add all of the items.. */
+  bool slept= false;
   char blob[1024]= { 0 };
   memcached_return rc;
   for (size_t x= 0; x < max_keys; ++x)
@@ -5601,38 +5812,60 @@ static test_return_t regression_bug_490486(memcached_st *memc)
     keys[x]= strdup(k);
     assert(keys[x] != NULL);
     rc= memcached_set(memc, keys[x], key_length[x], blob, sizeof(blob), 0, 0);
-    assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+#ifdef __APPLE__
+    if (rc == MEMCACHED_SERVER_MARKED_DEAD)
+    {
+      break; // We are out of business
+    }
+#endif
+    test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED || rc == MEMCACHED_TIMEOUT); // MEMCACHED_TIMEOUT <-- only observed on OSX
+
+    if (rc == MEMCACHED_TIMEOUT && slept == false)
+    {
+      x++;
+      sleep(1);// We will try to sleep
+      slept= true;
+    }
+    else if (rc == MEMCACHED_TIMEOUT && slept == true)
+    {
+      // We failed to send everything.
+      break;
+    }
   }
 
-  /* Try to get all of them with a large multiget */
-  size_t counter= 0;
-  memcached_execute_function callbacks[1]= { [0]= &callback_counter };
-  rc= memcached_mget_execute(memc, (const char**)keys, key_length,
-                             (size_t)max_keys, callbacks, &counter, 1);
+  if (rc != MEMCACHED_SERVER_MARKED_DEAD)
+  {
 
-  assert(rc == MEMCACHED_SUCCESS);
-  char* the_value= NULL;
-  char the_key[MEMCACHED_MAX_KEY];
-  size_t the_key_length;
-  size_t the_value_length;
-  uint32_t the_flags;
+    /* Try to get all of them with a large multiget */
+    size_t counter= 0;
+    memcached_execute_function callbacks[1]= { [0]= &callback_counter };
+    rc= memcached_mget_execute(memc, (const char**)keys, key_length,
+                               (size_t)max_keys, callbacks, &counter, 1);
 
-  do {
-    the_value= memcached_fetch(memc, the_key, &the_key_length, &the_value_length, &the_flags, &rc);
+    assert(rc == MEMCACHED_SUCCESS);
+    char* the_value= NULL;
+    char the_key[MEMCACHED_MAX_KEY];
+    size_t the_key_length;
+    size_t the_value_length;
+    uint32_t the_flags;
 
-    if ((the_value!= NULL) && (rc == MEMCACHED_SUCCESS))
-    {
-      ++counter;
-      free(the_value);
-    }
+    do {
+      the_value= memcached_fetch(memc, the_key, &the_key_length, &the_value_length, &the_flags, &rc);
 
-  } while ( (the_value!= NULL) && (rc == MEMCACHED_SUCCESS));
+      if ((the_value!= NULL) && (rc == MEMCACHED_SUCCESS))
+      {
+        ++counter;
+        free(the_value);
+      }
 
+    } while ( (the_value!= NULL) && (rc == MEMCACHED_SUCCESS));
 
-  assert(rc == MEMCACHED_END);
 
-  /* Verify that we got all of the items */
-  assert(counter == max_keys);
+    assert(rc == MEMCACHED_END);
+
+    /* Verify that we got all of the items */
+    assert(counter == max_keys);
+  }
 
   /* Release all allocated resources */
   for (size_t x= 0; x < max_keys; ++x)
@@ -5647,6 +5880,142 @@ static test_return_t regression_bug_490486(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+static test_return_t regression_bug_583031(memcached_st *unused)
+{
+  (void)unused;
+
+    memcached_st *memc= memcached_create(NULL);
+    assert(memc);
+    memcached_server_add(memc, "10.2.3.4", 11211);
+
+    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, 1000);
+    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 1000);
+    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, 1000);
+    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, 1000);
+    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, 1000);
+    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 3);
+
+    memcached_return_t rc;
+    size_t length;
+    uint32_t flags;
+
+    (void)memcached_get(memc, "dsf", 3, &length, &flags, &rc);
+
+    test_true(rc == MEMCACHED_TIMEOUT);
+
+    memcached_free(memc);
+
+    return TEST_SUCCESS;
+}
+
+static void memcached_die(memcached_st* mc, memcached_return error, const char* what, uint32_t it)
+{
+  fprintf(stderr, "Iteration #%u: ", it);
+
+  if(error == MEMCACHED_ERRNO)
+  {
+    fprintf(stderr, "system error %d from %s: %s\n",
+            errno, what, strerror(errno));
+  }
+  else
+  {
+    fprintf(stderr, "error %d from %s: %s\n", error, what,
+            memcached_strerror(mc, error));
+  }
+}
+
+#define TEST_CONSTANT_CREATION 200
+
+static test_return_t regression_bug_(memcached_st *memc)
+{
+  const char *remote_server;
+  (void)memc;
+
+  if (! (remote_server= getenv("LIBMEMCACHED_REMOTE_SERVER")))
+  {
+    return TEST_SKIPPED;
+  }
+
+  for (uint32_t x= 0; x < TEST_CONSTANT_CREATION; x++) 
+  {
+    memcached_st* mc= memcached_create(NULL);
+    memcached_return rc;
+
+    rc= memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
+    if (rc != MEMCACHED_SUCCESS)
+    {
+      memcached_die(mc, rc, "memcached_behavior_set", x);
+    }
+
+    rc= memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_CACHE_LOOKUPS, 1);
+    if (rc != MEMCACHED_SUCCESS)
+    {
+      memcached_die(mc, rc, "memcached_behavior_set", x);
+    }
+
+    rc= memcached_server_add(mc, remote_server, 0);
+    if (rc != MEMCACHED_SUCCESS)
+    {
+      memcached_die(mc, rc, "memcached_server_add", x);
+    }
+
+    const char *set_key= "akey";
+    const size_t set_key_len= strlen(set_key);
+    const char *set_value= "a value";
+    const size_t set_value_len= strlen(set_value);
+
+    if (rc == MEMCACHED_SUCCESS)
+    {
+      if (x > 0) 
+      {
+        size_t get_value_len;
+        char *get_value;
+        uint32_t get_value_flags;
+
+        get_value= memcached_get(mc, set_key, set_key_len, &get_value_len,
+                                 &get_value_flags, &rc);
+        if (rc != MEMCACHED_SUCCESS)
+        {
+          memcached_die(mc, rc, "memcached_get", x);
+        }
+        else
+        {
+
+          if (x != 0 &&
+              (get_value_len != set_value_len
+               || 0!=strncmp(get_value, set_value, get_value_len)))
+          {
+            fprintf(stderr, "Values don't match?\n");
+            rc= MEMCACHED_FAILURE;
+          }
+          free(get_value);
+        }
+      }
+
+      rc= memcached_set(mc,
+                        set_key, set_key_len,
+                        set_value, set_value_len,
+                        0, /* time */
+                        0  /* flags */
+                       );
+      if (rc != MEMCACHED_SUCCESS)
+      {
+        memcached_die(mc, rc, "memcached_set", x);
+      }
+    }
+
+    memcached_quit(mc);
+    memcached_free(mc);
+
+    if (rc != MEMCACHED_SUCCESS)
+    {
+      break;
+    }
+  }
+
+  return TEST_SUCCESS;
+}
+
 /*
  * Test that the sasl authentication works. We cannot use the default
  * pool of servers, because that would require that all servers we want
@@ -5739,6 +6108,7 @@ test_st tests[] ={
   {"analyzer", 1, (test_callback_fn)analyzer_test},
 #ifdef HAVE_LIBMEMCACHEDUTIL
   {"connectionpool", 1, (test_callback_fn)connection_pool_test },
+  {"ping", 1, (test_callback_fn)ping_test },
 #endif
   {"test_get_last_disconnect", 1, (test_callback_fn)test_get_last_disconnect},
   {"verbosity", 1, (test_callback_fn)test_verbosity},
@@ -5755,6 +6125,12 @@ test_st behavior_tests[] ={
   {0, 0, 0}
 };
 
+test_st regression_binary_vs_block[] ={
+  {"block add", 1, (test_callback_fn)block_add_regression},
+  {"binary add", 1, (test_callback_fn)binary_add_regression},
+  {0, 0, 0}
+};
+
 test_st async_tests[] ={
   {"add", 1, (test_callback_fn)add_wrapper },
   {0, 0, 0}
@@ -5838,12 +6214,14 @@ test_st replication_tests[]= {
 test_st regression_tests[]= {
   {"lp:434484", 1, (test_callback_fn)regression_bug_434484 },
   {"lp:434843", 1, (test_callback_fn)regression_bug_434843 },
-  {"lp:434843 buffered", 1, (test_callback_fn)regression_bug_434843_buffered },
+  {"lp:434843-buffered", 1, (test_callback_fn)regression_bug_434843_buffered },
   {"lp:421108", 1, (test_callback_fn)regression_bug_421108 },
   {"lp:442914", 1, (test_callback_fn)regression_bug_442914 },
   {"lp:447342", 1, (test_callback_fn)regression_bug_447342 },
   {"lp:463297", 1, (test_callback_fn)regression_bug_463297 },
   {"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_ },
   {0, 0, (test_callback_fn)0}
 };
 
@@ -5926,6 +6304,14 @@ test_st hash_tests[] ={
   {0, 0, (test_callback_fn)0}
 };
 
+test_st error_conditions[] ={
+  {"memcached_get_MEMCACHED_SOME_ERRORS", 0, (test_callback_fn)memcached_get_MEMCACHED_SOME_ERRORS },
+  {"memcached_get_MEMCACHED_NOTFOUND", 0, (test_callback_fn)memcached_get_MEMCACHED_NOTFOUND },
+  {"memcached_get_by_key_MEMCACHED_SOME_ERRORS", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_SOME_ERRORS },
+  {"memcached_get_by_key_MEMCACHED_NOTFOUND", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_NOTFOUND },
+  {0, 0, (test_callback_fn)0}
+};
+
 collection_st collection[] ={
 #if 0
   {"hash_sanity", 0, 0, hash_sanity},
@@ -5985,6 +6371,8 @@ collection_st collection[] ={
   {"replication_noblock", (test_callback_fn)pre_replication_noblock, 0, replication_tests},
   {"regression", 0, 0, regression_tests},
   {"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},
   {0, 0, 0, 0}
 };