You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by pq...@apache.org on 2007/09/21 00:19:00 UTC

svn commit: r577948 - /apr/apr-util/trunk/test/testmemcache.c

Author: pquerna
Date: Thu Sep 20 15:18:58 2007
New Revision: 577948

URL: http://svn.apache.org/viewvc?rev=577948&view=rev
Log:
Update memcache test case to run if a memcache server is located on localhost with the default port.

Submitted By: Josh Rotenberg <joshrotenberg gmail.com>
PR: 42358

Modified:
    apr/apr-util/trunk/test/testmemcache.c

Modified: apr/apr-util/trunk/test/testmemcache.c
URL: http://svn.apache.org/viewvc/apr/apr-util/trunk/test/testmemcache.c?rev=577948&r1=577947&r2=577948&view=diff
==============================================================================
--- apr/apr-util/trunk/test/testmemcache.c (original)
+++ apr/apr-util/trunk/test/testmemcache.c Thu Sep 20 15:18:58 2007
@@ -21,6 +21,7 @@
 #include "apr_strings.h"
 #include "apr_hash.h"
 #include "apr_memcache.h"
+#include "apr_network_io.h"
 
 #if APR_HAVE_STDLIB_H
 #include <stdlib.h>		/* for exit() */
@@ -32,9 +33,12 @@
 /* the total number of items to use for set/get testing */
 #define TDATA_SIZE 3000
 
-/* some smaller subset of TDATA_SIZE */
+/* some smaller subset of TDATA_SIZE used for multiget testing */
 #define TDATA_SET 100
 
+/* our custom hash function just returns this all the time */
+#define HASH_FUNC_RESULT 510
+
 /* all keys will be prefixed with this */
 const char prefix[] = "testmemcache";
 
@@ -50,6 +54,58 @@
 "convallis id, iaculis feugiat cras amet.";
 
 /*
+ * this datatype is for our custom server determination function. this might
+ * be useful if you don't want to rely on simply hashing keys to determine
+ * where a key belongs, but instead want to write something fancy, or use some
+ * other kind of configuration data, i.e. a hash plus some data about a 
+ * namespace, or whatever. see my_server_func, and test_memcache_user_funcs
+ * for the examples.
+ */
+typedef struct {
+  const char *someval;
+  apr_uint32_t which_server;
+} my_hash_server_baton;
+
+
+/* this could do something fancy and return some hash result. 
+ * for simplicity, just return the same value, so we can test it later on.
+ * if you wanted to use some external hashing library or functions for
+ * consistent hashing, for example, this would be a good place to do it.
+ */
+apr_uint32_t my_hash_func(void *baton, const char *data,
+                          apr_size_t data_len)
+{
+
+  return HASH_FUNC_RESULT;
+}
+
+/*
+ * a fancy function to determine which server to use given some kind of data
+ * and a hash value. this example actually ignores the hash value itself
+ * and pulls some number from the *baton, which is a struct that has some 
+ * kind of meaningful stuff in it.
+ */
+apr_memcache_server_t *my_server_func(void *baton, 
+                                      apr_memcache_t *mc,
+                                      const apr_uint32_t hash)
+{
+  apr_memcache_server_t *ms = NULL;
+  my_hash_server_baton *mhsb = (my_hash_server_baton *)baton;
+
+  if(mc->ntotal == 0) {
+    return NULL;
+  } 
+
+  if(mc->ntotal < mhsb->which_server) {
+    return NULL;
+  }
+
+  ms = mc->live_servers[mhsb->which_server - 1];
+
+  return ms;
+}
+
+/*
  * general test to make sure we can create the memcache struct and add
  * some servers, but not more than we tell it we can add
  */
@@ -60,8 +116,8 @@
   apr_status_t rv;
   apr_memcache_t *memcache;
   apr_memcache_server_t *server, *s;
-  int max_servers = 10;
-  int i;
+  apr_uint32_t max_servers = 10;
+  apr_uint32_t i;
   apr_uint32_t hash;
 
   rv = apr_memcache_create(pool, max_servers, 0, &memcache);
@@ -102,6 +158,55 @@
   
 }
 
+/* install our own custom hashing and server selection routines. */
+
+static void test_memcache_user_funcs(abts_case * tc, void *data)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_memcache_t *memcache;
+  apr_memcache_server_t *found, *server1, *server2;
+  apr_uint32_t max_servers = 10;
+  apr_uint32_t hres;
+  apr_port_t port;
+  apr_uint32_t i;
+  my_hash_server_baton *baton = 
+    apr_pcalloc(pool, sizeof(my_hash_server_baton));
+
+  rv = apr_memcache_create(pool, max_servers, 0, &memcache);
+  ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
+
+  /* as noted above, install our custom hash function, and call 
+   * apr_memcache_hash. the return value should be our predefined number,
+   * and our function just ignores the other args, for simplicity.
+   */
+  memcache->hash_func = my_hash_func;
+
+  hres = apr_memcache_hash(memcache, "whatever", sizeof("whatever") - 1);
+  ABTS_INT_EQUAL(tc, hres, HASH_FUNC_RESULT);
+  
+  /* add some servers */
+  for(i = 1; i <= 10; i++) {
+    apr_memcache_server_t *ms;
+
+    rv = apr_memcache_server_create(pool, HOST, i, 0, 1, 1, 60, &ms);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+    
+    rv = apr_memcache_add_server(memcache, ms);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+  }
+
+  /* 
+   * set 'which_server' in our server_baton to find the third server 
+   * which should have the same port.
+   */
+  baton->which_server = 3;
+  memcache->server_func = my_server_func; 
+  memcache->server_baton = baton;
+  found = apr_memcache_find_server_hash(memcache, 0);
+  ABTS_ASSERT(tc, "wrong server found", found->port == baton->which_server);
+}
+
 /* test non data related commands like stats and version */
 static void test_memcache_meta(abts_case * tc, void *data)
 {
@@ -176,7 +281,7 @@
  apr_hash_index_t *hi;
  char *result;
  apr_size_t len;
- int i;
+ apr_uint32_t i;
 
   rv = apr_memcache_create(pool, 1, 0, &memcache);
   ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
@@ -225,6 +330,7 @@
   }
 }
 
+/* basic tests of the increment and decrement commands */
 static void test_memcache_incrdecr(abts_case * tc, void *data)
 {
  apr_pool_t *pool = p;
@@ -234,7 +340,7 @@
  apr_uint32_t new, next = 2;
  char *result;
  apr_size_t len;
- int i;
+ apr_uint32_t i;
 
   rv = apr_memcache_create(pool, 1, 0, &memcache);
   ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
@@ -249,7 +355,7 @@
   ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
   
   for( i = 1; i <= TDATA_SIZE; i++) {
-    int expect;
+    apr_uint32_t expect;
 
     rv = apr_memcache_getp(memcache, pool, prefix, &result, &len, NULL);
     ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
@@ -277,7 +383,6 @@
 }
 
 /* test the multiget functionality */
-
 static void test_memcache_multiget(abts_case * tc, void *data)
 {
   apr_pool_t *pool = p;
@@ -287,7 +392,7 @@
   apr_memcache_server_t *server;
   apr_hash_t *tdata, *values;
   apr_hash_index_t *hi;
-  int i;
+  apr_uint32_t i;
 
   rv = apr_memcache_create(pool, 1, 0, &memcache);
   ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
@@ -358,7 +463,7 @@
     char *result, *k;
     apr_size_t len;
     apr_uint16_t flags;
-    int i;
+    apr_uint32_t i;
 
     rv = apr_memcache_create(pool, 1, 0, &memcache);
     ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
@@ -422,10 +527,10 @@
   return i;
 }
 
-int firsttime = 0;
-int randval(int high)
+apr_uint16_t firsttime = 0;
+int randval(apr_uint32_t high)
 {
-    unsigned int i = 0;
+    apr_uint32_t i = 0;
     double d = 0;
 
     if (firsttime == 0) {
@@ -439,17 +544,87 @@
     return i > 0 ? i : 1;
 }
 
+/* use apr_socket stuff to see if there is in fact a memcached server 
+ * running on PORT. 
+ */
+apr_status_t check_mc(void)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_socket_t *sock = NULL;
+  apr_sockaddr_t *sa;
+  struct iovec vec[2];
+  apr_size_t written;
+  char buf[128];
+  apr_size_t len;
+
+  rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, 0, pool);
+  if(rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_sockaddr_info_get(&sa, HOST, APR_INET, PORT, 0, pool);
+  if(rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_socket_timeout_set(sock, 1 * APR_USEC_PER_SEC);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_socket_connect(sock, sa);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  rv = apr_socket_timeout_set(sock, -1);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  vec[0].iov_base = "version";
+  vec[0].iov_len  = sizeof("version") - 1;
+
+  vec[1].iov_base = "\r\n";
+  vec[1].iov_len  = sizeof("\r\n") -1;
+
+  rv = apr_socket_sendv(sock, vec, 2, &written);
+  if (rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  len = sizeof(buf);
+  rv = apr_socket_recv(sock, buf, &len);
+  if(rv != APR_SUCCESS) {
+    return rv;
+  }
+
+  if(strncmp(buf, "VERSION", sizeof("VERSION")-1) != 0) {
+    rv = APR_EGENERAL;
+  }
+
+  apr_socket_close(sock);
+  return rv;
+}
+
 abts_suite *testmemcache(abts_suite * suite)
 {
+    apr_status_t rv;
     suite = ADD_SUITE(suite);
-    /* TODO: Determine if a memcache server is online, before proceding. */
-#if 0
-    abts_run_test(suite, test_memcache_create, NULL);
-    abts_run_test(suite, test_memcache_meta, NULL);
-    abts_run_test(suite, test_memcache_setget, NULL);
-    abts_run_test(suite, test_memcache_multiget, NULL);
-    abts_run_test(suite, test_memcache_addreplace, NULL);
-    abts_run_test(suite, test_memcache_incrdecr, NULL);
-#endif
+    /* check for a running memcached on the typical port before 
+     * trying to run the tests. succeed silently if we don't find one.
+     */
+    rv = check_mc();
+    if(rv == APR_SUCCESS) {
+      abts_run_test(suite, test_memcache_create, NULL);
+      abts_run_test(suite, test_memcache_user_funcs, NULL);
+      abts_run_test(suite, test_memcache_meta, NULL);
+      abts_run_test(suite, test_memcache_setget, NULL);
+      abts_run_test(suite, test_memcache_multiget, NULL);
+      abts_run_test(suite, test_memcache_addreplace, NULL);
+      abts_run_test(suite, test_memcache_incrdecr, NULL);
+    }
+
     return suite;
 }