/* Test-ZKVTree.cpp Author: James Russell Purpose : Unit tests for ZKVTree Changelog : 12/18/2011 - Removed dependency on ZString (crertel) 2/20/2011 - Created (jcrussell) */ #include "ZUnitTest.hpp" #include #include #include static const char* test_Put_Add_Begin_End(); static const char* test_Find_Iterator(); static const char* test_Get(); static const char* test_Erase_Clear(); static const char* test_Find(); static const char* test_Merge(); static const char* test_EmptyKey(); static const char* test_NestedSubscript(); static const char* test_Operators(); //List of unit tests ZUnitTest ZKVTreeUnitTests[] = { { "ZKVTree: Put, Add, Begin, End", test_Put_Add_Begin_End }, { "ZKVTree: Find, Iterator", test_Find_Iterator }, { "ZKVTree: Get", test_Get }, { "ZKVTree: Erase, Clear", test_Erase_Clear }, { "ZKVTree: Merge", test_Merge }, { "ZKVTree: Empty Key", test_EmptyKey }, { "ZKVTree: Nested Subscript", test_NestedSubscript }, { "ZKVTree: Operators", test_Operators }, }; DECLARE_ZTESTBLOCK(ZKVTree); /*************************************************************************/ static const char* test_Put_Add_Begin_End() { ZKVTree tree1; ZKVTree tree2; // adding out of order to test the insert order tree1.Put("a", "1"); tree1.Put("b", "4"); tree1.Put("a[1]", "2"); tree1.Put("a[2]", "3"); tree1.Put("A", "5"); tree1.Put("A.b", "6"); tree1.Put("A.c", "8"); tree1.Put("A.d", "9"); tree1.Put("A.b[1]", "7"); tree1.Put("A.B", "10"); tree1.Put("A.B.c[0]", "11"); tree1.Put("A.B.c[1]", "12"); tree1.Put("A.B[1]", "13"); tree1.Put("A.B[1].c", "14"); tree1.Put("A.B[1].d", "15"); tree1.Put("B", "16"); tree1.Put("B.c", "17"); tree1.Put("B.d", "18"); size_t count = 1; for (ZKVTree::Iterator itr = tree1.Begin(); itr != tree1.End(); ++itr) { //This is just to inspect the order of values iterated ZString name = itr.GetName(); ZString val = itr.GetValue(); TASSERT(ZStringAlgo::NumericInt(val) == (int)count, "ZRegistry::Iterator visited nodes in incorrect order!"); count++; } //This will build the registry as described at the top of ZRegistry.hpp tree2.Put("A", "0"); tree2.Add("A", "B", "8"); tree2.Add("A.B", "c", "16"); tree2.Add("A.B", "c", "32"); tree2.Add("A.B", "", "100"); tree2.Add("A.B", "", "200"); tree2.Add("A", "B", "8"); tree2.Add("A.B[1]", "c", "64"); tree2.Add("A.B[1]", "d", "128"); tree2.Add("A.B[1]", "", "10"); tree2.Add("A.B[1]", "", "20"); tree2.Add("A", "b", "5"); tree2.Add("A", "b", "10"); tree2.Add("A", "c", "15"); tree2.Add("A", "d", "20"); tree2.Put("B", "8"); tree2.Add("B", "c", "50"); tree2.Add("B", "d", "100"); tree2.Add("a", "1"); tree2.Add("a", "2"); tree2.Add("a", "3"); tree2.Put("b", "4"); //Test using get on each of those TASSERT(tree2.Get("a") == "1", "GetValue() failed to return correct value for path 'a'!"); TASSERT(tree2.Get("a[1]") == "2", "GetValue() failed to return correct value for path 'a[1]'!"); TASSERT(tree2.Get("a[2]") == "3", "GetValue() failed to return correct value for path 'a[2]'!"); TASSERT(tree2.Get("b") == "4", "GetValue() failed to return correct value for path 'b'!"); TASSERT(tree2.Get("A.b") == "5", "GetValue() failed to return correct value for path 'A.b'!"); TASSERT(tree2.Get("A.b[1]") == "10", "GetValue() failed to return correct value for path 'A.b[1]'!"); TASSERT(tree2.Get("A.c") == "15", "GetValue() failed to return correct value for path 'A.c'!"); TASSERT(tree2.Get("A.d") == "20", "GetValue() failed to return correct value for path 'A.d'!"); TASSERT(tree2.Get("B.c") == "50", "GetValue() faield to return correct value for path 'B.c'!"); TASSERT(tree2.Get("B.d") == "100", "GetValue() failed to return correct value for path 'B.d'!"); TASSERT(tree2.Get("A.B.c") == "16", "GetValue() failed to return correct value for path 'A.B.c'!"); TASSERT(tree2.Get("A.B.c[1]") == "32", "GetValue() failed to return correct value for path 'A.B.c[1]'!"); TASSERT(tree2.Get("A.B[1].c") == "64", "GetValue() failed to return corrrect value for path 'A.B[1].c'!"); TASSERT(tree2.Get("A.B[1].d") == "128", "GetValue() failed to return correct value for path 'A.B[1].d'!"); return ZTEST_SUCCESS; } /*************************************************************************/ static const char* test_Find_Iterator() { ZKVTree tree; tree.Put("a", "1"); tree.Put("b", "4"); tree.Put("a[1]", "2"); tree.Put("a[2]", "3"); tree.Put("A", "5"); tree.Put("A.b", "6"); tree.Put("A.c", "8"); tree.Put("A.d", "9"); tree.Put("A.b[1]", "7"); tree.Put("A.B", "10"); tree.Put("A.B.c[0]", "11"); tree.Put("A.B.c[1]", "12"); tree.Put("A.B[1]", "13"); tree.Put("A.B[1].c", "14"); tree.Put("A.B[1].d", "15"); tree.Put("B", "16"); tree.Put("B.c", "17"); tree.Put("B.d", "18"); ZKVTree::Iterator itr = tree.Find("A.B"); TASSERT(itr.GetName() == "B", "GetName() failed after ZKVTree::Find('A.B')!"); TASSERT(itr.GetValue() == "10", "GetValue() failed after ZKVTree::Find('A.B')!"); itr.NextSibling(); TASSERT(itr.GetName() == "B", "GetName() failed after Iterator::NextSibling()!"); TASSERT(itr.GetValue() == "13", "GetName() failed after Iterator::NextSibling()!"); itr.Child(1); TASSERT(itr.GetName() == "d", "GetName() failed after Iterator::Child()!"); TASSERT(itr.GetValue() == "15", "GetValue() failed after Iterator::Child()!"); itr.PrevSibling(); TASSERT(itr.GetName() == "c", "GetName() failed after Iterator::PrevSibling()!"); TASSERT(itr.GetValue() == "14", "GetValue() failed after Iterator::PrevSibling()!"); itr.Parent(); TASSERT(itr.GetName() == "B", "GetName() failed after Iterator::NextSibling()!"); TASSERT(itr.GetValue() == "13", "GetName() failed after Iterator::NextSibling()!"); TASSERT(itr.GetSiblingCount() == 6, "GetSiblingCount() failed on node 'A.B[1]'!"); TASSERT(itr.GetChildCount() == 2, "GetChildCount() failed on node 'A.B[1]'"); ZKVTree::Iterator child_itr = itr.ChildItr(0); ZKVTree::Iterator sibling_itr = itr.SiblingItr(1); TASSERT(child_itr.GetName() == "c", "GetName() failed after Iterator::GetChild(0)!"); TASSERT(child_itr.GetValue() == "14", "GetValue() failed after Iterator::GetChild(1)!"); TASSERT(sibling_itr.GetName() == "b", "GetName() failed after GetSibling(1)!"); TASSERT(sibling_itr.GetValue() == "7", "GetValue() failed after GetSibling(1)!"); child_itr = tree.Find(itr, "d"); TASSERT(child_itr.GetName() == "d", "GetName() failed after Find(itr, 'd')!"); TASSERT(child_itr.GetValue() == "15", "GetValue() failed after Find(itr, 'd')!"); return ZTEST_SUCCESS; } /*************************************************************************/ static const char* test_Get() { ZKVTree tree; TASSERT(tree.Put("a", "1") != tree.End(), "PutValue() failed on a valid path 'a'!"); TASSERT(tree.Put("a[1]", "2") != tree.End(), "PutValue() failed on a valid path 'a[1]'!"); TASSERT(tree.Put("A.b", "5") != tree.End(), "PutValue failed on a valid path 'A.b'!"); TASSERT(tree.Put("A.b[1]", "10") != tree.End(), "PutValue failed on a valid path 'A.b[1]'!"); ZString val; val = tree.Get("a"); TASSERT(val == "1", "GetValue() on the path 'a' returned an incorrect value!"); val = tree.Get("a[1]"); TASSERT(val == "2", "GetValue() on the path 'a[1]' returned an incorrect value!"); val = tree.Get("A.b"); TASSERT(val == "5", "GetValue() on the path 'A.b' returned an incorrect value!"); val = tree.Get("A.b[1]"); TASSERT(val == "10", "GetValue() on the path 'A.b[1]' returned an incorrect value!"); tree.Put("a", "3"); val = tree.Get("a"); TASSERT(val == "3", "GetValue() on the path 'a' returned an incorrect value after overwrite!"); return ZTEST_SUCCESS; } /*************************************************************************/ static const char* test_Erase_Clear() { ZKVTree tree; tree.Put("a", "1"); tree.Put("b", "4"); tree.Put("a[1]", "2"); tree.Put("a[2]", "3"); tree.Put("A", "5"); tree.Put("A.b", "6"); tree.Put("A.c", "8"); tree.Put("A.d", "9"); tree.Put("A.b[1]", "7"); tree.Put("A.B", "10"); tree.Put("A.B.c[0]", "11"); tree.Put("A.B.c[1]", "12"); tree.Put("A.B[1]", "13"); tree.Put("A.B[1].c", "14"); tree.Put("A.B[1].d", "15"); tree.Put("B", "16"); tree.Put("B.c", "17"); tree.Put("B.d", "18"); tree.Erase("A.B[1]"); TASSERT(tree.Find("A.B") != tree.End(), "Find('A.B') returns invalid iterator after Erase('A.B[1]')!"); TASSERT(tree.Find("A.B[1]") == tree.End(), "Find('A.B[1]') returns valid iterator after Erase('A.B[1]')!"); TASSERT(tree.Find("A.B[1].c") == tree.End(), "Find('A.B[1].c') returns valid iterator after Erase('A.B[1]')!"); tree.Put("A.B[1]", "derp"); TASSERT(tree.Find("A.B[1]").GetValue() == "derp", "Find('A.B[1]') returns invalid iterator after Erase / Put!"); tree.Clear(); ZKVTree::Iterator itr = tree.Begin(); TASSERT(itr == tree.End(), "Clear failed to erase values from the tree!"); TASSERT(tree.Find("B") == tree.End(), "Find('B') returns valid iterator after Clear()!"); TASSERT(tree.Find("B.c") == tree.End(), "Find('B.c') returns valid iterator after Clear()!"); return ZTEST_SUCCESS; } /*************************************************************************/ static const char* test_Merge() { ZKVTree tree1; ZKVTree tree2; ZKVTree tree3; tree1.Add("a", "10"); tree1.Add("b", "40"); tree1.Add("a", "20"); tree1.Add("a", "30"); tree2.Add("a", "10"); tree2.Add("b", "40"); tree2.Add("a", "20"); tree2.Add("a", "30"); tree3.Put("a", "1"); tree3.Put("b", "4"); tree3.Put("a[1]", "2"); tree3.Put("a[2]", "3"); tree3.Put("A", "5"); tree3.Put("A.b", "6"); tree3.Put("A.c", "8"); tree3.Put("A.d", "9"); tree3.Put("A.b[1]", "7"); tree3.Put("A.B", "10"); tree3.Put("A.B.c[0]", "11"); tree3.Put("A.B.c[1]", "12"); tree3.Put("A.B[1]", "13"); tree3.Put("A.B[1].c", "14"); tree3.Put("A.B[1].d", "15"); tree3.Put("B", "16"); tree3.Put("B.c", "17"); tree3.Put("B.d", "18"); tree1.Merge(tree3, false); tree2.Merge(tree3, true); TASSERT(tree1.Get("a") == "10", "Get('a') returned invalid value after Merge(false)!"); TASSERT(tree1.Get("b") == "40", "Get('b') returned invalid value after Merge(false)!"); TASSERT(tree1.Get("a[1]") == "20", "Get('a[1]') returned invalid value after Merge(false)!"); TASSERT(tree1.Get("a[2]") == "30", "Get('a[2]') returned invalid value after Merge(false)!"); TASSERT(tree2.Get("a") == "1", "Get('a') returned invalid value after Merge(true)!"); TASSERT(tree2.Get("b") == "4", "Get('b') returned invalid value after Merge(true)!"); TASSERT(tree2.Get("a[1]") == "2", "Get('a[1]') returned invalid value after Merge(true)!"); TASSERT(tree2.Get("a[2]") == "3", "Get('a[2]') returned invalid value after Merge(true)!"); TASSERT(tree1.Get("A.b") == "6", "Get('A.b') returned invalid value after Merge(false)!"); TASSERT(tree2.Get("A.b") == "6", "Get('A.b') returned invalid value after Merge(true)!"); TASSERT(tree1.Get("A.B[1].c") == "14", "Get('A.B[1].c') returned invalid value after Merge(false)!"); TASSERT(tree2.Get("A.B[1].c") == "14", "Get('A.B[1].c') returned invalid value after Merge(true)!"); return ZTEST_SUCCESS; } /*************************************************************************/ static const char* test_EmptyKey() { ZKVTree tree; tree.Add("", "1"); tree.Add("", "2"); tree.Add("", "3"); tree.Add("", "4"); TASSERT(tree.Get("") == "1", "First unnamed key has invalid value!"); TASSERT(tree.Get("[1]") == "2", "Second unnamed key has invalid value!"); TASSERT(tree.Get("[2]") == "3", "Third unnamed key has invalid value!"); TASSERT(tree.Get("[3]") == "4", "Fourth unnamed key has invalid value!"); tree.Add("", "", "11"); TASSERT(tree.Get("[0].[0]") == "11", "First child of first unnamed key has invalid value!"); TASSERT(tree.Get(".") == "11", "Invalid path conversion on first child of first unnamed key!"); return ZTEST_SUCCESS; } /*************************************************************************/ static const char* test_NestedSubscript() { ZKVTree tree; tree.Put("A", "A1"); tree.Put("A[0][0]", "A11"); tree.Add("A", "", "A12"); TASSERT(tree.Get("A[0]") == "A1", "Key A[0] has invalid value!"); TASSERT(tree.Get("A[0][0]") == "A11", "Key A[0][0] has invalid value!"); TASSERT(tree.Get("A[0][1]") == "A12", "Key A[0][1] has invalid value!"); return ZTEST_SUCCESS; } /*************************************************************************/ static const char* test_Operators() { ZKVTree tree1; ZKVTree tree2; tree1.Put("A", "A1"); tree1.Put("A[0][0]", "A11"); tree1.Add("A", "", "A12"); tree2 = tree1; TASSERT(tree2.Get("A[0]") == "A1", "Key A[0] has invalid value!"); TASSERT(tree2.Get("A[0][0]") == "A11", "Key A[0][0] has invalid value!"); TASSERT(tree2.Get("A[0][1]") == "A12", "Key A[0][1] has invalid value!"); return ZTEST_SUCCESS; }