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