Skip to content

Commit

Permalink
TreeMap: 1. Add object type test. 2. Add demo program.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZSShen committed Aug 22, 2016
1 parent 9be218a commit 72a0611
Show file tree
Hide file tree
Showing 3 changed files with 330 additions and 2 deletions.
177 changes: 176 additions & 1 deletion demo/demo_tree_map.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,183 @@
#include "cds.h"


typedef struct Employ_ {
int year;
int level;
int id;
} Employ;


int CompareKey(void* lhs, void* rhs)
{
return strcmp((char*)lhs, (char*)rhs);
}

void CleanKey(void* key)
{
free(key);
}

void CleanValue(void* value)
{
free(value);
}


void ManipulateNumerics()
{
/* We should initialize the container before any operations. */
TreeMap* map = TreeMapInit();

/* Insert numerics into the map. */
TreeMapPut(map, (void*)(intptr_t)1, (void*)(intptr_t)9999);
TreeMapPut(map, (void*)(intptr_t)2, (void*)(intptr_t)999);
TreeMapPut(map, (void*)(intptr_t)3, (void*)(intptr_t)99);
TreeMapPut(map, (void*)(intptr_t)4, (void*)(intptr_t)9);

/* Retrieve the value with the designated key. */
int val = (int)(intptr_t)TreeMapGet(map, (void*)(intptr_t)1);
assert(val == 9999);

/* Iterate through the map. */
Pair* ptr_pair;
TreeMapFirst(map);
int first = 1, second = 9999;
while ((ptr_pair = TreeMapNext(map)) != NULL) {
int key = (int)(intptr_t)ptr_pair->key;
int val = (int)(intptr_t)ptr_pair->value;
assert(key == first);
assert(val == second);
++first;
second /= 10;
}

first = 4;
second = 9;
while ((ptr_pair = TreeMapReverseNext(map)) != NULL) {
int key = (int)(intptr_t)ptr_pair->key;
int val = (int)(intptr_t)ptr_pair->value;
assert(key == first);
assert(val == second);
--first;
second *= 10;
second += 9;
}

/* Remove the key value pair with the designated key. */
TreeMapRemove(map, (void*)(intptr_t)2);

/* Check the map keys. */
assert(TreeMapFind(map, (void*)(intptr_t)1) == true);
assert(TreeMapFind(map, (void*)(intptr_t)2) == false);
assert(TreeMapFind(map, (void*)(intptr_t)3) == true);
assert(TreeMapFind(map, (void*)(intptr_t)4) == true);

/* Check the pair count in the map. */
unsigned size = TreeMapSize(map);
assert(size == 3);

/* We should deinitialize the container after all the relevant operations. */
TreeMapDeinit(map);
}

void ManipulateTexts()
{
char* names[4] = {"Alice\0", "Bob\0", "Chris\0", "David\0"};

/* We should initialize the container before any operations. */
TreeMap* map = TreeMapInit();

/* Set the custom key comparison functions. */
TreeMapSetCompare(map, CompareKey);

/* If we plan to delegate the resource clean task to the container, set the
custom clean functions. */
TreeMapSetCleanKey(map, CleanKey);
TreeMapSetCleanValue(map, CleanValue);

/* Insert complex data payload into the map. */
char* key = strdup(names[0]);
Employ* employ = (Employ*)malloc(sizeof(Employ));
employ->id = 1;
employ->year = 25;
employ->level = 100;
TreeMapPut(map, (void*)key, (void*)employ);

key = strdup(names[1]);
employ = (Employ*)malloc(sizeof(Employ));
employ->id = 2;
employ->year = 25;
employ->level = 90;
TreeMapPut(map, (void*)key, (void*)employ);

key = strdup(names[2]);
employ = (Employ*)malloc(sizeof(Employ));
employ->id = 3;
employ->year = 25;
employ->level = 80;
TreeMapPut(map, (void*)key, (void*)employ);

key = strdup(names[3]);
employ = (Employ*)malloc(sizeof(Employ));
employ->id = 4;
employ->year = 25;
employ->level = 70;
TreeMapPut(map, (void*)key, (void*)employ);


/* Retrieve the value with the designated key. */
employ = (Employ*)TreeMapGet(map, (void*)names[0]);
assert(employ != NULL);
assert(employ->id == 1);
assert(employ->year == 25);
assert(employ->level == 100);

/* Iterate through the map. */
Pair* ptr_pair;
TreeMapFirst(map);
int first = 0, second = 1;
while ((ptr_pair = TreeMapNext(map)) != NULL) {
char* name = (char*)ptr_pair->key;
employ = (Employ*)ptr_pair->value;
assert(strcmp(name, names[first]) == 0);
assert(employ->id == second);
++first;
++second;
}

TreeMapFirst(map);
first = 3;
second = 4;
while ((ptr_pair = TreeMapReverseNext(map)) != NULL) {
char* name = (char*)ptr_pair->key;
employ = (Employ*)ptr_pair->value;
assert(strcmp(name, names[first]) == 0);
assert(employ->id == second);
--first;
--second;
}

/* Remove the key value pair with the designated key. */
TreeMapRemove(map, (void*)names[1]);

/* Check the map keys. */
assert(TreeMapFind(map, (void*)names[0]) == true);
assert(TreeMapFind(map, (void*)names[1]) == false);
assert(TreeMapFind(map, (void*)names[2]) == true);
assert(TreeMapFind(map, (void*)names[3]) == true);

/* Check the pair count in the map. */
unsigned size = TreeMapSize(map);
assert(size == 3);

/* We should deinitialize the container after all the relevant operations. */
TreeMapDeinit(map);
}

int main()
{
ManipulateNumerics();
ManipulateTexts();
return 0;
}

19 changes: 18 additions & 1 deletion src/tree_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,9 @@ void _TreeMapDeinit(TreeMapData* data)
if (data->root_ == null)
return;

TreeMapCleanKey func_clean_key = data->func_clean_key_;
TreeMapCleanValue func_clean_val = data->func_clean_val_;

char direct = DOWN_LEFT;
TreeNode* curr = data->root_;
while (direct != STOP) {
Expand All @@ -621,6 +624,11 @@ void _TreeMapDeinit(TreeMapData* data)
direct = STOP;
else
direct = (temp == curr->left_)? UP_LEFT : UP_RIGHT;

if (func_clean_key)
func_clean_key(temp->pair_.key);
if (func_clean_val)
func_clean_val(temp->pair_.value);
free(temp);
continue;
}
Expand All @@ -638,6 +646,11 @@ void _TreeMapDeinit(TreeMapData* data)
direct = STOP;
else
direct = (temp == curr->left_)? UP_LEFT : UP_RIGHT;

if (func_clean_key)
func_clean_key(temp->pair_.key);
if (func_clean_val)
func_clean_val(temp->pair_.value);
free(temp);
continue;
}
Expand All @@ -648,8 +661,12 @@ void _TreeMapDeinit(TreeMapData* data)
direct = STOP;
else
direct = (temp == curr->left_)? UP_LEFT : UP_RIGHT;

if (func_clean_key)
func_clean_key(temp->pair_.key);
if (func_clean_val)
func_clean_val(temp->pair_.value);
free(temp);
continue;
}

return;
Expand Down
136 changes: 136 additions & 0 deletions test/unit_tree_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,124 @@ void TestReverseIterate()
TreeMapDeinit(map);
}

void TestPutDupText()
{
char buf[SIZE_TNY_TEST];
char* keys[SIZE_TNY_TEST];
TreeMap* map = TreeMapInit();
map->set_compare(map, CompareKey);
map->set_clean_key(map, CleanKey);
map->set_clean_value(map, CleanValue);

int i;
for (i = 0 ; i < SIZE_TNY_TEST ; ++i) {
snprintf(buf, SIZE_TNY_TEST, "key -> %d", i);
keys[i] = strdup(buf);
Employ* employ = (Employ*)malloc(sizeof(Employ));
employ->year = i;
employ->level = i;
employ->id = i;
map->put(map, (void*)keys[i], (void*)employ);
}

/* Insert the new key value pairs with the same key set. */
for (i = 0 ; i < SIZE_TNY_TEST ; ++i) {
snprintf(buf, SIZE_TNY_TEST, "key -> %d", i);
keys[i] = strdup(buf);
Employ* employ = (Employ*)malloc(sizeof(Employ));
employ->year = SIZE_TNY_TEST - i;
employ->level = SIZE_TNY_TEST - i;
employ->id = SIZE_TNY_TEST - i;
CU_ASSERT(map->put(map, (void*)keys[i], (void*)employ) == true);
}

/* Now the values of the existing pairs should be replaced. */
for (i = 0 ; i < SIZE_TNY_TEST ; ++i) {
Employ* employ = map->get(map, (void*)keys[i]);
CU_ASSERT_EQUAL(SIZE_TNY_TEST - i, employ->year);
CU_ASSERT_EQUAL(SIZE_TNY_TEST - i, employ->level);
CU_ASSERT_EQUAL(SIZE_TNY_TEST - i, employ->id);
}

TreeMapDeinit(map);
}

void TestRemoveTxt()
{
char buf[SIZE_TNY_TEST];
char* keys[SIZE_TNY_TEST];
TreeMap* map = TreeMapInit();
map->set_compare(map, CompareKey);
map->set_clean_key(map, CleanKey);
map->set_clean_value(map, CleanValue);

int i;
for (i = 0 ; i < SIZE_TNY_TEST ; ++i) {
snprintf(buf, SIZE_TNY_TEST, "key -> %d", i);
keys[i] = strdup(buf);
Employ* employ = (Employ*)malloc(sizeof(Employ));
employ->year = i;
employ->level = i;
employ->id = i;
map->put(map, (void*)keys[i], (void*)employ);
}

/* Remove the first half of the key value pairs. */
for (i = 0 ; i < SIZE_TNY_TEST >> 1 ; ++i)
CU_ASSERT(map->remove(map, (void*)keys[i]) == true);

/* Querying for the keys that are already removed should fail. */
for (i = 0 ; i < SIZE_TNY_TEST >> 1 ; ++i) {
snprintf(buf, SIZE_TNY_TEST, "key -> %d", i);
CU_ASSERT(map->remove(map, (void*)buf) == false);
CU_ASSERT(map->find(map, (void*)buf) == false);
}

/* Querying for the keys that still exist should success. */
for (i = SIZE_TNY_TEST >> 1 ; i < SIZE_TNY_TEST ; ++i)
CU_ASSERT(map->find(map, (void*)keys[i]) == true);

TreeMapDeinit(map);
}

void TestBulkTxt()
{
char buf[SIZE_MID_TEST];
char* keys[SIZE_MID_TEST];
TreeMap* map = TreeMapInit();
map->set_compare(map, CompareKey);
map->set_clean_key(map, CleanKey);
map->set_clean_value(map, CleanValue);

int i;
for (i = 0 ; i < SIZE_MID_TEST ; ++i) {
snprintf(buf, SIZE_MID_TEST, "key -> %d", i);
keys[i] = strdup(buf);
Employ* employ = (Employ*)malloc(sizeof(Employ));
employ->year = i;
employ->level = i;
employ->id = i;
map->put(map, (void*)keys[i], (void*)employ);
}

/* Remove the first half of the key value pairs. */
for (i = 0 ; i < SIZE_MID_TEST >> 1 ; ++i)
CU_ASSERT(map->remove(map, (void*)keys[i]) == true);

/* Querying for the keys that are already removed should fail. */
for (i = 0 ; i < SIZE_MID_TEST >> 1 ; ++i) {
snprintf(buf, SIZE_MID_TEST, "key -> %d", i);
CU_ASSERT(map->remove(map, (void*)buf) == false);
CU_ASSERT(map->find(map, (void*)buf) == false);
}

/* Querying for the keys that still exist should success. */
for (i = SIZE_MID_TEST >> 1 ; i < SIZE_MID_TEST ; ++i)
CU_ASSERT(map->find(map, (void*)keys[i]) == true);

TreeMapDeinit(map);
}


/*-----------------------------------------------------------------------------*
* The driver for TreeMap unit test *
Expand Down Expand Up @@ -418,6 +536,24 @@ bool AddSuite()
if (!unit)
return false;
}
{
/* Test its robustness to maintain complex data types and large data set. */
CU_pSuite suite = CU_add_suite("Complex Data Maintenance", NULL, NULL);
if (!suite)
return false;

CU_pTest unit = CU_add_test(suite, "Pair Replacement", TestPutDupText);
if (!unit)
return false;

unit = CU_add_test(suite, "Text Remove and Garbage Collection", TestRemoveTxt);
if (!unit)
return false;

unit = CU_add_test(suite, "Bulk Text Maintenance", TestBulkTxt);
if (!unit)
return false;
}

return true;
}
Expand Down

0 comments on commit 72a0611

Please sign in to comment.