Merge lp:~tangent-org/libmemcached/1.0-build/ Build: jenkins-Libmemcached-187
[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 <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 test_skip(true, libhashkit_has_algorithm(static_cast<hashkit_hash_algorithm_t>(algo)));
351
352 hashkit_return_t rc= hashkit_set_function(hashk, static_cast<hashkit_hash_algorithm_t>(algo));
353
354 test_compare_got(HASHKIT_SUCCESS, rc, hashkit_strerror(NULL, rc));
355
356 switch (algo)
357 {
358 case HASHKIT_HASH_DEFAULT:
359 list= one_at_a_time_values;
360 break;
361
362 case HASHKIT_HASH_MD5:
363 list= md5_values;
364 break;
365
366 case HASHKIT_HASH_CRC:
367 list= crc_values;
368 break;
369
370 case HASHKIT_HASH_FNV1_64:
371 list= fnv1_64_values;
372 break;
373
374 case HASHKIT_HASH_FNV1A_64:
375 list= fnv1a_64_values;
376 break;
377
378 case HASHKIT_HASH_FNV1_32:
379 list= fnv1_32_values;
380 break;
381
382 case HASHKIT_HASH_FNV1A_32:
383 list= fnv1a_32_values;
384 break;
385
386 case HASHKIT_HASH_HSIEH:
387 list= hsieh_values;
388 break;
389
390 case HASHKIT_HASH_MURMUR:
391 list= murmur_values;
392 break;
393
394 case HASHKIT_HASH_JENKINS:
395 list= jenkins_values;
396 break;
397
398 case HASHKIT_HASH_CUSTOM:
399 case HASHKIT_HASH_MAX:
400 default:
401 list= NULL;
402 break;
403 }
404
405 // Now we make sure we did set the hash correctly.
406 if (list)
407 {
408 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
409 {
410 test_compare(list[x],
411 hashkit_digest(hashk, *ptr, strlen(*ptr)));
412 }
413 }
414 else
415 {
416 return TEST_FAILURE;
417 }
418 }
419
420 return TEST_SUCCESS;
421 }
422
423 static uint32_t hash_test_function(const char *string, size_t string_length, void *)
424 {
425 return libhashkit_md5(string, string_length);
426 }
427
428 static test_return_t hashkit_set_custom_function_test(hashkit_st *hashk)
429 {
430 uint32_t x;
431 const char **ptr;
432
433
434 test_compare(HASHKIT_SUCCESS,
435 hashkit_set_custom_function(hashk, hash_test_function, NULL));
436
437 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
438 {
439 test_compare(md5_values[x],
440 hashkit_digest(hashk, *ptr, strlen(*ptr)));
441 }
442
443 return TEST_SUCCESS;
444 }
445
446 static test_return_t hashkit_set_distribution_function_test(hashkit_st *hashk)
447 {
448 for (int algo= int(HASHKIT_HASH_DEFAULT); algo < int(HASHKIT_HASH_MAX); algo++)
449 {
450 hashkit_return_t rc= hashkit_set_distribution_function(hashk, static_cast<hashkit_hash_algorithm_t>(algo));
451
452 /* Hsieh is disabled most of the time for patent issues */
453 if (rc == HASHKIT_INVALID_ARGUMENT)
454 continue;
455
456 test_compare(HASHKIT_SUCCESS, rc);
457 }
458
459 return TEST_SUCCESS;
460 }
461
462 static test_return_t hashkit_set_custom_distribution_function_test(hashkit_st *hashk)
463 {
464 test_compare(HASHKIT_SUCCESS,
465 hashkit_set_custom_distribution_function(hashk, hash_test_function, NULL));
466
467 return TEST_SUCCESS;
468 }
469
470
471 static test_return_t hashkit_get_function_test(hashkit_st *hashk)
472 {
473 for (int algo= int(HASHKIT_HASH_DEFAULT); algo < int(HASHKIT_HASH_MAX); algo++)
474 {
475
476 if (HASHKIT_HASH_CUSTOM)
477 {
478 continue;
479 }
480 test_skip(true, libhashkit_has_algorithm(static_cast<hashkit_hash_algorithm_t>(algo)));
481
482 test_compare(HASHKIT_SUCCESS,
483 hashkit_set_function(hashk, static_cast<hashkit_hash_algorithm_t>(algo)));
484
485 test_compare(hashkit_get_function(hashk), algo);
486 }
487 return TEST_SUCCESS;
488 }
489
490 static test_return_t hashkit_compare_test(hashkit_st *hashk)
491 {
492 hashkit_st *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 *)
512 {
513 test_true(libhashkit_digest("a", sizeof("a"), HASHKIT_HASH_DEFAULT));
514
515 return TEST_SUCCESS;
516 }
517
518 test_st library_functions[] ={
519 {"libhashkit_digest", 0, (test_callback_fn*)libhashkit_digest_test},
520 {0, 0, 0}
521 };
522
523 test_st hash_tests[] ={
524 {"one_at_a_time", 0, (test_callback_fn*)one_at_a_time_run },
525 {"md5", 0, (test_callback_fn*)md5_run },
526 {"crc", 0, (test_callback_fn*)crc_run },
527 {"fnv1_64", 0, (test_callback_fn*)fnv1_64_run },
528 {"fnv1a_64", 0, (test_callback_fn*)fnv1a_64_run },
529 {"fnv1_32", 0, (test_callback_fn*)fnv1_32_run },
530 {"fnv1a_32", 0, (test_callback_fn*)fnv1a_32_run },
531 {"hsieh", 0, (test_callback_fn*)hsieh_run },
532 {"murmur", 0, (test_callback_fn*)murmur_run },
533 {"murmur3", 0, (test_callback_fn*)murmur3_TEST },
534 {"jenkis", 0, (test_callback_fn*)jenkins_run },
535 {0, 0, (test_callback_fn*)0}
536 };
537
538 /*
539 * The following test suite is used to verify that we don't introduce
540 * regression bugs. If you want more information about the bug / test,
541 * you should look in the bug report at
542 * http://bugs.launchpad.net/libmemcached
543 */
544 test_st regression[]= {
545 {0, 0, 0}
546 };
547
548 collection_st collection[] ={
549 {"allocation", 0, 0, allocation},
550 {"hashkit_st_functions", 0, 0, hashkit_st_functions},
551 {"library_functions", 0, 0, library_functions},
552 {"hashing", 0, 0, hash_tests},
553 {"regression", 0, 0, regression},
554 {0, 0, 0, 0}
555 };
556
557 static void *world_create(libtest::server_startup_st&, test_return_t& error)
558 {
559 hashkit_st *hashk_ptr= hashkit_create(&global_hashk);
560
561 if (hashk_ptr != &global_hashk)
562 {
563 error= TEST_FAILURE;
564 return NULL;
565 }
566
567 if (hashkit_is_allocated(hashk_ptr) == true)
568 {
569 error= TEST_FAILURE;
570 return NULL;
571 }
572
573 return hashk_ptr;
574 }
575
576
577 static bool world_destroy(void *object)
578 {
579 hashkit_st *hashk= (hashkit_st *)object;
580 // Did we get back what we expected?
581 test_true(hashkit_is_allocated(hashk) == false);
582 hashkit_free(&global_hashk);
583
584 return TEST_SUCCESS;
585 }
586
587 void get_world(libtest::Framework* world)
588 {
589 world->collections(collection);
590 world->create(world_create);
591 world->destroy(world_destroy);
592 }