Import parser/etc
authorBrian Aker <brian@tangent.org>
Mon, 21 Mar 2011 07:07:48 +0000 (00:07 -0700)
committerBrian Aker <brian@tangent.org>
Mon, 21 Mar 2011 07:07:48 +0000 (00:07 -0700)
26 files changed:
libmemcached/array.c [new file with mode: 0644]
libmemcached/array.h [new file with mode: 0644]
libmemcached/auto.c
libmemcached/auto.h
libmemcached/behavior.c
libmemcached/common.h
libmemcached/error.c [new file with mode: 0644]
libmemcached/error.h [new file with mode: 0644]
libmemcached/include.am
libmemcached/is.h [new file with mode: 0644]
libmemcached/memcached.c
libmemcached/memcached.h
libmemcached/options.cc
libmemcached/options/parser.yy
libmemcached/options/scanner.l
libmemcached/string.h
libmemcached/types.h
libtest/server.c
tests/basic.cc [new file with mode: 0644]
tests/basic.h [new file with mode: 0644]
tests/error_conditions.cc [new file with mode: 0644]
tests/error_conditions.h [new file with mode: 0644]
tests/include.am
tests/mem_functions.c
tests/parser.cc
tests/parser.h

diff --git a/libmemcached/array.c b/libmemcached/array.c
new file mode 100644 (file)
index 0000000..f8facba
--- /dev/null
@@ -0,0 +1,64 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+
+#include "libmemcached/common.h"
+
+struct memcached_array_st
+{
+  size_t size;
+  char c_str[];
+};
+
+memcached_array_st *memcached_strcpy(const char *str, size_t str_length)
+{
+  memcached_array_st *array= (struct memcached_array_st *)malloc(sizeof(struct memcached_array_st) +str_length +1);
+
+  array->size= str_length;
+  memcpy(array->c_str, str, str_length);
+  array->c_str[str_length]= 0;
+
+  return array;
+}
+
+void memcached_array_free(memcached_array_st *array)
+{
+  WATCHPOINT_ASSERT(array);
+  if (array)
+    free(array);
+}
diff --git a/libmemcached/array.h b/libmemcached/array.h
new file mode 100644 (file)
index 0000000..78846b6
--- /dev/null
@@ -0,0 +1,53 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_LOCAL
+memcached_array_st *memcached_strcpy(const char *str, size_t str_length);
+
+LIBMEMCACHED_LOCAL
+void memcached_array_free(memcached_array_st *array);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
index a221144f06a75851e39d2779a1c4cad1ddf09d4e..c2033b37ceb96dad9302e850ee39a90da4fed1d3 100644 (file)
@@ -24,8 +24,8 @@ static memcached_return_t text_incr_decr(memcached_st *ptr,
   memcached_server_write_instance_st instance;
   bool no_reply= ptr->flags.no_reply;
 
-  unlikely (memcached_server_count(ptr) == 0)
-    return MEMCACHED_NO_SERVERS;
+  if (memcached_server_count(ptr) == 0)
+    return memcached_set_error(ptr, MEMCACHED_NO_SERVERS, NULL);
 
   if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
     return MEMCACHED_BAD_KEY_PROVIDED;
@@ -91,8 +91,8 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
   memcached_server_write_instance_st instance;
   bool no_reply= ptr->flags.no_reply;
 
-  unlikely (memcached_server_count(ptr) == 0)
-    return MEMCACHED_NO_SERVERS;
+  if (memcached_server_count(ptr) == 0)
+    return memcached_set_error(ptr, MEMCACHED_NO_SERVERS, NULL);
 
   server_key= memcached_generate_hash_with_redistribution(ptr, master_key, master_key_length);
   instance= memcached_server_instance_fetch(ptr, server_key);
@@ -140,6 +140,10 @@ memcached_return_t memcached_increment(memcached_st *ptr,
                                        uint32_t offset,
                                        uint64_t *value)
 {
+  uint64_t local_value;
+  if (! value)
+    value= &local_value;
+
   return memcached_increment_by_key(ptr, key, key_length, key, key_length, offset, value);
 }
 
@@ -148,6 +152,10 @@ memcached_return_t memcached_decrement(memcached_st *ptr,
                                        uint32_t offset,
                                        uint64_t *value)
 {
+  uint64_t local_value;
+  if (! value)
+    value= &local_value;
+
   return memcached_decrement_by_key(ptr, key, key_length, key, key_length, offset, value);
 }
 
@@ -161,6 +169,10 @@ memcached_return_t memcached_increment_by_key(memcached_st *ptr,
   unlikely (rc != MEMCACHED_SUCCESS)
     return rc;
 
+  uint64_t local_value;
+  if (! value)
+    value= &local_value;
+
   LIBMEMCACHED_MEMCACHED_INCREMENT_START();
   if (ptr->flags.binary_protocol)
   {
@@ -189,6 +201,10 @@ memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
   unlikely (rc != MEMCACHED_SUCCESS)
     return rc;
 
+  uint64_t local_value;
+  if (! value)
+    value= &local_value;
+
   LIBMEMCACHED_MEMCACHED_DECREMENT_START();
   if (ptr->flags.binary_protocol)
   {
@@ -215,6 +231,10 @@ memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
                                                     time_t expiration,
                                                     uint64_t *value)
 {
+  uint64_t local_value;
+  if (! value)
+    value= &local_value;
+
   return memcached_increment_with_initial_by_key(ptr, key, key_length,
                                                  key, key_length,
                                                  offset, initial, expiration, value);
@@ -234,6 +254,10 @@ memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
   unlikely (rc != MEMCACHED_SUCCESS)
     return rc;
 
+  uint64_t local_value;
+  if (! value)
+    value= &local_value;
+
   LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
   if (ptr->flags.binary_protocol)
     rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
@@ -256,6 +280,10 @@ memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
                                                     time_t expiration,
                                                     uint64_t *value)
 {
+  uint64_t local_value;
+  if (! value)
+    value= &local_value;
+
   return memcached_decrement_with_initial_by_key(ptr, key, key_length,
                                                  key, key_length,
                                                  offset, initial, expiration, value);
@@ -275,6 +303,10 @@ memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
   unlikely (rc != MEMCACHED_SUCCESS)
     return rc;
 
+  uint64_t local_value;
+  if (! value)
+    value= &local_value;
+
   LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
   if (ptr->flags.binary_protocol)
   {
index 227be9df040930199a100cf2bae62f8b9d384ef8..aa1b23dc8fd2075053ed841393df1e0011007969 100644 (file)
@@ -17,66 +17,69 @@ extern "C" {
 #endif
 
 LIBMEMCACHED_API
-memcached_return_t memcached_increment(memcached_st *ptr,
-                                     const char *key, size_t key_length,
-                                     uint32_t offset,
-                                     uint64_t *value);
+  memcached_return_t memcached_increment(memcached_st *ptr,
+                                         const char *key, size_t key_length,
+                                         uint32_t offset,
+                                         uint64_t *value);
 LIBMEMCACHED_API
-memcached_return_t memcached_decrement(memcached_st *ptr,
-                                     const char *key, size_t key_length,
-                                     uint32_t offset,
-                                     uint64_t *value);
+  memcached_return_t memcached_decrement(memcached_st *ptr,
+                                         const char *key, size_t key_length,
+                                         uint32_t offset,
+                                         uint64_t *value);
 
 LIBMEMCACHED_API
-memcached_return_t memcached_increment_by_key(memcached_st *ptr,
-                                            const char *master_key, size_t master_key_length,
-                                            const char *key, size_t key_length,
-                                            uint64_t offset,
-                                            uint64_t *value);
+  memcached_return_t memcached_increment_by_key(memcached_st *ptr,
+                                                const char *master_key, size_t master_key_length,
+                                                const char *key, size_t key_length,
+                                                uint64_t offset,
+                                                uint64_t *value);
 
 LIBMEMCACHED_API
-memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
-                                            const char *master_key, size_t master_key_length,
-                                            const char *key, size_t key_length,
-                                            uint64_t offset,
-                                            uint64_t *value);
+  memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
+                                                const char *master_key, size_t master_key_length,
+                                                const char *key, size_t key_length,
+                                                uint64_t offset,
+                                                uint64_t *value);
 
 LIBMEMCACHED_API
-memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
-                                                  const char *key,
-                                                  size_t key_length,
-                                                  uint64_t offset,
-                                                  uint64_t initial,
-                                                  time_t expiration,
-                                                  uint64_t *value);
+  memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
+                                                      const char *key,
+                                                      size_t key_length,
+                                                      uint64_t offset,
+                                                      uint64_t initial,
+                                                      time_t expiration,
+                                                      uint64_t *value);
+
 LIBMEMCACHED_API
-memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
-                                                  const char *key,
-                                                  size_t key_length,
-                                                  uint64_t offset,
-                                                  uint64_t initial,
-                                                  time_t expiration,
-                                                  uint64_t *value);
+  memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
+                                                      const char *key,
+                                                      size_t key_length,
+                                                      uint64_t offset,
+                                                      uint64_t initial,
+                                                      time_t expiration,
+                                                      uint64_t *value);
+
 LIBMEMCACHED_API
-memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
-                                                         const char *master_key,
-                                                         size_t master_key_length,
-                                                         const char *key,
-                                                         size_t key_length,
-                                                         uint64_t offset,
-                                                         uint64_t initial,
-                                                         time_t expiration,
-                                                         uint64_t *value);
+  memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
+                                                             const char *master_key,
+                                                             size_t master_key_length,
+                                                             const char *key,
+                                                             size_t key_length,
+                                                             uint64_t offset,
+                                                             uint64_t initial,
+                                                             time_t expiration,
+                                                             uint64_t *value);
+
 LIBMEMCACHED_API
-memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
-                                                         const char *master_key,
-                                                         size_t master_key_length,
-                                                         const char *key,
-                                                         size_t key_length,
-                                                         uint64_t offset,
-                                                         uint64_t initial,
-                                                         time_t expiration,
-                                                         uint64_t *value);
+  memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
+                                                             const char *master_key,
+                                                             size_t master_key_length,
+                                                             const char *key,
+                                                             size_t key_length,
+                                                             uint64_t offset,
+                                                             uint64_t initial,
+                                                             time_t expiration,
+                                                             uint64_t *value);
 
 #ifdef __cplusplus
 }
index da111351bee3a942c43f643e4f9861557478639c..5116b645fe783efabb5d817a98c03ef256e086ca 100644 (file)
@@ -317,18 +317,18 @@ uint64_t memcached_behavior_get(memcached_st *ptr,
         /* We just try the first host, and if it is down we return zero */
         if ((memcached_connect(instance)) != MEMCACHED_SUCCESS)
         {
-          return EXIT_SUCCESS;
+          return 0;
         }
 
         if (memcached_io_wait_for_write(instance) != MEMCACHED_SUCCESS)
         {
-          return EXIT_SUCCESS;
+          return 0;
         }
 
         if (getsockopt(instance->fd, SOL_SOCKET, SO_SNDBUF, &sock_size, &sock_length) < 0)
         {
           ptr->cached_errno= errno;
-          return EXIT_SUCCESS; /* Zero means error */
+          return 0; /* Zero means error */
         }
       }
 
@@ -353,18 +353,18 @@ uint64_t memcached_behavior_get(memcached_st *ptr,
         /* We just try the first host, and if it is down we return zero */
         if ((memcached_connect(instance)) != MEMCACHED_SUCCESS)
         {
-          return EXIT_SUCCESS;
+          return 0;
         }
 
         if (memcached_io_wait_for_write(instance) != MEMCACHED_SUCCESS)
         {
-          return EXIT_SUCCESS;
+          return 0;
         }
 
         if (getsockopt(instance->fd, SOL_SOCKET, SO_RCVBUF, &sock_size, &sock_length) < 0)
         {
           ptr->cached_errno= errno;
-          return EXIT_SUCCESS; /* Zero means error */
+          return 0; /* Zero means error */
         }
 
       }
@@ -390,7 +390,7 @@ uint64_t memcached_behavior_get(memcached_st *ptr,
   case MEMCACHED_BEHAVIOR_MAX:
   default:
     WATCHPOINT_ASSERT(0); /* Programming mistake if it gets this far */
-    return EXIT_SUCCESS;
+    return 0;
   }
 
   /* NOTREACHED */
index a7d95af71617c0b827f7156cae634d6cf4bbf94e..26182b19677dfc2790edcda19ce75a7702c39296 100644 (file)
@@ -16,7 +16,7 @@
 #ifndef __LIBMEMCACHED_COMMON_H__
 #define __LIBMEMCACHED_COMMON_H__
 
-#include "config.h"
+#include <config.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -47,6 +47,7 @@
 
 #include "libmemcached/memcached.h"
 #include "libmemcached/watchpoint.h"
+#include "libmemcached/is.h"
 
 typedef struct memcached_server_st * memcached_server_write_instance_st;
 
@@ -115,16 +116,6 @@ memcached_return_t run_distribution(memcached_st *ptr);
 #define memcached_server_response_decrement(A) (A)->cursor_active--
 #define memcached_server_response_reset(A) (A)->cursor_active=0
 
-// These are private 
-#define memcached_is_allocated(__object) ((__object)->options.is_allocated)
-#define memcached_is_initialized(__object) ((__object)->options.is_initialized)
-#define memcached_is_purging(__object) ((__object)->state.is_purging)
-#define memcached_is_processing_input(__object) ((__object)->state.is_processing_input)
-#define memcached_set_purging(__object, __value) ((__object)->state.is_purging= (__value))
-#define memcached_set_processing_input(__object, __value) ((__object)->state.is_processing_input= (__value))
-#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized(= (__value))
-#define memcached_set_allocated(__object, __value) ((__object)->options.is_allocated(= (__value))
-
 LIBMEMCACHED_LOCAL
 void set_last_disconnected_host(memcached_server_write_instance_st ptr);
 
diff --git a/libmemcached/error.c b/libmemcached/error.c
new file mode 100644 (file)
index 0000000..206e1b4
--- /dev/null
@@ -0,0 +1,166 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libmemcached/common.h"
+
+struct memcached_error_st
+{
+  memcached_st *root;
+  struct memcached_error_st *next;
+  memcached_return_t rc;
+  int local_errno;
+  size_t size;
+  char c_str[];
+};
+
+static memcached_error_st *_set(memcached_st *memc, memcached_string_t *str)
+{
+  if (! memc)
+    return NULL;
+
+  memcached_error_st *error;
+  error= (struct memcached_error_st *)libmemcached_malloc(memc, sizeof(struct memcached_error_st) +(str ? str->size :0) +1); 
+
+  if (! error)
+    return NULL;
+
+  error->root= memc;
+
+  if (str)
+  {
+    error->size= str->size;
+    memcpy(error->c_str, str->c_str, str->size);
+  }
+  error->c_str[(str ? str->size :0)]= 0;
+
+  error->next= memc->error_messages;
+  memc->error_messages= error;
+
+  return error;
+}
+
+memcached_return_t memcached_set_error(memcached_st *memc, memcached_return_t rc, memcached_string_t *str)
+{
+  if (rc == MEMCACHED_SUCCESS)
+    return MEMCACHED_SUCCESS;
+
+  memcached_error_st *error= _set(memc, str);
+
+  if (error)
+  {
+    error->local_errno= 0;
+    error->rc= rc;
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_set_errno(memcached_st *memc, int local_errno, memcached_string_t *str)
+{
+  memcached_error_st *error= _set(memc, str);
+
+  if (error)
+  {
+    error->local_errno= local_errno;
+    error->rc= MEMCACHED_ERRNO;
+  }
+
+  return error->rc;
+}
+
+static void _error_free(memcached_error_st *error)
+{
+  if (! error)
+    return;
+
+  _error_free(error->next);
+
+  if (error && error->root)
+  {
+    libmemcached_free(error->root, error);
+  }
+  else if (error)
+  {
+    free(error);
+  }
+}
+
+void memcached_error_free(memcached_st *self)
+{
+  if (! self)
+    return;
+
+  _error_free(self->error_messages);
+}
+
+const char *memcached_last_error_message(memcached_st *memc)
+{
+  if (! memc)
+    return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
+
+  if (! memc->error_messages)
+    return memcached_strerror(memc, MEMCACHED_SUCCESS);
+
+  if (! memc->error_messages->c_str)
+  {
+    return memcached_strerror(memc, memc->error_messages->rc);
+  }
+
+  return memc->error_messages->c_str;
+}
+
+memcached_return_t memcached_last_error(memcached_st *memc)
+{
+  if (! memc)
+    return MEMCACHED_INVALID_ARGUMENTS;
+
+  if (! memc->error_messages)
+    return MEMCACHED_SUCCESS;
+
+  return memc->error_messages->rc;
+}
+
+memcached_return_t memcached_last_error_errno(memcached_st *memc)
+{
+  if (! memc)
+    return MEMCACHED_INVALID_ARGUMENTS;
+
+  if (! memc->error_messages)
+    return MEMCACHED_SUCCESS;
+
+  return memc->error_messages->local_errno;
+}
diff --git a/libmemcached/error.h b/libmemcached/error.h
new file mode 100644 (file)
index 0000000..28038d0
--- /dev/null
@@ -0,0 +1,65 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_LOCAL
+  memcached_return_t memcached_set_error(memcached_st *memc, memcached_return_t rc, memcached_string_t *str);
+
+LIBMEMCACHED_LOCAL
+  memcached_return_t memcached_set_errno(memcached_st *memc, int local_errno, memcached_string_t *str);
+
+LIBMEMCACHED_LOCAL
+  void memcached_error_free(memcached_st *error);
+
+LIBMEMCACHED_API
+  const char *memcached_last_error_message(memcached_st *memc);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_last_error(memcached_st *memc);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_last_error_errno(memcached_st *memc);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
index 75bcf6005e97042e94c03890820800fbb6dbc6c8..b0d0731938c4d670e4c2836e65866e95ce29085c 100644 (file)
@@ -17,6 +17,7 @@ noinst_HEADERS+= \
                 libmemcached/do.h \
                 libmemcached/internal.h \
                 libmemcached/io.h \
+                libmemcached/is.h \
                 libmemcached/libmemcached_probes.h \
                 libmemcached/protocol/ascii_handler.h \
                 libmemcached/protocol/binary_handler.h \
@@ -26,6 +27,7 @@ noinst_HEADERS+= \
 nobase_include_HEADERS+= \
                         libmemcached/allocators.h \
                         libmemcached/analyze.h \
+                        libmemcached/array.h \
                         libmemcached/auto.h \
                         libmemcached/behavior.h \
                         libmemcached/callback.h \
@@ -33,6 +35,7 @@ nobase_include_HEADERS+= \
                         libmemcached/constants.h \
                         libmemcached/delete.h \
                         libmemcached/dump.h \
+                        libmemcached/error.h \
                         libmemcached/exception.hpp \
                         libmemcached/fetch.h \
                         libmemcached/flush.h \
@@ -92,22 +95,24 @@ libmemcached_libmemcached_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION}
 libmemcached_libmemcached_la_SOURCES+= \
                                       libmemcached/allocators.c \
                                       libmemcached/analyze.c \
+                                      libmemcached/array.c \
                                       libmemcached/auto.c \
                                       libmemcached/behavior.c \
                                       libmemcached/connect.c \
                                       libmemcached/delete.c \
                                       libmemcached/do.c \
                                       libmemcached/dump.c \
+                                      libmemcached/error.c \
                                       libmemcached/fetch.c \
                                       libmemcached/flush.c \
                                       libmemcached/flush_buffers.c \
                                       libmemcached/get.c \
                                       libmemcached/hash.c \
-                                      libmemcached/options.cc \
                                       libmemcached/hosts.c \
                                       libmemcached/io.c \
                                       libmemcached/key.c \
                                       libmemcached/memcached.c \
+                                      libmemcached/options.cc \
                                       libmemcached/parse.c \
                                       libmemcached/purge.c \
                                       libmemcached/quit.c \
diff --git a/libmemcached/is.h b/libmemcached/is.h
new file mode 100644 (file)
index 0000000..f155334
--- /dev/null
@@ -0,0 +1,48 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+/* These are private */ 
+#define memcached_is_allocated(__object) ((__object)->options.is_allocated)
+#define memcached_is_initialized(__object) ((__object)->options.is_initialized)
+#define memcached_is_purging(__object) ((__object)->state.is_purging)
+#define memcached_is_processing_input(__object) ((__object)->state.is_processing_input)
+#define memcached_set_purging(__object, __value) ((__object)->state.is_purging= (__value))
+#define memcached_set_processing_input(__object, __value) ((__object)->state.is_processing_input= (__value))
+#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized(= (__value))
+#define memcached_set_allocated(__object, __value) ((__object)->options.is_allocated= (__value))
index b0333569ec7fe8f45fe943a16d210b8d70eb502c..3a4e4c4a78d8edc6c1a18020e7b388d469f67c95 100644 (file)
@@ -97,9 +97,42 @@ static inline bool _memcached_init(memcached_st *self)
   self->sasl.callbacks= NULL;
   self->sasl.is_allocated= false;
 
+  self->error_messages= NULL;
+
   return true;
 }
 
+static void _free(memcached_st *ptr, bool release_st)
+{
+  /* If we have anything open, lets close it now */
+  memcached_quit(ptr);
+  memcached_server_list_free(memcached_server_list(ptr));
+  memcached_result_free(&ptr->result);
+
+  if (ptr->last_disconnected_server)
+    memcached_server_free(ptr->last_disconnected_server);
+
+  if (ptr->on_cleanup)
+    ptr->on_cleanup(ptr);
+
+  if (ptr->continuum)
+    libmemcached_free(ptr, ptr->continuum);
+
+  memcached_error_free(ptr);
+
+  if (ptr->sasl.callbacks)
+  {
+#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
+    memcached_destroy_sasl_auth_data(ptr);
+#endif
+  }
+
+  if (memcached_is_allocated(ptr) && release_st)
+  {
+    libmemcached_free(ptr, ptr);
+  }
+}
+
 memcached_st *memcached_create(memcached_st *ptr)
 {
   if (ptr == NULL)
@@ -140,6 +173,18 @@ memcached_st *memcached_create(memcached_st *ptr)
   return ptr;
 }
 
+void memcached_reset(memcached_st *ptr)
+{
+  WATCHPOINT_ASSERT(ptr);
+  if (! ptr)
+    return;
+
+  bool stored_is_allocated= memcached_is_allocated(ptr);
+  _free(ptr, false);
+  memcached_create(ptr);
+  memcached_set_allocated(ptr, stored_is_allocated);
+}
+
 void memcached_servers_reset(memcached_st *ptr)
 {
   memcached_server_list_free(memcached_server_list(ptr));
@@ -165,31 +210,7 @@ void memcached_reset_last_disconnected_server(memcached_st *ptr)
 
 void memcached_free(memcached_st *ptr)
 {
-  /* If we have anything open, lets close it now */
-  memcached_quit(ptr);
-  memcached_server_list_free(memcached_server_list(ptr));
-  memcached_result_free(&ptr->result);
-
-  if (ptr->last_disconnected_server)
-    memcached_server_free(ptr->last_disconnected_server);
-
-  if (ptr->on_cleanup)
-    ptr->on_cleanup(ptr);
-
-  if (ptr->continuum)
-    libmemcached_free(ptr, ptr->continuum);
-
-  if (ptr->sasl.callbacks)
-  {
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-    memcached_destroy_sasl_auth_data(ptr);
-#endif
-  }
-
-  if (memcached_is_allocated(ptr))
-  {
-    libmemcached_free(ptr, ptr);
-  }
+  _free(ptr, true);
 }
 
 /*
index 56a5a78f7777d7e642c525fd31d72828371d7293..bef6354a128280c56eb2295ca94082fda01752f3 100644 (file)
@@ -28,6 +28,8 @@
 #include <libmemcached/constants.h>
 #include <libmemcached/types.h>
 #include <libmemcached/string.h>
+#include <libmemcached/array.h>
+#include <libmemcached/error.h>
 #include <libmemcached/stats.h>
 #include <libhashkit/hashkit.h>
 // Everything above this line must be in the order specified.
@@ -127,6 +129,7 @@ struct memcached_st {
   memcached_trigger_delete_key_fn delete_trigger;
   memcached_callback_st *callbacks;
   struct memcached_sasl_st sasl;
+  struct memcached_error_st *error_messages;
   char prefix_key[MEMCACHED_PREFIX_KEY_MAX_SIZE];
   struct {
     bool is_allocated:1;
@@ -147,6 +150,9 @@ memcached_st *memcached_create(memcached_st *ptr);
 LIBMEMCACHED_API
 void memcached_free(memcached_st *ptr);
 
+LIBMEMCACHED_API
+void memcached_reset(memcached_st *ptr);
+
 LIBMEMCACHED_API
 void memcached_reset_last_disconnected_server(memcached_st *ptr);
 
index 1bf2ffa1b541eb9a02085036f03a3dc34f674ba1..0d8c39f2f0eff813dab35e37c0fae532fceaa28d 100644 (file)
@@ -48,6 +48,10 @@ memcached_return_t memcached_parse_options(memcached_st *self, char const *optio
 
   memset(&pp, 0, sizeof(type_st));
 
+  WATCHPOINT_ASSERT(self);
+  if (! self)
+    return MEMCACHED_INVALID_ARGUMENTS;
+
   pp.buf= option_string;
   pp.memc= self;
   pp.length= length;
index 3a7cee2eed170492600305dba1d031c33aee1fa7..8cd16d538f287cfb2d2518ad01faef065e50d1c8 100644 (file)
 #pragma GCC diagnostic ignored "-Wold-style-cast"
 #include <libmemcached/options/scanner.h>
 
-inline int libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner, const char *str)
+inline void libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner, const char *str)
 {
-#if 0
-  std::cerr << str << std::endl;
-#endif
-  return 0;
+  memcached_string_t local_string;
+  local_string.size= strlen(str);
+  local_string.c_str= str;
+  memcached_set_error(parser->memc, MEMCACHED_FAILURE, &local_string);
 }
 
 
@@ -98,6 +98,9 @@ inline int libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner,
 %token USE_UDP
 %token VERIFY_KEY
 
+/* Callbacks */
+%token PREFIX_KEY
+
 /* Hash types */
 %token MD5
 %token CRC
@@ -119,12 +122,15 @@ inline int libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner,
 
 %token <number> NUMBER
 %token <number> FLOAT
-%token <string> IDENTIFIER
-%token <string> SERVER_WITH_PORT
+%token <string> HOSTNAME
+%token <string> HOSTNAME_WITH_PORT
 %token <string> IPADDRESS
 %token <string> IPADDRESS_WITH_PORT
+%token <string> STRING
+%token <string> QUOTED_STRING
 
 %type <server> server
+%type <string> string
 %type <distribution> distribution
 %type <hash> hash
 %type <behavior> behavior_boolean
@@ -152,6 +158,10 @@ expression:
         ;
 
 behaviors:
+          PREFIX_KEY '=' string
+          {
+            memcached_callback_set(parser->memc, MEMCACHED_CALLBACK_PREFIX_KEY, std::string($3.c_str, $3.length).c_str());
+          }
         | DISTRIBUTION '=' distribution
           {
             memcached_behavior_set(parser->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $3);
@@ -311,13 +321,19 @@ server_list:
         ;
 
 server:
-          SERVER_WITH_PORT NUMBER
+          HOSTNAME_WITH_PORT NUMBER
           {
             $$.c_str= $1.c_str;
             $$.length= $1.length -1;
             $$.port= $2;
           }
-        | IDENTIFIER
+        | HOSTNAME
+          {
+            $$.c_str= $1.c_str;
+            $$.length= $1.length;
+            $$.port= MEMCACHED_DEFAULT_PORT;
+          }
+        | STRING /* a match can be against "localhost" which is just a string */
           {
             $$.c_str= $1.c_str;
             $$.length= $1.length;
@@ -376,6 +392,18 @@ hash:
           }
         ;
 
+string:
+          STRING
+          {
+            $$= $1;
+          }
+        | QUOTED_STRING
+          {
+            $$.c_str= $1.c_str +1;
+            $$.length= $1.length -2;
+          }
+        ;
+
 distribution:
           CONSISTENT
           {
index 1afc50eb5a12ca337dc03715ff7f1982e5516851..3a135ff92055c5c00f17ce341dbfec9d998c0537 100644 (file)
@@ -148,6 +148,9 @@ USER-DATA                   { return USER_DATA; }
 USE_UDP                                { return USE_UDP; }
 USE-UDP                                { return USE_UDP; }
 
+PREFIX-KEY                             { return PREFIX_KEY; }
+PREFIX_KEY                             { return PREFIX_KEY; }
+
 CONSISTENT      { return CONSISTENT; }
 MODULA          { return MODULA; }
 RANDOM          { return RANDOM; }
@@ -165,14 +168,15 @@ JENKINS                   { return JENKINS; }
 [[:alnum:]][[:alnum:].]*[[:alpha:]]: { 
       yylval->string.c_str = yytext;
       yylval->string.length = yyleng;
-      return SERVER_WITH_PORT;
+      return HOSTNAME_WITH_PORT;
     }
 
-[[:alnum:]][[:alnum:].]*[[:alpha:]] { 
+[[:alnum:]]+"."[[:alpha:].]+ { 
       yylval->string.c_str = yytext;
       yylval->string.length = yyleng;
-      return IDENTIFIER;
+      return HOSTNAME;
     }
+
 [[:digit:]]{1,3}"."[[:digit:]]{1,3}"."[[:digit:]]{1,3}"."[[:digit:]]{1,3}: { 
       yylval->string.c_str = yytext;
       yylval->string.length = yyleng;
@@ -185,6 +189,18 @@ JENKINS                    { return JENKINS; }
       return IPADDRESS;
     }
 
+[[:alnum:]]+ { 
+      yylval->string.c_str = yytext;
+      yylval->string.length = yyleng;
+      return STRING;
+    }
+
+\"[[:alnum:]]*\" { 
+      yylval->string.c_str = yytext;
+      yylval->string.length = yyleng;
+      return QUOTED_STRING;
+    }
+
 .   {
       return UNKNOWN;
     }
index 4b44e6eddc60aea02d52583266b34da220c15fe1..f6a13bb000f7b695fad5ed3d9beda7585bb6712b 100644 (file)
@@ -34,6 +34,11 @@ struct memcached_string_st {
   } options;
 };
 
+struct memcached_string_t {
+  size_t size;
+  const char *c_str;
+};
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -80,4 +85,10 @@ void memcached_string_set_length(memcached_string_st *self, size_t length);
 #endif
 
 
+#ifdef __cplusplus
+#define memcached_string_with_size(X) (X), (static_cast<size_t>((sizeof(X) - 1)))
+#else
+#define memcached_string_with_size(X) (X), ((size_t)((sizeof(X) - 1)))
+#endif
+
 #endif /* __LIBMEMCACHED_STRING_H__ */
index 28a1535c9f92b0ac151fb64dad0838d0ee6cc399..89c1203bcbd6e96cd6acb8dbe179d183c1ea0a91 100644 (file)
@@ -16,6 +16,8 @@ typedef struct memcached_st memcached_st;
 typedef struct memcached_stat_st memcached_stat_st;
 typedef struct memcached_analysis_st memcached_analysis_st;
 typedef struct memcached_result_st memcached_result_st;
+typedef struct memcached_array_st memcached_array_st;
+typedef struct memcached_error_st memcached_error_st;
 
 // All of the flavors of memcache_server_st
 typedef struct memcached_server_st memcached_server_st;
@@ -26,6 +28,7 @@ typedef struct memcached_callback_st memcached_callback_st;
 
 // The following two structures are internal, and never exposed to users.
 typedef struct memcached_string_st memcached_string_st;
+typedef struct memcached_string_t memcached_string_t;
 typedef struct memcached_continuum_item_st memcached_continuum_item_st;
 
 
index 4349a668fdbf5147d8ac5eeb11f37b99bf224aac..c96ffb5153d546cab133f2cf7e1f230d55cc1719 100644 (file)
@@ -47,7 +47,7 @@ static void global_sleep(void)
 
 static void kill_file(const char *file_buffer)
 {
-  FILE *fp= fopen(file_buffer, "r");
+  FILE *fp;
 
   while ((fp= fopen(file_buffer, "r")))
   {
diff --git a/tests/basic.cc b/tests/basic.cc
new file mode 100644 (file)
index 0000000..fea343d
--- /dev/null
@@ -0,0 +1,130 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/memcached.h>
+#include <libmemcached/is.h>
+#include <libtest/test.h>
+#include "tests/basic.h"
+
+test_return_t basic_init_test(memcached_st *junk)
+{
+  (void)junk;
+
+  memcached_st memc;
+  memcached_st *memc_ptr;
+
+  memc_ptr= memcached_create(&memc);
+  test_true(memc_ptr);
+  test_false(memcached_is_allocated(&memc));
+  memcached_free(memc_ptr);
+
+  return TEST_SUCCESS;
+}
+
+test_return_t basic_clone_test(memcached_st *memc)
+{
+  memcached_st *memc_ptr;
+
+  memc_ptr= memcached_clone(NULL, memc);
+  test_true(memc_ptr);
+  test_true(memcached_is_allocated(memc_ptr));
+  memcached_free(memc_ptr);
+
+  return TEST_SUCCESS;
+}
+
+test_return_t basic_reset_stack_test(memcached_st *junk)
+{
+  (void)junk;
+  memcached_st memc;
+
+  memcached_create(&memc);
+
+  memcached_reset(&memc);
+  test_false(memcached_is_allocated(&memc));
+
+  memcached_free(&memc);
+  test_false(memcached_is_allocated(&memc));
+
+  return TEST_SUCCESS;
+}
+
+test_return_t basic_reset_heap_test(memcached_st *junk)
+{
+  (void)junk;
+  memcached_st *memc_ptr;
+
+  memc_ptr= memcached_create(NULL);
+  test_true(memcached_is_allocated(memc_ptr));
+
+  memcached_reset(memc_ptr);
+  test_true(memcached_is_allocated(memc_ptr));
+
+  memcached_free(memc_ptr);
+
+  return TEST_SUCCESS;
+}
+
+test_return_t basic_reset_stack_clone_test(memcached_st *memc)
+{
+  memcached_st clone;
+  memcached_st *memc_ptr;
+
+  memset(&clone, 0, sizeof(clone));
+  memc_ptr= memcached_clone(&clone, memc);
+  test_true(memc_ptr);
+
+  memcached_reset(memc_ptr);
+
+  memcached_free(memc_ptr);
+
+  return TEST_SUCCESS;
+}
+
+test_return_t basic_reset_heap_clone_test(memcached_st *memc)
+{
+  memcached_st *memc_ptr;
+
+  memc_ptr= memcached_clone(NULL, memc);
+  test_true(memc_ptr);
+
+  memcached_reset(memc_ptr);
+
+  memcached_free(memc_ptr);
+
+  return TEST_SUCCESS;
+}
diff --git a/tests/basic.h b/tests/basic.h
new file mode 100644 (file)
index 0000000..7c1536e
--- /dev/null
@@ -0,0 +1,66 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libtest/visibility.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBTEST_INTERNAL_API
+test_return_t basic_init_test(memcached_st *junk);
+
+LIBTEST_INTERNAL_API
+test_return_t basic_clone_test(memcached_st *memc);
+
+LIBTEST_INTERNAL_API
+test_return_t basic_reset_stack_test(memcached_st *junk);
+
+LIBTEST_INTERNAL_API
+test_return_t basic_reset_heap_test(memcached_st *junk);
+
+LIBTEST_INTERNAL_API
+test_return_t basic_reset_stack_clone_test(memcached_st *memc);
+
+LIBTEST_INTERNAL_API
+test_return_t basic_reset_heap_clone_test(memcached_st *memc);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tests/error_conditions.cc b/tests/error_conditions.cc
new file mode 100644 (file)
index 0000000..b46b3ca
--- /dev/null
@@ -0,0 +1,70 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+
+#include <libmemcached/memcached.h>
+#include <libmemcached/is.h>
+#include <libtest/test.h>
+#include <tests/error_conditions.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+test_return_t memcached_increment_MEMCACHED_NO_SERVERS(memcached_st *junk)
+{
+  (void)junk;
+  memcached_st *memc_ptr;
+
+  memc_ptr= memcached_create(NULL);
+  test_true(memc_ptr);
+
+  memcached_increment(memc_ptr, memcached_string_with_size("dead key"), 1, NULL);
+  test_true(memcached_last_error(memc_ptr) == MEMCACHED_NO_SERVERS);
+
+  memcached_increment(memc_ptr, memcached_string_with_size("dead key"), 1, NULL);
+  test_true(memcached_last_error(memc_ptr) == MEMCACHED_NO_SERVERS);
+
+  memcached_free(memc_ptr);
+
+  return TEST_SUCCESS;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tests/error_conditions.h b/tests/error_conditions.h
new file mode 100644 (file)
index 0000000..1bfa9ed
--- /dev/null
@@ -0,0 +1,50 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libtest/test.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+test_return_t memcached_increment_MEMCACHED_NO_SERVERS(memcached_st *junk);
+
+#ifdef __cplusplus
+}
+#endif
index 6ed1cd9f07bd3db2d5ee1d9d7998ac48f3817df8..dcc19a91d3bb45528e9d16c6739e8fbef997264d 100644 (file)
@@ -28,6 +28,8 @@ EXTRA_DIST+= \
             tests/output_plus.res
 
 noinst_HEADERS+= \
+                tests/basic.h \
+                tests/error_conditions.h \
                 tests/hash_results.h \
                 tests/ketama_test_cases.h \
                 tests/ketama_test_cases_spy.h \
@@ -47,6 +49,8 @@ noinst_PROGRAMS+= \
 
 tests_testapp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
 tests_testapp_SOURCES= \
+                      tests/basic.cc \
+                      tests/error_conditions.cc \
                       tests/mem_functions.c \
                       tests/parser.cc \
                       tests/print.cc \
index 2cb8cfb95a428dc0d937a68ff6a6054d18751e89..3aff82fd13266fe5fcd6976347fb9f28526963f2 100644 (file)
@@ -36,6 +36,8 @@
 #include <libtest/test.h>
 #include "tests/parser.h"
 #include "tests/replication.h"
+#include "tests/basic.h"
+#include "tests/error_conditions.h"
 #include "tests/print.h"
 
 
@@ -6101,6 +6103,16 @@ test_st behavior_tests[] ={
   {0, 0, 0}
 };
 
+test_st basic_tests[] ={
+  {"init", 1, (test_callback_fn)basic_init_test},
+  {"clone", 1, (test_callback_fn)basic_clone_test},
+  {"reset", 1, (test_callback_fn)basic_reset_stack_test},
+  {"reset heap", 1, (test_callback_fn)basic_reset_heap_test},
+  {"reset stack clone", 1, (test_callback_fn)basic_reset_stack_clone_test},
+  {"reset heap clone", 1, (test_callback_fn)basic_reset_heap_clone_test},
+  {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},
@@ -6289,10 +6301,12 @@ test_st hash_tests[] ={
 };
 
 test_st error_conditions[] ={
-  {"memcached_get_MEMCACHED_ERRNO", 0, (test_callback_fn)memcached_get_MEMCACHED_ERRNO },
-  {"memcached_get_MEMCACHED_NOTFOUND", 0, (test_callback_fn)memcached_get_MEMCACHED_NOTFOUND },
-  {"memcached_get_by_key_MEMCACHED_ERRNO", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_ERRNO },
-  {"memcached_get_by_key_MEMCACHED_NOTFOUND", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_NOTFOUND },
+  {"memcached_get(MEMCACHED_ERRNO)", 0, (test_callback_fn)memcached_get_MEMCACHED_ERRNO },
+  {"memcached_get(MEMCACHED_NOTFOUND)", 0, (test_callback_fn)memcached_get_MEMCACHED_NOTFOUND },
+  {"memcached_get_by_key(MEMCACHED_ERRNO)", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_ERRNO },
+  {"memcached_get_by_key(MEMCACHED_NOTFOUND)", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_NOTFOUND },
+  {"memcached_get_by_key(MEMCACHED_NOTFOUND)", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_NOTFOUND },
+  {"memcached_increment(MEMCACHED_NO_SERVERS)", 0, (test_callback_fn)memcached_increment_MEMCACHED_NO_SERVERS },
   {0, 0, (test_callback_fn)0}
 };
 
@@ -6305,6 +6319,7 @@ test_st parser_tests[] ={
   {"number_options", 0, (test_callback_fn)parser_number_options_test },
   {"server", 0, (test_callback_fn)server_test },
   {"servers", 0, (test_callback_fn)servers_test },
+  {"prefix_key", 0, (test_callback_fn)parser_key_prefix_test },
   {0, 0, (test_callback_fn)0}
 };
 
@@ -6312,6 +6327,7 @@ collection_st collection[] ={
 #if 0
   {"hash_sanity", 0, 0, hash_sanity},
 #endif
+  {"basic", 0, 0, basic_tests},
   {"hsieh_availability", 0, 0, hsieh_availability},
   {"murmur_availability", 0, 0, murmur_availability},
   {"block", 0, 0, tests},
index 3ee37a2c2e6628a6ed32ce2aa4e0378b55cb93d9..9eb8171494b4037d58c8ad6cc2e692dff1e47507 100644 (file)
 #include "tests/parser.h"
 #include "tests/print.h"
 
+enum scanner_type_t
+{
+  NIL,
+  UNSIGNED,
+  SIGNED,
+  ARRAY
+};
+
+
 struct scanner_string_st {
-  const char *c_ptr;
+  const char *c_str;
   size_t size;
 };
 
-test_return_t server_test(memcached_st *junk)
+static inline scanner_string_st scanner_string(const char *arg, size_t arg_size)
 {
-  (void)junk;
-  memcached_return_t rc;
-  memcached_st *memc;
-  memc= memcached_create(NULL);
+  scanner_string_st local= { arg, arg_size };
+  return local;
+}
 
-  scanner_string_st test_strings[]= {
-    { STRING_WITH_LEN("--server=localhost") },
-    { STRING_WITH_LEN("--server=10.0.2.1") },
-    { STRING_WITH_LEN("--server=example.com") },
-    { STRING_WITH_LEN("--server=localhost:30") },
-    { STRING_WITH_LEN("--server=10.0.2.1:20") },
-    { STRING_WITH_LEN("--server=example.com:1024") },
-    { NULL, 0}
-  };
-
-  for (scanner_string_st *ptr= test_strings; ptr->size; ptr++)
-  {
-    rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size);
-    test_true(rc == MEMCACHED_SUCCESS);
-    memcached_servers_reset(memc);
-  }
+#define make_scanner_string(X) scanner_string((X), static_cast<size_t>(sizeof(X) - 1))
 
-  memcached_free(memc);
+static struct scanner_string_st scanner_string_null= { 0, 0};
+
+struct scanner_variable_t {
+  enum scanner_type_t type;
+  struct scanner_string_st option;
+  struct scanner_string_st result;
+  test_return_t (*check_func)(memcached_st *memc, const scanner_string_st &hostname);
+};
+
+// Check and make sure the first host is what we expect it to be
+static test_return_t __check_host(memcached_st *memc, const scanner_string_st &hostname)
+{
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc, 0);
+
+  test_true(instance);
+
+  const char *first_hostname = memcached_server_name(instance);
+  test_true(first_hostname);
+  test_strcmp(first_hostname, hostname.c_str);
 
   return TEST_SUCCESS;
 }
 
-test_return_t servers_test(memcached_st *junk)
+// Check and make sure the prefix_key is what we expect it to be
+static test_return_t __check_prefix_key(memcached_st *memc, const scanner_string_st &hostname)
 {
-  (void)junk;
-  memcached_st *memc;
-  memc= memcached_create(NULL);
+  memcached_server_instance_st instance=
+    memcached_server_instance_by_position(memc, 0);
 
-  scanner_string_st test_strings[]= {
-    { STRING_WITH_LEN("--servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225") },
-    { STRING_WITH_LEN("--servers=a.example.com:81,localhost:82,b.example.com") },
-    { STRING_WITH_LEN("--servers=localhost,localhost:80") },
-    { NULL, 0}
-  };
+  test_true(instance);
 
-  for (scanner_string_st *ptr= test_strings; ptr->size; ptr++)
-  {
-    memcached_return_t rc;
-    rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size);
-
-    test_true(rc == MEMCACHED_SUCCESS);
+  const char *first_hostname = memcached_server_name(instance);
+  test_true(first_hostname);
+  test_strcmp(first_hostname, hostname.c_str);
 
-    memcached_server_fn callbacks[1];
-    callbacks[0]= server_print_callback;
-    memcached_server_cursor(memc, callbacks, NULL,  1);
+  return TEST_SUCCESS;
+}
 
-    memcached_servers_reset(memc);
-  }
+static test_return_t __check_IO_MSG_WATERMARK(memcached_st *memc, const scanner_string_st &value)
+{
+  uint64_t value_number;
 
-  scanner_string_st bad_test_strings[]= {
-    { STRING_WITH_LEN("-servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225") },
-    { STRING_WITH_LEN("-- servers=a.example.com:81,localhost:82,b.example.com") },
-    { STRING_WITH_LEN("--servers=localhost80") },
-    { NULL, 0}
-  };
+  value_number= atoll(value.c_str);
 
-  for (scanner_string_st *ptr= bad_test_strings; ptr->size; ptr++)
-  {
-    memcached_return_t rc;
-    rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size);
+  test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK) == value_number);
+  return TEST_SUCCESS;
+}
 
-    test_false_with(rc == MEMCACHED_SUCCESS, ptr->c_ptr);
+static test_return_t __check_AUTO_EJECT_HOSTS(memcached_st *memc, const scanner_string_st &value)
+{
+  (void)value;
+  test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS));
+  return TEST_SUCCESS;
+}
 
-    memcached_server_fn callbacks[1];
-    callbacks[0]= server_print_callback;
-    memcached_server_cursor(memc, callbacks, NULL,  1);
+static test_return_t __check_CACHE_LOOKUPS(memcached_st *memc, const scanner_string_st &value)
+{
+  (void)value;
+  test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_CACHE_LOOKUPS));
+  return TEST_SUCCESS;
+}
 
-    memcached_servers_reset(memc);
-  }
+static test_return_t __check_NOREPLY(memcached_st *memc, const scanner_string_st &value)
+{
+  (void)value;
+  test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NOREPLY));
+  return TEST_SUCCESS;
+}
 
-  memcached_free(memc);
+static test_return_t __check_VERIFY_KEY(memcached_st *memc, const scanner_string_st &value)
+{
+  (void)value;
+  test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY));
+  return TEST_SUCCESS;
+}
 
+static test_return_t __check_distribution_RANDOM(memcached_st *memc, const scanner_string_st &value)
+{
+  (void)value;
+  test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION) == MEMCACHED_DISTRIBUTION_RANDOM);
   return TEST_SUCCESS;
 }
 
-scanner_string_st test_number_options[]= {
-  { STRING_WITH_LEN("--CONNECT_TIMEOUT=456") },
-  { STRING_WITH_LEN("--IO_MSG_WATERMARK=456") },
-  { STRING_WITH_LEN("--IO_BYTES_WATERMARK=456") },
-  { STRING_WITH_LEN("--IO_KEY_PREFETCH=456") },
-  { STRING_WITH_LEN("--NUMBER_OF_REPLICAS=456") },
-  { STRING_WITH_LEN("--POLL_TIMEOUT=456") },
-  { STRING_WITH_LEN("--RCV_TIMEOUT=456") },
-  { STRING_WITH_LEN("--RETRY_TIMEOUT=456") },
-  { STRING_WITH_LEN("--SERVER_FAILURE_LIMIT=456") },
-  { STRING_WITH_LEN("--SND_TIMEOUT=456") },
-  { STRING_WITH_LEN("--SOCKET_RECV_SIZE=456") },
-  { STRING_WITH_LEN("--SOCKET_SEND_SIZE=456") },
-  { NULL, 0}
+scanner_variable_t test_server_strings[]= {
+  { ARRAY, make_scanner_string("--server=localhost"), make_scanner_string("localhost"), __check_host },
+  { ARRAY, make_scanner_string("--server=10.0.2.1"), make_scanner_string("10.0.2.1"), __check_host },
+  { ARRAY, make_scanner_string("--server=example.com"), make_scanner_string("example.com"), __check_host },
+  { ARRAY, make_scanner_string("--server=localhost:30"), make_scanner_string("localhost"), __check_host },
+  { ARRAY, make_scanner_string("--server=10.0.2.1:20"), make_scanner_string("10.0.2.1"), __check_host },
+  { ARRAY, make_scanner_string("--server=example.com:1024"), make_scanner_string("example.com"), __check_host },
+  { NIL, scanner_string_null, scanner_string_null, NULL }
 };
 
-scanner_string_st test_boolean_options[]= {
-  { STRING_WITH_LEN("--AUTO_EJECT_HOSTS") },
-  { STRING_WITH_LEN("--BINARY_PROTOCOL") },
-  { STRING_WITH_LEN("--BUFFER_REQUESTS") },
-  { STRING_WITH_LEN("--CACHE_LOOKUPS") },
-  { STRING_WITH_LEN("--CORK") },
-  { STRING_WITH_LEN("--HASH_WITH_PREFIX_KEY") },
-  { STRING_WITH_LEN("--KETAMA") },
-  { STRING_WITH_LEN("--KETAMA_WEIGHTED") },
-  { STRING_WITH_LEN("--NOREPLY") },
-  { STRING_WITH_LEN("--RANDOMIZE_REPLICA_READ") },
-  { STRING_WITH_LEN("--SORT_HOSTS") },
-  { STRING_WITH_LEN("--SUPPORT_CAS") },
-  { STRING_WITH_LEN("--TCP_NODELAY") },
-  { STRING_WITH_LEN("--TCP_KEEPALIVE") },
-  { STRING_WITH_LEN("--TCP_KEEPIDLE") },
-  { STRING_WITH_LEN("--USE_UDP") },
-  { STRING_WITH_LEN("--VERIFY_KEY") },
-  { NULL, 0}
+scanner_variable_t test_servers_strings[]= {
+  { ARRAY, make_scanner_string("--servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225"), scanner_string_null, NULL },
+  { ARRAY, make_scanner_string("--servers=a.example.com:81,localhost:82,b.example.com"), scanner_string_null, NULL },
+  { ARRAY, make_scanner_string("--servers=localhost,localhost:80"), scanner_string_null, NULL },
+  { NIL, scanner_string_null, scanner_string_null, NULL}
 };
 
-test_return_t parser_number_options_test(memcached_st *junk)
+
+scanner_variable_t bad_test_strings[]= {
+  { ARRAY, make_scanner_string("-servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225"), scanner_string_null, NULL },
+  { ARRAY, make_scanner_string("-- servers=a.example.com:81,localhost:82,b.example.com"), scanner_string_null, NULL },
+  { ARRAY, make_scanner_string("--servers=localhost+80"), scanner_string_null, NULL},
+  { NIL, scanner_string_null, scanner_string_null, NULL}
+};
+
+scanner_variable_t test_number_options[]= {
+  { ARRAY,  make_scanner_string("--CONNECT_TIMEOUT=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--IO_MSG_WATERMARK=456"), make_scanner_string("456"), __check_IO_MSG_WATERMARK },
+  { ARRAY,  make_scanner_string("--IO_BYTES_WATERMARK=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--IO_KEY_PREFETCH=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--NUMBER_OF_REPLICAS=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--POLL_TIMEOUT=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--RCV_TIMEOUT=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--RETRY_TIMEOUT=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--SERVER_FAILURE_LIMIT=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--SND_TIMEOUT=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--SOCKET_RECV_SIZE=456"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--SOCKET_SEND_SIZE=456"), scanner_string_null, NULL },
+  { NIL, scanner_string_null, scanner_string_null, NULL}
+};
+
+scanner_variable_t test_boolean_options[]= {
+  { ARRAY,  make_scanner_string("--AUTO_EJECT_HOSTS"), scanner_string_null, __check_AUTO_EJECT_HOSTS },
+  { ARRAY,  make_scanner_string("--BINARY_PROTOCOL"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--BUFFER_REQUESTS"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--CACHE_LOOKUPS"), scanner_string_null, __check_CACHE_LOOKUPS },
+  { ARRAY,  make_scanner_string("--CORK"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--HASH_WITH_PREFIX_KEY"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--KETAMA"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--KETAMA_WEIGHTED"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--NOREPLY"), scanner_string_null, __check_NOREPLY },
+  { ARRAY,  make_scanner_string("--RANDOMIZE_REPLICA_READ"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--SORT_HOSTS"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--SUPPORT_CAS"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--TCP_NODELAY"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--TCP_KEEPALIVE"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--TCP_KEEPIDLE"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--USE_UDP"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--VERIFY_KEY"), scanner_string_null, __check_VERIFY_KEY },
+  { NIL, scanner_string_null, scanner_string_null, NULL}
+};
+
+scanner_variable_t prefix_key_strings[]= {
+  { ARRAY, make_scanner_string("--PREFIX_KEY=foo"), make_scanner_string("foo"), __check_prefix_key },
+  { ARRAY, make_scanner_string("--PREFIX-KEY=\"foo\""), make_scanner_string("foo"), __check_prefix_key },
+  { ARRAY, make_scanner_string("--PREFIX-KEY=\"This is a very long key\""), make_scanner_string("This is a very long key"), __check_prefix_key },
+  { NIL, scanner_string_null, scanner_string_null, NULL}
+};
+
+scanner_variable_t distribution_strings[]= {
+  { ARRAY,  make_scanner_string("--DISTRIBUTION=consistent"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--DISTRIBUTION=random"), scanner_string_null, __check_distribution_RANDOM },
+  { ARRAY,  make_scanner_string("--DISTRIBUTION=modula"), scanner_string_null, NULL },
+  { NIL, scanner_string_null, scanner_string_null, NULL}
+};
+
+scanner_variable_t hash_strings[]= {
+  { ARRAY,  make_scanner_string("--HASH=MD5"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--HASH=CRC"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--HASH=FNV1_64"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--HASH=FNV1A_64"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--HASH=FNV1_32"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--HASH=FNV1A_32"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--HASH=MURMUR"), scanner_string_null, NULL },
+  { ARRAY,  make_scanner_string("--HASH=JENKINS"), scanner_string_null, NULL },
+  { NIL, scanner_string_null, scanner_string_null, NULL}
+};
+
+
+static test_return_t _test_option(scanner_variable_t *scanner, bool test_true= true)
 {
-  (void)junk;
+  (void)test_true;
   memcached_st *memc;
   memc= memcached_create(NULL);
 
-  for (scanner_string_st *ptr= test_number_options; ptr->size; ptr++)
+  for (scanner_variable_t *ptr= scanner; ptr->type != NIL; ptr++)
   {
     memcached_return_t rc;
-    rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size);
-    test_true_got(rc == MEMCACHED_SUCCESS, ptr->c_ptr);
+    rc= memcached_parse_options(memc, ptr->option.c_str, ptr->option.size);
+    if (test_true)
+    {
+      test_true_got(rc == MEMCACHED_SUCCESS, memcached_last_error_message(memc));
+
+      if (ptr->check_func)
+      {
+        (*ptr->check_func)(memc, ptr->result);
+      }
+    }
+    else
+    {
+      test_false_with(rc == MEMCACHED_SUCCESS, ptr->option.c_str);
+    }
+    memcached_reset(memc);
   }
-
   memcached_free(memc);
 
   return TEST_SUCCESS;
 }
 
-test_return_t parser_boolean_options_test(memcached_st *junk)
+test_return_t server_test(memcached_st *junk)
+{
+  (void)junk;
+  return _test_option(test_server_strings);
+}
+
+test_return_t servers_test(memcached_st *junk)
 {
   (void)junk;
-  memcached_st *memc;
-  memc= memcached_create(NULL);
 
-  for (scanner_string_st *ptr= test_boolean_options; ptr->size; ptr++)
+  test_return_t rc;
+  if ((rc= _test_option(test_server_strings)) != TEST_SUCCESS)
   {
-    memcached_return_t rc;
-    rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size);
-    test_true_got(rc == MEMCACHED_SUCCESS, ptr->c_ptr);
+    return rc;
   }
 
-  memcached_free(memc);
+#if 0
+    memcached_server_fn callbacks[1];
+    callbacks[0]= server_print_callback;
+    memcached_server_cursor(memc, callbacks, NULL,  1);
+#endif
+
+  if ((rc= _test_option(bad_test_strings, false)) != TEST_SUCCESS)
+  {
+    return rc;
+  }
 
   return TEST_SUCCESS;
 }
 
+test_return_t parser_number_options_test(memcached_st *junk)
+{
+  (void)junk;
+  return _test_option(test_number_options);
+}
+
+test_return_t parser_boolean_options_test(memcached_st *junk)
+{
+  (void)junk;
+  return _test_option(test_boolean_options);
+}
+
 test_return_t behavior_parser_test(memcached_st *junk)
 {
   (void)junk;
@@ -211,55 +318,17 @@ test_return_t behavior_parser_test(memcached_st *junk)
 test_return_t parser_hash_test(memcached_st *junk)
 {
   (void)junk;
-  memcached_return_t rc;
-  memcached_st *memc;
-  memc= memcached_create(NULL);
-
-  scanner_string_st test_strings[]= {
-    { STRING_WITH_LEN("--HASH=MD5") },
-    { STRING_WITH_LEN("--HASH=CRC") },
-    { STRING_WITH_LEN("--HASH=FNV1_64") },
-    { STRING_WITH_LEN("--HASH=FNV1A_64") },
-    { STRING_WITH_LEN("--HASH=FNV1_32") },
-    { STRING_WITH_LEN("--HASH=FNV1A_32") },
-    { STRING_WITH_LEN("--HASH=HSIEH") },
-    { STRING_WITH_LEN("--HASH=MURMUR") },
-    { STRING_WITH_LEN("--HASH=JENKINS") },
-    { NULL, 0}
-  };
-
-  for (scanner_string_st *ptr= test_strings; ptr->size; ptr++)
-  {
-    rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size);
-    test_true_got(rc == MEMCACHED_SUCCESS, ptr->c_ptr);
-  }
-
-  memcached_free(memc);
-
-  return TEST_SUCCESS;
+  return _test_option(hash_strings);
 }
 
 test_return_t parser_distribution_test(memcached_st *junk)
 {
   (void)junk;
-  memcached_return_t rc;
-  memcached_st *memc;
-  memc= memcached_create(NULL);
-
-  scanner_string_st test_strings[]= {
-    { STRING_WITH_LEN("--DISTRIBUTION=consistent") },
-    { STRING_WITH_LEN("--DISTRIBUTION=random") },
-    { STRING_WITH_LEN("--DISTRIBUTION=modula") },
-    { NULL, 0}
-  };
-
-  for (scanner_string_st *ptr= test_strings; ptr->size; ptr++)
-  {
-    rc= memcached_parse_options(memc, ptr->c_ptr, ptr->size);
-    test_true_got(rc == MEMCACHED_SUCCESS, ptr->c_ptr);
-  }
-
-  memcached_free(memc);
+  return _test_option(distribution_strings);
+}
 
-  return TEST_SUCCESS;
+test_return_t parser_key_prefix_test(memcached_st *junk)
+{
+  (void)junk;
+  return _test_option(distribution_strings);
 }
index 78518d20288ec3c64df5948d2f0cd3ac5f8542f6..5c5ad7f22be7fccedaebd23040db55600f6dbc74 100644 (file)
@@ -64,6 +64,9 @@ test_return_t parser_hash_test(memcached_st *junk);
 LIBTEST_INTERNAL_API
 test_return_t parser_boolean_options_test(memcached_st *junk);
 
+LIBTEST_INTERNAL_API
+test_return_t parser_key_prefix_test(memcached_st *junk);
+
 #ifdef __cplusplus
 }
 #endif