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