449 lines
8.7 KiB
C
449 lines
8.7 KiB
C
|
|
#include <winpr/crt.h>
|
|
#include <winpr/tchar.h>
|
|
#include <winpr/collections.h>
|
|
|
|
static char* key1 = "key1";
|
|
static char* key2 = "key2";
|
|
static char* key3 = "key3";
|
|
|
|
static char* val1 = "val1";
|
|
static char* val2 = "val2";
|
|
static char* val3 = "val3";
|
|
|
|
static int test_hash_table_pointer(void)
|
|
{
|
|
int rc = -1;
|
|
size_t count = 0;
|
|
char* value = NULL;
|
|
wHashTable* table = NULL;
|
|
table = HashTable_New(TRUE);
|
|
|
|
if (!table)
|
|
return -1;
|
|
|
|
if (!HashTable_Insert(table, key1, val1))
|
|
goto fail;
|
|
if (!HashTable_Insert(table, key2, val2))
|
|
goto fail;
|
|
if (!HashTable_Insert(table, key3, val3))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 3)
|
|
{
|
|
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Remove(table, key2))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 2)
|
|
{
|
|
printf("HashTable_Count: Expected : 2, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Remove(table, key3))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 1)
|
|
{
|
|
printf("HashTable_Count: Expected : 1, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Remove(table, key1))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 0)
|
|
{
|
|
printf("HashTable_Count: Expected : 0, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Insert(table, key1, val1))
|
|
goto fail;
|
|
if (!HashTable_Insert(table, key2, val2))
|
|
goto fail;
|
|
if (!HashTable_Insert(table, key3, val3))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 3)
|
|
{
|
|
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
value = (char*)HashTable_GetItemValue(table, key1);
|
|
|
|
if (strcmp(value, val1) != 0)
|
|
{
|
|
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val1, value);
|
|
goto fail;
|
|
}
|
|
|
|
value = (char*)HashTable_GetItemValue(table, key2);
|
|
|
|
if (strcmp(value, val2) != 0)
|
|
{
|
|
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val2, value);
|
|
goto fail;
|
|
}
|
|
|
|
value = (char*)HashTable_GetItemValue(table, key3);
|
|
|
|
if (strcmp(value, val3) != 0)
|
|
{
|
|
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val3, value);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_SetItemValue(table, key2, "apple"))
|
|
goto fail;
|
|
value = (char*)HashTable_GetItemValue(table, key2);
|
|
|
|
if (strcmp(value, "apple") != 0)
|
|
{
|
|
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", "apple", value);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Contains(table, key2))
|
|
{
|
|
printf("HashTable_Contains: Expected : TRUE, Actual: FALSE\n");
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Remove(table, key2))
|
|
{
|
|
printf("HashTable_Remove: Expected : TRUE, Actual: FALSE\n");
|
|
goto fail;
|
|
}
|
|
|
|
if (HashTable_Remove(table, key2))
|
|
{
|
|
printf("HashTable_Remove: Expected : FALSE, Actual: TRUE\n");
|
|
goto fail;
|
|
}
|
|
|
|
HashTable_Clear(table);
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 0)
|
|
{
|
|
printf("HashTable_Count: Expected : 0, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
rc = 1;
|
|
fail:
|
|
HashTable_Free(table);
|
|
return rc;
|
|
}
|
|
|
|
static int test_hash_table_string(void)
|
|
{
|
|
int rc = -1;
|
|
size_t count = 0;
|
|
char* value = NULL;
|
|
wHashTable* table = HashTable_New(TRUE);
|
|
|
|
if (!table)
|
|
return -1;
|
|
|
|
if (!HashTable_SetupForStringData(table, TRUE))
|
|
goto fail;
|
|
|
|
if (!HashTable_Insert(table, key1, val1))
|
|
goto fail;
|
|
if (!HashTable_Insert(table, key2, val2))
|
|
goto fail;
|
|
if (!HashTable_Insert(table, key3, val3))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 3)
|
|
{
|
|
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Remove(table, key2))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 2)
|
|
{
|
|
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Remove(table, key3))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 1)
|
|
{
|
|
printf("HashTable_Count: Expected : 1, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Remove(table, key1))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 0)
|
|
{
|
|
printf("HashTable_Count: Expected : 0, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Insert(table, key1, val1))
|
|
goto fail;
|
|
if (!HashTable_Insert(table, key2, val2))
|
|
goto fail;
|
|
if (!HashTable_Insert(table, key3, val3))
|
|
goto fail;
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 3)
|
|
{
|
|
printf("HashTable_Count: Expected : 3, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
value = (char*)HashTable_GetItemValue(table, key1);
|
|
|
|
if (strcmp(value, val1) != 0)
|
|
{
|
|
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val1, value);
|
|
goto fail;
|
|
}
|
|
|
|
value = (char*)HashTable_GetItemValue(table, key2);
|
|
|
|
if (strcmp(value, val2) != 0)
|
|
{
|
|
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val2, value);
|
|
goto fail;
|
|
}
|
|
|
|
value = (char*)HashTable_GetItemValue(table, key3);
|
|
|
|
if (strcmp(value, val3) != 0)
|
|
{
|
|
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val3, value);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_SetItemValue(table, key2, "apple"))
|
|
goto fail;
|
|
value = (char*)HashTable_GetItemValue(table, key2);
|
|
|
|
if (strcmp(value, "apple") != 0)
|
|
{
|
|
printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", "apple", value);
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Contains(table, key2))
|
|
{
|
|
printf("HashTable_Contains: Expected : TRUE, Actual: FALSE\n");
|
|
goto fail;
|
|
}
|
|
|
|
if (!HashTable_Remove(table, key2))
|
|
{
|
|
printf("HashTable_Remove: Expected : TRUE, Actual: FALSE\n");
|
|
goto fail;
|
|
}
|
|
|
|
if (HashTable_Remove(table, key2))
|
|
{
|
|
printf("HashTable_Remove: Expected : FALSE, Actual: TRUE\n");
|
|
goto fail;
|
|
}
|
|
|
|
HashTable_Clear(table);
|
|
count = HashTable_Count(table);
|
|
|
|
if (count != 0)
|
|
{
|
|
printf("HashTable_Count: Expected : 0, Actual: %" PRIuz "\n", count);
|
|
goto fail;
|
|
}
|
|
|
|
rc = 1;
|
|
fail:
|
|
HashTable_Free(table);
|
|
return rc;
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
wHashTable* table;
|
|
size_t strlenCounter;
|
|
size_t foreachCalls;
|
|
|
|
BOOL test3error;
|
|
} ForeachData;
|
|
|
|
static BOOL foreachFn1(const void* key, void* value, void* arg)
|
|
{
|
|
ForeachData* d = (ForeachData*)arg;
|
|
WINPR_UNUSED(key);
|
|
d->strlenCounter += strlen((const char*)value);
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL foreachFn2(const void* key, void* value, void* arg)
|
|
{
|
|
ForeachData* d = (ForeachData*)arg;
|
|
WINPR_UNUSED(key);
|
|
WINPR_UNUSED(value);
|
|
d->foreachCalls++;
|
|
|
|
if (d->foreachCalls == 2)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL foreachFn3(const void* key, void* value, void* arg)
|
|
{
|
|
const char* keyStr = (const char*)key;
|
|
|
|
ForeachData* d = (ForeachData*)arg;
|
|
ForeachData d2;
|
|
|
|
WINPR_UNUSED(value);
|
|
WINPR_ASSERT(keyStr);
|
|
|
|
if (strcmp(keyStr, "key1") == 0)
|
|
{
|
|
/* when we pass on key1, let's remove key2 and check that the value is not
|
|
* visible anymore (even if has just been marked for removal)*/
|
|
HashTable_Remove(d->table, "key2");
|
|
|
|
if (HashTable_Contains(d->table, "key2"))
|
|
{
|
|
d->test3error = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
if (HashTable_ContainsValue(d->table, "value2"))
|
|
{
|
|
d->test3error = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/* number of elements of the table shall be correct too */
|
|
if (HashTable_Count(d->table) != 2)
|
|
{
|
|
d->test3error = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/* we try recursive HashTable_Foreach */
|
|
d2.table = d->table;
|
|
d2.strlenCounter = 0;
|
|
|
|
if (!HashTable_Foreach(d->table, foreachFn1, &d2))
|
|
{
|
|
d->test3error = TRUE;
|
|
return FALSE;
|
|
}
|
|
if (d2.strlenCounter != 8)
|
|
{
|
|
d->test3error = TRUE;
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static int test_hash_foreach(void)
|
|
{
|
|
ForeachData foreachData;
|
|
wHashTable* table = NULL;
|
|
int retCode = 0;
|
|
|
|
foreachData.table = table = HashTable_New(TRUE);
|
|
if (!table)
|
|
return -1;
|
|
|
|
if (!HashTable_SetupForStringData(table, TRUE))
|
|
goto out;
|
|
|
|
if (HashTable_Insert(table, key1, val1) < 0 || HashTable_Insert(table, key2, val2) < 0 ||
|
|
HashTable_Insert(table, key3, val3) < 0)
|
|
{
|
|
retCode = -2;
|
|
goto out;
|
|
}
|
|
|
|
/* let's try a first trivial foreach */
|
|
foreachData.strlenCounter = 0;
|
|
if (!HashTable_Foreach(table, foreachFn1, &foreachData))
|
|
{
|
|
retCode = -10;
|
|
goto out;
|
|
}
|
|
if (foreachData.strlenCounter != 12)
|
|
{
|
|
retCode = -11;
|
|
goto out;
|
|
}
|
|
|
|
/* interrupted foreach */
|
|
foreachData.foreachCalls = 0;
|
|
if (HashTable_Foreach(table, foreachFn2, &foreachData))
|
|
{
|
|
retCode = -20;
|
|
goto out;
|
|
}
|
|
if (foreachData.foreachCalls != 2)
|
|
{
|
|
retCode = -21;
|
|
goto out;
|
|
}
|
|
|
|
/* let's try a foreach() call that will remove a value from the table in the callback */
|
|
foreachData.test3error = FALSE;
|
|
if (!HashTable_Foreach(table, foreachFn3, &foreachData))
|
|
{
|
|
retCode = -30;
|
|
goto out;
|
|
}
|
|
if (foreachData.test3error)
|
|
{
|
|
retCode = -31;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
HashTable_Free(table);
|
|
return retCode;
|
|
}
|
|
|
|
int TestHashTable(int argc, char* argv[])
|
|
{
|
|
WINPR_UNUSED(argc);
|
|
WINPR_UNUSED(argv);
|
|
|
|
if (test_hash_table_pointer() < 0)
|
|
return 1;
|
|
|
|
if (test_hash_table_string() < 0)
|
|
return 2;
|
|
|
|
if (test_hash_foreach() < 0)
|
|
return 3;
|
|
return 0;
|
|
}
|