e13a854b794435c881d92d7ee26876ad983403cb
[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 #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 murmur_run (hashkit_st *)
266 {
267 test_skip(true, libhashkit_has_algorithm(HASHKIT_HASH_MURMUR));
268
269 #ifdef WORDS_BIGENDIAN
270 (void)murmur_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(murmur_values[x],
279 libhashkit_murmur(*ptr, strlen(*ptr)));
280 }
281
282 return TEST_SUCCESS;
283 #endif
284 }
285
286 static test_return_t jenkins_run (hashkit_st *)
287 {
288 uint32_t x;
289 const char **ptr;
290
291 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
292 {
293 test_compare(jenkins_values[x],
294 libhashkit_jenkins(*ptr, strlen(*ptr)));
295 }
296
297 return TEST_SUCCESS;
298 }
299
300
301
302
303 /**
304 @brief now we list out the tests.
305 */
306
307 test_st allocation[]= {
308 {"init", 0, (test_callback_fn*)init_test},
309 {"create and free", 0, (test_callback_fn*)allocation_test},
310 {"clone", 0, (test_callback_fn*)clone_test},
311 {0, 0, 0}
312 };
313
314 static test_return_t hashkit_digest_test(hashkit_st *hashk)
315 {
316 test_true(hashkit_digest(hashk, "a", sizeof("a")));
317
318 return TEST_SUCCESS;
319 }
320
321 static test_return_t hashkit_set_function_test(hashkit_st *hashk)
322 {
323 for (int algo= int(HASHKIT_HASH_DEFAULT); algo < int(HASHKIT_HASH_MAX); algo++)
324 {
325 uint32_t x;
326 const char **ptr;
327 uint32_t *list;
328
329 test_skip(true, libhashkit_has_algorithm(static_cast<hashkit_hash_algorithm_t>(algo)));
330
331 hashkit_return_t rc= hashkit_set_function(hashk, static_cast<hashkit_hash_algorithm_t>(algo));
332
333 test_compare_got(HASHKIT_SUCCESS, rc, hashkit_strerror(NULL, rc));
334
335 switch (algo)
336 {
337 case HASHKIT_HASH_DEFAULT:
338 list= one_at_a_time_values;
339 break;
340
341 case HASHKIT_HASH_MD5:
342 list= md5_values;
343 break;
344
345 case HASHKIT_HASH_CRC:
346 list= crc_values;
347 break;
348
349 case HASHKIT_HASH_FNV1_64:
350 list= fnv1_64_values;
351 break;
352
353 case HASHKIT_HASH_FNV1A_64:
354 list= fnv1a_64_values;
355 break;
356
357 case HASHKIT_HASH_FNV1_32:
358 list= fnv1_32_values;
359 break;
360
361 case HASHKIT_HASH_FNV1A_32:
362 list= fnv1a_32_values;
363 break;
364
365 case HASHKIT_HASH_HSIEH:
366 list= hsieh_values;
367 break;
368
369 case HASHKIT_HASH_MURMUR:
370 list= murmur_values;
371 break;
372
373 case HASHKIT_HASH_JENKINS:
374 list= jenkins_values;
375 break;
376
377 case HASHKIT_HASH_CUSTOM:
378 case HASHKIT_HASH_MAX:
379 default:
380 list= NULL;
381 break;
382 }
383
384 // Now we make sure we did set the hash correctly.
385 if (list)
386 {
387 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
388 {
389 test_compare(list[x],
390 hashkit_digest(hashk, *ptr, strlen(*ptr)));
391 }
392 }
393 else
394 {
395 return TEST_FAILURE;
396 }
397 }
398
399 return TEST_SUCCESS;
400 }
401
402 static uint32_t hash_test_function(const char *string, size_t string_length, void *)
403 {
404 return libhashkit_md5(string, string_length);
405 }
406
407 static test_return_t hashkit_set_custom_function_test(hashkit_st *hashk)
408 {
409 uint32_t x;
410 const char **ptr;
411
412
413 test_compare(HASHKIT_SUCCESS,
414 hashkit_set_custom_function(hashk, hash_test_function, NULL));
415
416 for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
417 {
418 test_compare(md5_values[x],
419 hashkit_digest(hashk, *ptr, strlen(*ptr)));
420 }
421
422 return TEST_SUCCESS;
423 }
424
425 static test_return_t hashkit_set_distribution_function_test(hashkit_st *hashk)
426 {
427 for (int algo= int(HASHKIT_HASH_DEFAULT); algo < int(HASHKIT_HASH_MAX); algo++)
428 {
429 hashkit_return_t rc= hashkit_set_distribution_function(hashk, static_cast<hashkit_hash_algorithm_t>(algo));
430
431 /* Hsieh is disabled most of the time for patent issues */
432 if (rc == HASHKIT_INVALID_ARGUMENT)
433 continue;
434
435 test_compare(HASHKIT_SUCCESS, rc);
436 }
437
438 return TEST_SUCCESS;
439 }
440
441 static test_return_t hashkit_set_custom_distribution_function_test(hashkit_st *hashk)
442 {
443 test_compare(HASHKIT_SUCCESS,
444 hashkit_set_custom_distribution_function(hashk, hash_test_function, NULL));
445
446 return TEST_SUCCESS;
447 }
448
449
450 static test_return_t hashkit_get_function_test(hashkit_st *hashk)
451 {
452 for (int algo= int(HASHKIT_HASH_DEFAULT); algo < int(HASHKIT_HASH_MAX); algo++)
453 {
454
455 if (HASHKIT_HASH_CUSTOM)
456 {
457 continue;
458 }
459 test_skip(true, libhashkit_has_algorithm(static_cast<hashkit_hash_algorithm_t>(algo)));
460
461 test_compare(HASHKIT_SUCCESS,
462 hashkit_set_function(hashk, static_cast<hashkit_hash_algorithm_t>(algo)));
463
464 test_compare(hashkit_get_function(hashk), algo);
465 }
466 return TEST_SUCCESS;
467 }
468
469 static test_return_t hashkit_compare_test(hashkit_st *hashk)
470 {
471 hashkit_st *clone= hashkit_clone(NULL, hashk);
472
473 test_true(hashkit_compare(clone, hashk));
474 hashkit_free(clone);
475
476 return TEST_SUCCESS;
477 }
478
479 test_st hashkit_st_functions[] ={
480 {"hashkit_digest", 0, (test_callback_fn*)hashkit_digest_test},
481 {"hashkit_set_function", 0, (test_callback_fn*)hashkit_set_function_test},
482 {"hashkit_set_custom_function", 0, (test_callback_fn*)hashkit_set_custom_function_test},
483 {"hashkit_get_function", 0, (test_callback_fn*)hashkit_get_function_test},
484 {"hashkit_set_distribution_function", 0, (test_callback_fn*)hashkit_set_distribution_function_test},
485 {"hashkit_set_custom_distribution_function", 0, (test_callback_fn*)hashkit_set_custom_distribution_function_test},
486 {"hashkit_compare", 0, (test_callback_fn*)hashkit_compare_test},
487 {0, 0, 0}
488 };
489
490 static test_return_t libhashkit_digest_test(hashkit_st *)
491 {
492 test_true(libhashkit_digest("a", sizeof("a"), HASHKIT_HASH_DEFAULT));
493
494 return TEST_SUCCESS;
495 }
496
497 test_st library_functions[] ={
498 {"libhashkit_digest", 0, (test_callback_fn*)libhashkit_digest_test},
499 {0, 0, 0}
500 };
501
502 test_st hash_tests[] ={
503 {"one_at_a_time", 0, (test_callback_fn*)one_at_a_time_run },
504 {"md5", 0, (test_callback_fn*)md5_run },
505 {"crc", 0, (test_callback_fn*)crc_run },
506 {"fnv1_64", 0, (test_callback_fn*)fnv1_64_run },
507 {"fnv1a_64", 0, (test_callback_fn*)fnv1a_64_run },
508 {"fnv1_32", 0, (test_callback_fn*)fnv1_32_run },
509 {"fnv1a_32", 0, (test_callback_fn*)fnv1a_32_run },
510 {"hsieh", 0, (test_callback_fn*)hsieh_run },
511 {"murmur", 0, (test_callback_fn*)murmur_run },
512 {"jenkis", 0, (test_callback_fn*)jenkins_run },
513 {0, 0, (test_callback_fn*)0}
514 };
515
516 /*
517 * The following test suite is used to verify that we don't introduce
518 * regression bugs. If you want more information about the bug / test,
519 * you should look in the bug report at
520 * http://bugs.launchpad.net/libmemcached
521 */
522 test_st regression[]= {
523 {0, 0, 0}
524 };
525
526 collection_st collection[] ={
527 {"allocation", 0, 0, allocation},
528 {"hashkit_st_functions", 0, 0, hashkit_st_functions},
529 {"library_functions", 0, 0, library_functions},
530 {"hashing", 0, 0, hash_tests},
531 {"regression", 0, 0, regression},
532 {0, 0, 0, 0}
533 };
534
535 static void *world_create(libtest::server_startup_st&, test_return_t& error)
536 {
537 hashkit_st *hashk_ptr= hashkit_create(&global_hashk);
538
539 if (hashk_ptr != &global_hashk)
540 {
541 error= TEST_FAILURE;
542 return NULL;
543 }
544
545 if (hashkit_is_allocated(hashk_ptr) == true)
546 {
547 error= TEST_FAILURE;
548 return NULL;
549 }
550
551 return hashk_ptr;
552 }
553
554
555 static bool world_destroy(void *object)
556 {
557 hashkit_st *hashk= (hashkit_st *)object;
558 // Did we get back what we expected?
559 test_true(hashkit_is_allocated(hashk) == false);
560 hashkit_free(&global_hashk);
561
562 return TEST_SUCCESS;
563 }
564
565 void get_world(Framework *world)
566 {
567 world->collections= collection;
568 world->_create= world_create;
569 world->_destroy= world_destroy;
570 }