10 #include "virhashdata.h"
11 #include "testutils.h"
14 #include "virstring.h"
16 #define VIR_FROM_THIS VIR_FROM_NONE
18 VIR_LOG_INIT("tests.hashtest");
20 #define testError(...) \
23 if (virAsprintfQuiet(&str, __VA_ARGS__) >= 0) { \
24 fprintf(stderr, "%s", str); \
27 /* Pad to line up with test name ... in virTestRun */ \
28 fprintf(stderr, "%74s", "... "); \
32 static virHashTablePtr
33 testHashInit(int size)
38 if (!(hash = virHashCreate(size, NULL)))
41 /* entires are added in reverse order so that they will be linked in
42 * collision list in the same order as in the uuids array
44 for (i = ARRAY_CARDINALITY(uuids) - 1; i >= 0; i--) {
45 ssize_t oldsize = virHashTableSize(hash);
46 if (virHashAddEntry(hash, uuids[i], (void *) uuids[i]) < 0) {
51 if (virHashTableSize(hash) != oldsize && virTestGetDebug()) {
52 VIR_WARN("hash grown from %zd to %zd",
53 (size_t)oldsize, (size_t)virHashTableSize(hash));
57 for (i = 0; i < ARRAY_CARDINALITY(uuids); i++) {
58 if (!virHashLookup(hash, uuids[i])) {
59 if (virTestGetVerbose()) {
60 VIR_WARN("\nentry \"%s\" could not be found\n",
68 if (size && size != virHashTableSize(hash) && virTestGetDebug())
69 fprintf(stderr, "\n");
75 testHashCheckForEachCount(void *payload ATTRIBUTE_UNUSED,
76 const void *name ATTRIBUTE_UNUSED,
77 void *data ATTRIBUTE_UNUSED)
82 testHashCheckCount(virHashTablePtr hash, size_t count)
84 ssize_t iter_count = 0;
86 if (virHashSize(hash) != count) {
87 testError("\nhash contains %zu instead of %zu elements\n",
88 (size_t)virHashSize(hash), count);
92 iter_count = virHashForEach(hash, testHashCheckForEachCount, NULL);
93 if (count != iter_count) {
94 testError("\nhash claims to have %zu elements but iteration finds %zu\n",
95 count, (size_t)iter_count);
110 testHashGrow(const void *data)
112 const struct testInfo *info = data;
113 virHashTablePtr hash;
116 if (!(hash = testHashInit(info->count)))
119 if (testHashCheckCount(hash, ARRAY_CARDINALITY(uuids)) < 0)
131 testHashUpdate(const void *data ATTRIBUTE_UNUSED)
133 int count = ARRAY_CARDINALITY(uuids) + ARRAY_CARDINALITY(uuids_new);
134 virHashTablePtr hash;
138 if (!(hash = testHashInit(0)))
141 for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) {
142 if (virHashUpdateEntry(hash, uuids_subset[i], (void *) 1) < 0) {
143 if (virTestGetVerbose()) {
144 fprintf(stderr, "\nentry \"%s\" could not be updated\n",
151 for (i = 0; i < ARRAY_CARDINALITY(uuids_new); i++) {
152 if (virHashUpdateEntry(hash, uuids_new[i], (void *) 1) < 0) {
153 if (virTestGetVerbose()) {
154 fprintf(stderr, "\nnew entry \"%s\" could not be updated\n",
161 if (testHashCheckCount(hash, count) < 0)
173 testHashRemove(const void *data ATTRIBUTE_UNUSED)
175 int count = ARRAY_CARDINALITY(uuids) - ARRAY_CARDINALITY(uuids_subset);
176 virHashTablePtr hash;
180 if (!(hash = testHashInit(0)))
183 for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) {
184 if (virHashRemoveEntry(hash, uuids_subset[i]) < 0) {
185 if (virTestGetVerbose()) {
186 fprintf(stderr, "\nentry \"%s\" could not be removed\n",
193 if (testHashCheckCount(hash, count) < 0)
204 const int testHashCountRemoveForEachSome =
205 ARRAY_CARDINALITY(uuids) - ARRAY_CARDINALITY(uuids_subset);
208 testHashRemoveForEachSome(void *payload ATTRIBUTE_UNUSED,
212 virHashTablePtr hash = data;
215 for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) {
216 if (STREQ(uuids_subset[i], name)) {
217 if (virHashRemoveEntry(hash, name) < 0 && virTestGetVerbose()) {
218 fprintf(stderr, "\nentry \"%s\" could not be removed",
227 const int testHashCountRemoveForEachAll = 0;
230 testHashRemoveForEachAll(void *payload ATTRIBUTE_UNUSED,
234 virHashTablePtr hash = data;
236 virHashRemoveEntry(hash, name);
240 const int testHashCountRemoveForEachForbidden = ARRAY_CARDINALITY(uuids);
243 testHashRemoveForEachForbidden(void *payload ATTRIBUTE_UNUSED,
247 virHashTablePtr hash = data;
250 for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) {
251 if (STREQ(uuids_subset[i], name)) {
252 int next = (i + 1) % ARRAY_CARDINALITY(uuids_subset);
254 if (virHashRemoveEntry(hash, uuids_subset[next]) == 0 &&
255 virTestGetVerbose()) {
257 "\nentry \"%s\" should not be allowed to be removed",
267 testHashRemoveForEach(const void *data)
269 const struct testInfo *info = data;
270 virHashTablePtr hash;
274 if (!(hash = testHashInit(0)))
277 count = virHashForEach(hash, (virHashIterator) info->data, hash);
279 if (count != ARRAY_CARDINALITY(uuids)) {
280 if (virTestGetVerbose()) {
281 testError("\nvirHashForEach didn't go through all entries,"
283 count, ARRAY_CARDINALITY(uuids));
288 if (testHashCheckCount(hash, info->count) < 0)
300 testHashSteal(const void *data ATTRIBUTE_UNUSED)
302 int count = ARRAY_CARDINALITY(uuids) - ARRAY_CARDINALITY(uuids_subset);
303 virHashTablePtr hash;
307 if (!(hash = testHashInit(0)))
310 for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) {
311 if (!virHashSteal(hash, uuids_subset[i])) {
312 if (virTestGetVerbose()) {
313 fprintf(stderr, "\nentry \"%s\" could not be stolen\n",
320 if (testHashCheckCount(hash, count) < 0)
332 testHashIter(void *payload ATTRIBUTE_UNUSED,
333 const void *name ATTRIBUTE_UNUSED,
334 void *data ATTRIBUTE_UNUSED)
340 testHashForEachIter(void *payload ATTRIBUTE_UNUSED,
341 const void *name ATTRIBUTE_UNUSED,
344 virHashTablePtr hash = data;
346 if (virHashAddEntry(hash, uuids_new[0], NULL) == 0 &&
347 virTestGetVerbose()) {
348 fprintf(stderr, "\nadding entries in ForEach should be forbidden");
351 if (virHashUpdateEntry(hash, uuids_new[0], NULL) == 0 &&
352 virTestGetVerbose()) {
353 fprintf(stderr, "\nupdating entries in ForEach should be forbidden");
356 if (virHashSteal(hash, uuids_new[0]) != NULL &&
357 virTestGetVerbose()) {
358 fprintf(stderr, "\nstealing entries in ForEach should be forbidden");
361 if (virHashSteal(hash, uuids_new[0]) != NULL &&
362 virTestGetVerbose()) {
363 fprintf(stderr, "\nstealing entries in ForEach should be forbidden");
366 if (virHashForEach(hash, testHashIter, NULL) >= 0 &&
367 virTestGetVerbose()) {
368 fprintf(stderr, "\niterating through hash in ForEach"
369 " should be forbidden");
374 testHashForEach(const void *data ATTRIBUTE_UNUSED)
376 virHashTablePtr hash;
380 if (!(hash = testHashInit(0)))
383 count = virHashForEach(hash, testHashForEachIter, hash);
385 if (count != ARRAY_CARDINALITY(uuids)) {
386 if (virTestGetVerbose()) {
387 testError("\nvirHashForEach didn't go through all entries,"
389 count, ARRAY_CARDINALITY(uuids));
403 testHashRemoveSetIter(const void *payload ATTRIBUTE_UNUSED,
407 int *count = (int *) data;
411 for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) {
412 if (STREQ(uuids_subset[i], name)) {
418 if (rem || rand() % 2) {
427 testHashRemoveSet(const void *data ATTRIBUTE_UNUSED)
429 virHashTablePtr hash;
434 if (!(hash = testHashInit(0)))
437 /* seed the generator so that rand() provides reproducible sequence */
440 rcount = virHashRemoveSet(hash, testHashRemoveSetIter, &count);
442 if (count != rcount) {
443 if (virTestGetVerbose()) {
444 testError("\nvirHashRemoveSet didn't remove expected number of"
445 " entries, %d != %u\n",
451 if (testHashCheckCount(hash, ARRAY_CARDINALITY(uuids) - count) < 0)
462 const int testSearchIndex = ARRAY_CARDINALITY(uuids_subset) / 2;
465 testHashSearchIter(const void *payload ATTRIBUTE_UNUSED,
467 const void *data ATTRIBUTE_UNUSED)
469 return STREQ(uuids_subset[testSearchIndex], name);
473 testHashSearch(const void *data ATTRIBUTE_UNUSED)
475 virHashTablePtr hash;
479 if (!(hash = testHashInit(0)))
482 entry = virHashSearch(hash, testHashSearchIter, NULL);
484 if (!entry || STRNEQ(uuids_subset[testSearchIndex], entry)) {
485 if (virTestGetVerbose()) {
486 testError("\nvirHashSearch didn't find entry '%s'\n",
487 uuids_subset[testSearchIndex]);
492 if (testHashCheckCount(hash, ARRAY_CARDINALITY(uuids)) < 0)
504 testHashGetItemsCompKey(const virHashKeyValuePair *a,
505 const virHashKeyValuePair *b)
507 return strcmp(a->key, b->key);
511 testHashGetItemsCompValue(const virHashKeyValuePair *a,
512 const virHashKeyValuePair *b)
514 return strcmp(a->value, b->value);
518 testHashGetItems(const void *data ATTRIBUTE_UNUSED)
520 virHashTablePtr hash;
521 virHashKeyValuePairPtr array = NULL;
530 if (!(hash = virHashCreate(0, NULL)) ||
531 virHashAddEntry(hash, keya, value3) < 0 ||
532 virHashAddEntry(hash, keyc, value1) < 0 ||
533 virHashAddEntry(hash, keyb, value2) < 0) {
534 if (virTestGetVerbose()) {
535 testError("\nfailed to create hash");
540 if (!(array = virHashGetItems(hash, NULL)) ||
541 array[3].key || array[3].value) {
542 if (virTestGetVerbose()) {
543 testError("\nfailed to get items with NULL sort");
549 if (!(array = virHashGetItems(hash, testHashGetItemsCompKey)) ||
550 STRNEQ(array[0].key, "a") ||
551 STRNEQ(array[0].value, "3") ||
552 STRNEQ(array[1].key, "b") ||
553 STRNEQ(array[1].value, "2") ||
554 STRNEQ(array[2].key, "c") ||
555 STRNEQ(array[2].value, "1") ||
556 array[3].key || array[3].value) {
557 if (virTestGetVerbose()) {
558 testError("\nfailed to get items with key sort");
564 if (!(array = virHashGetItems(hash, testHashGetItemsCompValue)) ||
565 STRNEQ(array[0].key, "c") ||
566 STRNEQ(array[0].value, "1") ||
567 STRNEQ(array[1].key, "b") ||
568 STRNEQ(array[1].value, "2") ||
569 STRNEQ(array[2].key, "a") ||
570 STRNEQ(array[2].value, "3") ||
571 array[3].key || array[3].value) {
572 if (virTestGetVerbose()) {
573 testError("\nfailed to get items with value sort");
587 testHashEqualCompValue(const void *value1, const void *value2)
589 return c_strcasecmp(value1, value2);
593 testHashEqual(const void *data ATTRIBUTE_UNUSED)
595 virHashTablePtr hash1, hash2 = NULL;
600 char value1_l[] = "m";
601 char value2_l[] = "n";
602 char value3_l[] = "o";
603 char value1_u[] = "M";
604 char value2_u[] = "N";
605 char value3_u[] = "O";
606 char value4_u[] = "P";
608 if (!(hash1 = virHashCreate(0, NULL)) ||
609 !(hash2 = virHashCreate(0, NULL)) ||
610 virHashAddEntry(hash1, keya, value1_l) < 0 ||
611 virHashAddEntry(hash1, keyb, value2_l) < 0 ||
612 virHashAddEntry(hash1, keyc, value3_l) < 0 ||
613 virHashAddEntry(hash2, keya, value1_u) < 0 ||
614 virHashAddEntry(hash2, keyb, value2_u) < 0) {
615 if (virTestGetVerbose()) {
616 testError("\nfailed to create hashes");
621 if (virHashEqual(hash1, hash2, testHashEqualCompValue)) {
622 if (virTestGetVerbose()) {
623 testError("\nfailed equal test for different number of elements");
628 if (virHashAddEntry(hash2, keyc, value4_u) < 0) {
629 if (virTestGetVerbose()) {
630 testError("\nfailed to add element to hash2");
635 if (virHashEqual(hash1, hash2, testHashEqualCompValue)) {
636 if (virTestGetVerbose()) {
637 testError("\nfailed equal test for same number of elements");
642 if (virHashUpdateEntry(hash2, keyc, value3_u) < 0) {
643 if (virTestGetVerbose()) {
644 testError("\nfailed to update element in hash2");
649 if (!virHashEqual(hash1, hash2, testHashEqualCompValue)) {
650 if (virTestGetVerbose()) {
651 testError("\nfailed equal test for equal hash tables");
670 #define DO_TEST_FULL(name, cmd, data, count) \
672 struct testInfo info = { data, count }; \
673 if (virtTestRun(name, testHash ## cmd, &info) < 0) \
677 #define DO_TEST_DATA(name, cmd, data) \
678 DO_TEST_FULL(name "(" #data ")", \
680 testHash ## cmd ## data, \
681 testHashCount ## cmd ## data)
683 #define DO_TEST_COUNT(name, cmd, count) \
684 DO_TEST_FULL(name "(" #count ")", cmd, NULL, count)
686 #define DO_TEST(name, cmd) \
687 DO_TEST_FULL(name, cmd, NULL, -1)
689 DO_TEST_COUNT("Grow", Grow, 1);
690 DO_TEST_COUNT("Grow", Grow, 10);
691 DO_TEST_COUNT("Grow", Grow, 42);
692 DO_TEST("Update", Update);
693 DO_TEST("Remove", Remove);
694 DO_TEST_DATA("Remove in ForEach", RemoveForEach, Some);
695 DO_TEST_DATA("Remove in ForEach", RemoveForEach, All);
696 DO_TEST_DATA("Remove in ForEach", RemoveForEach, Forbidden);
697 DO_TEST("Steal", Steal);
698 DO_TEST("Forbidden ops in ForEach", ForEach);
699 DO_TEST("RemoveSet", RemoveSet);
700 DO_TEST("Search", Search);
701 DO_TEST("GetItems", GetItems);
702 DO_TEST("Equal", Equal);
704 return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
707 VIRT_TEST_MAIN(mymain)