merge.
[m6w6/libmemcached] / tests / atomsmasher.c
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 "libmemcached/common.h"
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/time.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 #include <time.h>
25 #include "server.h"
26 #include "../clients/generator.h"
27 #include "../clients/execute.h"
28
29 #ifndef INT64_MAX
30 #define INT64_MAX LONG_MAX
31 #endif
32 #ifndef INT32_MAX
33 #define INT32_MAX INT_MAX
34 #endif
35
36
37 #include "test.h"
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 *memc __attribute__((unused)))
51 {
52 pairs_free(global_pairs);
53
54 return 0;
55 }
56
57 static test_return_t generate_pairs(memcached_st *memc __attribute__((unused)))
58 {
59 global_pairs= pairs_generate(GLOBAL_COUNT, 400);
60 global_count= GLOBAL_COUNT;
61
62 for (size_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 0;
69 }
70
71 static test_return_t drizzle(memcached_st *memc)
72 {
73 memcached_return_t rc;
74 char *return_value;
75 size_t return_value_length;
76 uint32_t flags;
77
78 infinite:
79 for (size_t x= 0; x < TEST_COUNTER; x++)
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 WATCHPOINT_ERROR(rc);
102 WATCHPOINT_ASSERT(rc);
103 }
104 }
105 else
106 {
107 rc= memcached_set(memc, global_pairs[test_bit].key,
108 global_pairs[test_bit].key_length,
109 global_pairs[test_bit].value,
110 global_pairs[test_bit].value_length,
111 0, 0);
112 if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
113 {
114 WATCHPOINT_ERROR(rc);
115 WATCHPOINT_ASSERT(0);
116 }
117 }
118 }
119
120 if (getenv("MEMCACHED_ATOM_BURIN_IN"))
121 goto infinite;
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 memcached_return_t rc;
140 const char *key= "foo";
141 const char *value= "when we sanitize";
142 unsigned long long setting_value;
143
144 setting_value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK);
145
146 rc= memcached_set(memc, key, strlen(key),
147 value, strlen(value),
148 (time_t)0, (uint32_t)0);
149 test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
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 /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */
156 if (setting_value)
157 {
158 test_true(rc == MEMCACHED_NOTSTORED || rc == MEMCACHED_STORED);
159 }
160 else
161 {
162 test_true(rc == MEMCACHED_NOTSTORED);
163 }
164
165 return 0;
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 for (size_t x= 0; x < TEST_COUNTER; x++)
175 {
176 add_test(memc);
177 }
178 return 0;
179 }
180
181 test_st smash_tests[] ={
182 {"generate_pairs", 1, (test_callback_fn)generate_pairs },
183 {"drizzle", 1, (test_callback_fn)drizzle },
184 {"cleanup", 1, (test_callback_fn)cleanup_pairs },
185 {"many_adds", 1, (test_callback_fn)many_adds },
186 {0, 0, 0}
187 };
188
189 #define BENCHMARK_TEST_LOOP 20000
190
191 struct benchmark_state_st
192 {
193 bool create_init;
194 bool clone_init;
195 memcached_st *create;
196 memcached_st *clone;
197 } benchmark_state;
198
199 static test_return_t memcached_create_benchmark(memcached_st *memc __attribute__((unused)))
200 {
201 benchmark_state.create_init= true;
202
203 for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
204 {
205 memcached_st *ptr;
206 ptr= memcached_create(&benchmark_state.create[x]);
207
208 test_true(ptr);
209 }
210
211 return TEST_SUCCESS;
212 }
213
214 static test_return_t memcached_clone_benchmark(memcached_st *memc)
215 {
216 benchmark_state.clone_init= true;
217
218 for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++)
219 {
220 memcached_st *ptr;
221 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 *memc __attribute__((unused)))
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 *memc __attribute__((unused)))
242 {
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(world_st *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->test.startup= (test_callback_fn)world_test_startup;
286 world->test.flush= (test_callback_fn)world_flush;
287 world->test.pre_run= (test_callback_fn)world_pre_run;
288 world->test.post_run= (test_callback_fn)world_post_run;
289 world->test.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 }