Merge in trunk
[awesomized/libmemcached] / tests / libmemcached-1.0 / atomsmasher.cc
1 /* LibMemcached
2 * Copyright (C) 2006-2009 Brian Aker
3 * All rights reserved.
4 *
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
7 *
8 * Summary:
9 *
10 */
11
12 /*
13 Sample test application.
14 */
15 #include <config.h>
16
17 #include <libtest/test.hpp>
18
19 #include <libmemcached/memcached.h>
20
21 #include <cstdio>
22 #include <cstdlib>
23 #include <stdint.h>
24 #include <cstring>
25 #include <sys/time.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <ctime>
30 #include <clients/generator.h>
31 #include <clients/execute.h>
32
33 #include <libtest/server.h>
34
35 #include <tests/debug.h>
36
37 using namespace libtest;
38
39 /* Number of items generated for tests */
40 #define GLOBAL_COUNT 100000
41
42 /* Number of times to run the test loop */
43 #define TEST_COUNTER 500000
44 static uint32_t global_count;
45
46 static pairs_st *global_pairs;
47 static char *global_keys[GLOBAL_COUNT];
48 static size_t global_keys_length[GLOBAL_COUNT];
49
50 static test_return_t cleanup_pairs(memcached_st *)
51 {
52 pairs_free(global_pairs);
53
54 return TEST_SUCCESS;
55 }
56
57 static test_return_t generate_pairs(memcached_st *)
58 {
59 global_pairs= pairs_generate(GLOBAL_COUNT, 400);
60 global_count= GLOBAL_COUNT;
61
62 for (ptrdiff_t x= 0; x < global_count; x++)
63 {
64 global_keys[x]= global_pairs[x].key;
65 global_keys_length[x]= global_pairs[x].key_length;
66 }
67
68 return TEST_SUCCESS;
69 }
70
71 static test_return_t drizzle(memcached_st *memc)
72 {
73 infinite:
74 for (ptrdiff_t x= 0; x < TEST_COUNTER; x++)
75 {
76 memcached_return_t rc;
77 char *return_value;
78 size_t return_value_length;
79 uint32_t flags;
80
81 uint32_t test_bit;
82 uint8_t which;
83
84 test_bit= (uint32_t)(random() % GLOBAL_COUNT);
85 which= (uint8_t)(random() % 2);
86
87 if (which == 0)
88 {
89 return_value= memcached_get(memc, global_keys[test_bit], global_keys_length[test_bit],
90 &return_value_length, &flags, &rc);
91 if (rc == MEMCACHED_SUCCESS && return_value)
92 {
93 free(return_value);
94 }
95 else if (rc == MEMCACHED_NOTFOUND)
96 {
97 continue;
98 }
99 else
100 {
101 test_compare(MEMCACHED_SUCCESS, rc);
102 }
103 }
104 else
105 {
106 rc= memcached_set(memc, global_pairs[test_bit].key,
107 global_pairs[test_bit].key_length,
108 global_pairs[test_bit].value,
109 global_pairs[test_bit].value_length,
110 0, 0);
111 if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
112 {
113 test_compare(MEMCACHED_SUCCESS, rc);
114 }
115 }
116 }
117
118 if (getenv("MEMCACHED_ATOM_BURIN_IN"))
119 {
120 goto infinite;
121 }
122
123 return TEST_SUCCESS;
124 }
125
126 static test_return_t pre_nonblock(memcached_st *memc)
127 {
128 memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 0);
129
130 return TEST_SUCCESS;
131 }
132
133 /*
134 Set the value, then quit to make sure it is flushed.
135 Come back in and test that add fails.
136 */
137 static test_return_t add_test(memcached_st *memc)
138 {
139 const char *key= "foo";
140 const char *value= "when we sanitize";
141
142 memcached_return_t rc;
143 rc= memcached_set(memc, key, strlen(key),
144 value, strlen(value),
145 (time_t)0, (uint32_t)0);
146 test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
147 memcached_quit(memc);
148 rc= memcached_add(memc, key, strlen(key),
149 value, strlen(value),
150 (time_t)0, (uint32_t)0);
151
152 if (rc == MEMCACHED_CONNECTION_FAILURE)
153 {
154 print_servers(memc);
155 }
156
157 /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */
158 if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK))
159 {
160 test_true(rc == MEMCACHED_NOTSTORED or rc == MEMCACHED_STORED);
161 }
162 else
163 {
164 test_compare_got(MEMCACHED_NOTSTORED, rc, memcached_strerror(NULL, rc));
165 }
166
167 return TEST_SUCCESS;
168 }
169
170 /*
171 * repeating add_tests many times
172 * may show a problem in timing
173 */
174 static test_return_t many_adds(memcached_st *memc)
175 {
176 test_true(memc);
177 for (ptrdiff_t x= 0; x < TEST_COUNTER; x++)
178 {
179 test_compare_got(TEST_SUCCESS, add_test(memc), x);
180 }
181 return TEST_SUCCESS;
182 }
183
184 test_st smash_tests[] ={
185 {"generate_pairs", true, (test_callback_fn*)generate_pairs },
186 {"drizzle", true, (test_callback_fn*)drizzle },
187 {"cleanup", true, (test_callback_fn*)cleanup_pairs },
188 {"many_adds", true, (test_callback_fn*)many_adds },
189 {0, 0, 0}
190 };
191
192 #define BENCHMARK_TEST_LOOP 20000
193
194 struct benchmark_state_st
195 {
196 bool create_init;
197 bool clone_init;
198 memcached_st *create;
199 memcached_st *clone;
200 } benchmark_state;
201
202 static test_return_t memcached_create_benchmark(memcached_st *)
203 {
204 benchmark_state.create_init= true;
205
206 for (ptrdiff_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
207 {
208 memcached_st *ptr;
209 ptr= memcached_create(&benchmark_state.create[x]);
210
211 test_true(ptr);
212 }
213
214 return TEST_SUCCESS;
215 }
216
217 static test_return_t memcached_clone_benchmark(memcached_st *memc)
218 {
219 benchmark_state.clone_init= true;
220
221 for (ptrdiff_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
222 {
223 memcached_st *ptr= memcached_clone(&benchmark_state.clone[x], memc);
224
225 test_true(ptr);
226 }
227
228 return TEST_SUCCESS;
229 }
230
231 static test_return_t pre_allocate(memcached_st *)
232 {
233 memset(&benchmark_state, 0, sizeof(benchmark_state));
234
235 benchmark_state.create= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st));
236 test_true(benchmark_state.create);
237 benchmark_state.clone= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st));
238 test_true(benchmark_state.clone);
239
240 return TEST_SUCCESS;
241 }
242
243 static test_return_t post_allocate(memcached_st *)
244 {
245 for (ptrdiff_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
246 {
247 if (benchmark_state.create_init)
248 {
249 memcached_free(&benchmark_state.create[x]);
250 }
251
252 if (benchmark_state.clone_init)
253 {
254 memcached_free(&benchmark_state.clone[x]);
255 }
256 }
257
258 free(benchmark_state.create);
259 free(benchmark_state.clone);
260
261 return TEST_SUCCESS;
262 }
263
264
265 test_st micro_tests[] ={
266 {"memcached_create", 1, (test_callback_fn*)memcached_create_benchmark },
267 {"memcached_clone", 1, (test_callback_fn*)memcached_clone_benchmark },
268 {0, 0, 0}
269 };
270
271
272 collection_st collection[] ={
273 {"smash", 0, 0, smash_tests},
274 {"smash_nonblock", (test_callback_fn*)pre_nonblock, 0, smash_tests},
275 {"micro-benchmark", (test_callback_fn*)pre_allocate, (test_callback_fn*)post_allocate, micro_tests},
276 {0, 0, 0, 0}
277 };
278
279
280 #define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10
281
282 #include "tests/libmemcached_world.h"
283
284 void get_world(Framework *world)
285 {
286 world->collections= collection;
287
288 world->_create= (test_callback_create_fn*)world_create;
289 world->_destroy= (test_callback_destroy_fn*)world_destroy;
290
291 world->item._startup= (test_callback_fn*)world_test_startup;
292 world->item._flush= (test_callback_fn*)world_flush;
293 world->item.set_pre((test_callback_fn*)world_pre_run);
294 world->item.set_post((test_callback_fn*)world_post_run);
295 world->_on_error= (test_callback_error_fn*)world_on_error;
296
297 world->collection_startup= (test_callback_fn*)world_container_startup;
298 world->collection_shutdown= (test_callback_fn*)world_container_shutdown;
299
300 world->set_runner(&defualt_libmemcached_runner);
301 }