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