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