diff options
Diffstat (limited to 'test/testmemcache.c')
-rw-r--r-- | test/testmemcache.c | 201 |
1 files changed, 137 insertions, 64 deletions
diff --git a/test/testmemcache.c b/test/testmemcache.c index c65381e3..5b498fea 100644 --- a/test/testmemcache.c +++ b/test/testmemcache.c @@ -22,9 +22,12 @@ #include "apr_hash.h" #include "apr_memcache.h" #include "apr_network_io.h" +#include "apr_thread_proc.h" +#include "apr_signal.h" +#include "testmemcache.h" #if APR_HAVE_STDLIB_H -#include <stdlib.h> /* for exit() */ +#include <stdlib.h> /* for exit() */ #endif #define HOST "localhost" @@ -57,7 +60,7 @@ const char txt[] = * 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 + * 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. */ @@ -67,7 +70,7 @@ typedef struct { } my_hash_server_baton; -/* this could do something fancy and return some hash result. +/* 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. @@ -82,10 +85,10 @@ static apr_uint32_t my_hash_func(void *baton, const char *data, /* * 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 + * and pulls some number from the *baton, which is a struct that has some * kind of meaningful stuff in it. */ -static apr_memcache_server_t *my_server_func(void *baton, +static apr_memcache_server_t *my_server_func(void *baton, apr_memcache_t *mc, const apr_uint32_t hash) { @@ -94,7 +97,7 @@ static apr_memcache_server_t *my_server_func(void *baton, if(mc->ntotal == 0) { return NULL; - } + } if(mc->ntotal < mhsb->which_server) { return NULL; @@ -112,8 +115,8 @@ static int randval(apr_uint32_t high) double d = 0; if (firsttime == 0) { - srand((unsigned) (getpid())); - firsttime = 1; + srand((unsigned) (getpid())); + firsttime = 1; } d = (double) rand() / ((double) RAND_MAX + 1); @@ -139,40 +142,40 @@ static void test_memcache_create(abts_case * tc, void *data) rv = apr_memcache_create(pool, max_servers, 0, &memcache); ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); - + for (i = 1; i <= max_servers; i++) { apr_port_t port; - + port = PORT + i; rv = apr_memcache_server_create(pool, HOST, PORT + i, 0, 1, 1, 60, &server); ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); - + rv = apr_memcache_add_server(memcache, server); ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); - + s = apr_memcache_find_server(memcache, HOST, port); ABTS_PTR_EQUAL(tc, server, s); - + rv = apr_memcache_disable_server(memcache, s); ABTS_ASSERT(tc, "server disable failed", rv == APR_SUCCESS); - + rv = apr_memcache_enable_server(memcache, s); ABTS_ASSERT(tc, "server enable failed", rv == APR_SUCCESS); - + hash = apr_memcache_hash(memcache, prefix, strlen(prefix)); ABTS_ASSERT(tc, "hash failed", hash > 0); - + s = apr_memcache_find_server_hash(memcache, hash); ABTS_PTR_NOTNULL(tc, s); } rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); - + rv = apr_memcache_add_server(memcache, server); ABTS_ASSERT(tc, "server add should have failed", rv != APR_SUCCESS); - + } /* install our own custom hashing and server selection routines. */ @@ -180,13 +183,13 @@ static void test_memcache_create(abts_case * tc, void *data) 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); } @@ -202,13 +205,13 @@ static void test_memcache_user_funcs(abts_case * tc, void *data) apr_uint32_t max_servers = 10; apr_uint32_t hres; apr_uint32_t i; - my_hash_server_baton *baton = + 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 + /* 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. */ @@ -216,24 +219,24 @@ static void test_memcache_user_funcs(abts_case * tc, void *data) hres = apr_memcache_hash(memcache, "whatever", sizeof("whatever") - 1); ABTS_INT_EQUAL(tc, HASH_FUNC_RESULT, hres); - + /* 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 + /* + * 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_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); @@ -266,11 +269,11 @@ static void test_memcache_meta(abts_case * tc, void *data) ABTS_STR_NEQUAL(tc, stats->version, result, 5); - /* + /* * no way to know exactly what will be in most of these, so * just make sure there is something. */ - + ABTS_ASSERT(tc, "pid", stats->pid >= 0); ABTS_ASSERT(tc, "time", stats->time >= 0); /* ABTS_ASSERT(tc, "pointer_size", stats->pointer_size >= 0); */ @@ -283,7 +286,7 @@ static void test_memcache_meta(abts_case * tc, void *data) ABTS_ASSERT(tc, "curr_connections", stats->curr_connections >= 0); ABTS_ASSERT(tc, "total_connections", stats->total_connections >= 0); - ABTS_ASSERT(tc, "connection_structures", + ABTS_ASSERT(tc, "connection_structures", stats->connection_structures >= 0); ABTS_ASSERT(tc, "cmd_get", stats->cmd_get >= 0); @@ -315,13 +318,13 @@ static void test_memcache_addreplace(abts_case * tc, void *data) rv = apr_memcache_create(pool, 1, 0, &memcache); ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); - + rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); - + rv = apr_memcache_add_server(memcache, server); ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); - + tdata = apr_hash_make(p); create_test_hash(pool, tdata); @@ -336,7 +339,7 @@ static void test_memcache_addreplace(abts_case * tc, void *data) /* doesn't exist yet, fail */ rv = apr_memcache_replace(memcache, key, v, strlen(v) - 1, 0, 27); ABTS_ASSERT(tc, "replace should have failed", rv != APR_SUCCESS); - + /* doesn't exist yet, succeed */ rv = apr_memcache_add(memcache, key, v, strlen(v), 0, 27); ABTS_ASSERT(tc, "add failed", rv == APR_SUCCESS); @@ -374,16 +377,16 @@ static void test_memcache_incrdecr(abts_case * tc, void *data) rv = apr_memcache_create(pool, 1, 0, &memcache); ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); - + rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); - + rv = apr_memcache_add_server(memcache, server); ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); rv = apr_memcache_set(memcache, prefix, "271", sizeof("271") - 1, 0, 27); ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS); - + for( i = 1; i <= TDATA_SIZE; i++) { apr_uint32_t expect; @@ -426,16 +429,16 @@ static void test_memcache_multiget(abts_case * tc, void *data) rv = apr_memcache_create(pool, 1, 0, &memcache); ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); - + rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); - + rv = apr_memcache_add_server(memcache, server); ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); - + values = apr_hash_make(p); tdata = apr_hash_make(p); - + create_test_hash(pool, tdata); for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) { @@ -449,34 +452,34 @@ static void test_memcache_multiget(abts_case * tc, void *data) rv = apr_memcache_set(memcache, key, v, strlen(v), 0, 27); ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS); } - + apr_pool_create(&tmppool, pool); for (i = 0; i < TDATA_SET; i++) apr_memcache_add_multget_key(pool, apr_pstrcat(pool, prefix, apr_itoa(pool, i), NULL), &values); - + rv = apr_memcache_multgetp(memcache, tmppool, pool, values); - + ABTS_ASSERT(tc, "multgetp failed", rv == APR_SUCCESS); ABTS_ASSERT(tc, "multgetp returned too few results", apr_hash_count(values) == TDATA_SET); - + 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_memcache_delete(memcache, key, 0); ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS); } - + } /* test setting and getting */ @@ -506,17 +509,17 @@ static void test_memcache_setget(abts_case * tc, void *data) create_test_hash(pool, tdata); for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) { - const void *k; - void *v; + const void *k; + void *v; const char *key; - apr_hash_this(hi, &k, NULL, &v); + apr_hash_this(hi, &k, NULL, &v); key = k; - rv = apr_memcache_set(memcache, key, v, strlen(v), 0, 27); - ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS); - rv = apr_memcache_getp(memcache, pool, key, &result, &len, NULL); - ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS); + rv = apr_memcache_set(memcache, key, v, strlen(v), 0, 27); + ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS); + rv = apr_memcache_getp(memcache, pool, key, &result, &len, NULL); + ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS); } rv = apr_memcache_getp(memcache, pool, "nothere3423", &result, &len, NULL); @@ -524,19 +527,19 @@ static void test_memcache_setget(abts_case * tc, void *data) 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; + const void *k; + const char *key; - apr_hash_this(hi, &k, NULL, NULL); - key = k; + apr_hash_this(hi, &k, NULL, NULL); + key = k; - rv = apr_memcache_delete(memcache, key, 0); - ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS); + rv = apr_memcache_delete(memcache, key, 0); + ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS); } } -/* use apr_socket stuff to see if there is in fact a memcached server - * running on PORT. +/* use apr_socket stuff to see if there is in fact a memcached server + * running on PORT. */ static apr_status_t check_mc(void) { @@ -599,11 +602,80 @@ static apr_status_t check_mc(void) return rv; } +static void test_connection_validation(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_memcache_t *memcache; + apr_memcache_server_t *memserver; + char *result; + apr_procattr_t *procattr; + apr_proc_t proc; + const char *args[2]; + int exitcode; + apr_exit_why_e why; +#ifdef SIGPIPE + /* + * If SIGPIPE is present ignore it as we will write to a closed socket. + * Otherwise we would be terminated by the default handler for SIGPIPE. + */ + apr_sigfunc_t *old_action; + + old_action = apr_signal(SIGPIPE, SIG_IGN); +#endif + + rv = apr_procattr_create(&procattr, p); + ABTS_ASSERT(tc, "Couldn't create procattr", rv == APR_SUCCESS); + + rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE, + APR_NO_PIPE); + ABTS_ASSERT(tc, "Couldn't set io in procattr", rv == APR_SUCCESS); + + rv = apr_procattr_error_check_set(procattr, 1); + ABTS_ASSERT(tc, "Couldn't set error check in procattr", rv == APR_SUCCESS); + + rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV); + ABTS_ASSERT(tc, "Couldn't set copy environment", rv == APR_SUCCESS); + + args[0] = "memcachedmock" EXTENSION; + args[1] = NULL; + rv = apr_proc_create(&proc, TESTBINPATH "memcachedmock" EXTENSION, args, NULL, + procattr, p); + ABTS_ASSERT(tc, "Couldn't launch program", rv == APR_SUCCESS); + + /* Wait for the mock memcached to start */ + apr_sleep(apr_time_from_sec(2)); + + rv = apr_memcache_create(p, 1, 0, &memcache); + ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); + + rv = apr_memcache_server_create(p, MOCK_HOST, MOCK_PORT, 0, 1, 1, 60000, &memserver); + ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); + + rv = apr_memcache_add_server(memcache, memserver); + ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); + + rv = apr_memcache_version(memserver, p, &result); + ABTS_ASSERT(tc, "Couldn't get initial version", rv == APR_SUCCESS); + + /* Wait for the mock memcached to shutdown the socket */ + apr_sleep(apr_time_from_sec(1)); + + rv = apr_memcache_version(memserver, p, &result); + ABTS_ASSERT(tc, "Couldn't get version after connection shutdown", rv == APR_SUCCESS); + +#ifdef SIGPIPE + /* Restore old SIGPIPE handler */ + apr_signal(SIGPIPE, old_action); +#endif + + apr_proc_wait(&proc, &exitcode, &why, APR_WAIT); +} + abts_suite *testmemcache(abts_suite * suite) { apr_status_t rv; suite = ADD_SUITE(suite); - /* check for a running memcached on the typical port before + /* check for a running memcached on the typical port before * trying to run the tests. succeed if we don't find one. */ rv = check_mc(); @@ -621,6 +693,7 @@ abts_suite *testmemcache(abts_suite * suite) "on %s:%d. Skipping apr_memcache tests...", rv, HOST, PORT); } + abts_run_test(suite, test_connection_validation, NULL); return suite; } |