#include "dynamictypes/DataArray.h" #include "dynamictypes/DataHashTable.h" #include "utilities/printfFormats.h" #include "unittest/TestSuite.h" #include static void testCreate() { DataHashTable * hashTable = hashCreate(); TestCase_assertPointerNonNULL(hashTable); TestCase_assertPointerNonNULL(hashTable->hashTable); TestCase_assertSizeEqual(hashTable->hashTable->count, 0); hashDispose(hashTable); } static void testCreateWithKeysAndValues() { DataHashTable * hashTable = hashCreateWithKeysAndValues("a", valueCreateBoolean(false), NULL); TestCase_assertPointerNonNULL(hashTable); TestCase_assertSizeEqual(hashGetCount(hashTable), 1); DataValue * value = hashGet(hashTable, "a"); TestCase_assertPointerNonNULL(value); TestCase_assertIntEqual(value->type, DATA_TYPE_BOOLEAN); TestCase_assertBoolFalse(value->value.boolean); hashDispose(hashTable); hashTable = hashCreateWithKeysAndValues("b", valueCreateBoolean(true), "foo", valueCreateInt8(2), NULL); TestCase_assertPointerNonNULL(hashTable); TestCase_assertSizeEqual(hashGetCount(hashTable), 2); value = hashGet(hashTable, "b"); TestCase_assertPointerNonNULL(value); TestCase_assertIntEqual(value->type, DATA_TYPE_BOOLEAN); TestCase_assertBoolTrue(value->value.boolean); value = hashGet(hashTable, "foo"); TestCase_assertPointerNonNULL(value); TestCase_assertIntEqual(value->type, DATA_TYPE_INT8); TestCase_assertIntEqual(value->value.int8, 2); hashDispose(hashTable); } static void testAccessors() { DataHashTable * hashTable = hashCreate(); TestCase_assertPointerNonNULL(hashTable); // Verify table empty TestCase_assertBoolFalse(hashHas(hashTable, "value1")); TestCase_assertBoolFalse(hashHas(hashTable, "value2")); // Verify hashGet returns NULL for unset keys DataValue * entry = hashGet(hashTable, "value1"); TestCase_assertPointerNULL(entry); entry = hashGet(hashTable, "value2"); TestCase_assertPointerNULL(entry); // Set values hashSet(hashTable, "value1", valueCreateBoolean(false)); TestCase_assertSizeEqual(hashGetCount(hashTable), 1); hashSet(hashTable, "value2", valueCreateBoolean(true)); TestCase_assertSizeEqual(hashGetCount(hashTable), 2); // Verify table full TestCase_assertBoolTrue(hashHas(hashTable, "value1")); TestCase_assertBoolTrue(hashHas(hashTable, "value2")); // Verify hashGet returns correct values for set keys entry = hashGet(hashTable, "value1"); TestCase_assertPointerNonNULL(entry); TestCase_assertIntEqual(entry->type, DATA_TYPE_BOOLEAN); TestCase_assertBoolFalse(entry->value.boolean); entry = hashGet(hashTable, "value2"); TestCase_assertPointerNonNULL(entry); TestCase_assertIntEqual(entry->type, DATA_TYPE_BOOLEAN); TestCase_assertBoolTrue(entry->value.boolean); } static void testCopy() { DataHashTable * hashTable = hashCreate(); DataHashTable * hashTableCopy = hashCopy(hashTable); TestCase_assertPointerNonNULL(hashTableCopy); TestCase_assertPointerUnequal(hashTableCopy, hashTable); TestCase_assertSizeEqual(hashGetCount(hashTable), hashGetCount(hashTableCopy)); hashDispose(hashTable); hashDispose(hashTableCopy); hashTable = hashCreate(); hashSet(hashTable, "a", valueCreateString("hello", DATA_USE_STRLEN, true, true)); hashSet(hashTable, "b", valueCreateBlob("foo", 3, true, true)); DataHashTable * subtable = hashCreate(); hashSet(subtable, "c", valueCreateString("foo", DATA_USE_STRLEN, true, true)); hashSet(subtable, "d", valueCreatePointer((void *) 0x1234)); hashSet(hashTable, "c", valueCreateHashTable(subtable, true, true)); hashDispose(subtable); hashTableCopy = hashCopy(hashTable); TestCase_assertPointerNonNULL(hashTableCopy); TestCase_assertPointerUnequal(hashTableCopy, hashTable); TestCase_assertSizeEqual(hashGetCount(hashTable), hashGetCount(hashTableCopy)); DataValue * string = hashGet(hashTable, "a"); DataValue * stringCopy = hashGet(hashTableCopy, "a"); TestCase_assertPointerNonNULL(string); TestCase_assertPointerNonNULL(stringCopy); TestCase_assertIntEqual(string->type, DATA_TYPE_STRING); TestCase_assertIntEqual(stringCopy->type, DATA_TYPE_STRING); TestCase_assertStringEqual(string->value.string, "hello"); TestCase_assertStringEqual(stringCopy->value.string, "hello"); TestCase_assertPointerUnequal(string->value.string, stringCopy->value.string); DataValue * blob = hashGet(hashTable, "b"); DataValue * blobCopy = hashGet(hashTableCopy, "b"); TestCase_assertPointerNonNULL(blob); TestCase_assertPointerNonNULL(blobCopy); TestCase_assertSizeEqual(blob->value.blob.length, 3); TestCase_assertSizeEqual(blobCopy->value.blob.length, 3); TestCase_assert(!memcmp(blob->value.blob.bytes, "foo", 3), "Expected \"foo\" but got \"%.*s\"", (unsigned int) blob->value.blob.length, (char *) blob->value.blob.bytes); TestCase_assert(!memcmp(blobCopy->value.blob.bytes, "foo", 3), "Expected \"foo\" but got \"%.*s\"", (unsigned int) blobCopy->value.blob.length, (char *) blobCopy->value.blob.bytes); TestCase_assertPointerUnequal(blob->value.blob.bytes, blobCopy->value.blob.bytes); DataValue * subtableValue = hashGet(hashTable, "c"); DataValue * subtableValueCopy = hashGet(hashTableCopy, "c"); TestCase_assertPointerNonNULL(subtableValue); TestCase_assertPointerNonNULL(subtableValueCopy); TestCase_assertSizeEqual(hashGetCount(subtableValue->value.hashTable), 2); TestCase_assertSizeEqual(hashGetCount(subtableValueCopy->value.hashTable), 2); TestCase_assertPointerUnequal(subtableValue->value.hashTable, subtableValueCopy->value.hashTable); hashDispose(hashTable); hashDispose(hashTableCopy); } static void testReplaceValues() { DataHashTable * hash = hashCreate(); hashSet(hash, "a", valueCreateInt32(1)); hashSet(hash, "b", valueCreateInt32(2)); TestCase_assertSizeEqual(hashGetCount(hash), 2); DataValue * int32Value = hashGet(hash, "b"); TestCase_assertIntEqual(int32Value->value.int32, 2); hashSet(hash, "b", valueCreateInt32(3)); TestCase_assertSizeEqual(hashGetCount(hash), 2); int32Value = hashGet(hash, "b"); TestCase_assertIntEqual(int32Value->value.int32, 3); hashSet(hash, "a", valueCreateString("hello", DATA_USE_STRLEN, false, false)); TestCase_assertSizeEqual(hashGetCount(hash), 2); DataValue * stringValue = hashGet(hash, "a"); TestCase_assertPointerNonNULL(stringValue); TestCase_assertIntEqual(stringValue->type, DATA_TYPE_STRING); TestCase_assertStringEqual(stringValue->value.string, "hello"); hashSet(hash, "a", valueCreateInt32(1)); TestCase_assertSizeEqual(hashGetCount(hash), 2); int32Value = hashGet(hash, "a"); TestCase_assertIntEqual(int32Value->value.int32, 1); size_t count; const char ** keys = hashGetKeys(hash, &count); TestCase_assertSizeEqual(count, 2); TestCase_assert((!strcmp(keys[0], "a") && !strcmp(keys[1], "b")) || (!strcmp(keys[0], "b") && !strcmp(keys[1], "a")), "Expected \"a\" and \"b\", but got \"%s\" and \"%s\"", keys[0], keys[1]); free(keys); } static void testDeleteValues() { DataHashTable * hash = hashCreate(); hashSet(hash, "a", valueCreateInt32(1)); hashSet(hash, "b", valueCreateInt32(2)); hashSet(hash, "c", valueCreateInt32(3)); TestCase_assertSizeEqual(hashGetCount(hash), 3); bool found = hashDelete(hash, "d"); TestCase_assertBoolFalse(found); found = hashDelete(hash, "b"); TestCase_assertBoolTrue(found); TestCase_assertSizeEqual(hashGetCount(hash), 2); TestCase_assertBoolFalse(hashHas(hash, "b")); size_t count; const char ** keys = hashGetKeys(hash, &count); TestCase_assertSizeEqual(count, 2); TestCase_assert((!strcmp(keys[0], "a") && !strcmp(keys[1], "c")) || (!strcmp(keys[0], "c") && !strcmp(keys[1], "a")), "Expected \"a\" and \"c\", but got \"%s\" and \"%s\"", keys[0], keys[1]); free(keys); found = hashDelete(hash, "b"); TestCase_assertBoolFalse(found); found = hashDelete(hash, "a"); TestCase_assertBoolTrue(found); TestCase_assertSizeEqual(hashGetCount(hash), 1); TestCase_assertBoolFalse(hashHas(hash, "a")); keys = hashGetKeys(hash, &count); TestCase_assertSizeEqual(count, 1); TestCase_assertStringEqual(keys[0], "c"); free(keys); hashDispose(hash); } static void testGetKeys() { DataHashTable * hashTable = hashCreate(); hashSet(hashTable, "a", valueCreateBoolean(false)); size_t count; const char ** keys = hashGetKeys(hashTable, &count); TestCase_assertPointerNonNULL(keys); TestCase_assertSizeEqual(count, 1); TestCase_assertStringEqual(keys[0], "a"); hashDispose(hashTable); free(keys); hashTable = hashCreate(); hashSet(hashTable, "bar", valueCreateBoolean(true)); hashSet(hashTable, "foo", valueCreateInt32(1)); count = 0; keys = hashGetKeys(hashTable, &count); TestCase_assertPointerNonNULL(keys); TestCase_assertSizeEqual(count, 2); TestCase_assert((!strcmp(keys[0], "foo") && !strcmp(keys[1], "bar")) || (!strcmp(keys[0], "bar") && !strcmp(keys[1], "foo")), "Expected \"foo\" and \"bar\" but got \"%s\" and \"%s\"", keys[0], keys[1]); hashDispose(hashTable); free(keys); } static void testGetKeyAtIndex() { DataHashTable * hashTable = hashCreate(); const char * key = hashGetKeyAtIndex(hashTable, 0); TestCase_assertPointerNULL(key); hashSet(hashTable, "a", valueCreateBoolean(false)); key = hashGetKeyAtIndex(hashTable, 0); TestCase_assertPointerNonNULL(key); TestCase_assertStringEqual(key, "a"); key = hashGetKeyAtIndex(hashTable, 1); TestCase_assertPointerNULL(key); hashDispose(hashTable); hashTable = hashCreate(); hashSet(hashTable, "bar", valueCreateBoolean(true)); hashSet(hashTable, "foo", valueCreateInt32(1)); key = hashGetKeyAtIndex(hashTable, 0); TestCase_assertPointerNonNULL(key); if (!strcmp(key, "foo")) { key = hashGetKeyAtIndex(hashTable, 1); TestCase_assertPointerNonNULL(key); TestCase_assertStringEqual(key, "bar"); } else if (!strcmp(key, "bar")) { key = hashGetKeyAtIndex(hashTable, 1); TestCase_assertPointerNonNULL(key); TestCase_assertStringEqual(key, "foo"); } else { TestCase_assert(false, "First key was neither expected value \"foo\" nor \"bar\"; got \"%s\" instead", key); } hashDispose(hashTable); } TEST_SUITE(DataHashTableTest, testCreate, testCreateWithKeysAndValues, testAccessors, testCopy, testReplaceValues, testDeleteValues, testGetKeys, testGetKeyAtIndex)