1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter#include "testutil.h" 18251876Speter#include "apr.h" 19251876Speter#include "apu.h" 20251876Speter#include "apr_general.h" 21251876Speter#include "apr_strings.h" 22251876Speter#include "apr_hash.h" 23251876Speter#include "apr_memcache.h" 24251876Speter#include "apr_network_io.h" 25251876Speter 26251876Speter#if APR_HAVE_STDLIB_H 27251876Speter#include <stdlib.h> /* for exit() */ 28251876Speter#endif 29251876Speter 30251876Speter#define HOST "localhost" 31251876Speter#define PORT 11211 32251876Speter 33251876Speter/* the total number of items to use for set/get testing */ 34251876Speter#define TDATA_SIZE 3000 35251876Speter 36251876Speter/* some smaller subset of TDATA_SIZE used for multiget testing */ 37251876Speter#define TDATA_SET 100 38251876Speter 39251876Speter/* our custom hash function just returns this all the time */ 40251876Speter#define HASH_FUNC_RESULT 510 41251876Speter 42251876Speter/* all keys will be prefixed with this */ 43251876Speterconst char prefix[] = "testmemcache"; 44251876Speter 45251876Speter/* text for values we store */ 46251876Speterconst char txt[] = 47251876Speter"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis at" 48251876Speter"lacus in ligula hendrerit consectetuer. Vestibulum tristique odio" 49251876Speter"iaculis leo. In massa arcu, ultricies a, laoreet nec, hendrerit non," 50251876Speter"neque. Nulla sagittis sapien ac risus. Morbi ligula dolor, vestibulum" 51251876Speter"nec, viverra id, placerat dapibus, arcu. Curabitur egestas feugiat" 52251876Speter"tellus. Donec dignissim. Nunc ante. Curabitur id lorem. In mollis" 53251876Speter"tortor sit amet eros auctor dapibus. Proin nulla sem, tristique in," 54251876Speter"convallis id, iaculis feugiat cras amet."; 55251876Speter 56251876Speter/* 57251876Speter * this datatype is for our custom server determination function. this might 58251876Speter * be useful if you don't want to rely on simply hashing keys to determine 59251876Speter * where a key belongs, but instead want to write something fancy, or use some 60251876Speter * other kind of configuration data, i.e. a hash plus some data about a 61251876Speter * namespace, or whatever. see my_server_func, and test_memcache_user_funcs 62251876Speter * for the examples. 63251876Speter */ 64251876Spetertypedef struct { 65251876Speter const char *someval; 66251876Speter apr_uint32_t which_server; 67251876Speter} my_hash_server_baton; 68251876Speter 69251876Speter 70251876Speter/* this could do something fancy and return some hash result. 71251876Speter * for simplicity, just return the same value, so we can test it later on. 72251876Speter * if you wanted to use some external hashing library or functions for 73251876Speter * consistent hashing, for example, this would be a good place to do it. 74251876Speter */ 75251876Speterstatic apr_uint32_t my_hash_func(void *baton, const char *data, 76251876Speter apr_size_t data_len) 77251876Speter{ 78251876Speter 79251876Speter return HASH_FUNC_RESULT; 80251876Speter} 81251876Speter 82251876Speter/* 83251876Speter * a fancy function to determine which server to use given some kind of data 84251876Speter * and a hash value. this example actually ignores the hash value itself 85251876Speter * and pulls some number from the *baton, which is a struct that has some 86251876Speter * kind of meaningful stuff in it. 87251876Speter */ 88251876Speterstatic apr_memcache_server_t *my_server_func(void *baton, 89251876Speter apr_memcache_t *mc, 90251876Speter const apr_uint32_t hash) 91251876Speter{ 92251876Speter apr_memcache_server_t *ms = NULL; 93251876Speter my_hash_server_baton *mhsb = (my_hash_server_baton *)baton; 94251876Speter 95251876Speter if(mc->ntotal == 0) { 96251876Speter return NULL; 97251876Speter } 98251876Speter 99251876Speter if(mc->ntotal < mhsb->which_server) { 100251876Speter return NULL; 101251876Speter } 102251876Speter 103251876Speter ms = mc->live_servers[mhsb->which_server - 1]; 104251876Speter 105251876Speter return ms; 106251876Speter} 107251876Speter 108251876Speterapr_uint16_t firsttime = 0; 109251876Speterstatic int randval(apr_uint32_t high) 110251876Speter{ 111251876Speter apr_uint32_t i = 0; 112251876Speter double d = 0; 113251876Speter 114251876Speter if (firsttime == 0) { 115251876Speter srand((unsigned) (getpid())); 116251876Speter firsttime = 1; 117251876Speter } 118251876Speter 119251876Speter d = (double) rand() / ((double) RAND_MAX + 1); 120251876Speter i = (int) (d * (high - 0 + 1)); 121251876Speter 122251876Speter return i > 0 ? i : 1; 123251876Speter} 124251876Speter 125251876Speter/* 126251876Speter * general test to make sure we can create the memcache struct and add 127251876Speter * some servers, but not more than we tell it we can add 128251876Speter */ 129251876Speter 130251876Speterstatic void test_memcache_create(abts_case * tc, void *data) 131251876Speter{ 132251876Speter apr_pool_t *pool = p; 133251876Speter apr_status_t rv; 134251876Speter apr_memcache_t *memcache; 135251876Speter apr_memcache_server_t *server, *s; 136251876Speter apr_uint32_t max_servers = 10; 137251876Speter apr_uint32_t i; 138251876Speter apr_uint32_t hash; 139251876Speter 140251876Speter rv = apr_memcache_create(pool, max_servers, 0, &memcache); 141251876Speter ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); 142251876Speter 143251876Speter for (i = 1; i <= max_servers; i++) { 144251876Speter apr_port_t port; 145251876Speter 146251876Speter port = PORT + i; 147251876Speter rv = 148251876Speter apr_memcache_server_create(pool, HOST, PORT + i, 0, 1, 1, 60, &server); 149251876Speter ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); 150251876Speter 151251876Speter rv = apr_memcache_add_server(memcache, server); 152251876Speter ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); 153251876Speter 154251876Speter s = apr_memcache_find_server(memcache, HOST, port); 155251876Speter ABTS_PTR_EQUAL(tc, server, s); 156251876Speter 157251876Speter rv = apr_memcache_disable_server(memcache, s); 158251876Speter ABTS_ASSERT(tc, "server disable failed", rv == APR_SUCCESS); 159251876Speter 160251876Speter rv = apr_memcache_enable_server(memcache, s); 161251876Speter ABTS_ASSERT(tc, "server enable failed", rv == APR_SUCCESS); 162251876Speter 163251876Speter hash = apr_memcache_hash(memcache, prefix, strlen(prefix)); 164251876Speter ABTS_ASSERT(tc, "hash failed", hash > 0); 165251876Speter 166251876Speter s = apr_memcache_find_server_hash(memcache, hash); 167251876Speter ABTS_PTR_NOTNULL(tc, s); 168251876Speter } 169251876Speter 170251876Speter rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); 171251876Speter ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); 172251876Speter 173251876Speter rv = apr_memcache_add_server(memcache, server); 174251876Speter ABTS_ASSERT(tc, "server add should have failed", rv != APR_SUCCESS); 175251876Speter 176251876Speter} 177251876Speter 178251876Speter/* install our own custom hashing and server selection routines. */ 179251876Speter 180251876Speterstatic int create_test_hash(apr_pool_t *p, apr_hash_t *h) 181251876Speter{ 182251876Speter int i; 183251876Speter 184251876Speter for (i = 0; i < TDATA_SIZE; i++) { 185251876Speter char *k, *v; 186251876Speter 187251876Speter k = apr_pstrcat(p, prefix, apr_itoa(p, i), NULL); 188251876Speter v = apr_pstrndup(p, txt, randval((apr_uint32_t)strlen(txt))); 189251876Speter 190251876Speter apr_hash_set(h, k, APR_HASH_KEY_STRING, v); 191251876Speter } 192251876Speter 193251876Speter return i; 194251876Speter} 195251876Speter 196251876Speterstatic void test_memcache_user_funcs(abts_case * tc, void *data) 197251876Speter{ 198251876Speter apr_pool_t *pool = p; 199251876Speter apr_status_t rv; 200251876Speter apr_memcache_t *memcache; 201251876Speter apr_memcache_server_t *found; 202251876Speter apr_uint32_t max_servers = 10; 203251876Speter apr_uint32_t hres; 204251876Speter apr_uint32_t i; 205251876Speter my_hash_server_baton *baton = 206251876Speter apr_pcalloc(pool, sizeof(my_hash_server_baton)); 207251876Speter 208251876Speter rv = apr_memcache_create(pool, max_servers, 0, &memcache); 209251876Speter ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); 210251876Speter 211251876Speter /* as noted above, install our custom hash function, and call 212251876Speter * apr_memcache_hash. the return value should be our predefined number, 213251876Speter * and our function just ignores the other args, for simplicity. 214251876Speter */ 215251876Speter memcache->hash_func = my_hash_func; 216251876Speter 217251876Speter hres = apr_memcache_hash(memcache, "whatever", sizeof("whatever") - 1); 218251876Speter ABTS_INT_EQUAL(tc, HASH_FUNC_RESULT, hres); 219251876Speter 220251876Speter /* add some servers */ 221251876Speter for(i = 1; i <= 10; i++) { 222251876Speter apr_memcache_server_t *ms; 223251876Speter 224251876Speter rv = apr_memcache_server_create(pool, HOST, i, 0, 1, 1, 60, &ms); 225251876Speter ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); 226251876Speter 227251876Speter rv = apr_memcache_add_server(memcache, ms); 228251876Speter ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); 229251876Speter } 230251876Speter 231251876Speter /* 232251876Speter * set 'which_server' in our server_baton to find the third server 233251876Speter * which should have the same port. 234251876Speter */ 235251876Speter baton->which_server = 3; 236251876Speter memcache->server_func = my_server_func; 237251876Speter memcache->server_baton = baton; 238251876Speter found = apr_memcache_find_server_hash(memcache, 0); 239251876Speter ABTS_ASSERT(tc, "wrong server found", found->port == baton->which_server); 240251876Speter} 241251876Speter 242251876Speter/* test non data related commands like stats and version */ 243251876Speterstatic void test_memcache_meta(abts_case * tc, void *data) 244251876Speter{ 245251876Speter apr_pool_t *pool = p; 246251876Speter apr_memcache_t *memcache; 247251876Speter apr_memcache_server_t *server; 248251876Speter apr_memcache_stats_t *stats; 249251876Speter char *result; 250251876Speter apr_status_t rv; 251251876Speter 252251876Speter rv = apr_memcache_create(pool, 1, 0, &memcache); 253251876Speter ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); 254251876Speter 255251876Speter rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); 256251876Speter ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); 257251876Speter 258251876Speter rv = apr_memcache_add_server(memcache, server); 259251876Speter ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); 260251876Speter 261251876Speter rv = apr_memcache_version(server, pool, &result); 262251876Speter ABTS_PTR_NOTNULL(tc, result); 263251876Speter 264251876Speter rv = apr_memcache_stats(server, p, &stats); 265251876Speter ABTS_PTR_NOTNULL(tc, stats); 266251876Speter 267251876Speter ABTS_STR_NEQUAL(tc, stats->version, result, 5); 268251876Speter 269251876Speter /* 270251876Speter * no way to know exactly what will be in most of these, so 271251876Speter * just make sure there is something. 272251876Speter */ 273251876Speter 274251876Speter ABTS_ASSERT(tc, "pid", stats->pid >= 0); 275251876Speter ABTS_ASSERT(tc, "time", stats->time >= 0); 276251876Speter /* ABTS_ASSERT(tc, "pointer_size", stats->pointer_size >= 0); */ 277251876Speter ABTS_ASSERT(tc, "rusage_user", stats->rusage_user >= 0); 278251876Speter ABTS_ASSERT(tc, "rusage_system", stats->rusage_system >= 0); 279251876Speter 280251876Speter ABTS_ASSERT(tc, "curr_items", stats->curr_items >= 0); 281251876Speter ABTS_ASSERT(tc, "total_items", stats->total_items >= 0); 282251876Speter ABTS_ASSERT(tc, "bytes", stats->bytes >= 0); 283251876Speter 284251876Speter ABTS_ASSERT(tc, "curr_connections", stats->curr_connections >= 0); 285251876Speter ABTS_ASSERT(tc, "total_connections", stats->total_connections >= 0); 286251876Speter ABTS_ASSERT(tc, "connection_structures", 287251876Speter stats->connection_structures >= 0); 288251876Speter 289251876Speter ABTS_ASSERT(tc, "cmd_get", stats->cmd_get >= 0); 290251876Speter ABTS_ASSERT(tc, "cmd_set", stats->cmd_set >= 0); 291251876Speter ABTS_ASSERT(tc, "get_hits", stats->get_hits >= 0); 292251876Speter ABTS_ASSERT(tc, "get_misses", stats->get_misses >= 0); 293251876Speter 294251876Speter /* ABTS_ASSERT(tc, "evictions", stats->evictions >= 0); */ 295251876Speter 296251876Speter ABTS_ASSERT(tc, "bytes_read", stats->bytes_read >= 0); 297251876Speter ABTS_ASSERT(tc, "bytes_written", stats->bytes_written >= 0); 298251876Speter ABTS_ASSERT(tc, "limit_maxbytes", stats->limit_maxbytes >= 0); 299251876Speter 300251876Speter /* ABTS_ASSERT(tc, "threads", stats->threads >= 0); */ 301251876Speter} 302251876Speter 303251876Speter/* test add and replace calls */ 304251876Speter 305251876Speterstatic void test_memcache_addreplace(abts_case * tc, void *data) 306251876Speter{ 307251876Speter apr_pool_t *pool = p; 308251876Speter apr_status_t rv; 309251876Speter apr_memcache_t *memcache; 310251876Speter apr_memcache_server_t *server; 311251876Speter apr_hash_t *tdata; 312251876Speter apr_hash_index_t *hi; 313251876Speter char *result; 314251876Speter apr_size_t len; 315251876Speter 316251876Speter rv = apr_memcache_create(pool, 1, 0, &memcache); 317251876Speter ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); 318251876Speter 319251876Speter rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); 320251876Speter ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); 321251876Speter 322251876Speter rv = apr_memcache_add_server(memcache, server); 323251876Speter ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); 324251876Speter 325251876Speter tdata = apr_hash_make(p); 326251876Speter create_test_hash(pool, tdata); 327251876Speter 328251876Speter for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) { 329251876Speter const void *k; 330251876Speter void *v; 331251876Speter const char *key; 332251876Speter 333251876Speter apr_hash_this(hi, &k, NULL, &v); 334251876Speter key = k; 335251876Speter 336251876Speter /* doesn't exist yet, fail */ 337251876Speter rv = apr_memcache_replace(memcache, key, v, strlen(v) - 1, 0, 27); 338251876Speter ABTS_ASSERT(tc, "replace should have failed", rv != APR_SUCCESS); 339251876Speter 340251876Speter /* doesn't exist yet, succeed */ 341251876Speter rv = apr_memcache_add(memcache, key, v, strlen(v), 0, 27); 342251876Speter ABTS_ASSERT(tc, "add failed", rv == APR_SUCCESS); 343251876Speter 344251876Speter /* exists now, succeed */ 345251876Speter rv = apr_memcache_replace(memcache, key, "new", sizeof("new") - 1, 0, 27); 346251876Speter ABTS_ASSERT(tc, "replace failed", rv == APR_SUCCESS); 347251876Speter 348251876Speter /* make sure its different */ 349251876Speter rv = apr_memcache_getp(memcache, pool, key, &result, &len, NULL); 350251876Speter ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS); 351251876Speter ABTS_STR_NEQUAL(tc, result, "new", 3); 352251876Speter 353251876Speter /* exists now, fail */ 354251876Speter rv = apr_memcache_add(memcache, key, v, strlen(v), 0, 27); 355251876Speter ABTS_ASSERT(tc, "add should have failed", rv != APR_SUCCESS); 356251876Speter 357251876Speter /* clean up */ 358251876Speter rv = apr_memcache_delete(memcache, key, 0); 359251876Speter ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS); 360251876Speter } 361251876Speter} 362251876Speter 363251876Speter/* basic tests of the increment and decrement commands */ 364251876Speterstatic void test_memcache_incrdecr(abts_case * tc, void *data) 365251876Speter{ 366251876Speter apr_pool_t *pool = p; 367251876Speter apr_status_t rv; 368251876Speter apr_memcache_t *memcache; 369251876Speter apr_memcache_server_t *server; 370251876Speter apr_uint32_t new; 371251876Speter char *result; 372251876Speter apr_size_t len; 373251876Speter apr_uint32_t i; 374251876Speter 375251876Speter rv = apr_memcache_create(pool, 1, 0, &memcache); 376251876Speter ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); 377251876Speter 378251876Speter rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); 379251876Speter ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); 380251876Speter 381251876Speter rv = apr_memcache_add_server(memcache, server); 382251876Speter ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); 383251876Speter 384251876Speter rv = apr_memcache_set(memcache, prefix, "271", sizeof("271") - 1, 0, 27); 385251876Speter ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS); 386251876Speter 387251876Speter for( i = 1; i <= TDATA_SIZE; i++) { 388251876Speter apr_uint32_t expect; 389251876Speter 390251876Speter rv = apr_memcache_getp(memcache, pool, prefix, &result, &len, NULL); 391251876Speter ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS); 392251876Speter 393251876Speter expect = i + atoi(result); 394251876Speter 395251876Speter rv = apr_memcache_incr(memcache, prefix, i, &new); 396251876Speter ABTS_ASSERT(tc, "incr failed", rv == APR_SUCCESS); 397251876Speter 398251876Speter ABTS_INT_EQUAL(tc, expect, new); 399251876Speter 400251876Speter rv = apr_memcache_decr(memcache, prefix, i, &new); 401251876Speter ABTS_ASSERT(tc, "decr failed", rv == APR_SUCCESS); 402251876Speter ABTS_INT_EQUAL(tc, atoi(result), new); 403251876Speter 404251876Speter } 405251876Speter 406251876Speter rv = apr_memcache_getp(memcache, pool, prefix, &result, &len, NULL); 407251876Speter ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS); 408251876Speter 409251876Speter ABTS_INT_EQUAL(tc, 271, atoi(result)); 410251876Speter 411251876Speter rv = apr_memcache_delete(memcache, prefix, 0); 412251876Speter ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS); 413251876Speter} 414251876Speter 415251876Speter/* test the multiget functionality */ 416251876Speterstatic void test_memcache_multiget(abts_case * tc, void *data) 417251876Speter{ 418251876Speter apr_pool_t *pool = p; 419251876Speter apr_pool_t *tmppool; 420251876Speter apr_status_t rv; 421251876Speter apr_memcache_t *memcache; 422251876Speter apr_memcache_server_t *server; 423251876Speter apr_hash_t *tdata, *values; 424251876Speter apr_hash_index_t *hi; 425251876Speter apr_uint32_t i; 426251876Speter 427251876Speter rv = apr_memcache_create(pool, 1, 0, &memcache); 428251876Speter ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); 429251876Speter 430251876Speter rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); 431251876Speter ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); 432251876Speter 433251876Speter rv = apr_memcache_add_server(memcache, server); 434251876Speter ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); 435251876Speter 436253734Speter values = apr_hash_make(p); 437251876Speter tdata = apr_hash_make(p); 438251876Speter 439251876Speter create_test_hash(pool, tdata); 440251876Speter 441251876Speter for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) { 442251876Speter const void *k; 443251876Speter void *v; 444251876Speter const char *key; 445251876Speter 446251876Speter apr_hash_this(hi, &k, NULL, &v); 447251876Speter key = k; 448251876Speter 449251876Speter rv = apr_memcache_set(memcache, key, v, strlen(v), 0, 27); 450251876Speter ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS); 451251876Speter } 452251876Speter 453251876Speter rv = apr_pool_create(&tmppool, pool); 454251876Speter for (i = 0; i < TDATA_SET; i++) 455251876Speter apr_memcache_add_multget_key(pool, 456251876Speter apr_pstrcat(pool, prefix, 457251876Speter apr_itoa(pool, i), NULL), 458251876Speter &values); 459251876Speter 460251876Speter rv = apr_memcache_multgetp(memcache, 461251876Speter tmppool, 462251876Speter pool, 463251876Speter values); 464251876Speter 465251876Speter ABTS_ASSERT(tc, "multgetp failed", rv == APR_SUCCESS); 466251876Speter ABTS_ASSERT(tc, "multgetp returned too few results", 467251876Speter apr_hash_count(values) == TDATA_SET); 468251876Speter 469251876Speter for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) { 470251876Speter const void *k; 471251876Speter const char *key; 472251876Speter 473251876Speter apr_hash_this(hi, &k, NULL, NULL); 474251876Speter key = k; 475251876Speter 476251876Speter rv = apr_memcache_delete(memcache, key, 0); 477251876Speter ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS); 478251876Speter } 479251876Speter 480251876Speter} 481251876Speter 482251876Speter/* test setting and getting */ 483251876Speter 484251876Speterstatic void test_memcache_setget(abts_case * tc, void *data) 485251876Speter{ 486251876Speter apr_pool_t *pool = p; 487251876Speter apr_status_t rv; 488251876Speter apr_memcache_t *memcache; 489251876Speter apr_memcache_server_t *server; 490251876Speter apr_hash_t *tdata; 491251876Speter apr_hash_index_t *hi; 492251876Speter char *result; 493251876Speter apr_size_t len; 494251876Speter 495251876Speter rv = apr_memcache_create(pool, 1, 0, &memcache); 496251876Speter ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS); 497251876Speter 498251876Speter rv = apr_memcache_server_create(pool, HOST, PORT, 0, 1, 1, 60, &server); 499251876Speter ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS); 500251876Speter 501251876Speter rv = apr_memcache_add_server(memcache, server); 502251876Speter ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS); 503251876Speter 504251876Speter tdata = apr_hash_make(pool); 505251876Speter 506251876Speter create_test_hash(pool, tdata); 507251876Speter 508251876Speter for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) { 509251876Speter const void *k; 510251876Speter void *v; 511251876Speter const char *key; 512251876Speter 513251876Speter apr_hash_this(hi, &k, NULL, &v); 514251876Speter key = k; 515251876Speter 516251876Speter rv = apr_memcache_set(memcache, key, v, strlen(v), 0, 27); 517251876Speter ABTS_ASSERT(tc, "set failed", rv == APR_SUCCESS); 518251876Speter rv = apr_memcache_getp(memcache, pool, key, &result, &len, NULL); 519251876Speter ABTS_ASSERT(tc, "get failed", rv == APR_SUCCESS); 520251876Speter } 521251876Speter 522251876Speter rv = apr_memcache_getp(memcache, pool, "nothere3423", &result, &len, NULL); 523251876Speter 524251876Speter ABTS_ASSERT(tc, "get should have failed", rv != APR_SUCCESS); 525251876Speter 526251876Speter for (hi = apr_hash_first(p, tdata); hi; hi = apr_hash_next(hi)) { 527251876Speter const void *k; 528251876Speter const char *key; 529251876Speter 530251876Speter apr_hash_this(hi, &k, NULL, NULL); 531251876Speter key = k; 532251876Speter 533251876Speter rv = apr_memcache_delete(memcache, key, 0); 534251876Speter ABTS_ASSERT(tc, "delete failed", rv == APR_SUCCESS); 535251876Speter } 536251876Speter} 537251876Speter 538251876Speter/* use apr_socket stuff to see if there is in fact a memcached server 539251876Speter * running on PORT. 540251876Speter */ 541251876Speterstatic apr_status_t check_mc(void) 542251876Speter{ 543251876Speter apr_pool_t *pool = p; 544251876Speter apr_status_t rv; 545251876Speter apr_socket_t *sock = NULL; 546251876Speter apr_sockaddr_t *sa; 547251876Speter struct iovec vec[2]; 548251876Speter apr_size_t written; 549251876Speter char buf[128]; 550251876Speter apr_size_t len; 551251876Speter 552251876Speter rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, 0, pool); 553251876Speter if(rv != APR_SUCCESS) { 554251876Speter return rv; 555251876Speter } 556251876Speter 557251876Speter rv = apr_sockaddr_info_get(&sa, HOST, APR_INET, PORT, 0, pool); 558251876Speter if(rv != APR_SUCCESS) { 559251876Speter return rv; 560251876Speter } 561251876Speter 562251876Speter rv = apr_socket_timeout_set(sock, 1 * APR_USEC_PER_SEC); 563251876Speter if (rv != APR_SUCCESS) { 564251876Speter return rv; 565251876Speter } 566251876Speter 567251876Speter rv = apr_socket_connect(sock, sa); 568251876Speter if (rv != APR_SUCCESS) { 569251876Speter return rv; 570251876Speter } 571251876Speter 572251876Speter rv = apr_socket_timeout_set(sock, -1); 573251876Speter if (rv != APR_SUCCESS) { 574251876Speter return rv; 575251876Speter } 576251876Speter 577251876Speter vec[0].iov_base = "version"; 578251876Speter vec[0].iov_len = sizeof("version") - 1; 579251876Speter 580251876Speter vec[1].iov_base = "\r\n"; 581251876Speter vec[1].iov_len = sizeof("\r\n") -1; 582251876Speter 583251876Speter rv = apr_socket_sendv(sock, vec, 2, &written); 584251876Speter if (rv != APR_SUCCESS) { 585251876Speter return rv; 586251876Speter } 587251876Speter 588251876Speter len = sizeof(buf); 589251876Speter rv = apr_socket_recv(sock, buf, &len); 590251876Speter if(rv != APR_SUCCESS) { 591251876Speter return rv; 592251876Speter } 593251876Speter 594251876Speter if(strncmp(buf, "VERSION", sizeof("VERSION")-1) != 0) { 595251876Speter rv = APR_EGENERAL; 596251876Speter } 597251876Speter 598251876Speter apr_socket_close(sock); 599251876Speter return rv; 600251876Speter} 601251876Speter 602251876Speterabts_suite *testmemcache(abts_suite * suite) 603251876Speter{ 604251876Speter apr_status_t rv; 605251876Speter suite = ADD_SUITE(suite); 606251876Speter /* check for a running memcached on the typical port before 607253734Speter * trying to run the tests. succeed if we don't find one. 608251876Speter */ 609251876Speter rv = check_mc(); 610253734Speter if (rv == APR_SUCCESS) { 611251876Speter abts_run_test(suite, test_memcache_create, NULL); 612251876Speter abts_run_test(suite, test_memcache_user_funcs, NULL); 613251876Speter abts_run_test(suite, test_memcache_meta, NULL); 614251876Speter abts_run_test(suite, test_memcache_setget, NULL); 615251876Speter abts_run_test(suite, test_memcache_multiget, NULL); 616251876Speter abts_run_test(suite, test_memcache_addreplace, NULL); 617251876Speter abts_run_test(suite, test_memcache_incrdecr, NULL); 618251876Speter } 619253734Speter else { 620253734Speter abts_log_message("Error %d occurred attempting to reach memcached " 621253734Speter "on %s:%d. Skipping apr_memcache tests...", 622253734Speter rv, HOST, PORT); 623253734Speter } 624251876Speter 625251876Speter return suite; 626251876Speter} 627