Merge working tree with build tree.
[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
45 static pairs_st *global_pairs;
46 static char *global_keys[GLOBAL_COUNT];
47 static size_t global_keys_length[GLOBAL_COUNT];
48
49 static test_return_t cleanup_pairs(memcached_st *)
50 {
51 pairs_free(global_pairs);
52
53 return TEST_SUCCESS;
54 }
55
56 static test_return_t generate_pairs(memcached_st *)
57 {
58 global_pairs= pairs_generate(GLOBAL_COUNT, 400);
59
60 for (ptrdiff_t x= 0; x < GLOBAL_COUNT; x++)
61 {
62 global_keys[x]= global_pairs[x].key;
63 global_keys_length[x]= global_pairs[x].key_length;
64 }
65
66 return TEST_SUCCESS;
67 }
68
69 static test_return_t drizzle(memcached_st *memc)
70 {
71 infinite:
72 for (ptrdiff_t x= 0; x < TEST_COUNTER; x++)
73 {
74 memcached_return_t rc;
75 char *return_value;
76 size_t return_value_length;
77 uint32_t flags;
78
79 uint32_t test_bit;
80 uint8_t which;
81
82 test_bit= (uint32_t)(random() % GLOBAL_COUNT);
83 which= (uint8_t)(random() % 2);
84
85 if (which == 0)
86 {
87 return_value= memcached_get(memc, global_keys[test_bit], global_keys_length[test_bit],
88 &return_value_length, &flags, &rc);
89 if (rc == MEMCACHED_SUCCESS && return_value)
90 {
91 free(return_value);
92 }
93 else if (rc == MEMCACHED_NOTFOUND)
94 {
95 continue;
96 }
97 else
98 {
99 test_compare(MEMCACHED_SUCCESS, rc);
100 }
101 }
102 else
103 {
104 rc= memcached_set(memc, global_pairs[test_bit].key,
105 global_pairs[test_bit].key_length,
106 global_pairs[test_bit].value,
107 global_pairs[test_bit].value_length,
108 0, 0);
109 if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
110 {
111 test_compare(MEMCACHED_SUCCESS, rc);
112 }
113 }
114 }
115
116 if (getenv("MEMCACHED_ATOM_BURIN_IN"))
117 {
118 goto infinite;
119 }
120
121 return TEST_SUCCESS;
122 }
123
124 static test_return_t pre_nonblock(memcached_st *memc)
125 {
126 memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 0);
127
128 return TEST_SUCCESS;
129 }
130
131 /*
132 Set the value, then quit to make sure it is flushed.
133 Come back in and test that add fails.
134 */
135 static test_return_t add_test(memcached_st *memc)
136 {
137 const char *key= "foo";
138 const char *value= "when we sanitize";
139
140 memcached_return_t rc;
141 rc= memcached_set(memc, key, strlen(key),
142 value, strlen(value),
143 (time_t)0, (uint32_t)0);
144 test_true_got(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED, memcached_strerror(NULL, rc));
145 memcached_quit(memc);
146 rc= memcached_add(memc, key, strlen(key),
147 value, strlen(value),
148 (time_t)0, (uint32_t)0);
149
150 if (rc == MEMCACHED_CONNECTION_FAILURE)
151 {
152 print_servers(memc);
153 }
154
155 /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */
156 if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK))
157 {
158 test_true(rc == MEMCACHED_NOTSTORED or rc == MEMCACHED_STORED);
159 }
160 else
161 {
162 test_compare_got(MEMCACHED_NOTSTORED, rc, memcached_strerror(NULL, rc));
163 }
164
165 return TEST_SUCCESS;
166 }
167
168 /*
169 * repeating add_tests many times
170 * may show a problem in timing
171 */
172 static test_return_t many_adds(memcached_st *memc)
173 {
174 test_true(memc);
175 for (ptrdiff_t x= 0; x < TEST_COUNTER; x++)
176 {
177 test_compare_got(TEST_SUCCESS, add_test(memc), x);
178 }
179 return TEST_SUCCESS;
180 }
181
182 test_st smash_tests[] ={
183 {"generate_pairs", true, (test_callback_fn*)generate_pairs },
184 {"drizzle", true, (test_callback_fn*)drizzle },
185 {"cleanup", true, (test_callback_fn*)cleanup_pairs },
186 {"many_adds", true, (test_callback_fn*)many_adds },
187 {0, 0, 0}
188 };
189
190 #define BENCHMARK_TEST_LOOP 20000
191
192 struct benchmark_state_st
193 {
194 bool create_init;
195 bool clone_init;
196 memcached_st *create;
197 memcached_st *clone;
198 } benchmark_state;
199
200 static test_return_t memcached_create_benchmark(memcached_st *)
201 {
202 benchmark_state.create_init= true;
203
204 for (ptrdiff_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
205 {
206 memcached_st *ptr;
207 ptr= memcached_create(&benchmark_state.create[x]);
208
209 test_true(ptr);
210 }
211
212 return TEST_SUCCESS;
213 }
214
215 static test_return_t memcached_clone_benchmark(memcached_st *memc)
216 {
217 benchmark_state.clone_init= true;
218
219 for (ptrdiff_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
220 {
221 memcached_st *ptr= memcached_clone(&benchmark_state.clone[x], memc);
222
223 test_true(ptr);
224 }
225
226 return TEST_SUCCESS;
227 }
228
229 static test_return_t pre_allocate(memcached_st *)
230 {
231 memset(&benchmark_state, 0, sizeof(benchmark_state));
232
233 benchmark_state.create= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st));
234 test_true(benchmark_state.create);
235 benchmark_state.clone= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st));
236 test_true(benchmark_state.clone);
237
238 return TEST_SUCCESS;
239 }
240
241 static test_return_t post_allocate(memcached_st *)
242 {
243 for (ptrdiff_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
244 {
245 if (benchmark_state.create_init)
246 {
247 memcached_free(&benchmark_state.create[x]);
248 }
249
250 if (benchmark_state.clone_init)
251 {
252 memcached_free(&benchmark_state.clone[x]);
253 }
254 }
255
256 free(benchmark_state.create);
257 free(benchmark_state.clone);
258
259 return TEST_SUCCESS;
260 }
261
262
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 },
266 {0, 0, 0}
267 };
268
269
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},
274 {0, 0, 0, 0}
275 };
276
277
278 #include "tests/libmemcached_world.h"
279
280 void get_world(Framework *world)
281 {
282 world->collections= collection;
283
284 world->_create= (test_callback_create_fn*)world_create;
285 world->_destroy= (test_callback_destroy_fn*)world_destroy;
286
287 world->item._startup= (test_callback_fn*)world_test_startup;
288 world->item._flush= (test_callback_fn*)world_flush;
289 world->_on_error= (test_callback_error_fn*)world_on_error;
290
291 world->collection_startup= (test_callback_fn*)world_container_startup;
292 world->collection_shutdown= (test_callback_fn*)world_container_shutdown;
293
294 world->set_runner(new LibmemcachedRunner);
295 }