Updating test framework for startup/shutdown of memcached.
authorBrian Aker <brian@tangent.org>
Fri, 1 Jul 2011 16:49:58 +0000 (09:49 -0700)
committerBrian Aker <brian@tangent.org>
Fri, 1 Jul 2011 16:49:58 +0000 (09:49 -0700)
40 files changed:
.bzrignore
libmemcached/assert.hpp [new file with mode: 0644]
libmemcached/common.h
libmemcached/connect.cc
libmemcached/error.cc
libmemcached/error.h
libmemcached/error.hpp
libmemcached/hosts.cc
libmemcached/include.am
libmemcached/io.cc
libmemcached/memcached.cc
libmemcached/memcached_util.h
libmemcached/response.cc
libmemcached/server.cc
libmemcached/server.h
libmemcached/server_list.cc
libmemcached/stats.cc
libmemcached/util/include.am
libmemcached/util/pid.cc [new file with mode: 0644]
libmemcached/util/pid.h [new file with mode: 0644]
libmemcached/util/ping.cc
libtest/error.h
libtest/framework.cc
libtest/framework.h
libtest/include.am
libtest/killpid.cc [new file with mode: 0644]
libtest/killpid.h [new file with mode: 0644]
libtest/memcached.cc
libtest/server.cc [new file with mode: 0644]
libtest/server.h
libtest/test.cc
libtest/test.hpp
libtest/wait.cc [new file with mode: 0644]
libtest/wait.h [new file with mode: 0644]
tests/cycle.cc [new file with mode: 0644]
tests/deprecated.cc
tests/include.am
tests/libmemcached_world.h
tests/mem_functions.cc
tests/start.cc [deleted file]

index f4695169333c534d92bd44e71624b6d95d7ad025..a64e1be4e954db59bc2283a59cda9f9959b86437 100644 (file)
@@ -99,3 +99,7 @@ tests/testplus
 tests/testudp
 tests/var/
 unittests/unittests
+libtest/wait
+docs/text
+docs/changes
+tests/cycle
diff --git a/libmemcached/assert.hpp b/libmemcached/assert.hpp
new file mode 100644 (file)
index 0000000..8a46784
--- /dev/null
@@ -0,0 +1,57 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libmcachedd client library.
+ *
+ *  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 <cstdlib>
+#include <cstdio>
+
+#ifdef NDEBUG
+#define        assert(__expr, __mesg)  ((void)0)
+#else
+
+#define assert_msg(__expr, __mesg) \
+do \
+{ \
+  if (not (__expr)) \
+  { \
+    fprintf(stderr, "\nAssertion \"%s\" failed for function \"%s\" likely for %s, at %s:%d\n", #__expr, __func__, (#__mesg),  __FILE__, __LINE__);\
+    abort(); \
+  } \
+} while (0)
+
+#endif
index 98072cb3138d4266994173ff4d59b63e1eadd838..ac300def96249c7c1296be9edefe8f9b1201fb51 100644 (file)
@@ -154,12 +154,12 @@ LIBMEMCACHED_LOCAL
 memcached_return_t memcached_purge(memcached_server_write_instance_st ptr);
 
 LIBMEMCACHED_LOCAL
-memcached_server_st *memcached_server_create_with(const memcached_st *memc,
-                                                  memcached_server_write_instance_st host,
-                                                  const char *hostname,
-                                                  in_port_t port,
-                                                  uint32_t weight,
-                                                  memcached_connection_t type);
+  memcached_server_st *__server_create_with(const memcached_st *memc,
+                                            memcached_server_write_instance_st host,
+                                            const char *hostname,
+                                            in_port_t port,
+                                            uint32_t weight,
+                                            memcached_connection_t type);
 
 
 static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary)
index 5e6c77f568a44b07c2dcc68ecb4e9163a2eee5fa..43924116fc69f20919bf7b01b30c4385528bc54e 100644 (file)
@@ -101,11 +101,11 @@ static memcached_return_t connect_poll(memcached_server_st *ptr)
           int err;
           socklen_t len= sizeof (err);
           (void)getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len);
-          ptr->cached_errno= (err == 0) ? get_socket_errno() : err;
+          memcached_set_errno(*ptr, (err == 0) ? get_socket_errno() : err, MEMCACHED_AT);
         }
         else
         {
-          ptr->cached_errno= get_socket_errno();
+          memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
         }
 
         WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
@@ -347,7 +347,8 @@ static memcached_return_t unix_socket_connect(memcached_server_st *ptr)
 
   if ((ptr->fd= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
   {
-    return memcached_set_errno(*ptr, errno, NULL);
+    memcached_set_errno(*ptr, errno, NULL);
+    return MEMCACHED_CONNECTION_FAILURE;
   }
 
   struct sockaddr_un servAddr;
@@ -374,7 +375,8 @@ static memcached_return_t unix_socket_connect(memcached_server_st *ptr)
 
       default:
         WATCHPOINT_ERRNO(errno);
-        return memcached_set_errno(*ptr, errno, MEMCACHED_AT);
+        memcached_set_errno(*ptr, errno, MEMCACHED_AT);
+        return MEMCACHED_CONNECTION_FAILURE;
       }
     }
   } while (0);
@@ -540,7 +542,9 @@ memcached_return_t memcached_connect(memcached_server_write_instance_st ptr)
   memcached_return_t rc= MEMCACHED_NO_SERVERS;
 
   if (ptr->fd != INVALID_SOCKET)
+  {
     return MEMCACHED_SUCCESS;
+  }
 
   LIBMEMCACHED_MEMCACHED_CONNECT_START();
 
index 5cfb4be29f6f3c45e9699c472b8f2520b65f90cf..a8f420431e71c0c8af37de62a08f6dac20894911 100644 (file)
@@ -50,12 +50,31 @@ struct memcached_error_t
   char message[MAX_ERROR_LENGTH];
 };
 
+static void _set(memcached_server_st& server, memcached_st& memc)
+{
+  if (server.error_messages && server.error_messages->query_id != server.root->query_id)
+  {
+    memcached_error_free(server);
+  }
+
+  if (memc.error_messages == NULL)
+    return;
+
+  memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
+  if (not error) // Bad business if this happens
+    return;
+
+  memcpy(error, memc.error_messages, sizeof(memcached_error_t));
+  error->next= server.error_messages;
+  server.error_messages= error;
+}
+
 static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
 {
   (void)at;
   if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
   {
-    memcached_error_free(&memc);
+    memcached_error_free(memc);
   }
 
   // For memory allocation we use our error since it is a bit more specific
@@ -196,6 +215,7 @@ memcached_return_t memcached_set_error(memcached_server_st& self, memcached_retu
     return rc;
 
   _set(*self.root, &error_host, rc, at);
+  _set(self, (*self.root));
 
   return rc;
 }
@@ -215,6 +235,7 @@ memcached_return_t memcached_set_error(memcached_server_st& self, memcached_retu
     return rc;
 
   _set(*self.root, &error_host, rc, at);
+  _set(self, *self.root);
 
   return rc;
 }
@@ -285,13 +306,12 @@ memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errn
 
   memcached_string_t error_host= { hostname_port_message, size };
 
-  self.cached_errno= local_errno; // Store in the actual server
-
   memcached_return_t rc= MEMCACHED_ERRNO;
   if (not self.root)
     return rc;
 
   _set(*self.root, &error_host, rc, at, local_errno);
+  _set(self, (*self.root));
 
   return rc;
 }
@@ -307,13 +327,12 @@ memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errn
 
   memcached_string_t error_host= { hostname_port_message, size };
 
-  self.cached_errno= local_errno; // Store in the actual server
-
   memcached_return_t rc= MEMCACHED_ERRNO;
   if (not self.root)
     return rc;
 
   _set(*self.root, &error_host, rc, at, local_errno);
+  _set(self, (*self.root));
 
   return rc;
 }
@@ -360,13 +379,16 @@ static void _error_free(memcached_error_t *error)
   }
 }
 
-void memcached_error_free(memcached_st *self)
+void memcached_error_free(memcached_stself)
 {
-  if (not self)
-    return;
+  _error_free(self.error_messages);
+  self.error_messages= NULL;
+}
 
-  _error_free(self->error_messages);
-  self->error_messages= NULL;
+void memcached_error_free(memcached_server_st& self)
+{
+  _error_free(self.error_messages);
+  self.error_messages= NULL;
 }
 
 const char *memcached_last_error_message(memcached_st *memc)
@@ -417,3 +439,40 @@ int memcached_last_error_errno(memcached_st *memc)
 
   return memc->error_messages->local_errno;
 }
+
+const char *memcached_server_error(memcached_server_instance_st server)
+{
+  if (not server)
+    return memcached_strerror(server->root, MEMCACHED_INVALID_ARGUMENTS);
+
+  if (not server->error_messages)
+    return memcached_strerror(server->root, MEMCACHED_SUCCESS);
+
+  if (not server->error_messages->size)
+    return memcached_strerror(server->root, server->error_messages->rc);
+
+  return server->error_messages->message;
+}
+
+
+memcached_error_t *memcached_error_copy(const memcached_server_st& server)
+{
+  if (not server.error_messages)
+    return NULL;
+
+  memcached_error_t *error= (memcached_error_t *)libmemcached_malloc(server.root, sizeof(memcached_error_t));
+  memcpy(error, server.error_messages, sizeof(memcached_error_t));
+  error->next= NULL;
+
+  return error;
+}
+
+memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr)
+{
+  if (ptr and ptr->error_messages)
+  {
+    return ptr->error_messages->rc;
+  }
+
+  return MEMCACHED_FAILURE;
+}
index 754cffe8699dab7d879b62fd1267658ba3249683..99beb8cafbc840c640f59dccc1cf75861399ef0c 100644 (file)
@@ -41,9 +41,6 @@
 extern "C" {
 #endif
 
-LIBMEMCACHED_LOCAL
-  void memcached_error_free(memcached_st *error);
-
 LIBMEMCACHED_API
   const char *memcached_last_error_message(memcached_st *memc);
 
@@ -56,6 +53,12 @@ LIBMEMCACHED_API
 LIBMEMCACHED_API
   int memcached_last_error_errno(memcached_st *memc);
 
+LIBMEMCACHED_API
+  const char *memcached_server_error(memcached_server_instance_st ptr);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 1c683fc5d7e5d2bf155af42a53fc0a2e75b23cba..55ff1bd9d06e429e29b54a5b8cf7648489f55f5b 100644 (file)
@@ -84,4 +84,13 @@ LIBMEMCACHED_LOCAL
 LIBMEMCACHED_LOCAL
 bool memcached_has_current_error(memcached_st &memc);
 
+LIBMEMCACHED_LOCAL
+void memcached_error_free(memcached_st&);
+
+LIBMEMCACHED_LOCAL
+void memcached_error_free(memcached_server_st&);
+
+LIBMEMCACHED_LOCAL
+memcached_error_t *memcached_error_copy(const memcached_server_st&);
+
 #endif
index 4c419b02549a1c030d27f9719bdc38ae413b7a05..db6398914a699472d6163c3d4327b9f882e93055 100644 (file)
@@ -344,7 +344,9 @@ static memcached_return_t update_continuum(memcached_st *ptr)
 memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list)
 {
   if (not list)
+  {
     return MEMCACHED_SUCCESS;
+  }
 
   uint32_t count= memcached_server_list_count(list);
 
@@ -362,8 +364,7 @@ memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_serv
     memcached_server_write_instance_st instance;
 
     if ((ptr->flags.use_udp && list[x].type != MEMCACHED_CONNECTION_UDP)
-        or ((list[x].type == MEMCACHED_CONNECTION_UDP)
-            and ! (ptr->flags.use_udp)) )
+        or ((list[x].type == MEMCACHED_CONNECTION_UDP) and not (ptr->flags.use_udp)) )
     {
       return MEMCACHED_INVALID_HOST_PROTOCOL;
     }
@@ -374,8 +375,8 @@ memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_serv
     instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr));
     WATCHPOINT_ASSERT(instance);
 
-    if (not memcached_server_create_with(ptr, instance, list[x].hostname,
-                                         list[x].port, list[x].weight, list[x].type))
+    if (not __server_create_with(ptr, instance, list[x].hostname,
+                                 list[x].port, list[x].weight, list[x].type))
     {
       return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
     }
@@ -453,7 +454,7 @@ memcached_return_t memcached_server_add_with_weight(memcached_st *ptr,
   if (not hostname)
     hostname= "localhost";
 
-  return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_TCP);
+  return server_add(ptr, hostname, port, weight, hostname[0] == '/' ? MEMCACHED_CONNECTION_UNIX_SOCKET  : MEMCACHED_CONNECTION_TCP);
 }
 
 static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
@@ -479,7 +480,7 @@ static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
   /* TODO: Check return type */
   memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr));
 
-  if (not memcached_server_create_with(ptr, instance, hostname, port, weight, type))
+  if (not __server_create_with(ptr, instance, hostname, port, weight, type))
   {
     return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
   }
index e1bed44fa07c423fbb659d717efb01de67401bb5..db612892245d430561b369b43b978547048741e8 100644 (file)
@@ -12,6 +12,7 @@ EXTRA_DIST+= \
             libmemcached/memcached/README.txt
 
 noinst_HEADERS+= \
+                libmemcached/assert.hpp \
                 libmemcached/byteorder.h \
                 libmemcached/common.h \
                 libmemcached/do.hpp \
index a787b0c288801b467e6ffe27837a154caabe69a8..f77a097325c84d0c166c5f4149c8d793c54427d5 100644 (file)
@@ -128,11 +128,11 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
           int err;
           socklen_t len= sizeof (err);
           (void)getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len);
-          ptr->cached_errno= (err == 0) ? get_socket_errno() : err;
+          memcached_set_errno(*ptr, (err == 0) ? get_socket_errno() : err, MEMCACHED_AT);
         }
         else
         {
-          ptr->cached_errno= get_socket_errno();
+          memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
         }
         memcached_quit_server(ptr, true);
 
@@ -141,10 +141,9 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
     }
   }
 
-  ptr->cached_errno= get_socket_errno();
   memcached_quit_server(ptr, true);
 
-  return memcached_set_error(*ptr, MEMCACHED_FAILURE, MEMCACHED_AT);
+  return memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
 }
 
 memcached_return_t memcached_io_wait_for_write(memcached_server_write_instance_st ptr)
@@ -711,7 +710,7 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr,
 
     if (sent_length == SOCKET_ERROR)
     {
-      ptr->cached_errno= get_socket_errno();
+      memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
 #if 0 // @todo I should look at why we hit this bit of code hard frequently
       WATCHPOINT_ERRNO(get_socket_errno());
       WATCHPOINT_NUMBER(get_socket_errno());
index f93f74b41169be93c343b694b4d9494c6121648b..f35e7cc90a0834e95cc13c29ddeec20134e0bec5 100644 (file)
@@ -163,7 +163,7 @@ static void _free(memcached_st *ptr, bool release_st)
   memcached_array_free(ptr->prefix_key);
   ptr->prefix_key= NULL;
 
-  memcached_error_free(ptr);
+  memcached_error_free(*ptr);
 
   if (ptr->sasl.callbacks)
   {
index 3f1185d195dcbb5c77ade6887eaa1b41be87000d..c0a4620af9aff1b3f396eea7997fa8a80d97a3bc 100644 (file)
@@ -38,6 +38,7 @@
 #pragma once
 
 
+#include <libmemcached/util/pid.h>
 #include <libmemcached/util/flush.h>
 #include <libmemcached/util/ping.h>
 #include <libmemcached/util/pool.h>
index 44ce840ab722fa32e99f3ea4093c05fd9531fd56..ce649bcbef49b16626c5fe90add051338d948883 100644 (file)
@@ -218,7 +218,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
     if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
     {
       memcached_quit_server(ptr, true);
-      return memcached_set_error(*ptr, rrc, MEMCACHED_AT);
+      return memcached_set_error(*ptr, MEMCACHED_IN_PROGRESS, MEMCACHED_AT);
     }
     else if (memcached_failed(rrc))
     {
@@ -291,28 +291,7 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
 
         while (*endptr != '\r' && *endptr != '\n') endptr++;
 
-        /*
-          Yes, we could make this "efficent" but to do that we would need
-          to maintain more state for the size of the buffer. Why waste
-          memory in the struct, which is important, for something that
-          rarely should happen?
-        */
-        char *rel_ptr= (char *)libmemcached_realloc(ptr->root,
-                                                    ptr->cached_server_error,
-                                                    (size_t) (endptr - startptr + 1));
-
-        if (rel_ptr == NULL)
-        {
-          /* If we happened to have some memory, we just null it since we don't know the size */
-          if (ptr->cached_server_error)
-            ptr->cached_server_error[0]= 0;
-          return MEMCACHED_SERVER_ERROR;
-        }
-        ptr->cached_server_error= rel_ptr;
-
-        memcpy(ptr->cached_server_error, startptr, (size_t) (endptr - startptr));
-        ptr->cached_server_error[endptr - startptr]= 0;
-        return MEMCACHED_SERVER_ERROR;
+        return memcached_set_error(*ptr, MEMCACHED_SERVER_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
       }
       else if (buffer[1] == 'T')
       {
index 52daefecf460b36fad99d156e8f5023a5cc5fba7..f5fe62e19bf3729fe867c1542c29bc286196ee45 100644 (file)
@@ -50,7 +50,6 @@ static inline void _server_init(memcached_server_st *self, memcached_st *root,
   self->number_of_hosts= 0;
   self->cursor_active= 0;
   self->port= port;
-  self->cached_errno= 0;
   self->fd= -1;
   self->io_bytes_sent= 0;
   self->server_failure_counter= 0;
@@ -61,8 +60,8 @@ static inline void _server_init(memcached_server_st *self, memcached_st *root,
   self->micro_version= UINT8_MAX;
   self->minor_version= UINT8_MAX;
   self->type= type;
+  self->error_messages= NULL;
   self->read_ptr= self->read_buffer;
-  self->cached_server_error= NULL;
   self->read_buffer_length= 0;
   self->read_data_length= 0;
   self->write_buffer_offset= 0;
@@ -113,10 +112,10 @@ static memcached_server_st *_server_create(memcached_server_st *self, const memc
   return self;
 }
 
-memcached_server_st *memcached_server_create_with(const memcached_st *memc,
-                                                  memcached_server_write_instance_st self,
-                                                  const char *hostname, in_port_t port,
-                                                  uint32_t weight, memcached_connection_t type)
+memcached_server_st *__server_create_with(const memcached_st *memc,
+                                          memcached_server_write_instance_st self,
+                                          const char *hostname, in_port_t port,
+                                          uint32_t weight, memcached_connection_t type)
 {
   self= _server_create(self, memc);
 
@@ -135,18 +134,16 @@ memcached_server_st *memcached_server_create_with(const memcached_st *memc,
   return self;
 }
 
-void memcached_server_free(memcached_server_st *self)
+void __server_free(memcached_server_st *self)
 {
-  if (not self)
-    return;
-
   memcached_quit_server(self, false);
 
-  if (self->cached_server_error)
-    free(self->cached_server_error);
-
   if (self->address_info)
+  {
     freeaddrinfo(self->address_info);
+  }
+
+  memcached_error_free(*self);
 
   if (memcached_is_allocated(self))
   {
@@ -158,6 +155,20 @@ void memcached_server_free(memcached_server_st *self)
   }
 }
 
+void memcached_server_free(memcached_server_st *self)
+{
+  if (not self)
+    return;
+
+  if (memcached_server_list_count(self))
+  {
+    memcached_server_list_free(self);
+    return;
+  }
+
+  __server_free(self);
+}
+
 /*
   If we do not have a valid object to clone from, we toss an error.
 */
@@ -168,15 +179,15 @@ memcached_server_st *memcached_server_clone(memcached_server_st *destination,
   if (not source)
     return NULL;
 
-  destination= memcached_server_create_with(source->root, destination,
-                                            source->hostname, source->port, source->weight,
-                                            source->type);
+  destination= __server_create_with(source->root, destination,
+                                    source->hostname, source->port, source->weight,
+                                    source->type);
   if (not destination)
   {
-    destination->cached_errno= source->cached_errno;
-
-    if (source->cached_server_error)
-      destination->cached_server_error= strdup(source->cached_server_error);
+    if (source->error_messages)
+    {
+      destination->error_messages= memcached_error_copy(*source);
+    }
   }
 
   return destination;
@@ -272,7 +283,7 @@ void memcached_server_error_reset(memcached_server_st *self)
   if (not self)
     return;
 
-  self->cached_server_error[0]= 0;
+  memcached_error_free(*self);
 }
 
 memcached_server_instance_st memcached_server_get_last_disconnect(const memcached_st *self)
@@ -284,23 +295,6 @@ memcached_server_instance_st memcached_server_get_last_disconnect(const memcache
   return self->last_disconnected_server;
 }
 
-void memcached_server_list_free(memcached_server_list_st self)
-{
-  if (not self)
-    return;
-
-  for (uint32_t x= 0; x < memcached_server_list_count(self); x++)
-  {
-    if (self[x].address_info)
-    {
-      freeaddrinfo(self[x].address_info);
-      self[x].address_info= NULL;
-    }
-  }
-
-  libmemcached_free(self->root, self);
-}
-
 uint32_t memcached_servers_set_count(memcached_server_st *servers, uint32_t count)
 {
   WATCHPOINT_ASSERT(servers);
@@ -346,11 +340,6 @@ uint32_t memcached_server_response_count(memcached_server_instance_st self)
   return self->cursor_active;
 }
 
-const char *memcached_server_error(memcached_server_instance_st ptr)
-{
-  return ptr ?  ptr->cached_server_error : NULL;
-}
-
 const char *memcached_server_type(memcached_server_instance_st ptr)
 {
   if (ptr)
index 425dfb01606892c347febbace178d2c47cbfab09..a45616a1010109f2f814f8682381e0dba98514f0 100644 (file)
@@ -55,7 +55,6 @@ struct memcached_server_st {
   uint32_t number_of_hosts;
   uint32_t cursor_active;
   in_port_t port;
-  int cached_errno;
   memcached_socket_t fd;
   uint32_t io_bytes_sent; /* # bytes sent since last read */
   uint32_t server_failure_counter;
@@ -70,7 +69,6 @@ struct memcached_server_st {
   uint8_t minor_version; // ditto
   memcached_connection_t type;
   char *read_ptr;
-  char *cached_server_error;
   size_t read_buffer_length;
   size_t read_data_length;
   size_t write_buffer_offset;
@@ -79,6 +77,7 @@ struct memcached_server_st {
   time_t next_retry;
   memcached_st *root;
   uint64_t limit_maxbytes;
+  struct memcached_error_t *error_messages;
   char read_buffer[MEMCACHED_MAX_BUFFER];
   char write_buffer[MEMCACHED_MAX_BUFFER];
   char hostname[NI_MAXHOST];
@@ -159,13 +158,12 @@ const char *memcached_server_name(memcached_server_instance_st self);
 LIBMEMCACHED_API
 in_port_t memcached_server_port(memcached_server_instance_st self);
 
-LIBMEMCACHED_API
-const char *memcached_server_error(memcached_server_instance_st ptr);
-
 LIBMEMCACHED_API
 const char *memcached_server_type(memcached_server_instance_st ptr);
 
 
+LIBMEMCACHED_LOCAL
+void __server_free(memcached_server_st *);
 
 #ifdef __cplusplus
 } // extern "C"
index 6cf6ae94c8930a1b7b5441feda06ddde0b0ad53c..4da1996354daee6c8cd802d89e2acfc2b58cf485 100644 (file)
@@ -1,16 +1,44 @@
-/* LibMemcached
- * Copyright (C) 2006-2010 Brian Aker
- * All rights reserved.
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
  *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
  *
- * Summary: 
+ *  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>
+#include <libmemcached/assert.hpp>
 
 memcached_server_list_st 
 memcached_server_list_append_with_weight(memcached_server_list_st ptr,
@@ -21,13 +49,23 @@ memcached_server_list_append_with_weight(memcached_server_list_st ptr,
   uint32_t count;
   memcached_server_list_st new_host_list;
 
-  if (hostname == NULL || error == NULL)
-    return NULL;
+  memcached_return_t unused;
+  if (error == NULL)
+    error= &unused;
+
+  if (hostname == NULL)
+  {
+    hostname= "localhost";
+  }
 
   if (hostname[0] == '/')
+  {
     port = 0;
-  else if (! port)
+  }
+  else if (not port)
+  {
     port= MEMCACHED_DEFAULT_PORT;
+  }
 
   /* Increment count for hosts */
   count= 1;
@@ -37,23 +75,23 @@ memcached_server_list_append_with_weight(memcached_server_list_st ptr,
   }
 
   new_host_list= (memcached_server_write_instance_st)realloc(ptr, sizeof(memcached_server_st) * count);
-  if (!new_host_list)
+  if (not new_host_list)
   {
-    ptr->cached_errno= errno;
-    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    *error= memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
     return NULL;
   }
 
   /* @todo Check return type */
-  if (not memcached_server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET))
+  if (not __server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET))
   {
-    ptr->cached_errno= errno;
-    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    *error= memcached_set_errno(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
     return NULL;
   }
 
+#if 0
   // Handset allocated since 
   new_host_list->options.is_allocated= true;
+#endif
 
   /* Backwards compatibility hack */
   memcached_servers_set_count(new_host_list, count);
@@ -86,3 +124,17 @@ void memcached_server_list_set(memcached_st *self, memcached_server_st *list)
 {
   self->servers= list;
 }
+
+void memcached_server_list_free(memcached_server_list_st self)
+{
+  if (not self)
+    return;
+
+  for (uint32_t x= 0; x < memcached_server_list_count(self); x++)
+  {
+    assert_msg(not memcached_is_allocated(&self[x]), "You have called memcached_server_list_free(), but you did not pass it a valid memcached_server_list_st");
+    __server_free(&self[x]);
+  }
+
+  libmemcached_free(self->root, self);
+}
index 5a2013e815b9d44a5da236dc0250170ee456527e..6e2ef31f5140452111a66215abf90693a1c58f4b 100644 (file)
@@ -493,6 +493,7 @@ memcached_stat_st *memcached_stat(memcached_st *self, char *args, memcached_retu
 
     stat_instance= stats +x;
 
+    stat_instance->pid= -1;
     stat_instance->root= self;
 
     instance= memcached_server_instance_fetch(self, x);
index 449b2c1882aded433e194cd63f178bf3163049ba..ea80eb8fc465a85fb38a43820bc598e61e240c27 100644 (file)
@@ -7,6 +7,7 @@ nobase_include_HEADERS+= \
                         libmemcached/memcached_util.h \
                         libmemcached/util.h \
                         libmemcached/util/flush.h \
+                        libmemcached/util/pid.h \
                         libmemcached/util/ping.h \
                         libmemcached/util/pool.h \
                         libmemcached/util/version.h
@@ -15,6 +16,7 @@ endif
 
 libmemcached_libmemcachedutil_la_SOURCES= \
                                          libmemcached/util/flush.cc \
+                                         libmemcached/util/pid.cc \
                                          libmemcached/util/ping.cc \
                                          libmemcached/util/pool.cc \
                                          libmemcached/util/version.cc
diff --git a/libmemcached/util/pid.cc b/libmemcached/util/pid.cc
new file mode 100644 (file)
index 0000000..75edd51
--- /dev/null
@@ -0,0 +1,76 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker 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.
+ *
+ * Summary: connects to a host, and determines what its pid is
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <libmemcached/memcached_util.h>
+
+
+// Never look at the stat object directly.
+
+
+pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret)
+{
+  memcached_st *memc_ptr= memcached_create(NULL);
+
+  pid_t pid= -1;
+
+  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+  if (memcached_success(rc))
+  {
+    if (memcached_success(memcached_version(memc_ptr)))
+    {
+      memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
+      if (stat and stat->pid > 0)
+      {
+        pid= stat->pid;
+      }
+
+      memcached_stat_free(memc_ptr, stat);
+    }
+  }
+  memcached_free(memc_ptr);
+
+  if (ret)
+  {
+    *ret= rc;
+  }
+
+  return pid;
+}
+
diff --git a/libmemcached/util/pid.h b/libmemcached/util/pid.h
new file mode 100644 (file)
index 0000000..f2fb748
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  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_API
+pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
+
index 37da864925f680b760a6f95f06691c9860aa9d63..52489b95fdef180a4fd97076bb2d04cb19a96be7 100644 (file)
@@ -51,6 +51,16 @@ bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_retu
     rc= memcached_version(memc_ptr);
   }
 
+  if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
+  {
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc_ptr, 0);
+
+    if (instance and instance->error_messages)
+    {
+      rc= memcached_server_error_return(instance);
+    }
+  }
   memcached_free(memc_ptr);
 
   if (ret)
@@ -58,5 +68,5 @@ bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_retu
     *ret= rc;
   }
 
-  return rc == MEMCACHED_SUCCESS;
+  return memcached_success(rc);
 }
index c4a3a70247733c9de07c2005f021a002aa4de348..a40868b3c1ba41cc8d0c1dd5ccf250aeb4a803ac 100644 (file)
@@ -16,3 +16,4 @@ enum test_return_t {
 
 
 #define test_failed(__test_return_t) ((__test_return_t) != TEST_SUCCESS)
+#define test_success(__test_return_t) ((__test_return_t) == TEST_SUCCESS)
index ff67f20b63b2306da620868f0b7409cceabc1806..eedbd5800f0fda3ce3e0d2f2b88789365e9475df 100644 (file)
@@ -55,3 +55,14 @@ test_return_t Framework::Item::startup(void* arg)
 
   return TEST_SUCCESS;
 }
+
+void* Framework::create(test_return_t* arg)
+{
+  if (_create)
+  {
+    return _create(arg);
+  }
+
+  return NULL;
+}
+
index 7a58cbeeb94cef276c424af3f94a304772ee651c..afb9001ad4847d65f26b0ce6287f94c61352d7a7 100644 (file)
@@ -19,15 +19,7 @@ struct Framework {
   test_callback_create_fn *_create;
   test_callback_fn *_destroy;
 
-  void* create(test_return_t* arg)
-  {
-    if (_create)
-    {
-      return _create(arg);
-    }
-
-    return NULL;
-  }
+  void* create(test_return_t* arg);
 
   test_return_t destroy(void*);
 
index a1ed6ede1d298c574d8d094708540ed3dd822825..0f4d910dd97906238c2a64c2e5000e685faab27f 100644 (file)
@@ -13,6 +13,7 @@ LIBUTEST_TMP = ${abs_top_builddir}/tests/var/tmp/
 
 CLEANFILES+= \
             tests/var/log/* \
+            tests/var/run/* \
             tests/var/tmp/*
 
 noinst_HEADERS+= \
@@ -24,16 +25,21 @@ noinst_HEADERS+= \
                 libtest/failed.h \
                 libtest/framework.h \
                 libtest/get.h \
+                libtest/killpid.h \
                 libtest/runner.h \
                 libtest/server.h \
                 libtest/stats.h \
                 libtest/strerror.h \
                 libtest/test.h \
                 libtest/test.hpp \
-                libtest/visibility.h
+                libtest/visibility.h \
+                libtest/wait.h
 
 noinst_LTLIBRARIES+= libtest/libserver.la
-libtest_libserver_la_SOURCES= libtest/memcached.cc
+libtest_libserver_la_SOURCES= \
+                             libtest/killpid.cc \
+                             libtest/memcached.cc \
+                             libtest/server.cc
 
 noinst_LTLIBRARIES+= libtest/libtest.la
 libtest_libtest_la_SOURCES=\
@@ -42,7 +48,13 @@ libtest_libtest_la_SOURCES=\
 libtest_libtest_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION} -DBUILDING_LIBTEST
 libtest_libtest_la_CPPFLAGS= ${AM_CPPFLAGS}
 
-tests/var: tests/var/log tests/var/tmp
+clearn-var:
+       @rm -f tests/var/log/*
+       @rm -f tests/var/run/*
+       @rm -f tests/var/tmp/*
+
+
+tests/var: tests/var/log tests/var/tmp tests/var/run clearn-var
        $(mkdir_p) tests/var
 
 tests/var/log:
@@ -50,3 +62,10 @@ tests/var/log:
 
 tests/var/tmp:
        $(mkdir_p) tests/var/tmp
+
+tests/var/run:
+       $(mkdir_p) tests/var/run
+
+noinst_PROGRAMS+= libtest/wait
+
+libtest_wait_SOURCES= libtest/wait.cc
diff --git a/libtest/killpid.cc b/libtest/killpid.cc
new file mode 100644 (file)
index 0000000..e963f4a
--- /dev/null
@@ -0,0 +1,116 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  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 <cerrno>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+#include <libtest/killpid.h>
+
+bool kill_pid(pid_t pid_arg)
+{
+  if ((kill(pid_arg, SIGTERM) == -1))
+  {
+    switch (errno)
+    {
+    case EPERM:
+      perror(__func__);
+      std::cerr << __func__ << " -> Does someone else have a process running locally for " << int(pid_arg) << "?" << std::endl;
+      return false;
+
+    case ESRCH:
+      perror(__func__);
+      std::cerr << "Process " << int(pid_arg) << " not found." << std::endl;
+      return false;
+
+    default:
+    case EINVAL:
+      perror(__func__);
+      return false;
+    }
+  }
+
+  int status= 0;
+  pid_t pid= waitpid(pid_arg, &status, 0);
+  if (pid == -1)
+  {
+    switch (errno)
+    {
+    case ECHILD:
+      return true;
+    }
+    std::cerr << std::endl << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(pid_arg) << std::endl;
+    return false;
+  }
+
+  if (WIFEXITED(status))
+    return true;
+
+  if (WCOREDUMP(status))
+    return true;
+
+  return false;
+}
+
+
+void kill_file(const std::string &filename)
+{
+  FILE *fp;
+
+  if (filename.empty())
+    return;
+
+  if ((fp= fopen(filename.c_str(), "r")))
+  {
+    char pid_buffer[1024];
+
+    char *ptr= fgets(pid_buffer, sizeof(pid_buffer), fp);
+    fclose(fp);
+
+    if (ptr)
+    {
+      pid_t pid= (pid_t)atoi(pid_buffer);
+      if (pid != 0)
+      {
+        kill_pid(pid);
+        unlink(filename.c_str()); // If this happens we may be dealing with a dead server that left its pid file.
+      }
+    }
+  }
+}
diff --git a/libtest/killpid.h b/libtest/killpid.h
new file mode 100644 (file)
index 0000000..d67ec94
--- /dev/null
@@ -0,0 +1,42 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  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
+
+
+bool kill_pid(pid_t pid_arg);
+
+void kill_file(const std::string &filename);
index 8c79b17ddd51984504e182f5d22294bb8f2d7aa1..e7e87f262006b0ed7f04bdccc93e61c806ceaf42 100644 (file)
 
 #define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT+10
 
-#include <config.h>
-
-#include <iso646.h>
-
-#include <assert.h>
+#include <libtest/common.h>
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
 #include <limits.h>
 #include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <sys/time.h>
-#include <time.h>
 #include <unistd.h>
-#include <errno.h>
+#include <iostream>
 
 #include <libmemcached/memcached.h>
 #include <libmemcached/util.h>
 
 #include <libtest/server.h>
+#include <libtest/killpid.h>
+#include <libtest/wait.h>
+
+#include <boost/lexical_cast.hpp>
+
+
+#define CERR_PREFIX std::endl << __FILE__ << ":" << __LINE__ << " "
 
 static void global_sleep(void)
 {
@@ -73,269 +79,221 @@ static void global_sleep(void)
 #endif
 }
 
-static bool wait_for_file(const char *filename)
-{
-  uint32_t timeout= 6;
-  uint32_t waited;
-  uint32_t this_wait;
-  uint32_t retry;
+#define SOCKET_FILE "/tmp/memcached.socket"
 
-  for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
-  {
-    if ((! access(filename, R_OK)) || (waited >= timeout))
-    {
-      return true;
-    }
-
-    this_wait= retry * retry / 3 + 1;
-    sleep(this_wait);
-  }
-
-  return false;
-}
-
-static void kill_file(const char *file_buffer)
+static bool cycle_server(server_st& server)
 {
-  FILE *fp;
-
-  while ((fp= fopen(file_buffer, "r")))
+  while (1)
   {
-    char pid_buffer[1024];
-
-    if (fgets(pid_buffer, sizeof(pid_buffer), fp) != NULL)
+    if (libmemcached_util_ping(server.hostname, server.port(), NULL))
     {
-      pid_t pid= (pid_t)atoi(pid_buffer);
-      if (pid != 0)
+      // First we try to kill it, and on fail of that we flush it.
+      pid_t pid= libmemcached_util_getpid(server.hostname, server.port(), NULL);
+
+      if (pid > 0 and kill_pid(pid))
       {
-        if (kill(pid, SIGTERM) == -1)
-        {
-          remove(file_buffer); // If this happens we may be dealing with a dead server that left its pid file.
-        }
-        else
-        {
-          uint32_t counter= 3;
-          while ((kill(pid, 0) == 0) && --counter)
-          {
-            global_sleep();
-          }
-        }
+        std::cerr << CERR_PREFIX << "Killed existing server," << server << " with pid:" << pid << std::endl;
+        continue;
+      }
+      else if (libmemcached_util_flush(server.hostname, server.port(), NULL)) // If we can flush it, we will just use it
+      { 
+        std::cerr << CERR_PREFIX << "Found server on port " << int(server.port()) << ", flushed it!" << std::endl;
+        server.set_used();
+        return true;
+      } // No idea what is wrong here, so we need to find a different port
+      else
+      {
+        return false;
       }
     }
 
-    global_sleep();
-
-    fclose(fp);
+    break;
   }
+
+  return true;
 }
 
-void server_startup(server_startup_st *construct)
+bool server_startup(server_startup_st *construct)
 {
-  if ((construct->server_list= getenv("MEMCACHED_SERVERS")))
+  if (getenv(((char *)"MEMCACHED_SERVERS")))
   {
-    printf("servers %s\n", construct->server_list);
+    construct->server_list= getenv(((char *)"MEMCACHED_SERVERS"));
+    printf("servers %s\n", construct->server_list.c_str());
     construct->count= 0;
   }
   else
   {
+    std::string server_config_string;
+
+    uint32_t port_base= 0;
+    for (uint32_t x= 0; x < (construct->count -1); x++)
     {
-      char server_string_buffer[8096];
-      char *end_ptr;
-      end_ptr= server_string_buffer;
+      server_st &server= construct->server[x];
 
-      uint32_t port_base= 0;
-      for (uint32_t x= 0; x < construct->count; x++)
       {
-        int status;
+        char *var;
+        char variable_buffer[1024];
+
+        snprintf(variable_buffer, sizeof(variable_buffer), "LIBMEMCACHED_PORT_%u", x);
 
-        snprintf(construct->pid_file[x], FILENAME_MAX, "/tmp/memcached.pidXXXXXX");
-        int fd;
-        if ((fd= mkstemp(construct->pid_file[x])) == -1)
+        if ((var= getenv(variable_buffer)))
         {
-          perror("mkstemp");
-          return;
+          server.set_port((in_port_t)atoi(var));
         }
-        close(fd);
-
+        else
         {
-          char *var;
-          char variable_buffer[1024];
-
-          snprintf(variable_buffer, sizeof(variable_buffer), "LIBMEMCACHED_PORT_%u", x);
+          server.set_port(in_port_t(x + TEST_PORT_BASE + port_base));
 
-          if ((var= getenv(variable_buffer)))
-          {
-            construct->port[x]= (in_port_t)atoi(var);
-          }
-          else
+          while (not cycle_server(server))
           {
-            do {
-              construct->port[x]= (in_port_t)(x + TEST_PORT_BASE + port_base);
-
-              if (libmemcached_util_ping("localhost", construct->port[x], NULL))
-              {
-                if (libmemcached_util_flush("localhost", construct->port[x], NULL))
-                { 
-                  fprintf(stderr, "Found server on port %d, flushed it!\n", (int)construct->port[x]);
-                  construct->is_used[x]= true;
-                } // If we can flush it, we will just use it
-                else
-                {
-                  fprintf(stderr, "Found server on port %d, could not flush it, so trying next port.\n", (int)construct->port[x]);
-                  port_base++;
-                  construct->port[x]= 0;
-                }
-              }
-            } while (construct->port[x] == 0);
+            std::cerr << CERR_PREFIX << "Found server " << server << ", could not flush it, so trying next port." << std::endl;
+            port_base++;
+            server.set_port(in_port_t(x + TEST_PORT_BASE + port_base));
           }
         }
+      }
 
+      if (server.is_used())
+      {
+        std::cerr << std::endl << "Using server at : " << server << std::endl;
+      }
+      else
+      {
         char buffer[FILENAME_MAX];
         if (x == 0)
         {
-          snprintf(buffer, sizeof(buffer), "%s -d -P %s -t 1 -p %u -U %u -m 128",
-                   MEMCACHED_BINARY, construct->pid_file[x], construct->port[x], construct->port[x]);
+          snprintf(buffer, sizeof(buffer), "%s -d -t 1 -p %u -U %u -m 128",
+                   MEMCACHED_BINARY, server.port(), server.port());
         }
         else
         {
-          snprintf(buffer, sizeof(buffer), "%s -d -P %s -t 1 -p %u -U %u",
-                   MEMCACHED_BINARY, construct->pid_file[x], construct->port[x], construct->port[x]);
+          snprintf(buffer, sizeof(buffer), "%s -d -t 1 -p %u -U %u",
+                   MEMCACHED_BINARY, server.port(), server.port());
         }
 
-        if (construct->is_used[x])
+        int status= system(buffer);
+        if (status == -1)
         {
-          fprintf(stderr, "USING SERVER: %s\n", buffer);
+          std::cerr << CERR_PREFIX << "Failed system(" << buffer << ")" << std::endl;
+          return false;
         }
-        else
+        fprintf(stderr, "STARTING SERVER: %s\n", buffer);
+
+        int count= 30;
+        memcached_return_t rc;
+        while (not libmemcached_util_ping(server.hostname, server.port(), &rc) and --count)
         {
-          if (libmemcached_util_ping("localhost", construct->port[x], NULL))
-          {
-            fprintf(stderr, "Server on port %u already exists\n", construct->port[x]);
-          }
-          else
-          {
-            status= system(buffer);
-            fprintf(stderr, "STARTING SERVER: %s  status:%d\n", buffer, status);
-          }
+          global_sleep();
         }
 
-        size_t remaining_length= sizeof(server_string_buffer) - (size_t)(end_ptr -server_string_buffer);
-        int count= snprintf(end_ptr, remaining_length,  "--server=localhost:%u ", construct->port[x]);
-
-        if ((size_t)count >= remaining_length or count < 0)
+        if (memcached_failed(rc))
         {
-          fprintf(stderr, "server names grew to be larger then buffer allowed\n");
-          abort();
+          std::cerr << CERR_PREFIX << "libmemcached_util_ping() failed:" << memcached_strerror(NULL, rc) << " Connection:" << server << std::endl;
+          return false;
         }
-        end_ptr+= count;
-      }
-      *end_ptr= 0;
-
 
-      for (uint32_t x= 0; x < construct->count; x++)
-      {
-        if (! wait_for_file(construct->pid_file[x]))
+        server.set_pid(libmemcached_util_getpid(server.hostname, server.port(), &rc));
+        if (not server.has_pid())
         {
-          abort();
+          std::cerr << CERR_PREFIX << "libmemcached_util_getpid() failed" << memcached_strerror(NULL, rc) << " Connection: " << server << std::endl;
+          return false;
         }
       }
 
-      for (uint32_t x= 0; x < construct->count; x++)
+      server_config_string+= "--server=";
+      server_config_string+= server.hostname;
+      server_config_string+= ":";
+      server_config_string+= boost::lexical_cast<std::string>(server.port());
+      server_config_string+= " ";
+      fprintf(stderr, " Port %d\n", server.port());
+    }
+
+    {
+      server_st &server= construct->server[construct->count -1];
+
       {
-        uint32_t counter= 3000; // Absurd, just to catch run away process
+        std::string socket_file;
+        char *var;
 
-        if (construct->is_used[x])
-          continue;
+        server.set_hostname(SOCKET_FILE);
 
-        while (construct->pids[x] <= 0  && --counter)
+        if ((var= getenv("LIBMEMCACHED_SOCKET")))
+        {
+          socket_file+= var;
+        }
+        else
         {
-          FILE *file= fopen(construct->pid_file[x], "r");
-          if (file)
+          if (not cycle_server(server))
           {
-            char pid_buffer[1024];
-            char *found= fgets(pid_buffer, sizeof(pid_buffer), file);
-
-            if (found)
-            {
-              construct->pids[x]= atoi(pid_buffer);
-              fclose(file);
-
-              if (construct->pids[x] > 0)
-                break;
-            }
-            fclose(file);
+            std::cerr << CERR_PREFIX << "Found server " << server << ", could not flush it, so trying next port." << std::endl;
+            return false;
           }
+        }
+      }
 
-          switch (errno)
-          {
-          default:
-            fprintf(stderr, "Could not open pid file %s -> fopen(%s) -> %s:%d\n", construct->pid_file[x], strerror(errno), __FILE__, __LINE__);
-            abort();
-
-          case ENOENT:
-          case EINTR:
-          case EACCES:
-          case EINPROGRESS:
-            break;
-
-          case ENOTCONN:
-            continue;
-          }
+      if (server.is_used())
+      {
+        std::cerr << std::endl << "Using server at : " << server << std::endl;
+      }
+      else
+      {
+        char buffer[FILENAME_MAX];
+        snprintf(buffer, sizeof(buffer), "%s -d -t 1 -s %s", MEMCACHED_BINARY, SOCKET_FILE);
 
-          // Safety 3rd, check to see if the file has gone away
-          if (! wait_for_file(construct->pid_file[x]))
-          {
-            abort();
-          }
+        int status= system(buffer);
+        if (status == -1)
+        {
+          std::cerr << CERR_PREFIX << "Failed system(" << buffer << ")" << std::endl;
+          return false;
         }
+        fprintf(stderr, "STARTING SERVER: %s\n", buffer);
 
-        bool was_started= false;
-        if (construct->pids[x] > 0)
+        int count= 30;
+        memcached_return_t rc;
+        while (not libmemcached_util_ping(server.hostname, server.port(), &rc) and --count)
         {
-          counter= 30;
-          while (--counter)
-          {
-            if (kill(construct->pids[x], 0) == 0)
-            {
-              was_started= true;
-              break;
-            }
-            global_sleep();
-          }
+          global_sleep();
         }
 
-        if (was_started == false)
+        if (memcached_failed(rc))
         {
-          fprintf(stderr, "Failed to open buffer %s(%d)\n", construct->pid_file[x], construct->pids[x]);
-          for (uint32_t y= 0; y < construct->count; y++)
-          {
-            if (construct->pids[y] > 0)
-              kill(construct->pids[y], SIGTERM);
-          }
-          abort();
+          std::cerr << CERR_PREFIX << "libmemcached_util_ping() failed:" << memcached_strerror(NULL, rc) << " Connection:" << server << std::endl;
+          return false;
+        }
+
+        server.set_pid(libmemcached_util_getpid(server.hostname, server.port(), &rc));
+        if (not server.has_pid())
+        {
+          std::cerr << CERR_PREFIX << "libmemcached_util_getpid() failed" << memcached_strerror(NULL, rc) << " Connection: " << server << std::endl;
+          return false;
         }
       }
 
-      construct->server_list= strndup(server_string_buffer, strlen(server_string_buffer) -1);
+      {
+        set_default_socket(server.hostname);
+        server_config_string+= "--socket=\"";
+        server_config_string+= server.hostname;
+        server_config_string+= "\" ";
+      }
     }
+
+    server_config_string.resize(server_config_string.size() -1); // Remove final space
+    construct->server_list= server_config_string;
   }
 
   srandom((unsigned int)time(NULL));
 
-  printf("\n");
+  std::cerr << std::endl;
+  return true;
 }
 
 void server_shutdown(server_startup_st *construct)
 {
-  if (construct->server_list)
+  for (uint32_t x= 0; x < construct->count; x++)
   {
-    for (uint32_t x= 0; x < construct->count; x++)
-    {
-      if (construct->is_used[x])
-        continue;
-
-      kill_file(construct->pid_file[x]);
-    }
+    if (construct->server[x].is_used())
+      continue;
 
-    free(construct->server_list);
+    construct->server[x].kill();
   }
 }
diff --git a/libtest/server.cc b/libtest/server.cc
new file mode 100644 (file)
index 0000000..78c2a77
--- /dev/null
@@ -0,0 +1,99 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker 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 <iostream>
+
+#include <libtest/server.h>
+#include <libtest/killpid.h>
+
+
+std::ostream& operator<<(std::ostream& output, const server_st &arg)
+{
+  if (arg.is_socket())
+  {
+    output << arg.hostname;
+  }
+  else
+  {
+    output << arg.hostname << ":" << arg.port();
+  }
+  return output;  // for multiple << operators
+}
+
+server_st::~server_st()
+{
+  if (not _used)
+  {
+    kill();
+  }
+}
+
+void server_st::reset_pid()
+{
+  pid_file[0]= 0;
+  _pid= -1;
+}
+
+bool server_st::kill()
+{
+  if (not has_pid() and pid_file[0] == 0)
+  {
+    return true;
+  }
+  
+  if (has_pid())
+  {
+    kill_pid(pid());
+    if (pid_file[0])
+    {
+      unlink(pid_file); // If this happens we may be dealing with a dead server that left its pid file.
+    }
+    reset_pid();
+
+    return true;
+  }
+  else if (pid_file[0])
+  {
+    kill_file(pid_file);
+    reset_pid();
+
+    return true;
+  }
+
+  return false;
+}
index 5444821d685d8aa24faf97ef95594fc74c57d4c3..c209881e3de25c3cf2b23ab97b87b44012de5235 100644 (file)
 
 #pragma once
 
+#include <cstring>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <string>
 #include <unistd.h>
 
-/*
-  Server startup and shutdown functions.
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
+#define SERVERS_TO_CREATE 5
 
-#include <libmemcached/memcached.h>
+struct server_st {
+private:
+  bool _used;
+  pid_t _pid;
+  in_port_t _port;
+  char pid_file[FILENAME_MAX]; // Did we start it, or was it just sitting there?
+public:
 
-typedef struct server_startup_st server_startup_st;
-#define SERVERS_TO_CREATE 5
+  char hostname[NI_MAXHOST];
+
+  server_st() :
+    _used(false),
+    _pid(-1),
+    _port(0)
+  {
+    pid_file[0]= 0;
+    strncpy(hostname, "localhost", sizeof(hostname));
+  }
+
+  void set_port(in_port_t arg)
+  {
+    _port= arg;
+  }
+
+  in_port_t port() const
+  {
+    return _port;
+  }
+
+  bool has_port() const
+  {
+    return not _port == 0;
+  }
+
+  void set_used()
+  {
+    _used= true;
+  }
+
+  void set_pid(pid_t arg)
+  {
+    _pid= arg;
+  }
+
+  pid_t pid() const
+  {
+    return _pid;
+  }
+
+  bool is_used() const
+  {
+    return _used;
+  }
+
+  ~server_st();
+
+  bool has_pid()
+  {
+    return _pid > 0;
+  }
+
+  bool is_socket() const
+  {
+    return hostname[0] == '/';
+  }
+
+  void set_hostname(const char *arg)
+  {
+    strncpy(hostname, arg, sizeof(hostname));
+  }
+
+  bool kill();
+
+private:
+  void reset_pid();
+};
+
+std::ostream& operator<<(std::ostream& output, const server_st &arg);
 
 struct server_startup_st
 {
   uint8_t count;
   uint8_t udp;
-  char *server_list;
-  char pid_file[SERVERS_TO_CREATE][FILENAME_MAX];
-  in_port_t port[SERVERS_TO_CREATE];
-  int pids[SERVERS_TO_CREATE];
-  bool is_used[SERVERS_TO_CREATE]; // Did we start it, or was it just sitting there?
+  std::string server_list;
+  server_st server[SERVERS_TO_CREATE];
+
+  server_startup_st() :
+    count(SERVERS_TO_CREATE),
+    udp(0)
+  { }
+
+  ~server_startup_st()
+  { }
 };
 
-void server_startup(server_startup_st *construct);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+bool server_startup(server_startup_st *construct);
 void server_shutdown(server_startup_st *construct);
 
 #ifdef __cplusplus
index ee743983fffa7f73e3422c698212efa495afc816..a1300a8ad2fd1302b1dfdeac228e3c682af44e31 100644 (file)
@@ -29,6 +29,7 @@
 #endif
 
 static in_port_t global_port= 0;
+static char global_socket[1024];
 
 in_port_t default_port()
 {
@@ -41,6 +42,17 @@ void set_default_port(in_port_t port)
   global_port= port;
 }
 
+const char *default_socket()
+{
+  assert(global_socket[0]);
+  return global_socket;
+}
+void set_default_socket(const char *socket)
+{
+  strncpy(global_socket, socket, strlen(socket));
+}
+
 static void stats_print(Stats *stats)
 {
   std::cout << "\tTotal Collections\t\t\t\t" << stats->collection_total << std::endl;
@@ -142,21 +154,22 @@ Framework::Framework() :
 
 int main(int argc, char *argv[])
 {
-  Framework world;
+  Framework *world= new Framework();
 
-  Stats stats;
-
-  get_world(&world);
-
-  if (not world.runner)
+  if (not world)
   {
-    world.runner= &defualt_runners;
+    return EXIT_FAILURE;
   }
 
+  Stats stats;
+
+  get_world(world);
+
   test_return_t error;
-  void *world_ptr= world.create(&error);
+  void *world_ptr= world->create(&error);
   if (test_failed(error))
   {
+    std::cerr << "create() failed" << std::endl;
     return EXIT_FAILURE;
   }
 
@@ -181,7 +194,7 @@ int main(int argc, char *argv[])
     wildcard= argv[2];
   }
 
-  for (collection_st *next= world.collections; next->name; next++)
+  for (collection_st *next= world->collections; next->name; next++)
   {
     test_return_t collection_rc= TEST_SUCCESS;
     bool failed= false;
@@ -192,11 +205,11 @@ int main(int argc, char *argv[])
 
     stats.collection_total++;
 
-    collection_rc= world.startup(world_ptr);
+    collection_rc= world->startup(world_ptr);
 
     if (collection_rc == TEST_SUCCESS and next->pre)
     {
-      collection_rc= world.runner->pre(next->pre, world_ptr);
+      collection_rc= world->runner->pre(next->pre, world_ptr);
     }
 
     switch (collection_rc)
@@ -232,21 +245,34 @@ int main(int argc, char *argv[])
 
       std::cerr << "\tTesting " << run->name;
 
-      world.item.startup(world_ptr);
-
-      world.item.flush(world_ptr, run);
-
-      world.item.pre(world_ptr);
-
       test_return_t return_code;
-      { // Runner Code
-       gettimeofday(&start_time, NULL);
-       return_code= world.runner->run(run->test_fn, world_ptr);
-       gettimeofday(&end_time, NULL);
-       load_time= timedif(end_time, start_time);
+      if (test_success(return_code= world->item.startup(world_ptr)))
+      {
+        if (test_success(return_code= world->item.flush(world_ptr, run)))
+        {
+          // @note pre will fail is SKIPPED is returned
+          if (test_success(return_code= world->item.pre(world_ptr)))
+          {
+            { // Runner Code
+              gettimeofday(&start_time, NULL);
+              return_code= world->runner->run(run->test_fn, world_ptr);
+              gettimeofday(&end_time, NULL);
+              load_time= timedif(end_time, start_time);
+            }
+          }
+
+          // @todo do something if post fails
+          (void)world->item.post(world_ptr);
+        }
+        else
+        {
+          std::cerr << __FILE__ << ":" << __LINE__ << " item.flush(failure)" << std::endl;
+        }
+      }
+      else
+      {
+        std::cerr << __FILE__ << ":" << __LINE__ << " item.startup(failure)" << std::endl;
       }
-
-      world.item.post(world_ptr);
 
       stats.total++;
 
@@ -276,15 +302,15 @@ int main(int argc, char *argv[])
 
       std::cerr << "[ " << test_strerror(return_code) << " ]" << std::endl;
 
-      if (test_failed(world.on_error(return_code, world_ptr)))
+      if (test_failed(world->on_error(return_code, world_ptr)))
       {
         break;
       }
     }
 
-    if (next->post && world.runner->post)
+    if (next->post and world->runner->post)
     {
-      (void) world.runner->post(next->post, world_ptr);
+      (void) world->runner->post(next->post, world_ptr);
     }
 
     if (failed == 0 and skipped == 0)
@@ -293,7 +319,7 @@ int main(int argc, char *argv[])
     }
 cleanup:
 
-    world.shutdown(world_ptr);
+    world->shutdown(world_ptr);
   }
 
   if (stats.collection_failed || stats.collection_skipped)
@@ -308,12 +334,14 @@ cleanup:
     std::cout << std::endl << std::endl <<  "All tests completed successfully." << std::endl << std::endl;
   }
 
-  if (test_failed(world.destroy(world_ptr)))
+  if (test_failed(world->destroy(world_ptr)))
   {
     stats.failed++; // We do this to make our exit code return EXIT_FAILURE
   }
 
   stats_print(&stats);
 
-  return stats.failed == 0 ? 0 : 1;
+  delete world;
+
+  return stats.failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
index 5953f82c3d36a8e4701eb8225a17290effcd8757..cf0e223d69cdecbcceee90dc5cb34609a25cd2d0 100644 (file)
@@ -37,6 +37,12 @@ LIBTEST_API
 LIBTEST_API
   void set_default_port(in_port_t port);
 
+LIBTEST_API
+  const char* default_socket();
+
+LIBTEST_API
+  void set_default_socket(const char *socket);
+
 #ifdef __cplusplus
 #define test_literal_param(X) (X), (static_cast<size_t>((sizeof(X) - 1)))
 #else
diff --git a/libtest/wait.cc b/libtest/wait.cc
new file mode 100644 (file)
index 0000000..9326591
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest
+ *
+ *  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 <cstdlib>
+#include <libtest/wait.h>
+
+int main(int argc, char *argv[])
+{
+  if (argc == 2)
+  {
+    libtest::Wait wait(argv[1]);
+
+    if (wait.successful())
+      return EXIT_SUCCESS;
+  }
+
+  return EXIT_FAILURE;
+}
diff --git a/libtest/wait.h b/libtest/wait.h
new file mode 100644 (file)
index 0000000..33c4db5
--- /dev/null
@@ -0,0 +1,78 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest
+ *
+ *  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 <unistd.h>
+#include <string>
+
+namespace libtest {
+
+class Wait 
+{
+public:
+
+  Wait(const std::string &filename, uint32_t timeout= 6) :
+    _successful(false)
+  {
+    uint32_t waited;
+    uint32_t this_wait;
+    uint32_t retry;
+
+    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
+    {
+      if ((not access(filename.c_str(), R_OK)) or (waited >= timeout))
+      {
+        _successful= true;
+        break;
+      }
+
+      this_wait= retry * retry / 3 + 1;
+      sleep(this_wait);
+    }
+  }
+
+  bool successful() const
+  {
+    return _successful;
+  }
+
+private:
+  bool _successful;
+};
+
+} // namespace libtest
diff --git a/tests/cycle.cc b/tests/cycle.cc
new file mode 100644 (file)
index 0000000..3b0aa24
--- /dev/null
@@ -0,0 +1,91 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  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.
+ *
+ */
+
+
+/*
+  Test that we are cycling the servers we are creating during testing.
+*/
+
+#include <libtest/common.h>
+
+#include <libmemcached/common.h>
+
+
+#include <libtest/server.h>
+
+#define SERVERS_TO_CREATE 5
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+
+test_st ping[] ={
+  {0, 0, 0}
+};
+
+collection_st collection[] ={
+  {0, 0, 0, 0}
+};
+
+static server_startup_st *world_create(test_return_t *error)
+{
+  server_startup_st *servers= new server_startup_st();
+
+  server_startup(servers);
+
+  *error= TEST_SUCCESS;
+
+  return servers;
+}
+
+static test_return_t world_destroy(server_startup_st *servers)
+{
+  server_shutdown(servers);
+  delete servers;
+
+  return TEST_SUCCESS;
+}
+
+
+
+void get_world(Framework *world)
+{
+  world->collections= collection;
+
+  world->_create= (test_callback_create_fn*)world_create;
+  world->_destroy= (test_callback_fn*)world_destroy;
+}
+
index bf0e0c6dbe6ebe75379549c327285c59aa2dc47e..ab40b6392706fa9e4a7276dedb893cf389f2d6b6 100644 (file)
@@ -49,13 +49,16 @@ test_return_t server_list_null_test(memcached_st *ptr)
   (void)ptr;
 
   server_list= memcached_server_list_append_with_weight(NULL, NULL, 0, 0, NULL);
-  test_true(server_list == NULL);
+  test_true(server_list);
+  memcached_server_list_free(server_list);
 
   server_list= memcached_server_list_append_with_weight(NULL, "localhost", 0, 0, NULL);
-  test_true(server_list == NULL);
+  test_true(server_list);
+  memcached_server_list_free(server_list);
 
   server_list= memcached_server_list_append_with_weight(NULL, NULL, 0, 0, &rc);
-  test_true(server_list == NULL);
+  test_true(server_list);
+  memcached_server_list_free(server_list);
 
   return TEST_SUCCESS;
 }
@@ -63,7 +66,7 @@ test_return_t server_list_null_test(memcached_st *ptr)
 // Look for memory leak
 test_return_t regression_bug_728286(memcached_st *)
 {
-  memcached_server_st *servers = memcached_servers_parse("1.2.3.4:99");
+  memcached_server_st *servers= memcached_servers_parse("1.2.3.4:99");
   assert(servers);
   memcached_server_free(servers);
 
index fb72ea8d78edbf78faff1945d9541e091116cfc3..e254670979273aba36d3c3434b43f3de2aadb775 100644 (file)
@@ -46,13 +46,21 @@ noinst_HEADERS+= \
 
 noinst_PROGRAMS+= \
                  tests/atomsmasher \
+                 tests/cycle \
                  tests/hash_plus \
-                 tests/startservers \
                  tests/testapp \
                  tests/testhashkit \
                  tests/testplus \
                  tests/testudp
 
+# Cycle should always run first
+tests_cycle_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
+tests_cycle_SOURCES= tests/cycle.cc
+tests_cycle_DEPENDENCIES= $(TESTS_LDADDS)
+tests_cycle_LDADD= $(tests_cycle_DEPENDENCIES)
+check_PROGRAMS+= tests/cycle
+
+
 tests_testapp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
 tests_testapp_SOURCES= \
                       tests/basic.cc \
@@ -79,6 +87,7 @@ tests_testapp_LDADD= \
                     $(TESTS_LDADDS) \
                     libhashkit/libhashkit.la \
                     libmemcached/libmemcachedinternal.la
+check_PROGRAMS+= tests/testapp
 
 tests_testplus_SOURCES= tests/plus.cpp
 tests_testplus_CXXFLAGS = $(AM_CXXFLAGS) $(NO_EFF_CXX)
@@ -86,25 +95,23 @@ tests_testplus_DEPENDENCIES= $(TESTS_LDADDS)
 tests_testplus_LDADD= $(tests_testplus_DEPENDENCIES) $(LIBSASL)
 check_PROGRAMS+= tests/testplus
 
-tests_atomsmasher_SOURCES= tests/atomsmasher.cc
-tests_atomsmasher_SOURCES+= clients/generator.cc clients/execute.cc
+tests_atomsmasher_SOURCES= \
+                          tests/atomsmasher.cc \
+                          clients/generator.cc \
+                          clients/execute.cc
 tests_atomsmasher_DEPENDENCIES= $(TESTS_LDADDS)
-
 tests_atomsmasher_LDADD= $(tests_atomsmasher_DEPENDENCIES) $(LIBSASL)
 
 tests_testudp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
 tests_testudp_SOURCES= tests/mem_udp.cc
 tests_testudp_DEPENDENCIES= $(TESTS_LDADDS)
-
 tests_testudp_LDADD= $(tests_testudp_DEPENDENCIES) $(LIBSASL)
-
-tests_startservers_SOURCES= tests/start.cc
-tests_startservers_DEPENDENCIES= $(TESTS_LDADDS)
-tests_startservers_LDADD= $(tests_startservers_DEPENDENCIES) $(LIBSASL)
+check_PROGRAMS+= tests/testudp
 
 tests_testhashkit_SOURCES = tests/hashkit_functions.cc
 tests_testhashkit_DEPENDENCIES = libtest/libtest.la libhashkit/libhashkit.la
 tests_testhashkit_LDADD = $(tests_testhashkit_DEPENDENCIES)
+check_PROGRAMS+= tests/testhashkit
 
 tests_hash_plus_SOURCES= tests/hash_plus.cc
 tests_hash_plus_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
@@ -114,10 +121,10 @@ check_PROGRAMS+= tests/hash_plus
 
 test: check
 
-check-local: tests/var $(TEST_DOCS) test-mem test-hash memcapable
+check-local: tests/var $(TEST_DOCS) memcapable
        @echo "Tests completed"
 
-test-x: check-local test-plus test-memcat test-memcp test-memrm test-memerror test-memdump test-memflush test-memstat
+test-x: tests/var test-plus test-memcat test-memcp test-memrm test-memerror test-memdump test-memflush test-memstat
        @echo "Tests completed"
 
 memcapable: clients/memcapable
@@ -242,30 +249,35 @@ TESTPLUS_COMMAND= tests/testplus $(COLLECTION) $(SUITE)
 
 HASHPLUS_COMMAND= tests/hashplus $(COLLECTION) $(SUITE)
 
+CYCLE_COMMAND= tests/cycle $(COLLECTION) $(SUITE)
+
 ATOM_COMMAND= tests/atomsmasher $(COLLECTION) $(SUITE)
 
 UDP_COMMAND= tests/testudp $(COLLECTION) $(SUITE)
 
 HASH_COMMAND= tests/testhashkit $(COLLECTION) $(SUITE)
 
-test-mem: tests/testapp
+test-mem: tests/var tests/testapp
        $(MEM_COMMAND)
 
-test-udp: tests/testudp
+test-udp: tests/var tests/testudp
        $(UDP_COMMAND)
 
-test-atom: tests/atomsmasher
+test-atom: tests/var tests/atomsmasher
        $(ATOM_COMMAND)
 
-test-plus: tests/testplus
+test-plus: tests/var tests/testplus
        $(TESTPLUS_COMMAND)
 
-test-hash: tests/testhashkit
+test-hash: tests/var tests/testhashkit
        $(HASH_COMMAND)
 
-test-hashplus: tests/hashplus
+test-hashplus: tests/var tests/hashplus
        $(HASHPLUS_COMMAND)
 
+test-cycle: tests/var tests/cycle
+       $(CYCLE_COMMAND)
+
 pahole-mem: tests/testapp
        $(PAHOLE_COMMAND)  $(MEM_COMMAND)
 
@@ -287,6 +299,9 @@ gdb-hash: tests/testhashkit
 gdb-hashplus: tests/hashplus
        $(DEBUG_COMMAND) $(HASHPLUS_COMMAND)
 
+gdb-cycle: tests/cycle
+       $(DEBUG_COMMAND) $(CYCLE_COMMAND)
+
 gdb-memslap: clients/memslap
        $(DEBUG_COMMAND)  $(MEMSLAP_COMMAND)
 
index ea08db776a94a208a3924763e22912e014ed7ac8..a6de23a0f520bc1252d11c14003dcbdedcc0f194 100644 (file)
@@ -9,9 +9,9 @@
  *
  */
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#pragma once
+
+#include <cassert>
 
 /* The structure we use for the test system */
 struct libmemcached_test_container_st
@@ -23,11 +23,13 @@ struct libmemcached_test_container_st
   libmemcached_test_container_st() :
     parent(NULL),
     memc(NULL)
-  {
-    memset(&construct, 0, sizeof(server_startup_st));
-  }
+  { }
 };
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Prototypes for functions we will pass to test framework */
 libmemcached_test_container_st *world_create(test_return_t *error);
 test_return_t world_test_startup(libmemcached_test_container_st *);
@@ -50,7 +52,11 @@ libmemcached_test_container_st *world_create(test_return_t *error)
 {
   global_container.construct.count= SERVERS_TO_CREATE;
   global_container.construct.udp= 0;
-  server_startup(&global_container.construct);
+  if (not server_startup(&global_container.construct))
+  {
+    *error= TEST_FAILURE;
+    return NULL;
+  }
 
   *error= TEST_SUCCESS;
 
@@ -62,11 +68,12 @@ test_return_t world_container_startup(libmemcached_test_container_st *container)
   char buffer[BUFSIZ];
 
   test_compare_got(MEMCACHED_SUCCESS,
-                   libmemcached_check_configuration(container->construct.server_list, strlen(container->construct.server_list),
+                   libmemcached_check_configuration(container->construct.server_list.c_str(), container->construct.server_list.size(),
                                                     buffer, sizeof(buffer)),
                    buffer);
 
-  container->parent= memcached(container->construct.server_list, strlen(container->construct.server_list));
+  assert(not container->parent);
+  container->parent= memcached(container->construct.server_list.c_str(), container->construct.server_list.size());
   test_true(container->parent);
 
   return TEST_SUCCESS;
@@ -82,6 +89,9 @@ test_return_t world_container_shutdown(libmemcached_test_container_st *container
 
 test_return_t world_test_startup(libmemcached_test_container_st *container)
 {
+  assert(container);
+  assert(not container->memc);
+  assert(container->parent);
   container->memc= memcached_clone(NULL, container->parent);
   test_true(container->memc);
 
@@ -90,6 +100,7 @@ test_return_t world_test_startup(libmemcached_test_container_st *container)
 
 test_return_t world_flush(libmemcached_test_container_st *container)
 {
+  assert(container->memc);
   memcached_flush(container->memc, 0);
   memcached_quit(container->memc);
 
@@ -98,6 +109,7 @@ test_return_t world_flush(libmemcached_test_container_st *container)
 
 test_return_t world_pre_run(libmemcached_test_container_st *container)
 {
+  assert(container->memc);
   for (uint32_t loop= 0; loop < memcached_server_list_count(container->memc->servers); loop++)
   {
     memcached_server_instance_st instance=
@@ -121,6 +133,7 @@ test_return_t world_post_run(libmemcached_test_container_st *container)
 test_return_t world_on_error(test_return_t test_state, libmemcached_test_container_st *container)
 {
   (void)test_state;
+  assert(container->memc);
   memcached_free(container->memc);
   container->memc= NULL;
 
@@ -145,6 +158,8 @@ static test_return_t _runner_default(libmemcached_test_callback_fn func, libmemc
 {
   if (func)
   {
+    assert(container);
+    assert(container->memc);
     return func(container->memc);
   }
   else
index d7402dbd0b2f8b4786f396c79cb4f6d711cb0555..180f1e7e2fe4c2e319810f29e9ae20439a211280 100644 (file)
@@ -4150,7 +4150,7 @@ static test_return_t check_for_1_2_3(memcached_st *memc)
     memcached_server_instance_by_position(memc, 0);
 
   if ((instance->major_version >= 1 && (instance->minor_version == 2 && instance->micro_version >= 4))
-      || instance->minor_version > 2)
+      or instance->minor_version > 2)
   {
     return TEST_SUCCESS;
   }
@@ -4160,17 +4160,17 @@ static test_return_t check_for_1_2_3(memcached_st *memc)
 
 static test_return_t pre_unix_socket(memcached_st *memc)
 {
-  memcached_return_t rc;
   struct stat buf;
 
   memcached_servers_reset(memc);
+  const char *socket_file= default_socket();
 
-  if (stat("/tmp/memcached.socket", &buf))
-    return TEST_SKIPPED;
+  test_skip(0, stat(socket_file, &buf));
 
-  rc= memcached_server_add_unix_socket_with_weight(memc, "/tmp/memcached.socket", 0);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_server_add_unix_socket_with_weight(memc, socket_file, 0));
 
-  return ( rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_FAILURE );
+  return TEST_SUCCESS;
 }
 
 static test_return_t pre_nodelay(memcached_st *memc)
@@ -5556,6 +5556,9 @@ static test_return_t test_verbosity(memcached_st *memc)
 
 static test_return_t test_server_failure(memcached_st *memc)
 {
+  if (memcached_server_count(memc) < 2)
+    return TEST_SKIPPED;
+
   memcached_server_instance_st instance= memcached_server_instance_by_position(memc, 0);
 
   memcached_st *local_memc= memcached_create(NULL);
@@ -5591,7 +5594,12 @@ static test_return_t test_server_failure(memcached_st *memc)
 
 static test_return_t test_cull_servers(memcached_st *memc)
 {
-  uint32_t count = memcached_server_count(memc);
+  uint32_t count= memcached_server_count(memc);
+
+  if (count < 2)
+  {
+    return TEST_SKIPPED;
+  }
 
   // Do not do this in your code, it is not supported.
   memc->servers[1].options.is_dead= true;
@@ -6452,7 +6460,7 @@ test_st parser_tests[] ={
   {"libmemcached_check_configuration_with_filename", 0, (test_callback_fn*)libmemcached_check_configuration_with_filename_test },
   {"number_options", 0, (test_callback_fn*)parser_number_options_test },
   {"randomly generated options", 0, (test_callback_fn*)random_statement_build_test },
-  {"prefix_key", 0, (test_callback_fn*)parser_key_prefix_test },
+  {"namespace", 0, (test_callback_fn*)parser_key_prefix_test },
   {"server", 0, (test_callback_fn*)server_test },
   {"bad server strings", 0, (test_callback_fn*)servers_bad_test },
   {"server with weights", 0, (test_callback_fn*)server_with_weight_test },
diff --git a/tests/start.cc b/tests/start.cc
deleted file mode 100644 (file)
index 6ea0e47..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <libtest/server.h>
-
-int main(void)
-{
-  server_startup_st construct;
-
-  memset(&construct, 0, sizeof(server_startup_st));
-
-  construct.count= 4;
-
-  server_startup(&construct);
-
-  return EXIT_SUCCESS;
-}