Index: src/libchcore/ConfigNodeContainer.cpp =================================================================== diff -u -r5324d0ca7af614cb066df1f121a7a338c4f7d7ed -rf354b6f39d2a0425c1827906c84cbc1377b8c8d3 --- src/libchcore/ConfigNodeContainer.cpp (.../ConfigNodeContainer.cpp) (revision 5324d0ca7af614cb066df1f121a7a338c4f7d7ed) +++ src/libchcore/ConfigNodeContainer.cpp (.../ConfigNodeContainer.cpp) (revision f354b6f39d2a0425c1827906c84cbc1377b8c8d3) @@ -204,23 +204,51 @@ } } + namespace + { + struct PredIsPrefixedWith + { + private: + PredIsPrefixedWith& operator=(const PredIsPrefixedWith&); + PredIsPrefixedWith(); + + public: + PredIsPrefixedWith(PCTSTR pszPrefix, TRemovedObjects& rRemovedObjects) : m_strPrefix(pszPrefix), m_rRemovedObjects(rRemovedObjects) {} + PredIsPrefixedWith(const PredIsPrefixedWith& rSrc) : m_strPrefix(rSrc.m_strPrefix), m_rRemovedObjects(rSrc.m_rRemovedObjects) {} + + bool operator()(const ConfigNode& rNode) const + { + if(rNode.m_strNodeName.Get().StartsWith(m_strPrefix.c_str())) + { + m_rRemovedObjects.Add(rNode.m_stObjectID); + return true; + } + return false; + } + + TString m_strPrefix; + TRemovedObjects& m_rRemovedObjects; + }; + } + void ConfigNodeContainer::DeleteNode(PCTSTR pszPropName) { boost::unique_lock<boost::shared_mutex> lock(m_lock); - std::pair<ConfigNodeContainer::NodeContainer::const_iterator, ConfigNodeContainer::NodeContainer::const_iterator> pairFnd - = m_mic.equal_range(boost::make_tuple(pszPropName)); + PredIsPrefixedWith pred(pszPropName, m_setRemovedObjects); - if(pairFnd.first == m_mic.end()) - return; - - ConfigNodeContainer::NodeContainer::const_iterator iter = pairFnd.first; - while(iter != m_mic.end() && iter != pairFnd.second) + bool bWasFoundBefore = false; + ConfigNodeContainer::NodeContainer::iterator iterCurrent = m_mic.begin(); + while(iterCurrent != m_mic.end()) { - m_setRemovedObjects.Add(iter->m_stObjectID); + // NOTE: PredIsPrefixedWith registers the object IDs as deleted in m_setRemovedObjects (for change management purposes) + if(pred(*iterCurrent)) + iterCurrent = m_mic.erase(iterCurrent); + else if(bWasFoundBefore) + break; // as the elements are sorted, when we matched something earlier and now we don't - it means that there are no more matching elements + else + ++iterCurrent; } - - m_mic.erase(pairFnd.first, pairFnd.second); } bool ConfigNodeContainer::ExtractNodes(PCTSTR pszNode, ConfigNodeContainer& tNewContainer) const @@ -272,6 +300,8 @@ size_t stPos = strName.Find(_T("]")); if(stPos == std::numeric_limits<size_t>::max()) THROW_CORE_EXCEPTION(eErr_InvalidData); + if(strName.GetAt(stPos + 1) != _T('.')) + THROW_CORE_EXCEPTION(eErr_InvalidData); size_t stNodeIndex = boost::lexical_cast<size_t>(strName.Left(stPos)); if(stNodeIndex != stLastIndex) @@ -282,7 +312,8 @@ stLastIndex = stNodeIndex; } - pCurrentContainer->m_mic.insert(ConfigNode(++pCurrentContainer->m_stLastObjectID, strName.Mid(stPos + 1), iter->GetOrder(), iter->m_strValue)); + strName.Delete(0, stPos + 2); // skip "]." at the beginning + pCurrentContainer->m_mic.insert(ConfigNode(++pCurrentContainer->m_stLastObjectID, strName, iter->GetOrder(), iter->m_strValue)); } } @@ -499,6 +530,10 @@ strGroupNode = strNodeName.Left(stBracketPos); TString strSubnodeName = strNodeName.Mid(stSecondBracketPos + 1); + wchar_t chDot = 0; + if(!strSubnodeName.GetAt(0, chDot) || chDot != L'.') + THROW_CORE_EXCEPTION(eErr_InvalidData); + strSubnodeName.Delete(0, 1); size_t stBracketID = boost::lexical_cast<size_t>(strNodeName.Mid(stBracketPos + 1, stSecondBracketPos - stBracketPos - 1)); if(stBracketID != stLastBracketID) @@ -513,6 +548,7 @@ // same ID - add new element to existing property tree node treeSubnodes.put(strSubnodeName.c_str(), iter->m_strValue.Get()); + stLastBracketID = stBracketID; } else { Index: src/libchcore/Tests/TestsTConfig.cpp =================================================================== diff -u -r5324d0ca7af614cb066df1f121a7a338c4f7d7ed -rf354b6f39d2a0425c1827906c84cbc1377b8c8d3 --- src/libchcore/Tests/TestsTConfig.cpp (.../TestsTConfig.cpp) (revision 5324d0ca7af614cb066df1f121a7a338c4f7d7ed) +++ src/libchcore/Tests/TestsTConfig.cpp (.../TestsTConfig.cpp) (revision f354b6f39d2a0425c1827906c84cbc1377b8c8d3) @@ -4,6 +4,8 @@ #include <fstream> #include <locale> #include "../TConfig.h" +#include "../TStringArray.h" +#include "../TConfigArray.h" using namespace chcore; @@ -77,6 +79,49 @@ std::wstring m_strTempFilePath; }; +class InitializedConfigFixture : public ::testing::Test +{ +protected: + virtual void SetUp() + { + m_strInputXmlString = + L"<?xml version=\"1.0\" encoding=\"utf-8\"?>\ +<CHConfig>\ + <Core>\ + <AutosaveInterval>30000</AutosaveInterval>\ + <Notifications>\ + <Sounds>\ + <Enable>true</Enable>\ + <ErrorSoundPath><WINDOWS>\\media\\chord.wav</ErrorSoundPath>\ + <FinishedSoundPath><WINDOWS>\\media\\ding.wav</FinishedSoundPath>\ + </Sounds>\ + <PathList>\ + <Path>c:\\Windows\\System32</Path>\ + <Path>d:\\Movies</Path>\ + <Path>x:\\Music</Path>\ + <Path>s:\\projects\\ch-rw</Path>\ + </PathList>\ + </Notifications>\ + <CompositeObjects>\ + <Object>\ + <Path><WINDOWS>\\FirstPath</Path>\ + <Name>FirstName</Name>\ + </Object>\ + <Object>\ + <Path><WINDOWS>\\SecondPath</Path>\ + <Name>SecondName</Name>\ + </Object>\ + </CompositeObjects>\ + </Core>\ +</CHConfig>"; + + m_cfg.ReadFromString(m_strInputXmlString); + } + + TString m_strInputXmlString; + TConfig m_cfg; +}; + /////////////////////////////////////////////////////////////////////////// // read from/write to file @@ -121,45 +166,11 @@ /////////////////////////////////////////////////////////////////////////// // store in/load from string -TEST(TConfigTests, ReadFromString) +TEST_F(InitializedConfigFixture, ReadFromString) { - std::wstring wstrData = - L"<?xml version=\"1.0\" encoding=\"utf-8\"?>\ -<CHConfig>\ - <Core>\ - <AutosaveInterval>30000</AutosaveInterval>\ - <Notifications>\ - <Sounds>\ - <Enable>true</Enable>\ - <ErrorSoundPath><WINDOWS>\\media\\chord.wav</ErrorSoundPath>\ - <FinishedSoundPath><WINDOWS>\\media\\ding.wav</FinishedSoundPath>\ - </Sounds>\ - <PathList>\ - <Path>c:\\Windows\\System32</Path>\ - <Path>d:\\Movies</Path>\ - <Path>x:\\Music</Path>\ - <Path>s:\\projects\\ch-rw</Path>\ - </PathList>\ - </Notifications>\ - <CompositeObjects>\ - <Object>\ - <Path><WINDOWS>\\FirstPath</Path>\ - <Name>FirstName</Name>\ - </Object>\ - <Object>\ - <Path><WINDOWS>\\SecondPath</Path>\ - <Name>SecondName</Name>\ - </Object>\ - </CompositeObjects>\ - </Core>\ -</CHConfig>"; - - TConfig cfg; - cfg.ReadFromString(TString(wstrData.c_str())); - - EXPECT_EQ(true, cfg.GetBool(_T("CHConfig.Core.Notifications.Sounds.Enable"), false)); - EXPECT_EQ(30000, cfg.GetInt(_T("CHConfig.Core.AutosaveInterval"), 0)); - EXPECT_EQ(TString(_T("<WINDOWS>\\media\\ding.wav")), cfg.GetString(_T("CHConfig.Core.Notifications.Sounds.FinishedSoundPath"), _T(""))); + EXPECT_EQ(true, m_cfg.GetBool(_T("CHConfig.Core.Notifications.Sounds.Enable"), false)); + EXPECT_EQ(30000, m_cfg.GetInt(_T("CHConfig.Core.AutosaveInterval"), 0)); + EXPECT_EQ(TString(_T("<WINDOWS>\\media\\ding.wav")), m_cfg.GetString(_T("CHConfig.Core.Notifications.Sounds.FinishedSoundPath"), _T(""))); } TEST(TConfigTests, WriteToString) @@ -220,80 +231,424 @@ EXPECT_EQ(strXmlData, strWriteXmlData); } +/////////////////////////////////////////////////////////////////////////// TEST(TConfigTests, GetSetInt) { TConfig cfg; // store data in config - cfg.SetValue(_T("Root.Node.Value1"), 1489); - cfg.SetValue(_T("Root.Node.Value2"), -12987); + cfg.SetValue(_T("Root.Node.Value1"), 2147483647); + cfg.SetValue(_T("Root.Node.Value2"), (-2147483647 - 1)); // check if stored successfully (typed get) - EXPECT_EQ(1489, cfg.GetInt(_T("Root.Node.Value1"))); - EXPECT_EQ(-12987, cfg.GetInt(_T("Root.Node.Value2"))); + EXPECT_EQ(2147483647, cfg.GetInt(_T("Root.Node.Value1"))); + EXPECT_EQ((-2147483647 - 1), cfg.GetInt(_T("Root.Node.Value2"))); // check if stored successfully (GetValue) int iValue = 0; cfg.GetValue(_T("Root.Node.Value1"), iValue); - EXPECT_EQ(1489, iValue); + EXPECT_EQ(2147483647, iValue); cfg.GetValue(_T("Root.Node.Value2"), iValue); - EXPECT_EQ(-12987, iValue); + EXPECT_EQ((-2147483647 - 1), iValue); } TEST(TConfigTests, GetSetIntExport) { TConfig cfg; TString strXmlData(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ -<Root><Node><Value1>1489</Value1><Value2>-12987</Value2></Node></Root>")); +<Root><Node><Value1>2147483647</Value1><Value2>-2147483648</Value2></Node></Root>")); // store in string cfg.ReadFromString(strXmlData); - EXPECT_EQ(1489, cfg.GetInt(_T("Root.Node.Value1"))); - EXPECT_EQ(-12987, cfg.GetInt(_T("Root.Node.Value2"))); + EXPECT_EQ(2147483647, cfg.GetInt(_T("Root.Node.Value1"))); + EXPECT_EQ((-2147483647 - 1), cfg.GetInt(_T("Root.Node.Value2"))); TString strWriteXmlData; cfg.WriteToString(strWriteXmlData); EXPECT_EQ(strXmlData, strWriteXmlData); } +/////////////////////////////////////////////////////////////////////////// TEST(TConfigTests, GetSetUInt) { TConfig cfg; // store data in config cfg.SetValue(_T("Root.Node.Value1"), (unsigned int)1489); - cfg.SetValue(_T("Root.Node.Value2"), (unsigned int)12987); + cfg.SetValue(_T("Root.Node.Value2"), (unsigned int)4294967295); // check if stored successfully (typed get) EXPECT_EQ(1489, cfg.GetUInt(_T("Root.Node.Value1"))); - EXPECT_EQ(12987, cfg.GetUInt(_T("Root.Node.Value2"))); + EXPECT_EQ(4294967295, cfg.GetUInt(_T("Root.Node.Value2"))); // check if stored successfully (GetValue) - int value = 0; + unsigned int value = 0; cfg.GetValue(_T("Root.Node.Value1"), value); EXPECT_EQ(1489, value); cfg.GetValue(_T("Root.Node.Value2"), value); - EXPECT_EQ(12987, value); + EXPECT_EQ(4294967295, value); } TEST(TConfigTests, GetSetUIntExport) { TConfig cfg; TString strXmlData(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ -<Root><Node><Value1>1489</Value1><Value2>12987</Value2></Node></Root>")); +<Root><Node><Value1>1489</Value1><Value2>4294967295</Value2></Node></Root>")); // store in string cfg.ReadFromString(strXmlData); - EXPECT_EQ(1489, cfg.GetInt(_T("Root.Node.Value1"))); - EXPECT_EQ(12987, cfg.GetInt(_T("Root.Node.Value2"))); + EXPECT_EQ(1489, cfg.GetUInt(_T("Root.Node.Value1"))); + EXPECT_EQ(4294967295, cfg.GetUInt(_T("Root.Node.Value2"))); TString strWriteXmlData; cfg.WriteToString(strWriteXmlData); EXPECT_EQ(strXmlData, strWriteXmlData); } + +/////////////////////////////////////////////////////////////////////////// +TEST(TConfigTests, GetSetLongLong) +{ + TConfig cfg; + + // store data in config + cfg.SetValue(_T("Root.Node.Value1"), (long long)9223372036854775807); + cfg.SetValue(_T("Root.Node.Value2"), (long long)(-9223372036854775807 - 1)); + + // check if stored successfully (typed get) + EXPECT_EQ((long long)9223372036854775807, cfg.GetLongLong(_T("Root.Node.Value1"))); + EXPECT_EQ((long long)(-9223372036854775807 - 1), cfg.GetLongLong(_T("Root.Node.Value2"))); + + // check if stored successfully (GetValue) + long long value = 0; + cfg.GetValue(_T("Root.Node.Value1"), value); + EXPECT_EQ((long long)9223372036854775807, value); + cfg.GetValue(_T("Root.Node.Value2"), value); + EXPECT_EQ((long long)(-9223372036854775807 - 1), value); +} + +TEST(TConfigTests, GetSetLongLongExport) +{ + TConfig cfg; + + TString strXmlData(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<Root><Node><Value1>9223372036854775807</Value1><Value2>-9223372036854775808</Value2></Node></Root>")); + + // store in string + cfg.ReadFromString(strXmlData); + + EXPECT_EQ((long long)9223372036854775807, cfg.GetLongLong(_T("Root.Node.Value1"))); + EXPECT_EQ((long long)(-9223372036854775807 - 1), cfg.GetLongLong(_T("Root.Node.Value2"))); + + TString strWriteXmlData; + cfg.WriteToString(strWriteXmlData); + + EXPECT_EQ(strXmlData, strWriteXmlData); +} + +/////////////////////////////////////////////////////////////////////////// +TEST(TConfigTests, GetSetULongLong) +{ + TConfig cfg; + + // store data in config + cfg.SetValue(_T("Root.Node.Value1"), (unsigned long long)1489); + cfg.SetValue(_T("Root.Node.Value2"), (unsigned long long)18446744073709551615); + + // check if stored successfully (typed get) + EXPECT_EQ((unsigned long long)1489, cfg.GetULongLong(_T("Root.Node.Value1"))); + EXPECT_EQ((unsigned long long)18446744073709551615, cfg.GetULongLong(_T("Root.Node.Value2"))); + + // check if stored successfully (GetValue) + unsigned long long value = 0; + cfg.GetValue(_T("Root.Node.Value1"), value); + EXPECT_EQ((unsigned long long)1489, value); + cfg.GetValue(_T("Root.Node.Value2"), value); + EXPECT_EQ((unsigned long long)18446744073709551615, value); +} + +TEST(TConfigTests, GetSetULongLongExport) +{ + TConfig cfg; + + TString strXmlData(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<Root><Node><Value1>1489</Value1><Value2>18446744073709551615</Value2></Node></Root>")); + + // store in string + cfg.ReadFromString(strXmlData); + + EXPECT_EQ((unsigned long long)1489, cfg.GetULongLong(_T("Root.Node.Value1"))); + EXPECT_EQ((unsigned long long)18446744073709551615, cfg.GetULongLong(_T("Root.Node.Value2"))); + + TString strWriteXmlData; + cfg.WriteToString(strWriteXmlData); + + EXPECT_EQ(strXmlData, strWriteXmlData); +} + +/////////////////////////////////////////////////////////////////////////// +TEST(TConfigTests, GetSetDouble) +{ + TConfig cfg; + + // store data in config + cfg.SetValue(_T("Root.Node.Value1"), (double)0.0); + cfg.SetValue(_T("Root.Node.Value2"), 1.7976931348623158e+308); + + // check if stored successfully (typed get) + EXPECT_DOUBLE_EQ(0.0, cfg.GetDouble(_T("Root.Node.Value1"))); + EXPECT_DOUBLE_EQ(1.7976931348623158e+308, cfg.GetDouble(_T("Root.Node.Value2"))); + + // check if stored successfully (GetValue) + double value = 0; + cfg.GetValue(_T("Root.Node.Value1"), value); + EXPECT_DOUBLE_EQ(0.0, value); + cfg.GetValue(_T("Root.Node.Value2"), value); + EXPECT_DOUBLE_EQ(1.7976931348623158e+308, value); +} + +TEST(TConfigTests, GetSetDoubleExport) +{ + TConfig cfg; + + TString strXmlData(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<Root><Node><Value1>0</Value1><Value2>1.7976931348623158e+308</Value2></Node></Root>")); + + // store in string + cfg.ReadFromString(strXmlData); + + EXPECT_DOUBLE_EQ(0.0, cfg.GetDouble(_T("Root.Node.Value1"))); + EXPECT_DOUBLE_EQ(1.7976931348623158e+308, cfg.GetDouble(_T("Root.Node.Value2"))); + + TString strWriteXmlData; + cfg.WriteToString(strWriteXmlData); + + EXPECT_EQ(strXmlData, strWriteXmlData); +} + +/////////////////////////////////////////////////////////////////////////// +TEST(TConfigTests, GetSetString) +{ + TConfig cfg; + + // store data in config + cfg.SetValue(_T("Root.Node.Value1"), _T("Some basic string")); + cfg.SetValue(_T("Root.Node.Value2"), L"!@#$%^&*()[]\\/<>,.QWERTYqwerty\x2021"); + + // check if stored successfully (typed get) + EXPECT_EQ(TString(_T("Some basic string")), cfg.GetString(_T("Root.Node.Value1"))); + EXPECT_EQ(TString(L"!@#$%^&*()[]\\/<>,.QWERTYqwerty\x2021"), cfg.GetString(_T("Root.Node.Value2"))); + + // check if stored successfully (GetValue) + TString value; + cfg.GetValue(_T("Root.Node.Value1"), value); + EXPECT_EQ(TString(_T("Some basic string")), value); + cfg.GetValue(_T("Root.Node.Value2"), value); + EXPECT_EQ(TString(L"!@#$%^&*()[]\\/<>,.QWERTYqwerty\x2021"), value); +} + +TEST(TConfigTests, GetSetStringExport) +{ + TConfig cfg; + + TString strXmlData(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<Root><Node><Value1>Some basic string</Value1><Value2>!@#$%^&*()[]\\/<>,.QWERTYqwerty\x2021</Value2></Node></Root>")); + + // store in string + cfg.ReadFromString(strXmlData); + + EXPECT_EQ(TString(_T("Some basic string")), cfg.GetString(_T("Root.Node.Value1"))); + EXPECT_EQ(TString(L"!@#$%^&*()[]\\/<>,.QWERTYqwerty\x2021"), cfg.GetString(_T("Root.Node.Value2"))); + + TString strWriteXmlData; + cfg.WriteToString(strWriteXmlData); + + EXPECT_EQ(strXmlData, strWriteXmlData); +} + +/////////////////////////////////////////////////////////////////////////// +TEST(TConfigTests, GetSetPath) +{ + TConfig cfg; + + // store data in config + cfg.SetValue(_T("Root.Node.Value1"), _T("c:\\Windows\\System32")); + cfg.SetValue(_T("Root.Node.Value2"), _T("\\\\machine\\share\\SomeFile.dat")); + + // check if stored successfully (typed get) + EXPECT_EQ(PathFromString(_T("c:\\Windows\\System32")), cfg.GetPath(_T("Root.Node.Value1"))); + EXPECT_EQ(PathFromString(_T("\\\\machine\\share\\SomeFile.dat")), cfg.GetPath(_T("Root.Node.Value2"))); + + // check if stored successfully (GetValue) + TSmartPath value; + cfg.GetValue(_T("Root.Node.Value1"), value); + EXPECT_EQ(PathFromString(_T("c:\\Windows\\System32")), value); + cfg.GetValue(_T("Root.Node.Value2"), value); + EXPECT_EQ(PathFromString(_T("\\\\machine\\share\\SomeFile.dat")), value); +} + +TEST(TConfigTests, GetSetPathExport) +{ + TConfig cfg; + + TString strXmlData(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<Root><Node><Value1>c:\\Windows\\System32</Value1><Value2>\\\\machine\\share\\SomeFile.dat</Value2></Node></Root>")); + + // store in string + cfg.ReadFromString(strXmlData); + + EXPECT_EQ(PathFromString(_T("c:\\Windows\\System32")), cfg.GetPath(_T("Root.Node.Value1"))); + EXPECT_EQ(PathFromString(_T("\\\\machine\\share\\SomeFile.dat")), cfg.GetPath(_T("Root.Node.Value2"))); + + TString strWriteXmlData; + cfg.WriteToString(strWriteXmlData); + + EXPECT_EQ(strXmlData, strWriteXmlData); +} + +/////////////////////////////////////////////////////////////////////////// +TEST(TConfigTests, GetSetStringArray) +{ + TConfig cfg; + + TStringArray arrString; + arrString.Add(_T("String1")); + arrString.Add(_T("SampleStringPath")); + arrString.Add(_T("!@#$%^&*()")); + arrString.Add(_T("")); + + // store data in config + cfg.SetValue(_T("Root.Node.Values.Node"), arrString); + + // check if stored successfully (typed get) + TStringArray arrRead; + cfg.GetValue(_T("Root.Node.Values.Node"), arrRead); + + EXPECT_EQ(arrString.GetCount(), arrRead.GetCount()); + EXPECT_EQ(arrString.GetAt(0), arrRead.GetAt(0)); + EXPECT_EQ(arrString.GetAt(1), arrRead.GetAt(1)); + EXPECT_EQ(arrString.GetAt(2), arrRead.GetAt(2)); + EXPECT_EQ(arrString.GetAt(3), arrRead.GetAt(3)); +} + +TEST_F(InitializedConfigFixture, GetSetStringArrayImport) +{ + TStringArray arrRead; + m_cfg.GetValue(_T("CHConfig.Core.Notifications.PathList.Path"), arrRead); + + EXPECT_EQ(arrRead.GetCount(), 4); + EXPECT_EQ(TString(_T("c:\\Windows\\System32")), arrRead.GetAt(0)); + EXPECT_EQ(TString(_T("d:\\Movies")), arrRead.GetAt(1)); + EXPECT_EQ(TString(_T("x:\\Music")), arrRead.GetAt(2)); + EXPECT_EQ(TString(_T("s:\\projects\\ch-rw")), arrRead.GetAt(3)); +} + +TEST(TConfigTests, GetSetStringArrayExport) +{ + TConfig cfg; + + TStringArray arrString; + arrString.Add(_T("String1")); + arrString.Add(_T("SampleStringPath")); + arrString.Add(_T("!@#$%^&*()")); + arrString.Add(_T("")); + + // store data in config + cfg.SetValue(_T("Root.Node.Values.Node"), arrString); + + // store in string + TString wstrData; + cfg.WriteToString(wstrData); + + EXPECT_EQ(TString(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<Root><Node><Values><Node>String1</Node><Node>SampleStringPath</Node><Node>!@#$%^&*()</Node><Node/></Values></Node></Root>")), wstrData); +} + +/////////////////////////////////////////////////////////////////////////// +TEST_F(InitializedConfigFixture, CompositeObjectsReadWriteString) +{ + TString wstrWithDeletion; + m_cfg.WriteToString(wstrWithDeletion); + + EXPECT_EQ(TString(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<CHConfig><Core><AutosaveInterval>30000</AutosaveInterval>\ +<CompositeObjects><Object><Name>FirstName</Name><Path><WINDOWS>\\FirstPath</Path></Object><Object><Name>SecondName</Name><Path><WINDOWS>\\SecondPath</Path></Object></CompositeObjects>\ +<Notifications><PathList><Path>c:\\Windows\\System32</Path><Path>d:\\Movies</Path><Path>x:\\Music</Path><Path>s:\\projects\\ch-rw</Path></PathList>\ +<Sounds><Enable>true</Enable><ErrorSoundPath><WINDOWS>\\media\\chord.wav</ErrorSoundPath>\ +<FinishedSoundPath><WINDOWS>\\media\\ding.wav</FinishedSoundPath></Sounds></Notifications></Core></CHConfig>")), wstrWithDeletion); +} + +/////////////////////////////////////////////////////////////////////////// +TEST_F(InitializedConfigFixture, DeleteNodeTest) +{ + m_cfg.DeleteNode(_T("CHConfig.Core.Notifications")); + + TString wstrWithDeletion; + m_cfg.WriteToString(wstrWithDeletion); + + EXPECT_EQ(TString(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<CHConfig><Core><AutosaveInterval>30000</AutosaveInterval><CompositeObjects><Object><Name>FirstName</Name><Path><WINDOWS>\\FirstPath</Path></Object>\ +<Object><Name>SecondName</Name><Path><WINDOWS>\\SecondPath</Path></Object></CompositeObjects></Core></CHConfig>")), wstrWithDeletion); +} + +/////////////////////////////////////////////////////////////////////////// +TEST_F(InitializedConfigFixture, ExtractConfig) +{ + TConfig cfgSub; + + m_cfg.ExtractSubConfig(_T("CHConfig.Core.Notifications.Sounds"), cfgSub); + EXPECT_EQ(true, cfgSub.GetBool(_T("Enable"))); + EXPECT_EQ(TString(_T("<WINDOWS>\\media\\chord.wav")), cfgSub.GetString(_T("ErrorSoundPath"))); + EXPECT_EQ(TString(_T("<WINDOWS>\\media\\ding.wav")), cfgSub.GetString(_T("FinishedSoundPath"))); +} + +TEST_F(InitializedConfigFixture, ExtractMultipleConfigs) +{ + TConfigArray cfgSubArray; + + m_cfg.ExtractMultiSubConfigs(_T("CHConfig.Core.CompositeObjects.Object"), cfgSubArray); + + EXPECT_EQ(2, cfgSubArray.GetCount()); + + EXPECT_EQ(TString(_T("FirstName")), cfgSubArray.GetAt(0).GetString(_T("Name"))); + EXPECT_EQ(TString(_T("<WINDOWS>\\FirstPath")), cfgSubArray.GetAt(0).GetString(_T("Path"))); + EXPECT_EQ(TString(_T("SecondName")), cfgSubArray.GetAt(1).GetString(_T("Name"))); + EXPECT_EQ(TString(_T("<WINDOWS>\\SecondPath")), cfgSubArray.GetAt(1).GetString(_T("Path"))); +} + +TEST(TConfigTests, PutSubConfig) +{ + TConfig mainCfg; + + TConfig cfgSub; + cfgSub.SetValue(_T("Node1"), true); + cfgSub.SetValue(_T("NameNode"), _T("TestNode")); + + mainCfg.PutSubConfig(_T("Root.NodeSet"), cfgSub); + + EXPECT_EQ(true, mainCfg.GetBool(_T("Root.NodeSet.Node1"))); + EXPECT_EQ(TString(_T("TestNode")), mainCfg.GetString(_T("Root.NodeSet.NameNode"))); +} + +TEST(TConfigTests, AddSubConfig) +{ + TConfig mainCfg; + + TConfig cfgSub; + cfgSub.SetValue(_T("Node1"), true); + cfgSub.SetValue(_T("NameNode"), _T("TestNode")); + + mainCfg.AddSubConfig(_T("Root.NodeSet.Node"), cfgSub); + mainCfg.AddSubConfig(_T("Root.NodeSet.Node"), cfgSub); + + TString strXml; + mainCfg.WriteToString(strXml); + + EXPECT_EQ(TString(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<Root><NodeSet><Node><NameNode>TestNode</NameNode><Node1>true</Node1></Node><Node><NameNode>TestNode</NameNode><Node1>true</Node1></Node></NodeSet></Root>")), strXml); +}