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