2 * Copyright (C) 2006-2009 Brian Aker
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
13 Sample test application.
17 #include <libtest/test.hpp>
19 #include <libmemcached/memcached.h>
20 #include <libmemcached/watchpoint.h>
27 #include <sys/types.h>
31 #include <clients/generator.h>
32 #include <clients/execute.h>
34 #include <libtest/server.h>
36 using namespace libtest
;
38 /* Number of items generated for tests */
39 #define GLOBAL_COUNT 100000
41 /* Number of times to run the test loop */
42 #define TEST_COUNTER 500000
43 static uint32_t global_count
;
45 static pairs_st
*global_pairs
;
46 static char *global_keys
[GLOBAL_COUNT
];
47 static size_t global_keys_length
[GLOBAL_COUNT
];
49 static test_return_t
cleanup_pairs(memcached_st
*memc
)
52 pairs_free(global_pairs
);
57 static test_return_t
generate_pairs(memcached_st
*memc
)
60 global_pairs
= pairs_generate(GLOBAL_COUNT
, 400);
61 global_count
= GLOBAL_COUNT
;
63 for (size_t x
= 0; x
< global_count
; x
++)
65 global_keys
[x
]= global_pairs
[x
].key
;
66 global_keys_length
[x
]= global_pairs
[x
].key_length
;
72 static test_return_t
drizzle(memcached_st
*memc
)
74 memcached_return_t rc
;
76 size_t return_value_length
;
80 for (size_t x
= 0; x
< TEST_COUNTER
; x
++)
85 test_bit
= (uint32_t)(random() % GLOBAL_COUNT
);
86 which
= (uint8_t)(random() % 2);
90 return_value
= memcached_get(memc
, global_keys
[test_bit
], global_keys_length
[test_bit
],
91 &return_value_length
, &flags
, &rc
);
92 if (rc
== MEMCACHED_SUCCESS
&& return_value
)
96 else if (rc
== MEMCACHED_NOTFOUND
)
102 WATCHPOINT_ERROR(rc
);
103 WATCHPOINT_ASSERT(rc
);
108 rc
= memcached_set(memc
, global_pairs
[test_bit
].key
,
109 global_pairs
[test_bit
].key_length
,
110 global_pairs
[test_bit
].value
,
111 global_pairs
[test_bit
].value_length
,
113 if (rc
!= MEMCACHED_SUCCESS
&& rc
!= MEMCACHED_BUFFERED
)
115 WATCHPOINT_ERROR(rc
);
116 WATCHPOINT_ASSERT(0);
121 if (getenv("MEMCACHED_ATOM_BURIN_IN"))
127 static test_return_t
pre_nonblock(memcached_st
*memc
)
129 memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_NO_BLOCK
, 0);
135 Set the value, then quit to make sure it is flushed.
136 Come back in and test that add fails.
138 static test_return_t
add_test(memcached_st
*memc
)
140 memcached_return_t rc
;
141 const char *key
= "foo";
142 const char *value
= "when we sanitize";
143 unsigned long long setting_value
;
145 setting_value
= memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_NO_BLOCK
);
147 rc
= memcached_set(memc
, key
, strlen(key
),
148 value
, strlen(value
),
149 (time_t)0, (uint32_t)0);
150 test_true(rc
== MEMCACHED_SUCCESS
|| rc
== MEMCACHED_BUFFERED
);
151 memcached_quit(memc
);
152 rc
= memcached_add(memc
, key
, strlen(key
),
153 value
, strlen(value
),
154 (time_t)0, (uint32_t)0);
156 /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */
159 test_true(rc
== MEMCACHED_NOTSTORED
|| rc
== MEMCACHED_STORED
);
163 test_true(rc
== MEMCACHED_NOTSTORED
);
170 * repeating add_tests many times
171 * may show a problem in timing
173 static test_return_t
many_adds(memcached_st
*memc
)
175 for (size_t x
= 0; x
< TEST_COUNTER
; x
++)
182 test_st smash_tests
[] ={
183 {"generate_pairs", 1, (test_callback_fn
*)generate_pairs
},
184 {"drizzle", 1, (test_callback_fn
*)drizzle
},
185 {"cleanup", 1, (test_callback_fn
*)cleanup_pairs
},
186 {"many_adds", 1, (test_callback_fn
*)many_adds
},
190 #define BENCHMARK_TEST_LOOP 20000
192 struct benchmark_state_st
196 memcached_st
*create
;
200 static test_return_t
memcached_create_benchmark(memcached_st
*memc
)
203 benchmark_state
.create_init
= true;
205 for (size_t x
= 0; x
< BENCHMARK_TEST_LOOP
; x
++)
208 ptr
= memcached_create(&benchmark_state
.create
[x
]);
216 static test_return_t
memcached_clone_benchmark(memcached_st
*memc
)
218 benchmark_state
.clone_init
= true;
220 for (size_t x
= 0; x
< BENCHMARK_TEST_LOOP
; x
++)
223 ptr
= memcached_clone(&benchmark_state
.clone
[x
], memc
);
231 static test_return_t
pre_allocate(memcached_st
*memc
)
234 memset(&benchmark_state
, 0, sizeof(benchmark_state
));
236 benchmark_state
.create
= (memcached_st
*)calloc(BENCHMARK_TEST_LOOP
, sizeof(memcached_st
));
237 test_true(benchmark_state
.create
);
238 benchmark_state
.clone
= (memcached_st
*)calloc(BENCHMARK_TEST_LOOP
, sizeof(memcached_st
));
239 test_true(benchmark_state
.clone
);
244 static test_return_t
post_allocate(memcached_st
*memc
)
247 for (size_t x
= 0; x
< BENCHMARK_TEST_LOOP
; x
++)
249 if (benchmark_state
.create_init
)
250 memcached_free(&benchmark_state
.create
[x
]);
252 if (benchmark_state
.clone_init
)
253 memcached_free(&benchmark_state
.clone
[x
]);
256 free(benchmark_state
.create
);
257 free(benchmark_state
.clone
);
263 test_st micro_tests
[] ={
264 {"memcached_create", 1, (test_callback_fn
*)memcached_create_benchmark
},
265 {"memcached_clone", 1, (test_callback_fn
*)memcached_clone_benchmark
},
270 collection_st collection
[] ={
271 {"smash", 0, 0, smash_tests
},
272 {"smash_nonblock", (test_callback_fn
*)pre_nonblock
, 0, smash_tests
},
273 {"micro-benchmark", (test_callback_fn
*)pre_allocate
, (test_callback_fn
*)post_allocate
, micro_tests
},
278 #define SERVERS_TO_CREATE 5
280 #include "libmemcached_world.h"
282 void get_world(Framework
*world
)
284 world
->collections
= collection
;
286 world
->_create
= (test_callback_create_fn
*)world_create
;
287 world
->_destroy
= (test_callback_destroy_fn
*)world_destroy
;
289 world
->item
._startup
= (test_callback_fn
*)world_test_startup
;
290 world
->item
._flush
= (test_callback_fn
*)world_flush
;
291 world
->item
.set_pre((test_callback_fn
*)world_pre_run
);
292 world
->item
.set_post((test_callback_fn
*)world_post_run
);
293 world
->_on_error
= (test_callback_error_fn
*)world_on_error
;
295 world
->collection_startup
= (test_callback_fn
*)world_container_startup
;
296 world
->collection_shutdown
= (test_callback_fn
*)world_container_shutdown
;
298 world
->set_runner(&defualt_libmemcached_runner
);