Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
446
third_party/FreeRDP/winpr/libwinpr/utils/test/TestHashTable.c
vendored
Normal file
446
third_party/FreeRDP/winpr/libwinpr/utils/test/TestHashTable.c
vendored
Normal file
@@ -0,0 +1,446 @@
|
||||
|
||||
#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 = nullptr;
|
||||
wHashTable* table = nullptr;
|
||||
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 = nullptr;
|
||||
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++;
|
||||
|
||||
return (d->foreachCalls != 2);
|
||||
}
|
||||
|
||||
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 = nullptr;
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user