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>&lt;WINDOWS&gt;\\media\\chord.wav</ErrorSoundPath>\
+				<FinishedSoundPath>&lt;WINDOWS&gt;\\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>&lt;WINDOWS&gt;\\FirstPath</Path>\
+				<Name>FirstName</Name>\
+			</Object>\
+			<Object>\
+				<Path>&lt;WINDOWS&gt;\\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>&lt;WINDOWS&gt;\\media\\chord.wav</ErrorSoundPath>\
-				<FinishedSoundPath>&lt;WINDOWS&gt;\\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>&lt;WINDOWS&gt;\\FirstPath</Path>\
-				<Name>FirstName</Name>\
-			</Object>\
-			<Object>\
-				<Path>&lt;WINDOWS&gt;\\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>!@#$%^&amp;*()[]\\/&lt;&gt;,.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>!@#$%^&amp;*()</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>&lt;WINDOWS&gt;\\FirstPath</Path></Object><Object><Name>SecondName</Name><Path>&lt;WINDOWS&gt;\\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>&lt;WINDOWS&gt;\\media\\chord.wav</ErrorSoundPath>\
+<FinishedSoundPath>&lt;WINDOWS&gt;\\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>&lt;WINDOWS&gt;\\FirstPath</Path></Object>\
+<Object><Name>SecondName</Name><Path>&lt;WINDOWS&gt;\\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);
+}