Merge in all scanner tree + virtual buckets.
[awesomized/libmemcached] / tests / hashkit_functions.c
1 /* libHashKit Functions Test
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
9 #include "config.h"
10
11 #include <assert.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include <libhashkit/hashkit.h>
17
18 #include <libtest/test.h>
19
20 #include "hash_results.h"
21
22 static hashkit_st global_hashk;
23
24 /**
25 @brief hash_test_st is a structure we use in testing. It is currently empty.
26 */
27 typedef struct hash_test_st hash_test_st;
28
29 struct hash_test_st
30 {
31 bool _unused;
32 };
33
34 static test_return_t init_test(void *not_used)
35 {
36 hashkit_st hashk;
37 hashkit_st *hashk_ptr;
38 (void)not_used;
39
40 hashk_ptr= hashkit_create(&hashk);
41 test_true(hashk_ptr);
42 test_true(hashk_ptr == &hashk);
43 test_true(hashkit_is_allocated(hashk_ptr) == false);
44
45 hashkit_free(hashk_ptr);
46
47 return TEST_SUCCESS;
48 }
49
50 static test_return_t allocation_test(void *not_used)
51 {
52 hashkit_st *hashk_ptr;
53 (void)not_used;
54
55 hashk_ptr= hashkit_create(NULL);
56 test_true(hashk_ptr);
57 test_true(hashkit_is_allocated(hashk_ptr) == true);
58 hashkit_free(hashk_ptr);
59
60 return TEST_SUCCESS;
61 }
62
63 static test_return_t clone_test(hashkit_st *hashk)
64 {
65 // First we make sure that the testing system is giving us what we expect.
66 assert(&global_hashk == hashk);
67
68 // Second we test if hashk is even valid
69
70 /* All null? */
71 {
72 hashkit_st *hashk_ptr;
73 hashk_ptr= hashkit_clone(NULL, NULL);
74 test_true(hashk_ptr);
75 test_true(hashkit_is_allocated(hashk_ptr));
76 hashkit_free(hashk_ptr);
77 }
78
79 /* Can we init from null? */
80 {
81 hashkit_st *hashk_ptr;
82
83 hashk_ptr= hashkit_clone(NULL, hashk);
84
85 test_true(hashk_ptr);
86 test_true(hashkit_is_allocated(hashk_ptr));
87
88 hashkit_free(hashk_ptr);
89 }
90
91 /* Can we init from struct? */
92 {
93 hashkit_st declared_clone;
94 hashkit_st *hash_clone;
95
96 hash_clone= hashkit_clone(&declared_clone, NULL);
97 test_true(hash_clone);
98 test_true(hash_clone == &declared_clone);
99 test_false(hashkit_is_allocated(hash_clone));
100
101 hashkit_free(hash_clone);
102 }
103
104 /* Can we init from struct? */
105 {
106 hashkit_st declared_clone;
107 hashkit_st *hash_clone;
108
109 hash_clone= hashkit_clone(&declared_clone, hashk);
110 test_true(hash_clone);
111 test_true(hash_clone == &declared_clone);
112 test_false(hashkit_is_allocated(hash_clone));
113
114 hashkit_free(hash_clone);
115 }
116
117 return TEST_SUCCESS;
118 }
119
120 static test_return_t one_at_a_time_run (hashkit_st *hashk)
121 {
122 uint32_t x;
123 const char **ptr;
124 (void)hashk;
125
126 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
127 {
128 uint32_t hash_val;
129
130 hash_val= libhashkit_one_at_a_time(*ptr, strlen(*ptr));
131 test_true(one_at_a_time_values[x] == hash_val);
132 }
133
134 return TEST_SUCCESS;
135 }
136
137 static test_return_t md5_run (hashkit_st *hashk)
138 {
139 uint32_t x;
140 const char **ptr;
141 (void)hashk;
142
143 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
144 {
145 uint32_t hash_val;
146
147 hash_val= libhashkit_md5(*ptr, strlen(*ptr));
148 test_true(md5_values[x] == hash_val);
149 }
150
151 return TEST_SUCCESS;
152 }
153
154 static test_return_t crc_run (hashkit_st *hashk)
155 {
156 uint32_t x;
157 const char **ptr;
158 (void)hashk;
159
160 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
161 {
162 uint32_t hash_val;
163
164 hash_val= libhashkit_crc32(*ptr, strlen(*ptr));
165 assert(crc_values[x] == hash_val);
166 }
167
168 return TEST_SUCCESS;
169 }
170
171 static test_return_t fnv1_64_run (hashkit_st *hashk)
172 {
173 uint32_t x;
174 const char **ptr;
175 (void)hashk;
176
177 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
178 {
179 uint32_t hash_val;
180
181 hash_val= libhashkit_fnv1_64(*ptr, strlen(*ptr));
182 assert(fnv1_64_values[x] == hash_val);
183 }
184
185 return TEST_SUCCESS;
186 }
187
188 static test_return_t fnv1a_64_run (hashkit_st *hashk)
189 {
190 uint32_t x;
191 const char **ptr;
192 (void)hashk;
193
194 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
195 {
196 uint32_t hash_val;
197
198 hash_val= libhashkit_fnv1a_64(*ptr, strlen(*ptr));
199 assert(fnv1a_64_values[x] == hash_val);
200 }
201
202 return TEST_SUCCESS;
203 }
204
205 static test_return_t fnv1_32_run (hashkit_st *hashk)
206 {
207 uint32_t x;
208 const char **ptr;
209 (void)hashk;
210
211 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
212 {
213 uint32_t hash_val;
214
215 hash_val= libhashkit_fnv1_32(*ptr, strlen(*ptr));
216 assert(fnv1_32_values[x] == hash_val);
217 }
218
219 return TEST_SUCCESS;
220 }
221
222 static test_return_t fnv1a_32_run (hashkit_st *hashk)
223 {
224 uint32_t x;
225 const char **ptr;
226 (void)hashk;
227
228 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
229 {
230 uint32_t hash_val;
231
232 hash_val= libhashkit_fnv1a_32(*ptr, strlen(*ptr));
233 assert(fnv1a_32_values[x] == hash_val);
234 }
235
236 return TEST_SUCCESS;
237 }
238
239 static test_return_t hsieh_run (hashkit_st *hashk)
240 {
241 uint32_t x;
242 const char **ptr;
243 (void)hashk;
244
245 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
246 {
247 uint32_t hash_val;
248
249 #ifdef HAVE_HSIEH_HASH
250 hash_val= libhashkit_hsieh(*ptr, strlen(*ptr));
251 #else
252 hash_val= 1;
253 #endif
254 assert(hsieh_values[x] == hash_val);
255 }
256
257 return TEST_SUCCESS;
258 }
259
260 static test_return_t murmur_run (hashkit_st *hashk)
261 {
262 (void)hashk;
263
264 #ifdef WORDS_BIGENDIAN
265 (void)murmur_values;
266 return TEST_SKIPPED;
267 #else
268 uint32_t x;
269 const char **ptr;
270
271 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
272 {
273 uint32_t hash_val;
274
275 #ifdef HAVE_MURMUR_HASH
276 hash_val= libhashkit_murmur(*ptr, strlen(*ptr));
277 #else
278 hash_val= 1;
279 #endif
280 assert(murmur_values[x] == hash_val);
281 }
282
283 return TEST_SUCCESS;
284 #endif
285 }
286
287 static test_return_t jenkins_run (hashkit_st *hashk)
288 {
289 uint32_t x;
290 const char **ptr;
291 (void)hashk;
292
293 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
294 {
295 uint32_t hash_val;
296
297 hash_val= libhashkit_jenkins(*ptr, strlen(*ptr));
298 assert(jenkins_values[x] == hash_val);
299 }
300
301 return TEST_SUCCESS;
302 }
303
304
305
306
307 /**
308 @brief now we list out the tests.
309 */
310
311 test_st allocation[]= {
312 {"init", 0, (test_callback_fn)init_test},
313 {"create and free", 0, (test_callback_fn)allocation_test},
314 {"clone", 0, (test_callback_fn)clone_test},
315 {0, 0, 0}
316 };
317
318 static test_return_t hashkit_digest_test(hashkit_st *hashk)
319 {
320 uint32_t value;
321 value= hashkit_digest(hashk, "a", sizeof("a"));
322
323 return TEST_SUCCESS;
324 }
325
326 static test_return_t hashkit_set_function_test(hashkit_st *hashk)
327 {
328 for (hashkit_hash_algorithm_t algo = HASHKIT_HASH_DEFAULT; algo < HASHKIT_HASH_MAX; algo++)
329 {
330 hashkit_return_t rc;
331 uint32_t x;
332 const char **ptr;
333 uint32_t *list;
334
335 rc= hashkit_set_function(hashk, algo);
336
337 /* Hsieh is disabled most of the time for patent issues */
338 #ifndef HAVE_HSIEH_HASH
339 if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_HSIEH)
340 continue;
341 #endif
342
343 #ifndef HAVE_MURMUR_HASH
344 if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_MURMUR)
345 continue;
346 #endif
347
348 if (rc == HASHKIT_INVALID_ARGUMENT && algo == HASHKIT_HASH_CUSTOM)
349 continue;
350
351 test_true_got(rc == HASHKIT_SUCCESS, hashkit_strerror(NULL, rc));
352
353 switch (algo)
354 {
355 case HASHKIT_HASH_DEFAULT:
356 list= one_at_a_time_values;
357 break;
358 case HASHKIT_HASH_MD5:
359 list= md5_values;
360 break;
361 case HASHKIT_HASH_CRC:
362 list= crc_values;
363 break;
364 case HASHKIT_HASH_FNV1_64:
365 list= fnv1_64_values;
366 break;
367 case HASHKIT_HASH_FNV1A_64:
368 list= fnv1a_64_values;
369 break;
370 case HASHKIT_HASH_FNV1_32:
371 list= fnv1_32_values;
372 break;
373 case HASHKIT_HASH_FNV1A_32:
374 list= fnv1a_32_values;
375 break;
376 case HASHKIT_HASH_HSIEH:
377 list= hsieh_values;
378 break;
379 case HASHKIT_HASH_MURMUR:
380 list= murmur_values;
381 break;
382 case HASHKIT_HASH_JENKINS:
383 list= jenkins_values;
384 break;
385 case HASHKIT_HASH_CUSTOM:
386 case HASHKIT_HASH_MAX:
387 default:
388 list= NULL;
389 break;
390 }
391
392 // Now we make sure we did set the hash correctly.
393 if (list)
394 {
395 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
396 {
397 uint32_t hash_val;
398
399 hash_val= hashkit_digest(hashk, *ptr, strlen(*ptr));
400 test_true(list[x] == hash_val);
401 }
402 }
403 else
404 {
405 return TEST_FAILURE;
406 }
407 }
408
409 return TEST_SUCCESS;
410 }
411
412 static uint32_t hash_test_function(const char *string, size_t string_length, void *context)
413 {
414 (void)context;
415 return libhashkit_md5(string, string_length);
416 }
417
418 static test_return_t hashkit_set_custom_function_test(hashkit_st *hashk)
419 {
420 hashkit_return_t rc;
421 uint32_t x;
422 const char **ptr;
423
424
425 rc= hashkit_set_custom_function(hashk, hash_test_function, NULL);
426 test_true(rc == HASHKIT_SUCCESS);
427
428 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
429 {
430 uint32_t hash_val;
431
432 hash_val= hashkit_digest(hashk, *ptr, strlen(*ptr));
433 test_true(md5_values[x] == hash_val);
434 }
435
436 return TEST_SUCCESS;
437 }
438
439 static test_return_t hashkit_set_distribution_function_test(hashkit_st *hashk)
440 {
441 for (hashkit_hash_algorithm_t algo = HASHKIT_HASH_DEFAULT; algo < HASHKIT_HASH_MAX; algo++)
442 {
443 hashkit_return_t rc;
444
445 rc= hashkit_set_distribution_function(hashk, algo);
446
447 /* Hsieh is disabled most of the time for patent issues */
448 if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_HSIEH)
449 continue;
450
451 if (rc == HASHKIT_INVALID_ARGUMENT && algo == HASHKIT_HASH_CUSTOM)
452 continue;
453
454 test_true(rc == HASHKIT_SUCCESS);
455 }
456
457 return TEST_SUCCESS;
458 }
459
460 static test_return_t hashkit_set_custom_distribution_function_test(hashkit_st *hashk)
461 {
462 hashkit_return_t rc;
463
464 rc= hashkit_set_custom_distribution_function(hashk, hash_test_function, NULL);
465 test_true(rc == HASHKIT_SUCCESS);
466
467 return TEST_SUCCESS;
468 }
469
470
471 static test_return_t hashkit_get_function_test(hashkit_st *hashk)
472 {
473 for (hashkit_hash_algorithm_t algo = HASHKIT_HASH_DEFAULT; algo < HASHKIT_HASH_MAX; algo++)
474 {
475 hashkit_return_t rc;
476
477 if (HASHKIT_HASH_CUSTOM || HASHKIT_HASH_HSIEH)
478 continue;
479
480 rc= hashkit_set_function(hashk, algo);
481 test_true(rc == HASHKIT_SUCCESS);
482
483 test_true(hashkit_get_function(hashk) == algo);
484 }
485 return TEST_SUCCESS;
486 }
487
488 static test_return_t hashkit_compare_test(hashkit_st *hashk)
489 {
490 hashkit_st *clone;
491
492 clone= hashkit_clone(NULL, hashk);
493
494 test_true(hashkit_compare(clone, hashk));
495 hashkit_free(clone);
496
497 return TEST_SUCCESS;
498 }
499
500 test_st hashkit_st_functions[] ={
501 {"hashkit_digest", 0, (test_callback_fn)hashkit_digest_test},
502 {"hashkit_set_function", 0, (test_callback_fn)hashkit_set_function_test},
503 {"hashkit_set_custom_function", 0, (test_callback_fn)hashkit_set_custom_function_test},
504 {"hashkit_get_function", 0, (test_callback_fn)hashkit_get_function_test},
505 {"hashkit_set_distribution_function", 0, (test_callback_fn)hashkit_set_distribution_function_test},
506 {"hashkit_set_custom_distribution_function", 0, (test_callback_fn)hashkit_set_custom_distribution_function_test},
507 {"hashkit_compare", 0, (test_callback_fn)hashkit_compare_test},
508 {0, 0, 0}
509 };
510
511 static test_return_t libhashkit_digest_test(hashkit_st *hashk)
512 {
513 uint32_t value;
514
515 (void)hashk;
516
517 value= libhashkit_digest("a", sizeof("a"), HASHKIT_HASH_DEFAULT);
518
519 return TEST_SUCCESS;
520 }
521
522 test_st library_functions[] ={
523 {"libhashkit_digest", 0, (test_callback_fn)libhashkit_digest_test},
524 {0, 0, 0}
525 };
526
527 test_st hash_tests[] ={
528 {"one_at_a_time", 0, (test_callback_fn)one_at_a_time_run },
529 {"md5", 0, (test_callback_fn)md5_run },
530 {"crc", 0, (test_callback_fn)crc_run },
531 {"fnv1_64", 0, (test_callback_fn)fnv1_64_run },
532 {"fnv1a_64", 0, (test_callback_fn)fnv1a_64_run },
533 {"fnv1_32", 0, (test_callback_fn)fnv1_32_run },
534 {"fnv1a_32", 0, (test_callback_fn)fnv1a_32_run },
535 {"hsieh", 0, (test_callback_fn)hsieh_run },
536 {"murmur", 0, (test_callback_fn)murmur_run },
537 {"jenkis", 0, (test_callback_fn)jenkins_run },
538 {0, 0, (test_callback_fn)0}
539 };
540
541 /*
542 * The following test suite is used to verify that we don't introduce
543 * regression bugs. If you want more information about the bug / test,
544 * you should look in the bug report at
545 * http://bugs.launchpad.net/libmemcached
546 */
547 test_st regression[]= {
548 {0, 0, 0}
549 };
550
551 collection_st collection[] ={
552 {"allocation", 0, 0, allocation},
553 {"hashkit_st_functions", 0, 0, hashkit_st_functions},
554 {"library_functions", 0, 0, library_functions},
555 {"hashing", 0, 0, hash_tests},
556 {"regression", 0, 0, regression},
557 {0, 0, 0, 0}
558 };
559
560 /* Prototypes for functions we will pass to test framework */
561 void *world_create(test_return_t *error);
562 test_return_t world_destroy(hashkit_st *hashk);
563
564 void *world_create(test_return_t *error)
565 {
566 hashkit_st *hashk_ptr;
567
568 hashk_ptr= hashkit_create(&global_hashk);
569
570 if (hashk_ptr != &global_hashk)
571 {
572 *error= TEST_FAILURE;
573 return NULL;
574 }
575
576 if (hashkit_is_allocated(hashk_ptr) == true)
577 {
578 *error= TEST_FAILURE;
579 return NULL;
580 }
581
582 *error= TEST_SUCCESS;
583
584 return hashk_ptr;
585 }
586
587
588 test_return_t world_destroy(hashkit_st *hashk)
589 {
590 // Did we get back what we expected?
591 assert(hashkit_is_allocated(hashk) == false);
592 hashkit_free(&global_hashk);
593
594 return TEST_SUCCESS;
595 }
596
597 void get_world(world_st *world)
598 {
599 world->collections= collection;
600 world->create= (test_callback_create_fn)world_create;
601 world->destroy= (test_callback_fn)world_destroy;
602 }