+/* 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:
+ *
+ */
+
/*
Sample test application.
*/
-#include <assert.h>
-#include <memcached.h>
+#include "config.h"
+
+#include "libmemcached/memcached.h"
+#include "libmemcached/watchpoint.h"
+
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
-#include "server.h"
-#include "../lib/common.h"
-#include "../src/generator.h"
-#include "../src/execute.h"
-
-#ifndef INT64_MAX
-#define INT64_MAX LONG_MAX
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX INT_MAX
-#endif
-
+#include "../clients/generator.h"
+#include "../clients/execute.h"
-#include "test.h"
+#include <libtest/server.h>
+#include <libtest/test.h>
+/* Number of items generated for tests */
#define GLOBAL_COUNT 100000
-#define TEST_COUNTER 100000
+
+/* Number of times to run the test loop */
+#define TEST_COUNTER 500000
static uint32_t global_count;
static pairs_st *global_pairs;
static char *global_keys[GLOBAL_COUNT];
static size_t global_keys_length[GLOBAL_COUNT];
-uint8_t cleanup_pairs(memcached_st *memc)
+static test_return_t cleanup_pairs(memcached_st *memc)
{
+ (void)memc;
pairs_free(global_pairs);
- return 0;
+ return EXIT_SUCCESS;
}
-uint8_t generate_pairs(memcached_st *memc)
+static test_return_t generate_pairs(memcached_st *memc)
{
- unsigned long long x;
+ (void)memc;
global_pairs= pairs_generate(GLOBAL_COUNT, 400);
global_count= GLOBAL_COUNT;
- for (x= 0; x < global_count; x++)
+ for (size_t x= 0; x < global_count; x++)
{
- global_keys[x]= global_pairs[x].key;
+ global_keys[x]= global_pairs[x].key;
global_keys_length[x]= global_pairs[x].key_length;
}
- return 0;
+ return EXIT_SUCCESS;
}
-uint8_t drizzle(memcached_st *memc)
+static test_return_t drizzle(memcached_st *memc)
{
- unsigned int x;
- memcached_return rc;
+ memcached_return_t rc;
+ char *return_value;
+ size_t return_value_length;
+ uint32_t flags;
+infinite:
+ for (size_t x= 0; x < TEST_COUNTER; x++)
{
- char *return_value;
- size_t return_value_length;
- uint32_t flags;
-
- for (x= 0; x < TEST_COUNTER; x++)
- {
- uint32_t test_bit;
- uint8_t which;
+ uint32_t test_bit;
+ uint8_t which;
- test_bit= random() % GLOBAL_COUNT;
- which= random() % 2;
+ test_bit= (uint32_t)(random() % GLOBAL_COUNT);
+ which= (uint8_t)(random() % 2);
- if (which == 0)
+ if (which == 0)
+ {
+ return_value= memcached_get(memc, global_keys[test_bit], global_keys_length[test_bit],
+ &return_value_length, &flags, &rc);
+ if (rc == MEMCACHED_SUCCESS && return_value)
{
- return_value= memcached_get(memc, global_keys[test_bit], global_keys_length[test_bit],
- &return_value_length, &flags, &rc);
- if (rc == MEMCACHED_SUCCESS && return_value)
- free(return_value);
- else
- WATCHPOINT_ERROR(rc);
- }
+ free(return_value);
+ }
+ else if (rc == MEMCACHED_NOTFOUND)
+ {
+ continue;
+ }
else
{
- rc= memcached_set(memc, global_pairs[test_bit].key,
- global_pairs[test_bit].key_length,
- global_pairs[test_bit].value,
- global_pairs[test_bit].value_length,
- 0, 0);
- if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
- {
- WATCHPOINT_ERROR(rc);
- WATCHPOINT_ASSERT(0);
- }
+ WATCHPOINT_ERROR(rc);
+ WATCHPOINT_ASSERT(rc);
+ }
+ }
+ else
+ {
+ rc= memcached_set(memc, global_pairs[test_bit].key,
+ global_pairs[test_bit].key_length,
+ global_pairs[test_bit].value,
+ global_pairs[test_bit].value_length,
+ 0, 0);
+ if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
+ {
+ WATCHPOINT_ERROR(rc);
+ WATCHPOINT_ASSERT(0);
}
}
}
- return 0;
+ if (getenv("MEMCACHED_ATOM_BURIN_IN"))
+ goto infinite;
+
+ return TEST_SUCCESS;
}
-memcached_return pre_nonblock(memcached_st *memc)
+static test_return_t pre_nonblock(memcached_st *memc)
{
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, NULL);
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 0);
- return MEMCACHED_SUCCESS;
+ return TEST_SUCCESS;
}
-memcached_return pre_md5(memcached_st *memc)
+/*
+ Set the value, then quit to make sure it is flushed.
+ Come back in and test that add fails.
+*/
+static test_return_t add_test(memcached_st *memc)
{
- memcached_hash value= MEMCACHED_HASH_MD5;
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, &value);
+ memcached_return_t rc;
+ const char *key= "foo";
+ const char *value= "when we sanitize";
+ unsigned long long setting_value;
+
+ setting_value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK);
+
+ rc= memcached_set(memc, key, strlen(key),
+ value, strlen(value),
+ (time_t)0, (uint32_t)0);
+ test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+ memcached_quit(memc);
+ rc= memcached_add(memc, key, strlen(key),
+ value, strlen(value),
+ (time_t)0, (uint32_t)0);
+
+ /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */
+ if (setting_value)
+ {
+ test_true(rc == MEMCACHED_NOTSTORED || rc == MEMCACHED_STORED);
+ }
+ else
+ {
+ test_true(rc == MEMCACHED_NOTSTORED);
+ }
- return MEMCACHED_SUCCESS;
+ return EXIT_SUCCESS;
}
-memcached_return pre_hsieh(memcached_st *memc)
+/*
+ * repeating add_tests many times
+ * may show a problem in timing
+ */
+static test_return_t many_adds(memcached_st *memc)
{
- memcached_hash value= MEMCACHED_HASH_HSIEH;
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, &value);
-
- return MEMCACHED_SUCCESS;
+ for (size_t x= 0; x < TEST_COUNTER; x++)
+ {
+ add_test(memc);
+ }
+ return EXIT_SUCCESS;
}
-memcached_return enable_consistent(memcached_st *memc)
+test_st smash_tests[] ={
+ {"generate_pairs", 1, (test_callback_fn)generate_pairs },
+ {"drizzle", 1, (test_callback_fn)drizzle },
+ {"cleanup", 1, (test_callback_fn)cleanup_pairs },
+ {"many_adds", 1, (test_callback_fn)many_adds },
+ {0, 0, 0}
+};
+
+#define BENCHMARK_TEST_LOOP 20000
+
+struct benchmark_state_st
{
- memcached_server_distribution value= MEMCACHED_DISTRIBUTION_CONSISTENT;
- memcached_hash hash;
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, &value);
- pre_hsieh(memc);
+ bool create_init;
+ bool clone_init;
+ memcached_st *create;
+ memcached_st *clone;
+} benchmark_state;
- value= (memcached_server_distribution)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION);
- assert(value == MEMCACHED_DISTRIBUTION_CONSISTENT);
+static test_return_t memcached_create_benchmark(memcached_st *memc)
+{
+ (void)memc;
+ benchmark_state.create_init= true;
- hash= (memcached_hash)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_HASH);
- assert(hash == MEMCACHED_HASH_HSIEH);
+ for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
+ {
+ memcached_st *ptr;
+ ptr= memcached_create(&benchmark_state.create[x]);
+ test_true(ptr);
+ }
- return MEMCACHED_SUCCESS;
+ return TEST_SUCCESS;
}
-test_st generate_tests[] ={
- {"generate_pairs", 1, generate_pairs },
- {"cleanup", 1, cleanup_pairs },
- {0, 0, 0}
-};
+static test_return_t memcached_clone_benchmark(memcached_st *memc)
+{
+ benchmark_state.clone_init= true;
+ for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
+ {
+ memcached_st *ptr;
+ ptr= memcached_clone(&benchmark_state.clone[x], memc);
-collection_st collection[] ={
- {"generate", 0, 0, generate_tests},
- {"generate_hsieh", pre_hsieh, 0, generate_tests},
- {"generate_hsieh_consistent", enable_consistent, 0, generate_tests},
- {"generate_md5", pre_md5, 0, generate_tests},
- {"generate_nonblock", pre_nonblock, 0, generate_tests},
- {0, 0, 0, 0}
-};
+ test_true(ptr);
+ }
-#define SERVERS_TO_CREATE 5
+ return TEST_SUCCESS;
+}
-void *world_create(void)
+static test_return_t pre_allocate(memcached_st *memc)
{
- server_startup_st *construct;
+ (void)memc;
+ memset(&benchmark_state, 0, sizeof(benchmark_state));
- construct= (server_startup_st *)malloc(sizeof(server_startup_st));
- memset(construct, 0, sizeof(server_startup_st));
- construct->count= SERVERS_TO_CREATE;
- construct->udp= 0;
- server_startup(construct);
+ benchmark_state.create= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st));
+ test_true(benchmark_state.create);
+ benchmark_state.clone= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st));
+ test_true(benchmark_state.clone);
- return construct;
+ return TEST_SUCCESS;
}
-void world_destroy(void *p)
+static test_return_t post_allocate(memcached_st *memc)
{
- server_startup_st *construct= (server_startup_st *)p;
- memcached_server_st *servers= (memcached_server_st *)construct->servers;
- memcached_server_list_free(servers);
+ (void)memc;
+ for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
+ {
+ if (benchmark_state.create_init)
+ memcached_free(&benchmark_state.create[x]);
- server_shutdown(construct);
- free(construct);
+ if (benchmark_state.clone_init)
+ memcached_free(&benchmark_state.clone[x]);
+ }
+
+ free(benchmark_state.create);
+ free(benchmark_state.clone);
+
+ return TEST_SUCCESS;
}
+
+test_st micro_tests[] ={
+ {"memcached_create", 1, (test_callback_fn)memcached_create_benchmark },
+ {"memcached_clone", 1, (test_callback_fn)memcached_clone_benchmark },
+ {0, 0, 0}
+};
+
+
+collection_st collection[] ={
+ {"smash", 0, 0, smash_tests},
+ {"smash_nonblock", (test_callback_fn)pre_nonblock, 0, smash_tests},
+ {"micro-benchmark", (test_callback_fn)pre_allocate, (test_callback_fn)post_allocate, micro_tests},
+ {0, 0, 0, 0}
+};
+
+
+#define SERVERS_TO_CREATE 5
+
+#include "libmemcached_world.h"
+
void get_world(world_st *world)
{
world->collections= collection;
- world->create= world_create;
- world->destroy= world_destroy;
+
+ world->create= (test_callback_create_fn)world_create;
+ world->destroy= (test_callback_fn)world_destroy;
+
+ world->test.startup= (test_callback_fn)world_test_startup;
+ world->test.flush= (test_callback_fn)world_flush;
+ world->test.pre_run= (test_callback_fn)world_pre_run;
+ world->test.post_run= (test_callback_fn)world_post_run;
+ world->test.on_error= (test_callback_error_fn)world_on_error;
+
+ world->collection.startup= (test_callback_fn)world_container_startup;
+ world->collection.shutdown= (test_callback_fn)world_container_shutdown;
+
+ world->runner= &defualt_libmemcached_runner;
}