You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by ji...@apache.org on 2016/11/03 21:01:56 UTC

svn commit: r1767973 - in /apr/apr-util/branches/1.6.x: redis/apr_redis.c test/Makefile.in test/abts_tests.h test/testredis.c test/testutil.h

Author: jim
Date: Thu Nov  3 21:01:56 2016
New Revision: 1767973

URL: http://svn.apache.org/viewvc?rev=1767973&view=rev
Log:
And tests

Added:
    apr/apr-util/branches/1.6.x/test/testredis.c
Modified:
    apr/apr-util/branches/1.6.x/redis/apr_redis.c
    apr/apr-util/branches/1.6.x/test/Makefile.in
    apr/apr-util/branches/1.6.x/test/abts_tests.h
    apr/apr-util/branches/1.6.x/test/testutil.h

Modified: apr/apr-util/branches/1.6.x/redis/apr_redis.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/redis/apr_redis.c?rev=1767973&r1=1767972&r2=1767973&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/redis/apr_redis.c (original)
+++ apr/apr-util/branches/1.6.x/redis/apr_redis.c Thu Nov  3 21:01:56 2016
@@ -21,7 +21,6 @@
 #include <string.h>
 
 #define BUFFER_SIZE 512
-#define INT64_LEN 22
 struct apr_redis_conn_t
 {
     char *buffer;
@@ -447,6 +446,9 @@ APU_DECLARE(apr_status_t) apr_redis_serv
     server->port = port;
     server->status = APR_RC_SERVER_DEAD;
     server->rwto = rwto;
+    server->version.major = 0;
+    server->version.minor = 0;
+    server->version.patch = 0;
 
 #if APR_HAS_THREADS
     rv = apr_thread_mutex_create(&server->lock, APR_THREAD_MUTEX_DEFAULT, np);
@@ -646,15 +648,10 @@ APU_DECLARE(apr_status_t) apr_redis_set(
     apr_status_t rv;
     apr_size_t written;
     struct iovec vec[9];
-    char keysize_str[INT64_LEN];
+    char keysize_str[BUFFER_SIZE];
     char datasize_str[BUFFER_SIZE];
     apr_size_t len, klen;
 
-
-    if (data_size >= BUFFER_SIZE) {
-        return APR_NOTFOUND;
-    }
-
     klen = strlen(key);
     hash = apr_redis_hash(rc, key, klen);
 
@@ -690,7 +687,7 @@ APU_DECLARE(apr_status_t) apr_redis_set(
     vec[2].iov_base = RC_SET;
     vec[2].iov_len = RC_SET_LEN;
 
-    len = apr_snprintf(keysize_str, INT64_LEN, "$%" APR_SIZE_T_FMT "", klen);
+    len = apr_snprintf(keysize_str, BUFFER_SIZE, "$%" APR_SIZE_T_FMT "\r\n", klen);
     vec[3].iov_base = keysize_str;
     vec[3].iov_len = len;
 
@@ -700,7 +697,7 @@ APU_DECLARE(apr_status_t) apr_redis_set(
     vec[5].iov_base = RC_EOL;
     vec[5].iov_len = RC_EOL_LEN;
 
-    len = apr_snprintf(datasize_str, INT64_LEN, "$%" APR_SIZE_T_FMT "",
+    len = apr_snprintf(datasize_str, BUFFER_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
                      data_size);
     vec[6].iov_base = datasize_str;
     vec[6].iov_len = len;
@@ -753,17 +750,13 @@ APU_DECLARE(apr_status_t) apr_redis_sete
     apr_status_t rv;
     apr_size_t written;
     struct iovec vec[11];
-    char keysize_str[INT64_LEN];
-    char expire_str[INT64_LEN];
-    char expiresize_str[INT64_LEN];
+    char keysize_str[BUFFER_SIZE];
+    char expire_str[BUFFER_SIZE];
+    char expiresize_str[BUFFER_SIZE];
     char datasize_str[BUFFER_SIZE];
     apr_size_t len, klen, expire_len;
 
 
-    if (data_size >= BUFFER_SIZE) {
-        return APR_NOTFOUND;
-    }
-
     klen = strlen(key);
     hash = apr_redis_hash(rc, key, klen);
 
@@ -801,7 +794,7 @@ APU_DECLARE(apr_status_t) apr_redis_sete
     vec[2].iov_base = RC_SETEX;
     vec[2].iov_len = RC_SETEX_LEN;
 
-    len = apr_snprintf(keysize_str, INT64_LEN, "$%" APR_SIZE_T_FMT "", klen);
+    len = apr_snprintf(keysize_str, BUFFER_SIZE, "$%" APR_SIZE_T_FMT "\r\n", klen);
     vec[3].iov_base = keysize_str;
     vec[3].iov_len = len;
 
@@ -811,8 +804,8 @@ APU_DECLARE(apr_status_t) apr_redis_sete
     vec[5].iov_base = RC_EOL;
     vec[5].iov_len = RC_EOL_LEN;
 
-    expire_len = apr_snprintf(expire_str, INT64_LEN, "%u\r\n", timeout);
-    len = apr_snprintf(expiresize_str, INT64_LEN, "$%" APR_SIZE_T_FMT "\r\n",
+    expire_len = apr_snprintf(expire_str, BUFFER_SIZE, "%u\r\n", timeout);
+    len = apr_snprintf(expiresize_str, BUFFER_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
                      expire_len - 2);
     vec[6].iov_base = (void *) expiresize_str;
     vec[6].iov_len = len;
@@ -820,7 +813,7 @@ APU_DECLARE(apr_status_t) apr_redis_sete
     vec[7].iov_base = (void *) expire_str;
     vec[7].iov_len = expire_len;
 
-    len = apr_snprintf(datasize_str, INT64_LEN, "$%" APR_SIZE_T_FMT "",
+    len = apr_snprintf(datasize_str, BUFFER_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
                      data_size);
     vec[8].iov_base = datasize_str;
     vec[8].iov_len = len;
@@ -926,7 +919,7 @@ APU_DECLARE(apr_status_t) apr_redis_getp
                                          const char *key,
                                          char **baton,
                                          apr_size_t *new_length,
-                                         apr_uint16_t *flags_)
+                                         apr_uint16_t *flags)
 {
     apr_status_t rv;
     apr_redis_server_t *rs;
@@ -935,11 +928,12 @@ APU_DECLARE(apr_status_t) apr_redis_getp
     apr_size_t written;
     apr_size_t len, klen;
     struct iovec vec[6];
-    char keysize_str[INT64_LEN];
+    char keysize_str[BUFFER_SIZE];
 
     klen = strlen(key);
     hash = apr_redis_hash(rc, key, klen);
     rs = apr_redis_find_server_hash(rc, hash);
+
     if (rs == NULL)
         return APR_NOTFOUND;
 
@@ -962,12 +956,12 @@ APU_DECLARE(apr_status_t) apr_redis_getp
     vec[0].iov_len = RC_RESP_2_LEN;
 
     vec[1].iov_base = RC_GET_SIZE;
-    vec[2].iov_len = RC_GET_SIZE_LEN;
+    vec[1].iov_len = RC_GET_SIZE_LEN;
 
     vec[2].iov_base = RC_GET;
     vec[2].iov_len = RC_GET_LEN;
 
-    len = apr_snprintf(keysize_str, INT64_LEN, "$%" APR_SIZE_T_FMT "\r\n",
+    len = apr_snprintf(keysize_str, BUFFER_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
                      klen);
     vec[3].iov_base = keysize_str;
     vec[3].iov_len = len;
@@ -980,6 +974,7 @@ APU_DECLARE(apr_status_t) apr_redis_getp
 
     rv = apr_socket_sendv(conn->sock, vec, 6, &written);
 
+
     if (rv != APR_SUCCESS) {
         rs_bad_conn(rs, conn);
         apr_redis_disable_server(rc, rs);
@@ -1018,7 +1013,7 @@ APU_DECLARE(apr_status_t)
     apr_size_t written;
     struct iovec vec[6];
     apr_size_t len, klen;
-    char keysize_str[INT64_LEN];
+    char keysize_str[BUFFER_SIZE];
 
     klen = strlen(key);
     hash = apr_redis_hash(rc, key, klen);
@@ -1045,12 +1040,12 @@ APU_DECLARE(apr_status_t)
     vec[0].iov_len = RC_RESP_2_LEN;
 
     vec[1].iov_base = RC_DEL_SIZE;
-    vec[2].iov_len = RC_DEL_SIZE_LEN;
+    vec[1].iov_len = RC_DEL_SIZE_LEN;
 
     vec[2].iov_base = RC_DEL;
     vec[2].iov_len = RC_DEL_LEN;
 
-    len = apr_snprintf(keysize_str, INT64_LEN, "$%" APR_SIZE_T_FMT "\r\n",
+    len = apr_snprintf(keysize_str, BUFFER_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
                      klen);
     vec[3].iov_base = keysize_str;
     vec[3].iov_len = len;
@@ -1195,7 +1190,7 @@ apr_redis_version(apr_redis_server_t *rs
     apr_pool_t *subpool;
 
     /* Have we already obtained the version number? */
-    if (rs->version.major != 0) {
+    if (rs->version.minor != 0) {
         if (baton)
             *baton = apr_pstrdup(p, rs->version.number);
         return APR_SUCCESS;
@@ -1245,8 +1240,8 @@ static apr_status_t plus_minus(apr_redis
     apr_size_t written;
     apr_size_t len, klen;
     struct iovec vec[8];
-    char keysize_str[INT64_LEN];
-    char inc_str[INT64_LEN];
+    char keysize_str[BUFFER_SIZE];
+    char inc_str[BUFFER_SIZE];
     int i = 0;
 
     klen = strlen(key);
@@ -1271,42 +1266,58 @@ static apr_status_t plus_minus(apr_redis
      *   key
      *   <:inc>
      */
-    vec[i].iov_base = RC_RESP_2;
-    vec[i++].iov_len = RC_RESP_2_LEN;
+    if (inc == 1) {
+        vec[i].iov_base = RC_RESP_2;
+        vec[i].iov_len = RC_RESP_2_LEN;
+        i++;
 
-    vec[i].iov_base = "$4\r\n";
-    vec[i++].iov_len = 6;
+        vec[i].iov_base = "$4\r\n";
+        vec[i].iov_len = sizeof("$4\r\n")-1;
+        i++;
 
-    if (inc == 1) {
         if (incr)
             vec[i].iov_base = "INCR\r\n";
         else
             vec[i].iov_base = "DECR\r\n";
-        vec[i++].iov_len = 8;
+        vec[i].iov_len = sizeof("INCR\r\n")-1;
+        i++;
     }
     else {
-        if (incr)
+        vec[i].iov_base = RC_RESP_3;
+        vec[i].iov_len = RC_RESP_3_LEN;
+        i++;
+
+        vec[i].iov_base = "$6\r\n";
+        vec[i].iov_len = sizeof("$6\r\n")-1;
+        i++;
+
+       if (incr)
             vec[i].iov_base = "INCRBY\r\n";
         else
             vec[i].iov_base = "DECRBY\r\n";
-        vec[i++].iov_len = 10;
+        vec[i].iov_len = sizeof("INCRBY\r\n")-1;
+        i++;
     }
 
-    len = apr_snprintf(keysize_str, INT64_LEN, "$%" APR_SIZE_T_FMT "\r\n",
+    len = apr_snprintf(keysize_str, BUFFER_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
                      klen);
     vec[i].iov_base = keysize_str;
-    vec[i++].iov_len = len;
+    vec[i].iov_len = len;
+    i++;
 
     vec[i].iov_base = (void *) key;
-    vec[i++].iov_len = klen;
+    vec[i].iov_len = klen;
+    i++;
 
     if (inc != 1) {
-        len = apr_snprintf(inc_str, INT64_LEN, ":%d\r\n", inc);
+        len = apr_snprintf(inc_str, BUFFER_SIZE, ":%d\r\n", inc);
         vec[i].iov_base = inc_str;
-        vec[i++].iov_len = len;
+        vec[i].iov_len = len;
+        i++;
     }
     vec[i].iov_base = RC_EOL;
-    vec[i++].iov_len = RC_EOL_LEN;
+    vec[i].iov_len = RC_EOL_LEN;
+    i++;
 
     rv = apr_socket_sendv(conn->sock, vec, i, &written);
 
@@ -1332,7 +1343,6 @@ static apr_status_t plus_minus(apr_redis
     else {
         rv = APR_EGENERAL;
     }
-
     return rv;
 }
 

Modified: apr/apr-util/branches/1.6.x/test/Makefile.in
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/test/Makefile.in?rev=1767973&r1=1767972&r2=1767973&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/test/Makefile.in (original)
+++ apr/apr-util/branches/1.6.x/test/Makefile.in Thu Nov  3 21:01:56 2016
@@ -17,7 +17,7 @@ STDTEST_PORTABLE = dbd testall
 TESTS = teststrmatch.lo testuri.lo testuuid.lo testbuckets.lo testpass.lo \
 	testmd4.lo testmd5.lo testldap.lo testdate.lo testdbm.lo testdbd.lo \
 	testxml.lo testrmm.lo testreslist.lo testqueue.lo testxlate.lo \
-	testmemcache.lo testcrypto.lo testsiphash.lo
+	testmemcache.lo testcrypto.lo testsiphash.lo testredis.lo
 
 PROGRAMS = $(STDTEST_PORTABLE)
 

Modified: apr/apr-util/branches/1.6.x/test/abts_tests.h
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/test/abts_tests.h?rev=1767973&r1=1767972&r2=1767973&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/test/abts_tests.h (original)
+++ apr/apr-util/branches/1.6.x/test/abts_tests.h Thu Nov  3 21:01:56 2016
@@ -35,6 +35,7 @@ const struct testlist {
     {testdbd},
     {testdate},
     {testmemcache},
+    {testredis},
     {testxml},
     {testxlate},
     {testrmm},

Added: apr/apr-util/branches/1.6.x/test/testredis.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/test/testredis.c?rev=1767973&view=auto
==============================================================================
--- apr/apr-util/branches/1.6.x/test/testredis.c (added)
+++ apr/apr-util/branches/1.6.x/test/testredis.c Thu Nov  3 21:01:56 2016
@@ -0,0 +1,418 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testutil.h"
+#include "apr.h"
+#include "apu.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+#include "apr_redis.h"
+#include "apr_network_io.h"
+
+#include <stdio.h>
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>		/* for exit() */
+#endif
+
+#define HOST "localhost"
+#define PORT 6379
+
+/* the total number of items to use for set/get testing */
+#define TDATA_SIZE 3000
+
+/* 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 */
+static const char prefix[] = "testredis";
+
+/* text for values we store */
+static const char txt[] =
+"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis at"
+"lacus in ligula hendrerit consectetuer. Vestibulum tristique odio"
+"iaculis leo. In massa arcu, ultricies a, laoreet nec, hendrerit non,"
+"neque. Nulla sagittis sapien ac risus. Morbi ligula dolor, vestibulum"
+"nec, viverra id, placerat dapibus, arcu. Curabitur egestas feugiat"
+"tellus. Donec dignissim. Nunc ante. Curabitur id lorem. In mollis"
+"tortor sit amet eros auctor dapibus. Proin nulla sem, tristique in,"
+"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_redis_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.
+ */
+static 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.
+ */
+static apr_redis_server_t *my_server_func(void *baton,
+                                             apr_redis_t *mc,
+                                             const apr_uint32_t hash)
+{
+  apr_redis_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;
+}
+
+static apr_uint16_t firsttime = 0;
+static int randval(apr_uint32_t high)
+{
+    apr_uint32_t i = 0;
+    double d = 0;
+
+    if (firsttime == 0) {
+	srand((unsigned) (getpid()));
+	firsttime = 1;
+    }
+
+    d = (double) rand() / ((double) RAND_MAX + 1);
+    i = (int) (d * (high - 0 + 1));
+
+    return i > 0 ? i : 1;
+}
+
+/*
+ * general test to make sure we can create the redis struct and add
+ * some servers, but not more than we tell it we can add
+ */
+
+static void test_redis_create(abts_case * tc, void *data)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_redis_t *redis;
+  apr_redis_server_t *server, *s;
+  apr_uint32_t max_servers = 10;
+  apr_uint32_t i;
+  apr_uint32_t hash;
+
+  rv = apr_redis_create(pool, max_servers, 0, &redis);
+  ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+  
+  for (i = 1; i <= max_servers; i++) {
+    apr_port_t port;
+    
+    port = PORT + i;
+    rv =
+      apr_redis_server_create(pool, HOST, PORT + i, 0, 1, 1, 60, 5, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+    
+    rv = apr_redis_add_server(redis, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+    
+    s = apr_redis_find_server(redis, HOST, port);
+    ABTS_PTR_EQUAL(tc, server, s);
+    
+    rv = apr_redis_disable_server(redis, s);
+    ABTS_ASSERT(tc, "server disable failed", rv == APR_SUCCESS);
+    
+    rv = apr_redis_enable_server(redis, s);
+    ABTS_ASSERT(tc, "server enable failed", rv == APR_SUCCESS);
+    
+    hash = apr_redis_hash(redis, prefix, strlen(prefix));
+    ABTS_ASSERT(tc, "hash failed", hash > 0);
+    
+    s = apr_redis_find_server_hash(redis, hash);
+    ABTS_PTR_NOTNULL(tc, s);
+  }
+
+  rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 5, &server);
+  ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+  
+  rv = apr_redis_add_server(redis, server);
+  ABTS_ASSERT(tc, "server add should have failed", rv != APR_SUCCESS);
+  
+}
+
+/* install our own custom hashing and server selection routines. */
+
+static int create_test_hash(apr_pool_t *p, apr_hash_t *h)
+{
+  int i;
+  
+  for (i = 0; i < TDATA_SIZE; i++) {
+    char *k, *v;
+    
+    k = apr_pstrcat(p, prefix, apr_itoa(p, i), NULL);
+    v = apr_pstrndup(p, txt, randval((apr_uint32_t)strlen(txt)));
+    
+    apr_hash_set(h, k, APR_HASH_KEY_STRING, v);
+  }
+
+  return i;
+}
+
+static void test_redis_user_funcs(abts_case * tc, void *data)
+{
+  apr_pool_t *pool = p;
+  apr_status_t rv;
+  apr_redis_t *redis;
+  apr_redis_server_t *found;
+  apr_uint32_t max_servers = 10;
+  apr_uint32_t hres;
+  apr_uint32_t i;
+  my_hash_server_baton *baton = 
+    apr_pcalloc(pool, sizeof(my_hash_server_baton));
+
+  rv = apr_redis_create(pool, max_servers, 0, &redis);
+  ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+  /* as noted above, install our custom hash function, and call 
+   * apr_redis_hash. the return value should be our predefined number,
+   * and our function just ignores the other args, for simplicity.
+   */
+  redis->hash_func = my_hash_func;
+
+  hres = apr_redis_hash(redis, "whatever", sizeof("whatever") - 1);
+  ABTS_INT_EQUAL(tc, HASH_FUNC_RESULT, hres);
+  
+  /* add some servers */
+  for(i = 1; i <= 10; i++) {
+    apr_redis_server_t *ms;
+
+    rv = apr_redis_server_create(pool, HOST, i, 0, 1, 1, 60, 5, &ms);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+    
+    rv = apr_redis_add_server(redis, 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;
+  redis->server_func = my_server_func;
+  redis->server_baton = baton;
+  found = apr_redis_find_server_hash(redis, 0);
+  ABTS_ASSERT(tc, "wrong server found", found->port == baton->which_server);
+}
+
+/* test non data related commands like stats and version */
+static void test_redis_meta(abts_case * tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_redis_t *redis;
+    apr_redis_server_t *server;
+    apr_redis_stats_t *stats;
+    char *result;
+    apr_status_t rv;
+
+    rv = apr_redis_create(pool, 1, 0, &redis);
+    ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 5, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_add_server(redis, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_version(server, pool, &result);
+    ABTS_PTR_NOTNULL(tc, result);
+
+    rv = apr_redis_stats(server, p, &stats);
+    ABTS_PTR_NOTNULL(tc, stats);
+
+    /* 
+     * no way to know exactly what will be in most of these, so
+     * just make sure there is something.
+     */
+    ABTS_ASSERT(tc, "major", stats->major >= 1);
+    ABTS_ASSERT(tc, "minor", stats->minor >= 0);
+    ABTS_ASSERT(tc, "patch", stats->patch >= 0);
+    ABTS_ASSERT(tc, "process_id", stats->process_id >= 0);
+    ABTS_ASSERT(tc, "uptime_in_seconds", stats->uptime_in_seconds >= 0);
+    ABTS_ASSERT(tc, "arch_bits", stats->arch_bits >= 0);
+    ABTS_ASSERT(tc, "connected_clients", stats->connected_clients >= 0);
+    ABTS_ASSERT(tc, "blocked_clients", stats->blocked_clients >= 0);
+    ABTS_ASSERT(tc, "maxmemory", stats->maxmemory >= 0);
+    ABTS_ASSERT(tc, "used_memory", stats->used_memory >= 0);
+    ABTS_ASSERT(tc, "total_system_memory", stats->total_system_memory >= 0);
+    ABTS_ASSERT(tc, "total_connections_received", stats->total_connections_received >= 0);
+    ABTS_ASSERT(tc, "total_commands_processed", stats->total_commands_processed >= 0);
+    ABTS_ASSERT(tc, "total_net_input_bytes", stats->total_net_input_bytes >= 0);
+    ABTS_ASSERT(tc, "total_net_output_bytes", stats->total_net_output_bytes >= 0);
+    ABTS_ASSERT(tc, "keyspace_hits", stats->keyspace_hits >= 0);
+    ABTS_ASSERT(tc, "keyspace_misses", stats->keyspace_misses >= 0);
+    ABTS_ASSERT(tc, "role", stats->role >= 0);
+    ABTS_ASSERT(tc, "connected_slaves", stats->connected_slaves >= 0);
+    ABTS_ASSERT(tc, "used_cpu_sys", stats->used_cpu_sys >= 0);
+    ABTS_ASSERT(tc, "used_cpu_user", stats->used_cpu_user >= 0);
+    ABTS_ASSERT(tc, "cluster_enabled", stats->cluster_enabled >= 0);
+}
+
+
+/* basic tests of the increment and decrement commands */
+static void test_redis_incrdecr(abts_case * tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_redis_t *redis;
+ apr_redis_server_t *server;
+ apr_uint32_t new;
+ char *result;
+ apr_size_t len;
+ apr_uint32_t i;
+
+  rv = apr_redis_create(pool, 1, 0, &redis);
+  ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+  
+  rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 5, &server);
+  ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+  
+  rv = apr_redis_add_server(redis, server);
+  ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+  rv = apr_redis_set(redis, prefix, "271", sizeof("271") - 1, 27);
+  ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+  
+  for( i = 1; i <= TDATA_SIZE; i++) {
+    apr_uint32_t expect;
+
+    rv = apr_redis_getp(redis, pool, prefix, &result, &len, NULL);
+    ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+
+    expect = i + atoi(result);
+
+    rv = apr_redis_incr(redis, prefix, i, &new);
+    ABTS_ASSERT(tc, "incr failed", rv == APR_SUCCESS);
+
+    ABTS_INT_EQUAL(tc, expect, new);
+
+    rv = apr_redis_decr(redis, prefix, i, &new);
+    ABTS_ASSERT(tc, "decr failed", rv == APR_SUCCESS);
+
+    ABTS_INT_EQUAL(tc, atoi(result), new);
+
+  }
+
+  rv = apr_redis_getp(redis, pool, prefix, &result, &len, NULL);
+  ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+
+  ABTS_INT_EQUAL(tc, 271, atoi(result));
+
+  rv = apr_redis_delete(redis, prefix, 0);
+  ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+}
+
+
+/* test setting and getting */
+
+static void test_redis_setget(abts_case * tc, void *data)
+{
+    apr_pool_t *pool = p;
+    apr_status_t rv;
+    apr_redis_t *redis;
+    apr_redis_server_t *server;
+    apr_hash_t *tdata;
+    apr_hash_index_t *hi;
+    char *result;
+    apr_size_t len;
+
+    rv = apr_redis_create(pool, 1, 0, &redis);
+    ABTS_ASSERT(tc, "redis create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_server_create(pool, HOST, PORT, 0, 1, 1, 60, 5, &server);
+    ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+    rv = apr_redis_add_server(redis, server);
+    ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+    tdata = apr_hash_make(pool);
+
+    create_test_hash(pool, tdata);
+
+    for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+	const void *k;
+	void *v;
+        const char *key;
+
+	apr_hash_this(hi, &k, NULL, &v);
+        key = k;
+
+	rv = apr_redis_set(redis, key, v, strlen(v), 27);
+	ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS);
+	rv = apr_redis_getp(redis, pool, key, &result, &len, NULL);
+	ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS);
+    }
+
+    rv = apr_redis_getp(redis, pool, "nothere3423", &result, &len, NULL);
+
+    ABTS_ASSERT(tc, "get should have failed", rv != APR_SUCCESS);
+
+    for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) {
+	const void *k;
+	const char *key;
+
+	apr_hash_this(hi, &k, NULL, NULL);
+	key = k;
+
+	rv = apr_redis_delete(redis, key, 0);
+	ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS);
+    }
+}
+
+abts_suite *testredis(abts_suite * suite)
+{
+    suite = ADD_SUITE(suite);
+    abts_run_test(suite, test_redis_create, NULL);
+    abts_run_test(suite, test_redis_user_funcs, NULL);
+    abts_run_test(suite, test_redis_meta, NULL);
+    abts_run_test(suite, test_redis_setget, NULL);
+    /* abts_run_test(suite, test_redis_multiget, NULL); */
+    abts_run_test(suite, test_redis_incrdecr, NULL);
+
+    return suite;
+}

Modified: apr/apr-util/branches/1.6.x/test/testutil.h
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/test/testutil.h?rev=1767973&r1=1767972&r2=1767973&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/test/testutil.h (original)
+++ apr/apr-util/branches/1.6.x/test/testutil.h Thu Nov  3 21:01:56 2016
@@ -61,6 +61,7 @@ abts_suite *testldap(abts_suite *suite);
 abts_suite *testdbd(abts_suite *suite);
 abts_suite *testdate(abts_suite *suite);
 abts_suite *testmemcache(abts_suite *suite);
+abts_suite *testredis(abts_suite *suite);
 abts_suite *testreslist(abts_suite *suite);
 abts_suite *testqueue(abts_suite *suite);
 abts_suite *testxml(abts_suite *suite);