1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3 * libHashKit Functions Test
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
6 * Copyright (C) 2006-2009 Brian Aker All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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
20 * * The names of its contributors may not be used to endorse or
21 * promote products derived from this software without specific prior
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.
38 #include <libtest/common.h>
45 #include <libhashkit/hashkit.h>
47 #include "hash_results.h"
49 static hashkit_st global_hashk
;
52 @brief hash_test_st is a structure we use in testing. It is currently empty.
54 typedef struct hash_test_st hash_test_st
;
61 static test_return_t
init_test(void *not_used
)
64 hashkit_st
*hashk_ptr
;
67 hashk_ptr
= hashkit_create(&hashk
);
69 test_true(hashk_ptr
== &hashk
);
70 test_true(hashkit_is_allocated(hashk_ptr
) == false);
72 hashkit_free(hashk_ptr
);
77 static test_return_t
allocation_test(void *not_used
)
79 hashkit_st
*hashk_ptr
;
82 hashk_ptr
= hashkit_create(NULL
);
84 test_true(hashkit_is_allocated(hashk_ptr
) == true);
85 hashkit_free(hashk_ptr
);
90 static test_return_t
clone_test(hashkit_st
*hashk
)
92 // First we make sure that the testing system is giving us what we expect.
93 assert(&global_hashk
== hashk
);
95 // Second we test if hashk is even valid
99 hashkit_st
*hashk_ptr
;
100 hashk_ptr
= hashkit_clone(NULL
, NULL
);
101 test_true(hashk_ptr
);
102 test_true(hashkit_is_allocated(hashk_ptr
));
103 hashkit_free(hashk_ptr
);
106 /* Can we init from null? */
108 hashkit_st
*hashk_ptr
;
110 hashk_ptr
= hashkit_clone(NULL
, hashk
);
112 test_true(hashk_ptr
);
113 test_true(hashkit_is_allocated(hashk_ptr
));
115 hashkit_free(hashk_ptr
);
118 /* Can we init from struct? */
120 hashkit_st declared_clone
;
121 hashkit_st
*hash_clone
;
123 hash_clone
= hashkit_clone(&declared_clone
, NULL
);
124 test_true(hash_clone
);
125 test_true(hash_clone
== &declared_clone
);
126 test_false(hashkit_is_allocated(hash_clone
));
128 hashkit_free(hash_clone
);
131 /* Can we init from struct? */
133 hashkit_st declared_clone
;
134 hashkit_st
*hash_clone
;
136 hash_clone
= hashkit_clone(&declared_clone
, hashk
);
137 test_true(hash_clone
);
138 test_true(hash_clone
== &declared_clone
);
139 test_false(hashkit_is_allocated(hash_clone
));
141 hashkit_free(hash_clone
);
147 static test_return_t
one_at_a_time_run (hashkit_st
*hashk
)
153 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
157 hash_val
= libhashkit_one_at_a_time(*ptr
, strlen(*ptr
));
158 test_true(one_at_a_time_values
[x
] == hash_val
);
164 static test_return_t
md5_run (hashkit_st
*hashk
)
170 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
174 hash_val
= libhashkit_md5(*ptr
, strlen(*ptr
));
175 test_true(md5_values
[x
] == hash_val
);
181 static test_return_t
crc_run (hashkit_st
*hashk
)
187 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
191 hash_val
= libhashkit_crc32(*ptr
, strlen(*ptr
));
192 assert(crc_values
[x
] == hash_val
);
198 static test_return_t
fnv1_64_run (hashkit_st
*hashk
)
204 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
208 hash_val
= libhashkit_fnv1_64(*ptr
, strlen(*ptr
));
209 assert(fnv1_64_values
[x
] == hash_val
);
215 static test_return_t
fnv1a_64_run (hashkit_st
*hashk
)
221 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
225 hash_val
= libhashkit_fnv1a_64(*ptr
, strlen(*ptr
));
226 assert(fnv1a_64_values
[x
] == hash_val
);
232 static test_return_t
fnv1_32_run (hashkit_st
*hashk
)
238 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
242 hash_val
= libhashkit_fnv1_32(*ptr
, strlen(*ptr
));
243 assert(fnv1_32_values
[x
] == hash_val
);
249 static test_return_t
fnv1a_32_run (hashkit_st
*hashk
)
255 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
259 hash_val
= libhashkit_fnv1a_32(*ptr
, strlen(*ptr
));
260 assert(fnv1a_32_values
[x
] == hash_val
);
266 static test_return_t
hsieh_run (hashkit_st
*hashk
)
272 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
276 #ifdef HAVE_HSIEH_HASH
277 hash_val
= libhashkit_hsieh(*ptr
, strlen(*ptr
));
281 assert(hsieh_values
[x
] == hash_val
);
287 static test_return_t
murmur_run (hashkit_st
*hashk
)
291 #ifdef WORDS_BIGENDIAN
298 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
302 #ifdef HAVE_MURMUR_HASH
303 hash_val
= libhashkit_murmur(*ptr
, strlen(*ptr
));
307 assert(murmur_values
[x
] == hash_val
);
314 static test_return_t
jenkins_run (hashkit_st
*hashk
)
320 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
324 hash_val
= libhashkit_jenkins(*ptr
, strlen(*ptr
));
325 assert(jenkins_values
[x
] == hash_val
);
335 @brief now we list out the tests.
338 test_st allocation
[]= {
339 {"init", 0, (test_callback_fn
*)init_test
},
340 {"create and free", 0, (test_callback_fn
*)allocation_test
},
341 {"clone", 0, (test_callback_fn
*)clone_test
},
345 static test_return_t
hashkit_digest_test(hashkit_st
*hashk
)
348 value
= hashkit_digest(hashk
, "a", sizeof("a"));
353 static test_return_t
hashkit_set_function_test(hashkit_st
*hashk
)
355 for (int algo
= int(HASHKIT_HASH_DEFAULT
); algo
< int(HASHKIT_HASH_MAX
); algo
++)
361 hashkit_return_t rc
= hashkit_set_function(hashk
, static_cast<hashkit_hash_algorithm_t
>(algo
));
363 /* Hsieh is disabled most of the time for patent issues */
364 #ifndef HAVE_HSIEH_HASH
365 if (rc
== HASHKIT_FAILURE
&& algo
== HASHKIT_HASH_HSIEH
)
369 #ifndef HAVE_MURMUR_HASH
370 if (rc
== HASHKIT_FAILURE
&& algo
== HASHKIT_HASH_MURMUR
)
374 if (rc
== HASHKIT_INVALID_ARGUMENT
&& algo
== HASHKIT_HASH_CUSTOM
)
377 test_true_got(rc
== HASHKIT_SUCCESS
, hashkit_strerror(NULL
, rc
));
381 case HASHKIT_HASH_DEFAULT
:
382 list
= one_at_a_time_values
;
384 case HASHKIT_HASH_MD5
:
387 case HASHKIT_HASH_CRC
:
390 case HASHKIT_HASH_FNV1_64
:
391 list
= fnv1_64_values
;
393 case HASHKIT_HASH_FNV1A_64
:
394 list
= fnv1a_64_values
;
396 case HASHKIT_HASH_FNV1_32
:
397 list
= fnv1_32_values
;
399 case HASHKIT_HASH_FNV1A_32
:
400 list
= fnv1a_32_values
;
402 case HASHKIT_HASH_HSIEH
:
405 case HASHKIT_HASH_MURMUR
:
408 case HASHKIT_HASH_JENKINS
:
409 list
= jenkins_values
;
411 case HASHKIT_HASH_CUSTOM
:
412 case HASHKIT_HASH_MAX
:
418 // Now we make sure we did set the hash correctly.
421 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
425 hash_val
= hashkit_digest(hashk
, *ptr
, strlen(*ptr
));
426 test_true(list
[x
] == hash_val
);
438 static uint32_t hash_test_function(const char *string
, size_t string_length
, void *context
)
441 return libhashkit_md5(string
, string_length
);
444 static test_return_t
hashkit_set_custom_function_test(hashkit_st
*hashk
)
451 rc
= hashkit_set_custom_function(hashk
, hash_test_function
, NULL
);
452 test_true(rc
== HASHKIT_SUCCESS
);
454 for (ptr
= list_to_hash
, x
= 0; *ptr
; ptr
++, x
++)
458 hash_val
= hashkit_digest(hashk
, *ptr
, strlen(*ptr
));
459 test_true(md5_values
[x
] == hash_val
);
465 static test_return_t
hashkit_set_distribution_function_test(hashkit_st
*hashk
)
467 for (int algo
= int(HASHKIT_HASH_DEFAULT
); algo
< int(HASHKIT_HASH_MAX
); algo
++)
469 hashkit_return_t rc
= hashkit_set_distribution_function(hashk
, static_cast<hashkit_hash_algorithm_t
>(algo
));
471 /* Hsieh is disabled most of the time for patent issues */
472 if (rc
== HASHKIT_FAILURE
&& algo
== HASHKIT_HASH_HSIEH
)
475 if (rc
== HASHKIT_INVALID_ARGUMENT
&& algo
== HASHKIT_HASH_CUSTOM
)
478 test_true(rc
== HASHKIT_SUCCESS
);
484 static test_return_t
hashkit_set_custom_distribution_function_test(hashkit_st
*hashk
)
486 hashkit_return_t rc
= hashkit_set_custom_distribution_function(hashk
, hash_test_function
, NULL
);
487 test_true(rc
== HASHKIT_SUCCESS
);
493 static test_return_t
hashkit_get_function_test(hashkit_st
*hashk
)
495 for (int algo
= int(HASHKIT_HASH_DEFAULT
); algo
< int(HASHKIT_HASH_MAX
); algo
++)
498 if (HASHKIT_HASH_CUSTOM
or HASHKIT_HASH_HSIEH
)
501 hashkit_return_t rc
= hashkit_set_function(hashk
, static_cast<hashkit_hash_algorithm_t
>(algo
));
502 test_true(rc
== HASHKIT_SUCCESS
);
504 test_true(hashkit_get_function(hashk
) == algo
);
509 static test_return_t
hashkit_compare_test(hashkit_st
*hashk
)
511 hashkit_st
*clone
= hashkit_clone(NULL
, hashk
);
513 test_true(hashkit_compare(clone
, hashk
));
519 test_st hashkit_st_functions
[] ={
520 {"hashkit_digest", 0, (test_callback_fn
*)hashkit_digest_test
},
521 {"hashkit_set_function", 0, (test_callback_fn
*)hashkit_set_function_test
},
522 {"hashkit_set_custom_function", 0, (test_callback_fn
*)hashkit_set_custom_function_test
},
523 {"hashkit_get_function", 0, (test_callback_fn
*)hashkit_get_function_test
},
524 {"hashkit_set_distribution_function", 0, (test_callback_fn
*)hashkit_set_distribution_function_test
},
525 {"hashkit_set_custom_distribution_function", 0, (test_callback_fn
*)hashkit_set_custom_distribution_function_test
},
526 {"hashkit_compare", 0, (test_callback_fn
*)hashkit_compare_test
},
530 static test_return_t
libhashkit_digest_test(hashkit_st
*hashk
)
535 uint32_t value
= libhashkit_digest("a", sizeof("a"), HASHKIT_HASH_DEFAULT
);
541 test_st library_functions
[] ={
542 {"libhashkit_digest", 0, (test_callback_fn
*)libhashkit_digest_test
},
546 test_st hash_tests
[] ={
547 {"one_at_a_time", 0, (test_callback_fn
*)one_at_a_time_run
},
548 {"md5", 0, (test_callback_fn
*)md5_run
},
549 {"crc", 0, (test_callback_fn
*)crc_run
},
550 {"fnv1_64", 0, (test_callback_fn
*)fnv1_64_run
},
551 {"fnv1a_64", 0, (test_callback_fn
*)fnv1a_64_run
},
552 {"fnv1_32", 0, (test_callback_fn
*)fnv1_32_run
},
553 {"fnv1a_32", 0, (test_callback_fn
*)fnv1a_32_run
},
554 {"hsieh", 0, (test_callback_fn
*)hsieh_run
},
555 {"murmur", 0, (test_callback_fn
*)murmur_run
},
556 {"jenkis", 0, (test_callback_fn
*)jenkins_run
},
557 {0, 0, (test_callback_fn
*)0}
561 * The following test suite is used to verify that we don't introduce
562 * regression bugs. If you want more information about the bug / test,
563 * you should look in the bug report at
564 * http://bugs.launchpad.net/libmemcached
566 test_st regression
[]= {
570 collection_st collection
[] ={
571 {"allocation", 0, 0, allocation
},
572 {"hashkit_st_functions", 0, 0, hashkit_st_functions
},
573 {"library_functions", 0, 0, library_functions
},
574 {"hashing", 0, 0, hash_tests
},
575 {"regression", 0, 0, regression
},
579 /* Prototypes for functions we will pass to test framework */
580 void *world_create(test_return_t
*error
);
581 test_return_t
world_destroy(hashkit_st
*hashk
);
583 void *world_create(test_return_t
*error
)
585 hashkit_st
*hashk_ptr
= hashkit_create(&global_hashk
);
587 if (hashk_ptr
!= &global_hashk
)
589 *error
= TEST_FAILURE
;
593 if (hashkit_is_allocated(hashk_ptr
) == true)
595 *error
= TEST_FAILURE
;
599 *error
= TEST_SUCCESS
;
605 test_return_t
world_destroy(hashkit_st
*hashk
)
607 // Did we get back what we expected?
608 assert(hashkit_is_allocated(hashk
) == false);
609 hashkit_free(&global_hashk
);
614 void get_world(Framework
*world
)
616 world
->collections
= collection
;
617 world
->_create
= (test_callback_create_fn
*)world_create
;
618 world
->_destroy
= (test_callback_fn
*)world_destroy
;