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