#include "../Tests.h" #include "core/HashMap.h" #include "core/ToString.h" HASHMAP(size_t, size_t, Size) typedef struct { size_t a; size_t b; } A; static size_t hashA(A key) { return key.a ^ key.b; } static bool equalA(A a, A b) { return a.a == b.a && a.b == b.b; } static bool isInvalidKeyA(A key) { return key.a == 0 && key.b == 0; } HASHMAP(A, int, A) HASHMAP_SOURCE(A, int, A) static HashMapSize getTestSizeMap() { HashMapSize map; initHashMapSize(&map); *putHashMapKeySize(&map, 1) = 3; *putHashMapKeySize(&map, 2) = 4; *putHashMapKeySize(&map, 3) = 5; *putHashMapKeySize(&map, 0) = 20; return map; } static void checkSizeMap(HashMapSize* map) { size_t* a = searchHashMapKeySize(map, 1); size_t* b = searchHashMapKeySize(map, 2); size_t* c = searchHashMapKeySize(map, 3); size_t* d = searchHashMapKeySize(map, 0); if(TEST_NOT_NULL(a) && TEST_NOT_NULL(b) && TEST_NOT_NULL(c) && TEST_NOT_NULL(d)) { TEST_SIZE(3, *a); TEST_SIZE(4, *b); TEST_SIZE(5, *c); TEST_SIZE(20, *d); } } static void testAdd() { HashMapSize map; initHashMapSize(&map); *putHashMapKeySize(&map, 5) = 4; size_t* value = searchHashMapKeySize(&map, 5); if(TEST_NOT_NULL(value)) { TEST_SIZE(4, *value); } destroyHashMapSize(&map); } static void testMultipleAdd() { HashMapSize map = getTestSizeMap(); TEST_NOT_NULL(searchHashMapKeySize(&map, 0)); TEST_NOT_NULL(searchHashMapKeySize(&map, 1)); TEST_NOT_NULL(searchHashMapKeySize(&map, 2)); TEST_NOT_NULL(searchHashMapKeySize(&map, 3)); checkSizeMap(&map); destroyHashMapSize(&map); } static void testSearch() { HashMapSize map = getTestSizeMap(); TEST_NULL(searchHashMapKeySize(&map, 6)); *putHashMapKeySize(&map, 5) = 4; *putHashMapKeySize(&map, 10) = 3; *putHashMapKeySize(&map, 15) = 2; TEST_NULL(searchHashMapKeySize(&map, 6)); destroyHashMapSize(&map); } static void testSearchEmpty() { HashMapSize map; initHashMapSize(&map); TEST_NULL(searchHashMapKeySize(&map, 6)); destroyHashMapSize(&map); } static void testAddReplace() { HashMapSize map = getTestSizeMap(); *putHashMapKeySize(&map, 5) = 4; *putHashMapKeySize(&map, 5) = 10; TEST_NOT_NULL(searchHashMapKeySize(&map, 5)); size_t* a = searchHashMapKeySize(&map, 5); if(TEST_NOT_NULL(a)) { TEST_SIZE(10, *a); } destroyHashMapSize(&map); } static void testClear() { HashMapSize map = getTestSizeMap(); *putHashMapKeySize(&map, 5) = 4; *putHashMapKeySize(&map, 4) = 10; clearHashMapSize(&map); TEST_NULL(searchHashMapKeySize(&map, 5)); TEST_NULL(searchHashMapKeySize(&map, 4)); destroyHashMapSize(&map); } static void testClearEmpty() { HashMapSize map; initHashMapSize(&map); clearHashMapSize(&map); destroyHashMapSize(&map); } static void testOverflow(bool light) { size_t limit = light ? 10000 : 100000; HashMapSize map = getTestSizeMap(); for(size_t i = 0; i < limit; i++) { *putHashMapKeySize(&map, i) = i; } for(size_t i = 0; i < limit; i++) { TEST_NOT_NULL(searchHashMapKeySize(&map, i)); } destroyHashMapSize(&map); } static void testToString() { HashMapSize map = getTestSizeMap(); char buffer[128]; size_t n = toStringHashMapSize(&map, buffer, sizeof(buffer), toStringSize, toStringSize); TEST_SIZE(29, n); TEST_STRING("[2 = 4, 1 = 3, 3 = 5, 0 = 20]", buffer); clearHashMapSize(&map); *putHashMapKeySize(&map, 1) = 3; n = toStringHashMapSize(&map, buffer, sizeof(buffer), toStringSize, toStringSize); TEST_SIZE(7, n); TEST_STRING("[1 = 3]", buffer); clearHashMapSize(&map); n = toStringHashMapSize(&map, buffer, sizeof(buffer), toStringSize, toStringSize); TEST_SIZE(2, n); TEST_STRING("[]", buffer); destroyHashMapSize(&map); } static void testEntryForEach() { HashMapSize map; initHashMapSize(&map); *putHashMapKeySize(&map, 0) = 1; *putHashMapKeySize(&map, 5) = 4; *putHashMapKeySize(&map, 10) = 3; *putHashMapKeySize(&map, 15) = 2; size_t counter = 0; HashMapIteratorSize i; initHashMapIteratorSize(&i, &map); while(hasNextHashMapNodeSize(&i)) { HashMapNodeSize* n = nextHashMapNodeSize(&i); counter += *n->key + *n->value; } TEST_SIZE(40, counter); destroyHashMapSize(&map); } static void testInvalidPut() { HashMapSize map; initHashMapSize(&map); char buffer[128]; toStringHashMapSize(&map, buffer, sizeof(buffer), toStringSize, toStringSize); TEST_STRING("[]", buffer); *putHashMapKeySize(&map, 0) = 3; size_t* v = searchHashMapKeySize(&map, 0); if(TEST_NOT_NULL(v)) { TEST_SIZE(3, *v); } toStringHashMapSize(&map, buffer, sizeof(buffer), toStringSize, toStringSize); TEST_STRING("[0 = 3]", buffer); clearHashMapSize(&map); TEST_NULL(searchHashMapKeySize(&map, 0)); destroyHashMapSize(&map); } static void testAddCollisions() { HashMapSize map = getTestSizeMap(); for(size_t i = 0; i < 16; i++) { *putHashMapKeySize(&map, i * 64) = i; } destroyHashMapSize(&map); } static void testRemove() { HashMapSize map; initHashMapSize(&map); *putHashMapKeySize(&map, 1) = 3; *putHashMapKeySize(&map, 2) = 4; *putHashMapKeySize(&map, 3) = 5; TEST_TRUE(removeHashMapKeySize(&map, 2)); TEST_FALSE(removeHashMapKeySize(&map, 7)); size_t* a = searchHashMapKeySize(&map, 1); size_t* b = searchHashMapKeySize(&map, 2); size_t* c = searchHashMapKeySize(&map, 3); TEST_NULL(b); if(TEST_NOT_NULL(a) && TEST_NOT_NULL(c)) { TEST_SIZE(3, *a); TEST_SIZE(5, *c); } destroyHashMapSize(&map); } static void testHash() { const char* s = "wusi"; TEST_TRUE(hashString(s) != 0); } static size_t toStringA(const A* a, char* buffer, size_t n) { return toString(buffer, n, "{%zu, %zu}", a->a, a->b); } static void testSearchStruct() { HashMapA map; initHashMapA(&map); clearHashMapA(&map); A a = {1, 2}; A b = {1, 3}; A c = {0, 0}; TEST_NULL(searchHashMapKeyA(&map, a)); TEST_NULL(searchHashMapKeyA(&map, b)); TEST_NULL(searchHashMapKeyA(&map, c)); *putHashMapKeyA(&map, a) = 3; *putHashMapKeyA(&map, (A){5, 6}) = 5; char buffer[128]; size_t n = toStringHashMapA(&map, buffer, sizeof(buffer), toStringA, toStringInt); TEST_SIZE(24, n); TEST_STRING("[{5, 6} = 5, {1, 2} = 3]", buffer); int* ap = searchHashMapKeyA(&map, a); if(TEST_NOT_NULL(ap)) { TEST_INT(3, *ap); } TEST_NULL(searchHashMapKeyA(&map, b)); TEST_NULL(searchHashMapKeyA(&map, c)); *putHashMapKeyA(&map, c) = 4; int* cp = searchHashMapKeyA(&map, c); if(TEST_NOT_NULL(cp)) { TEST_INT(4, *cp); } for(size_t i = 0; i < 16; i++) { *putHashMapKeyA(&map, (A){i * 64, 0}) = (int)i; } HashMapIteratorA iter; initHashMapIteratorA(&iter, &map); size_t sum = 0; while(hasNextHashMapNodeA(&iter)) { HashMapNodeA* node = nextHashMapNodeA(&iter); sum += node->key->b; } TEST_SIZE(8, sum); removeHashMapKeyA(&map, (A){0, 1}); removeHashMapKeyA(&map, (A){0, 0}); clearHashMapA(&map); destroyHashMapA(&map); } static void testSearchSize() { HashMapSize map; initHashMapSize(&map); TEST_NULL(searchHashMapKeySize(&map, 0)); TEST_NULL(searchHashMapKeySize(&map, 1)); TEST_NULL(searchHashMapKeySize(&map, 2)); *putHashMapKeySize(&map, 1) = 3; size_t* ap = searchHashMapKeySize(&map, 1); if(TEST_NOT_NULL(ap)) { TEST_SIZE(3, *ap); } TEST_NULL(searchHashMapKeySize(&map, 0)); TEST_NULL(searchHashMapKeySize(&map, 2)); *putHashMapKeySize(&map, 0) = 4; size_t* cp = searchHashMapKeySize(&map, 0); if(TEST_NOT_NULL(cp)) { TEST_SIZE(4, *cp); } destroyHashMapSize(&map); } void testHashMap(bool light) { testAdd(); testMultipleAdd(); testSearch(); testSearchEmpty(); testAddReplace(); testClear(); testClearEmpty(); testOverflow(light); testToString(); testEntryForEach(); testInvalidPut(); testAddCollisions(); testRemove(); testHash(); testSearchStruct(); testSearchSize(); }