Index: src/libchcore/TLocalFilesystem.cpp
===================================================================
diff -u -r548382442cbf7bed7f744b279ce3f66b54992724 -rf18d23588f370de68d37adb285dcf5e046a8d37c
--- src/libchcore/TLocalFilesystem.cpp	(.../TLocalFilesystem.cpp)	(revision 548382442cbf7bed7f744b279ce3f66b54992724)
+++ src/libchcore/TLocalFilesystem.cpp	(.../TLocalFilesystem.cpp)	(revision f18d23588f370de68d37adb285dcf5e046a8d37c)
@@ -113,12 +113,14 @@
 		return ::CreateDirectory(PrependPathExtensionIfNeeded(pathDirectory).ToString(), NULL) != FALSE;
 	else
 	{
-		std::vector<TSmartPath> vComponents;
+		TPathContainer vComponents;
 		pathDirectory.SplitPath(vComponents);
 
 		TSmartPath pathToTest;
-		BOOST_FOREACH(const TSmartPath& pathComponent, vComponents)
+		for(size_t stIndex = 0; stIndex < vComponents.GetCount(); ++stIndex)
 		{
+			const TSmartPath& pathComponent = vComponents.GetAt(stIndex);
+
 			pathToTest += pathComponent;
 			// try to create subsequent paths
 			if(!pathToTest.IsDrive() && !pathToTest.IsServerName())
Index: src/libchcore/TPath.cpp
===================================================================
diff -u -r9545b48aadb1592a5bf22ac5a227b1666d7710c6 -rf18d23588f370de68d37adb285dcf5e046a8d37c
--- src/libchcore/TPath.cpp	(.../TPath.cpp)	(revision 9545b48aadb1592a5bf22ac5a227b1666d7710c6)
+++ src/libchcore/TPath.cpp	(.../TPath.cpp)	(revision f18d23588f370de68d37adb285dcf5e046a8d37c)
@@ -35,91 +35,94 @@
 
 #define DEFAULT_PATH_SEPARATOR _T("\\")
 
-// ============================================================================
-/// TPath::TPath
-/// @date 2009/11/29
-///
-/// @brief     Constructs the TPath object.
-// ============================================================================
-TPath::TPath() :
-m_strPath(),
-m_lRefCount(1)
+namespace details
 {
-}
+	// ============================================================================
+	/// TPath::TPath
+	/// @date 2009/11/29
+	///
+	/// @brief     Constructs the TPath object.
+	// ============================================================================
+	TPath::TPath() :
+		m_strPath(),
+		m_lRefCount(1)
+	{
+	}
 
-// ============================================================================
-/// TPath::TPath
-/// @date 2009/11/29
-///
-/// @brief     Constructs the TPath object.
-// ============================================================================
-TPath::TPath(const TPath& rSrc) :
-m_strPath(rSrc.m_strPath),
-m_lRefCount(1)
-{
-}
+	// ============================================================================
+	/// TPath::TPath
+	/// @date 2009/11/29
+	///
+	/// @brief     Constructs the TPath object.
+	// ============================================================================
+	TPath::TPath(const TPath& rSrc) :
+	m_strPath(rSrc.m_strPath),
+	m_lRefCount(1)
+	{
+	}
 
-// ============================================================================
-/// TPath::~TPath
-/// @date 2009/11/29
-///
-/// @brief     Destructs the TPath object.
-// ============================================================================
-TPath::~TPath()
-{
-}
+	// ============================================================================
+	/// TPath::~TPath
+	/// @date 2009/11/29
+	///
+	/// @brief     Destructs the TPath object.
+	// ============================================================================
+	TPath::~TPath()
+	{
+	}
 
-// ============================================================================
-/// TPath::Release
-/// @date 2009/11/29
-///
-/// @brief     Releases a reference to this object. Deletes the object if no reference exists.
-/// @return    Current reference count.
-// ============================================================================
-long TPath::Release()
-{
-	if(--m_lRefCount == 0)
+	// ============================================================================
+	/// TPath::Release
+	/// @date 2009/11/29
+	///
+	/// @brief     Releases a reference to this object. Deletes the object if no reference exists.
+	/// @return    Current reference count.
+	// ============================================================================
+	long TPath::Release()
 	{
-		delete this;
-		return 0;
+		if(--m_lRefCount == 0)
+		{
+			delete this;
+			return 0;
+		}
+		return m_lRefCount;
 	}
-	return m_lRefCount;
-}
 
-// ============================================================================
-/// TPath::New
-/// @date 2009/11/29
-///
-/// @brief     Allocates a new, empty TPath object.
-/// @return    Pointer to the newly allocated object.
-// ============================================================================
-TPath* TPath::New()
-{
-	return new TPath();
-}
+	// ============================================================================
+	/// TPath::New
+	/// @date 2009/11/29
+	///
+	/// @brief     Allocates a new, empty TPath object.
+	/// @return    Pointer to the newly allocated object.
+	// ============================================================================
+	TPath* TPath::New()
+	{
+		return new TPath();
+	}
 
-// ============================================================================
-/// TPath::New
-/// @date 2010/10/07
-///
-/// @brief     Clones this object.
-/// @return    Pointer to the newly allocated object.
-// ============================================================================
-TPath* TPath::Clone()
-{
-	return new TPath(*this);
-}
+	// ============================================================================
+	/// TPath::New
+	/// @date 2010/10/07
+	///
+	/// @brief     Clones this object.
+	/// @return    Pointer to the newly allocated object.
+	// ============================================================================
+	TPath* TPath::Clone()
+	{
+		return new TPath(*this);
+	}
 
-// ============================================================================
-/// TPath::Delete
-/// @date 2009/11/29
-///
-/// @brief     Deletes the TPath object 
-/// @param[in] pPath - pointer to the object to delete.
-// ============================================================================
-void TPath::Delete(TPath* pPath)
-{
-	delete pPath;
+	// ============================================================================
+	/// TPath::Delete
+	/// @date 2009/11/29
+	///
+	/// @brief     Deletes the TPath object 
+	/// @param[in] pPath - pointer to the object to delete.
+	// ============================================================================
+	void TPath::Delete(TPath* pPath)
+	{
+		delete pPath;
+	}
 }
 
 // ============================================================================
@@ -250,20 +253,7 @@
 // ============================================================================
 bool TSmartPath::operator==(const TSmartPath& rPath) const
 {
-	if(m_pPath == rPath.m_pPath)
-		return true;
-	else if(m_pPath == NULL || rPath.m_pPath == NULL)
-		return false;
-	else
-	{
-		// NOTE: Windows paths are usually case insensitive and that would warrant usage of
-		//       iequals, however, in very specific cases (i.e. enabling case sensitivity for ntfs,
-		//       network paths) we need case sensitivity.
-		//       For now we'll try to support case sensitivity. If that will ever be a problem
-		//       we'll need to support case insensitivity (not trivial though).
-//		return boost::iequals(m_pPath->m_strPath, rPath.m_pPath->m_strPath);
-		return m_pPath->m_strPath == rPath.m_pPath->m_strPath;
-	}
+	return Compare(rPath) == 0;
 }
 
 // ============================================================================
@@ -276,12 +266,7 @@
 // ============================================================================
 bool TSmartPath::operator<(const TSmartPath& rPath) const
 {
-	if(m_pPath == rPath.m_pPath)
-		return false;
-	else if(m_pPath == NULL || rPath.m_pPath == NULL)
-		return m_pPath < rPath.m_pPath;
-	else
-		return m_pPath->m_strPath < rPath.m_pPath->m_strPath;
+	return Compare(rPath) < 0;
 }
 
 // ============================================================================
@@ -294,12 +279,7 @@
 // ============================================================================
 bool TSmartPath::operator>(const TSmartPath& rPath) const
 {
-	if(m_pPath == rPath.m_pPath)
-		return false;
-	else if(m_pPath == NULL || rPath.m_pPath == NULL)
-		return m_pPath > rPath.m_pPath;
-	else
-		return m_pPath->m_strPath > rPath.m_pPath->m_strPath;
+	return Compare(rPath) > 0;
 }
 
 // ============================================================================
@@ -338,7 +318,7 @@
 void TSmartPath::FromString(const wchar_t* pszPath)
 {
 	if(!pszPath)
-		THROW(_T("Invalid pointer"), 0, 0, 0);
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
 
 	PrepareToWrite();
 	m_pPath->m_strPath = pszPath;
@@ -394,18 +374,26 @@
 /// @param[in] rPath - path to compare to.
 /// @return    Result of the comparison.
 // ============================================================================
-bool TSmartPath::Compare(const TSmartPath& rPath, bool bCaseSensitive) const
+int TSmartPath::Compare(const TSmartPath& rPath, bool bCaseSensitive) const
 {
 	if(m_pPath == rPath.m_pPath)
-		return true;
+		return 0;
 	else if(m_pPath == NULL || rPath.m_pPath == NULL)
-		return m_pPath == rPath.m_pPath;
+	{
+		TString strThis = m_pPath ? m_pPath->m_strPath : _T("");
+		TString strOther = rPath.m_pPath ? rPath.m_pPath->m_strPath : _T("");
+
+		if(bCaseSensitive)
+			return strThis.Compare(strOther);
+		else
+			return strThis.CompareNoCase(strOther);
+	}
 	else
 	{
 		if(bCaseSensitive)
-			return m_pPath->m_strPath.Compare(rPath.m_pPath->m_strPath) == 0;
+			return m_pPath->m_strPath.Compare(rPath.m_pPath->m_strPath);
 		else
-			return m_pPath->m_strPath.CompareNoCase(rPath.m_pPath->m_strPath) == 0;
+			return m_pPath->m_strPath.CompareNoCase(rPath.m_pPath->m_strPath);
 	}
 }
 
@@ -416,24 +404,24 @@
 /// @brief     Splits path to components.
 /// @param[in] vComponents - receives the split path.
 // ============================================================================
-void TSmartPath::SplitPath(std::vector<TSmartPath>& vComponents) const
+void TSmartPath::SplitPath(TPathContainer& vComponents) const
 {
-	vComponents.clear();
+	vComponents.Clear();
 
 	if(IsNetworkPath())
 	{
 		// server name first
-		vComponents.push_back(GetServerName());
+		vComponents.Add(GetServerName());
 
 		// now the split directories
-		std::vector<TSmartPath> vDirSplit;
+		TPathContainer vDirSplit;
 		TSmartPath spDir = GetFileDir();
 		spDir.SplitPath(vDirSplit);
 
-		vComponents.insert(vComponents.end(), vDirSplit.begin(), vDirSplit.end());
+		vComponents.Append(vDirSplit);
 
 		// and file name last
-		vComponents.push_back(GetFileName());
+		vComponents.Add(GetFileName());
 	}
 	else
 	{
@@ -444,7 +432,7 @@
 		{
 			const TString& strComponent = vStrings.GetAt(stIndex);
 			if(!strComponent.IsEmpty())
-				vComponents.push_back(PathFromWString(strComponent));
+				vComponents.Add(PathFromWString(strComponent));
 		}
 	}
 }
@@ -477,10 +465,10 @@
 /// @param[in] bCaseSensitive - Compare path with case sensitivity on/off.
 /// @return    True if conversion to relative path succeeded, false otherwise.
 // ============================================================================
-void TSmartPath::MakeRelativePath(const TSmartPath& rReferenceBasePath, bool bCaseSensitive)
+bool TSmartPath::MakeRelativePath(const TSmartPath& rReferenceBasePath, bool bCaseSensitive)
 {
 	if(!m_pPath || !rReferenceBasePath.m_pPath)
-		return;		// nothing to do; in this case we might as well treat the path as relative one
+		return true;		// nothing to do; in this case we might as well treat the path as relative one
 
 	bool bStartsWith = false;
 	if(bCaseSensitive)
@@ -492,9 +480,10 @@
 	{
 		PrepareToWrite();
 		m_pPath->m_strPath.Delete(0, rReferenceBasePath.m_pPath->m_strPath.GetLength());
+		return true;
 	}
 	else
-		THROW(_T("Incompatible paths"), 0, 0, 0);
+		return false;
 }
 
 // ============================================================================
@@ -692,7 +681,7 @@
 		if(stEndPos == TString::npos)
 			wstrPath = m_pPath->m_strPath;
 		else
-			wstrPath = m_pPath->m_strPath.Left(stEndPos - 1);
+			wstrPath = m_pPath->m_strPath.Left(stEndPos);
 		return PathFromWString(wstrPath);
 	}
 
@@ -771,8 +760,10 @@
 	size_t stStart = 0;
 	if(IsNetworkPath())
 		stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\"), 2);
-	else
+	else if(HasDrive())
 		stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\"));
+	else
+		stStart = 0;
 
 	size_t stEnd = m_pPath->m_strPath.FindLastOf(_T("/\\"));
 	if(stStart != TString::npos && stEnd >= stStart)
@@ -823,10 +814,12 @@
 		return *this;
 	if(stStart == TString::npos)	// if does not exist, start from beginning
 		stStart = 0;
+	else
+		++stStart;
 	if(stEnd == TString::npos || stEnd < stStart)		// if does not exist or we have ".\\", use up to the end
 		stEnd = m_pPath->m_strPath.GetLength();
 
-	return PathFromWString(m_pPath->m_strPath.MidRange(stStart + 1, stEnd));
+	return PathFromWString(m_pPath->m_strPath.MidRange(stStart, stEnd));
 }
 
 // ============================================================================
@@ -879,7 +872,10 @@
 		return false;
 
 	size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/"));
-	return (stIndex != TString::npos && stIndex != m_pPath->m_strPath.GetLength() - 1);
+	if(stIndex == TString::npos)	// no path separator?
+		return true;
+	else
+		return (stIndex != TString::npos && stIndex != m_pPath->m_strPath.GetLength() - 1);
 }
 
 // ============================================================================
@@ -897,8 +893,8 @@
 	size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/"));
 	if(stIndex != TString::npos)
 		return PathFromWString(m_pPath->m_strPath.MidRange(stIndex + 1, m_pPath->m_strPath.GetLength()));	// "test.txt" for "c:\windows\test.txt"
-
-	return TSmartPath();
+	else
+		return *this;
 }
 
 // ============================================================================
@@ -918,6 +914,11 @@
 		PrepareToWrite();
 		m_pPath->m_strPath.Delete(stIndex + 1, m_pPath->m_strPath.GetLength() - stIndex - 1);	// "test.txt" for "c:\windows\test.txt"
 	}
+	else
+	{
+		// no path separator inside - everything in this path is a filename
+		Clear();
+	}
 }
 
 // ============================================================================
@@ -1106,14 +1107,14 @@
 {
 	if(m_pPath && m_pPath->IsShared())
 	{
-		TPath* pPath = m_pPath->Clone();
+		details::TPath* pPath = m_pPath->Clone();
 		Clear();
 		m_pPath = pPath;
 	}
 
 	// create new internal path if does not exist
 	if(!m_pPath)
-		m_pPath = TPath::New();
+		m_pPath = details::TPath::New();
 }
 
 // ============================================================================
@@ -1223,6 +1224,11 @@
 	m_vPaths.push_back(spPath);
 }
 
+void TPathContainer::Append(const TPathContainer& vPaths)
+{
+	m_vPaths.insert(m_vPaths.end(), vPaths.m_vPaths.begin(), vPaths.m_vPaths.end());
+}
+
 // ============================================================================
 /// TPathContainer::GetAt
 /// @date 2009/11/30
Index: src/libchcore/TPath.h
===================================================================
diff -u -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c -rf18d23588f370de68d37adb285dcf5e046a8d37c
--- src/libchcore/TPath.h	(.../TPath.h)	(revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c)
+++ src/libchcore/TPath.h	(.../TPath.h)	(revision f18d23588f370de68d37adb285dcf5e046a8d37c)
@@ -24,31 +24,37 @@
 
 BEGIN_CHCORE_NAMESPACE
 
-class LIBCHCORE_API TPath
+class TSmartPath;
+class TPathContainer;
+
+namespace details
 {
-public:
-	TPath();
-	TPath(const TPath& rSrc);
-	~TPath();
+	class TPath
+	{
+	public:
+		TPath();
+		TPath(const TPath& rSrc);
+		~TPath();
 
-	long AddRef() { return ++m_lRefCount; }
-	long Release();
-	bool IsShared() const { return m_lRefCount > 1; }
+		long AddRef() { return ++m_lRefCount; }
+		long Release();
+		bool IsShared() const { return m_lRefCount > 1; }
 
-protected:
-	static TPath* New();
-	TPath* Clone();
-	static void Delete(TPath* pPath);
+	protected:
+		static TPath* New();
+		TPath* Clone();
+		static void Delete(TPath* pPath);
 
-protected:
+	protected:
 #pragma warning(push)
 #pragma warning(disable: 4251)
-	TString m_strPath;
+		TString m_strPath;
 #pragma warning(pop)
-	long m_lRefCount;
+		long m_lRefCount;
 
-	friend class TSmartPath;
-};
+		friend class TSmartPath;
+	};
+}
 
 class LIBCHCORE_API TSmartPath
 {
@@ -85,12 +91,12 @@
 	TSmartPath AppendCopy(const TSmartPath& pathToAppend, bool bEnsurePathSeparatorExists = true) const;
 	TSmartPath& Append(const TSmartPath& pathToAppend, bool bEnsurePathSeparatorExists = true);
 
-	void SplitPath(std::vector<TSmartPath>& vComponents) const;
+	void SplitPath(TPathContainer& vComponents) const;
 
-	bool Compare(const TSmartPath& rPath, bool bCaseSensitive = DefaultCaseSensitivity) const;
+	int Compare(const TSmartPath& rPath, bool bCaseSensitive = DefaultCaseSensitivity) const;
 	bool IsChildOf(const TSmartPath& rPath, bool bCaseSensitive = DefaultCaseSensitivity) const;
 
-	void MakeRelativePath(const TSmartPath& rReferenceBasePath, bool bCaseSensitive = DefaultCaseSensitivity);
+	bool MakeRelativePath(const TSmartPath& rReferenceBasePath, bool bCaseSensitive = DefaultCaseSensitivity);
 
 	void AppendIfNotExists(const wchar_t* pszPostfix, bool bCaseSensitive = DefaultCaseSensitivity);
 	void CutIfExists(const wchar_t* pszPostfix, bool bCaseSensitive = DefaultCaseSensitivity);
@@ -146,7 +152,7 @@
 	static bool IsSeparator(wchar_t wchSeparator);
 
 protected:
-	TPath* m_pPath;
+	details::TPath* m_pPath;
 };
 
 LIBCHCORE_API TSmartPath PathFromString(const wchar_t* pszPath);
@@ -162,6 +168,7 @@
 	TPathContainer& operator=(const TPathContainer& rSrcContainer);
 
 	void Add(const TSmartPath& spPath);
+	void Append(const TPathContainer& vPaths);
 	
 	const TSmartPath& GetAt(size_t stIndex) const;
 	TSmartPath& GetAt(size_t stIndex);
Index: src/libchcore/Tests/TestsTSmartPath.cpp
===================================================================
diff -u
--- src/libchcore/Tests/TestsTSmartPath.cpp	(revision 0)
+++ src/libchcore/Tests/TestsTSmartPath.cpp	(revision f18d23588f370de68d37adb285dcf5e046a8d37c)
@@ -0,0 +1,1119 @@
+#include "stdafx.h"
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "../TPath.h"
+#include "../TCoreException.h"
+
+using namespace chcore;
+
+TEST(TSmartPathTests, EmptyPathToString)
+{
+	TSmartPath tPath;
+	EXPECT_STREQ(tPath.ToString(), _T(""));
+}
+
+TEST(TSmartPathTests, PathFromString)
+{
+	TSmartPath tPath;
+	tPath.FromString(_T("c:\\test"));
+	EXPECT_STREQ(tPath.ToString(), _T("c:\\test"));
+}
+
+TEST(TSmartPathTests, PathFromNullString)
+{
+	TSmartPath tPath;
+	EXPECT_THROW(tPath.FromString(NULL), TCoreException);
+}
+
+TEST(TSmartPathTests, PathFromTStringToWString)
+{
+	TSmartPath tPath;
+	tPath.FromString(TString(_T("c:\\test")));
+	EXPECT_EQ(tPath.ToWString(), TString(_T("c:\\test")));
+}
+
+TEST(TSmartPathTests, PathFromEmptyTStringToString)
+{
+	TSmartPath tPath;
+	tPath.FromString(TString());
+	EXPECT_STREQ(tPath.ToString(), _T(""));
+}
+
+// path comparison
+TEST(TSmartPathTests, PathComparison)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\test path"));
+	path2.FromString(_T("C:\\Test Path"));
+
+	EXPECT_TRUE(path1 == path2);
+}
+
+TEST(TSmartPathTests, PathComparisonLTGT)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path"));
+	path2.FromString(_T("C:\\Test Path"));
+
+	EXPECT_TRUE(path1 < path2);
+	EXPECT_TRUE(path2 > path1);
+}
+
+TEST(TSmartPathTests, PathClear)
+{
+	TSmartPath path;
+
+	path.FromString(_T("c:\\First path"));
+	path.Clear();
+
+	EXPECT_STREQ(path.ToString(), _T(""));
+}
+
+TEST(TSmartPathTests, AppendCopyWithSeparator)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path"));
+	path2.FromString(_T("some directory"));
+
+	TSmartPath retPath = path1.AppendCopy(path2, true);
+	EXPECT_STREQ(retPath.ToString(), _T("c:\\First path\\some directory"));
+}
+
+TEST(TSmartPathTests, AppendCopyWithoutSeparator)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path"));
+	path2.FromString(_T("some directory"));
+
+	TSmartPath retPath = path1.AppendCopy(path2, false);
+	EXPECT_STREQ(retPath.ToString(), _T("c:\\First pathsome directory"));
+}
+
+
+TEST(TSmartPathTests, AppendWithSeparator)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path"));
+	path2.FromString(_T("some directory"));
+
+	path1.Append(path2, true);
+	EXPECT_STREQ(path1.ToString(), _T("c:\\First path\\some directory"));
+}
+
+TEST(TSmartPathTests, AppendWithoutSeparator)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path"));
+	path2.FromString(_T("some directory"));
+
+	path1.Append(path2, false);
+	EXPECT_STREQ(path1.ToString(), _T("c:\\First pathsome directory"));
+}
+
+TEST(TSmartPathTests, SplitPath)
+{
+	TSmartPath path;
+	TPathContainer vPaths;
+
+	path.FromString(_T("c:\\First path\\some directory\\file.txt"));
+	path.SplitPath(vPaths);
+
+	EXPECT_EQ(4, vPaths.GetCount());
+	EXPECT_STREQ(_T("c:"), vPaths.GetAt(0).ToString());
+	EXPECT_STREQ(_T("First path"), vPaths.GetAt(1).ToString());
+	EXPECT_STREQ(_T("some directory"), vPaths.GetAt(2).ToString());
+	EXPECT_STREQ(_T("file.txt"), vPaths.GetAt(3).ToString());
+}
+
+TEST(TSmartPathTests, SplitEmptyPath)
+{
+	TSmartPath path;
+	TPathContainer vPaths;
+
+	path.FromString(_T(""));
+	path.SplitPath(vPaths);
+
+	EXPECT_EQ(0, vPaths.GetCount());
+}
+
+TEST(TSmartPathTests, CompareLTGTCaseInsensitive)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path"));
+	path2.FromString(_T("C:\\Test Path"));
+
+	EXPECT_TRUE(path1.Compare(path2, false) < 0);
+	EXPECT_TRUE(path2.Compare(path1, false) > 0);
+}
+
+TEST(TSmartPathTests, CompareEQCaseInsensitive)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path"));
+	path2.FromString(_T("C:\\first Path"));
+
+	EXPECT_TRUE(path1.Compare(path2, false) == 0);
+}
+
+TEST(TSmartPathTests, CompareLTGTCaseSensitive)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path"));
+	path2.FromString(_T("C:\\Test Path"));
+
+	EXPECT_TRUE(path1.Compare(path2, false) < 0);
+	EXPECT_TRUE(path2.Compare(path1, false) > 0);
+}
+
+TEST(TSmartPathTests, CompareEQCaseSensitive)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path"));
+	path2.FromString(_T("C:\\first Path"));
+
+	EXPECT_TRUE(path1.Compare(path2, true) != 0);
+}
+
+TEST(TSmartPathTests, CompareEQCaseSensitive2)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\first path"));
+	path2.FromString(_T("c:\\first path"));
+
+	EXPECT_TRUE(path1.Compare(path2, true) == 0);
+}
+
+TEST(TSmartPathTests, IsChildOf_CaseInsensitive)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path\\second path"));
+	path2.FromString(_T("C:\\first path"));
+
+	EXPECT_TRUE(path1.IsChildOf(path2, false));
+}
+
+TEST(TSmartPathTests, IsChildOf_CaseSensitive_NegativeCase)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\First path\\second path"));
+	path2.FromString(_T("C:\\first path"));
+
+	EXPECT_FALSE(path1.IsChildOf(path2, true));
+}
+
+TEST(TSmartPathTests, IsChildOf_CaseSensitive_PositiveCase)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\first path\\second path"));
+	path2.FromString(_T("c:\\first path"));
+
+	EXPECT_TRUE(path1.IsChildOf(path2, true));
+}
+
+TEST(TSmartPathTests, MakeRelativePath_CaseInensitive)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\first path\\second path"));
+	path2.FromString(_T("C:\\First Path"));
+
+	EXPECT_TRUE(path1.MakeRelativePath(path2, false));
+	EXPECT_STREQ(_T("\\second path"), path1.ToString());
+}
+
+TEST(TSmartPathTests, MakeRelativePath_CaseSensitive_NegativeCase)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\first path\\second path"));
+	path2.FromString(_T("C:\\First Path"));
+
+	EXPECT_FALSE(path1.MakeRelativePath(path2, true));
+	EXPECT_STREQ(_T("c:\\first path\\second path"), path1.ToString());
+}
+
+TEST(TSmartPathTests, MakeRelativePath_CaseSensitive_PositiveCase)
+{
+	TSmartPath path1;
+	TSmartPath path2;
+
+	path1.FromString(_T("c:\\first path\\second path"));
+	path2.FromString(_T("c:\\first path"));
+
+	EXPECT_TRUE(path1.MakeRelativePath(path2, true));
+	EXPECT_STREQ(_T("\\second path"), path1.ToString());
+}
+
+TEST(TSmartPathTests, AppendIfNotExists_CaseInsensitive_PositiveCase)
+{
+	TSmartPath path2;
+
+	path2.FromString(_T("c:\\first path"));
+
+	path2.AppendIfNotExists(_T("\\second path"), false);
+	EXPECT_STREQ(_T("c:\\first path\\second path"), path2.ToString());
+}
+
+TEST(TSmartPathTests, AppendIfNotExists_CaseInsensitive_NegativeCase)
+{
+	TSmartPath path2;
+
+	path2.FromString(_T("c:\\first path\\Second Path"));
+
+	path2.AppendIfNotExists(_T("\\second path"), false);
+	EXPECT_STREQ(_T("c:\\first path\\Second Path"), path2.ToString());
+}
+
+
+TEST(TSmartPathTests, AppendIfNotExists_CaseSensitive_PositiveCase)
+{
+	TSmartPath path2;
+
+	path2.FromString(_T("c:\\first path"));
+
+	path2.AppendIfNotExists(_T("\\second path"), true);
+	EXPECT_STREQ(_T("c:\\first path\\second path"), path2.ToString());
+}
+
+TEST(TSmartPathTests, AppendIfNotExists_CaseSensitive_NegativeCase)
+{
+	TSmartPath path2;
+
+	path2.FromString(_T("c:\\first path\\second path"));
+
+	path2.AppendIfNotExists(_T("\\second path"), true);
+	EXPECT_STREQ(_T("c:\\first path\\second path"), path2.ToString());
+}
+
+TEST(TSmartPathTests, CutIfExists_CaseInsensitive_PositiveCase)
+{
+	TSmartPath path2;
+
+	path2.FromString(_T("c:\\first path"));
+
+	path2.CutIfExists(_T("\\second path"), false);
+	EXPECT_STREQ(_T("c:\\first path"), path2.ToString());
+}
+
+TEST(TSmartPathTests, CutIfExists_CaseInsensitive_NegativeCase)
+{
+	TSmartPath path2;
+
+	path2.FromString(_T("c:\\first path\\Second Path"));
+
+	path2.CutIfExists(_T("\\second path"), false);
+	EXPECT_STREQ(_T("c:\\first path"), path2.ToString());
+}
+
+
+TEST(TSmartPathTests, CutIfExists_CaseSensitive_PositiveCase)
+{
+	TSmartPath path2;
+
+	path2.FromString(_T("c:\\first path"));
+
+	path2.CutIfExists(_T("\\second path"), true);
+	EXPECT_STREQ(_T("c:\\first path"), path2.ToString());
+}
+
+TEST(TSmartPathTests, CutIfExists_CaseSensitive_NegativeCase)
+{
+	TSmartPath path2;
+
+	path2.FromString(_T("c:\\first path\\second path"));
+
+	path2.CutIfExists(_T("\\second path"), true);
+	EXPECT_STREQ(_T("c:\\first path"), path2.ToString());
+}
+
+TEST(TSmartPathTests, IsNetworkPath_Negative)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_FALSE(path.IsNetworkPath());
+}
+
+TEST(TSmartPathTests, IsNetworkPath_Positive)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_TRUE(path.IsNetworkPath());
+}
+
+TEST(TSmartPathTests, IsDrive_Negative)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_FALSE(path.IsDrive());
+}
+
+TEST(TSmartPathTests, IsDrive_Negative_2)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\"));
+
+	EXPECT_FALSE(path.IsDrive());
+}
+
+TEST(TSmartPathTests, IsDrive_Positive)
+{
+	TSmartPath path;
+	path.FromString(_T("c:"));
+
+	EXPECT_TRUE(path.IsDrive());
+}
+
+TEST(TSmartPathTests, HasDrive_Positive)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasDrive());
+}
+
+TEST(TSmartPathTests, HasDrive_Positive_2)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\"));
+
+	EXPECT_TRUE(path.HasDrive());
+}
+
+TEST(TSmartPathTests, HasDrive_Positive_3)
+{
+	TSmartPath path;
+	path.FromString(_T("c:"));
+
+	EXPECT_TRUE(path.HasDrive());
+}
+
+TEST(TSmartPathTests, HasDrive_Negative)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\share"));
+
+	EXPECT_FALSE(path.HasDrive());
+}
+
+TEST(TSmartPathTests, GetDriveAndDriveLetterFromLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	TSmartPath pathDrive = path.GetDrive();
+	wchar_t wchDrive = path.GetDriveLetter();	// makes drive letter uppercase
+
+	EXPECT_STREQ(_T("c:"), pathDrive.ToString());
+	EXPECT_EQ(_T('C'), wchDrive);
+}
+
+TEST(TSmartPathTests, GetDriveAndDriveLetterFromNonLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\serv01\\first path\\second path"));
+
+	TSmartPath pathDrive = path.GetDrive();
+	wchar_t wchDrive = path.GetDriveLetter();	// makes drive letter uppercase
+
+	EXPECT_STREQ(_T(""), pathDrive.ToString());
+	EXPECT_EQ(_T('\0'), wchDrive);
+}
+
+TEST(TSmartPathTests, IsServerName_Negative)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_FALSE(path.IsServerName());
+}
+
+TEST(TSmartPathTests, IsServerName_Negative_2)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\"));
+
+	EXPECT_FALSE(path.IsServerName());
+}
+
+TEST(TSmartPathTests, IsServerName_Positive)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01"));
+
+	EXPECT_TRUE(path.IsServerName());
+}
+
+TEST(TSmartPathTests, HasServerName_Positive)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasServerName());
+}
+
+TEST(TSmartPathTests, HasServerName_Positive_2)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\"));
+
+	EXPECT_TRUE(path.HasServerName());
+}
+
+TEST(TSmartPathTests, HasServerName_Positive_3)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01"));
+
+	EXPECT_TRUE(path.HasServerName());
+}
+
+TEST(TSmartPathTests, HasServerName_Negative)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\path"));
+
+	EXPECT_FALSE(path.HasServerName());
+}
+
+TEST(TSmartPathTests, GetServerName)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	TSmartPath pathServerName = path.GetServerName();
+
+	EXPECT_STREQ(_T("\\\\serv01"), pathServerName.ToString());
+}
+
+TEST(TSmartPathTests, GetServerNameFromLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	TSmartPath pathServerName = path.GetServerName();
+
+	EXPECT_STREQ(_T(""), pathServerName.ToString());
+}
+
+TEST(TSmartPathTests, HasFileRootLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasFileRoot());
+}
+
+TEST(TSmartPathTests, HasFileRootRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasFileRoot());
+}
+
+TEST(TSmartPathTests, HasFileRootRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\file.txt"));
+
+	EXPECT_TRUE(path.HasFileRoot());
+}
+
+TEST(TSmartPathTests, HasFileRootFileNameOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("file.txt"));
+
+	EXPECT_FALSE(path.HasFileRoot());
+}
+
+TEST(TSmartPathTests, GetFileRootLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_STREQ(_T("c:\\first path\\"), path.GetFileRoot().ToString());
+}
+
+TEST(TSmartPathTests, GetFileRootRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_STREQ(_T("\\\\serv01\\first path\\"), path.GetFileRoot().ToString());
+}
+
+TEST(TSmartPathTests, GetFileRootRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\file.txt"));
+
+	EXPECT_STREQ(_T("..\\"), path.GetFileRoot().ToString());
+}
+
+TEST(TSmartPathTests, GetFileRootFileNameOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("file.txt"));
+
+	EXPECT_STREQ(_T(""), path.GetFileRoot().ToString());
+}
+
+// has/get file dir
+TEST(TSmartPathTests, HasFileDirLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasFileDir());
+}
+
+TEST(TSmartPathTests, HasFileDirRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasFileDir());
+}
+
+TEST(TSmartPathTests, HasFileDirRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\file.txt"));
+
+	EXPECT_TRUE(path.HasFileDir());
+}
+
+TEST(TSmartPathTests, HasFileDirFileNameOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("file.txt"));
+
+	EXPECT_FALSE(path.HasFileDir());
+}
+
+TEST(TSmartPathTests, GetFileDirLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_STREQ(_T("\\first path\\"), path.GetFileDir().ToString());
+}
+
+TEST(TSmartPathTests, GetFileDirRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_STREQ(_T("\\first path\\"), path.GetFileDir().ToString());
+}
+
+TEST(TSmartPathTests, GetFileDirRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\file.txt"));
+
+	EXPECT_STREQ(_T("..\\"), path.GetFileDir().ToString());
+}
+
+TEST(TSmartPathTests, GetFileDirFileNameOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("file.txt"));
+
+	EXPECT_STREQ(_T(""), path.GetFileDir().ToString());
+}
+
+// has/get file title
+TEST(TSmartPathTests, HasFileTitleLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasFileTitle());
+}
+
+TEST(TSmartPathTests, HasFileTitleRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasFileTitle());
+}
+
+TEST(TSmartPathTests, HasFileTitleRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\file.txt"));
+
+	EXPECT_TRUE(path.HasFileTitle());
+}
+
+TEST(TSmartPathTests, HasFileTitleFileNameOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("file.txt"));
+
+	EXPECT_TRUE(path.HasFileTitle());
+}
+
+TEST(TSmartPathTests, HasFileTitleFileDirOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory\\"));
+
+	EXPECT_FALSE(path.HasFileTitle());
+}
+
+TEST(TSmartPathTests, GetFileTitleLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_STREQ(_T("second path"), path.GetFileTitle().ToString());
+}
+
+TEST(TSmartPathTests, GetFileTitleRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_STREQ(_T("second path"), path.GetFileTitle().ToString());
+}
+
+TEST(TSmartPathTests, GetFileTitleRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\file.txt"));
+
+	EXPECT_STREQ(_T("file"), path.GetFileTitle().ToString());
+}
+
+TEST(TSmartPathTests, GetFileTitleFileNameOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("file.txt"));
+
+	EXPECT_STREQ(_T("file"), path.GetFileTitle().ToString());
+}
+
+TEST(TSmartPathTests, GetFileTitleFileDirOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory\\"));
+
+	EXPECT_STREQ(_T(""), path.GetFileTitle().ToString());
+}
+
+// has/get file name
+TEST(TSmartPathTests, HasFileNameLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasFileName());
+}
+
+TEST(TSmartPathTests, HasFileNameRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_TRUE(path.HasFileName());
+}
+
+TEST(TSmartPathTests, HasFileNameRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\file.txt"));
+
+	EXPECT_TRUE(path.HasFileName());
+}
+
+TEST(TSmartPathTests, HasFileNameFileNameOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("file.txt"));
+
+	EXPECT_TRUE(path.HasFileName());
+}
+
+TEST(TSmartPathTests, HasFileNameFileDirOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory\\"));
+
+	EXPECT_FALSE(path.HasFileName());
+}
+
+TEST(TSmartPathTests, GetFileNameLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_STREQ(_T("second path"), path.GetFileName().ToString());
+}
+
+TEST(TSmartPathTests, GetFileNameRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_STREQ(_T("second path"), path.GetFileName().ToString());
+}
+
+TEST(TSmartPathTests, GetFileNameRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\file.txt"));
+
+	EXPECT_STREQ(_T("file.txt"), path.GetFileName().ToString());
+}
+
+TEST(TSmartPathTests, GetFileNameFileNameOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("file.txt"));
+
+	EXPECT_STREQ(_T("file.txt"), path.GetFileName().ToString());
+}
+
+TEST(TSmartPathTests, GetFileNameFileDirOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory\\"));
+
+	EXPECT_STREQ(_T(""), path.GetFileName().ToString());
+}
+
+// delete filename
+TEST(TSmartPathTests, DeleteFileNameLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	path.DeleteFileName();
+
+	EXPECT_STREQ(_T("c:\\first path\\"), path.ToString());
+}
+
+TEST(TSmartPathTests, DeleteFileNameRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	path.DeleteFileName();
+
+	EXPECT_STREQ(_T("\\\\serv01\\first path\\"), path.ToString());
+}
+
+TEST(TSmartPathTests, DeleteFileNameRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\file.txt"));
+
+	path.DeleteFileName();
+
+	EXPECT_STREQ(_T("..\\"), path.ToString());
+}
+
+TEST(TSmartPathTests, DeleteFileNameFileNameOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("file.txt"));
+
+	path.DeleteFileName();
+
+	EXPECT_STREQ(_T(""), path.ToString());
+}
+
+TEST(TSmartPathTests, DeleteFileNameFileDirOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory\\"));
+
+	path.DeleteFileName();
+
+	EXPECT_STREQ(_T("c:\\directory\\"), path.ToString());
+}
+
+// has/get file extension
+TEST(TSmartPathTests, HasExtensionLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path.txt"));
+
+	EXPECT_TRUE(path.HasExtension());
+}
+
+TEST(TSmartPathTests, HasExtensionRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path.txt"));
+
+	EXPECT_TRUE(path.HasExtension());
+}
+
+TEST(TSmartPathTests, HasExtensionLocalPathNegative)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_FALSE(path.HasExtension());
+}
+
+TEST(TSmartPathTests, HasExtensionRemotePathNegatice)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_FALSE(path.HasExtension());
+}
+
+TEST(TSmartPathTests, HasExtensionRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\directory"));
+
+	EXPECT_FALSE(path.HasExtension());
+}
+
+TEST(TSmartPathTests, HasExtensionFileDirOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory.ext\\"));
+
+	EXPECT_FALSE(path.HasExtension());
+}
+
+TEST(TSmartPathTests, GetExtensionLocalPath)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path.txt"));
+
+	EXPECT_STREQ(_T(".txt"), path.GetExtension().ToString());
+}
+
+TEST(TSmartPathTests, GetExtensionRemotePath)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path.txt"));
+
+	EXPECT_STREQ(_T(".txt"), path.GetExtension().ToString());
+}
+
+TEST(TSmartPathTests, GetExtensionLocalPathNegative)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\first path\\second path"));
+
+	EXPECT_STREQ(_T(""), path.GetExtension().ToString());
+}
+
+TEST(TSmartPathTests, GetExtensionRemotePathNegatice)
+{
+	TSmartPath path;
+	path.FromString(_T("\\\\serv01\\first path\\second path"));
+
+	EXPECT_STREQ(_T(""), path.GetExtension().ToString());
+}
+
+TEST(TSmartPathTests, GetExtensionRelativePath)
+{
+	TSmartPath path;
+	path.FromString(_T("..\\directory"));
+
+	EXPECT_STREQ(_T(""), path.GetExtension().ToString());
+}
+
+TEST(TSmartPathTests, GetExtensionFileDirOnly)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory.ext\\"));
+
+	EXPECT_STREQ(_T(""), path.GetExtension().ToString());
+}
+
+// separator operations
+TEST(TSmartPathTests, EndsWithSeparator_True)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory.ext\\"));
+
+	EXPECT_TRUE(path.EndsWithSeparator());
+}
+
+TEST(TSmartPathTests, EndsWithSeparator_False)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory.ext"));
+
+	EXPECT_FALSE(path.EndsWithSeparator());
+}
+
+TEST(TSmartPathTests, AppendSeparator_AlreadyExists)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory.ext\\"));
+	path.AppendSeparatorIfDoesNotExist();
+	EXPECT_STREQ(_T("c:\\directory.ext\\"), path.ToString());
+}
+
+TEST(TSmartPathTests, AppendSeparator_DoesNotExist)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory.ext"));
+	path.AppendSeparatorIfDoesNotExist();
+	EXPECT_STREQ(_T("c:\\directory.ext\\"), path.ToString());
+}
+
+TEST(TSmartPathTests, StripSeparator_AlreadyExists)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory.ext\\"));
+	path.StripSeparatorAtEnd();
+	EXPECT_STREQ(_T("c:\\directory.ext"), path.ToString());
+}
+
+TEST(TSmartPathTests, StripSeparator_DoesNotExist)
+{
+	TSmartPath path;
+	path.FromString(_T("c:\\directory.ext"));
+	path.StripSeparatorAtEnd();
+	EXPECT_STREQ(_T("c:\\directory.ext"), path.ToString());
+}
+
+// separator at front
+TEST(TSmartPathTests, StartsWithSeparator_True)
+{
+	TSmartPath path;
+	path.FromString(_T("\\directory.ext\\"));
+
+	EXPECT_TRUE(path.StartsWithSeparator());
+}
+
+TEST(TSmartPathTests, StartsWithSeparator_False)
+{
+	TSmartPath path;
+	path.FromString(_T("directory.ext"));
+
+	EXPECT_FALSE(path.StartsWithSeparator());
+}
+
+TEST(TSmartPathTests, PrependSeparator_AlreadyExists)
+{
+	TSmartPath path;
+	path.FromString(_T("\\directory.ext"));
+	path.PrependSeparatorIfDoesNotExist();
+	EXPECT_STREQ(_T("\\directory.ext"), path.ToString());
+}
+
+TEST(TSmartPathTests, PrependSeparator_DoesNotExist)
+{
+	TSmartPath path;
+	path.FromString(_T("directory.ext"));
+	path.PrependSeparatorIfDoesNotExist();
+	EXPECT_STREQ(_T("\\directory.ext"), path.ToString());
+}
+
+TEST(TSmartPathTests, StripSeparatorAtFront_AlreadyExists)
+{
+	TSmartPath path;
+	path.FromString(_T("\\directory.ext"));
+	path.StripSeparatorAtFront();
+	EXPECT_STREQ(_T("directory.ext"), path.ToString());
+}
+
+TEST(TSmartPathTests, StripSeparatorAtFront_DoesNotExist)
+{
+	TSmartPath path;
+	path.FromString(_T("directory.ext"));
+	path.StripSeparatorAtFront();
+	EXPECT_STREQ(_T("directory.ext"), path.ToString());
+}
+
+// isempty, get length
+TEST(TSmartPathTests, IsEmpty_Empty)
+{
+	TSmartPath path;
+	path.FromString(_T(""));
+	EXPECT_TRUE(path.IsEmpty());
+}
+
+TEST(TSmartPathTests, IsEmpty_NotInitializedEmpty)
+{
+	TSmartPath path;
+	EXPECT_TRUE(path.IsEmpty());
+}
+
+TEST(TSmartPathTests, IsEmpty_NotEmpty)
+{
+	TSmartPath path;
+	path.FromString(_T("some path"));
+	EXPECT_FALSE(path.IsEmpty());
+}
+
+TEST(TSmartPathTests, GetLength_Empty)
+{
+	TSmartPath path;
+	path.FromString(_T(""));
+	EXPECT_EQ(0, path.GetLength());
+}
+
+TEST(TSmartPathTests, GetLength_NotInitializedEmpty)
+{
+	TSmartPath path;
+	EXPECT_EQ(0, path.GetLength());
+}
+
+TEST(TSmartPathTests, GetLength_NotEmpty)
+{
+	TSmartPath path;
+	path.FromString(_T("some path"));
+	EXPECT_EQ(9, path.GetLength());
+}
+
+/*
+bool IsEmpty() const;
+size_t GetLength() const;
+
+// Serialization
+void Serialize(TReadBinarySerializer& rSerializer);
+void Serialize(TWriteBinarySerializer& rSerializer) const;
+
+void StoreInConfig(TConfig& rConfig, PCTSTR pszPropName) const;
+bool ReadFromConfig(const TConfig& rConfig, PCTSTR pszPropName);
+*/
Index: src/libchcore/libchcore.vc90.vcproj
===================================================================
diff -u -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f -rf18d23588f370de68d37adb285dcf5e046a8d37c
--- src/libchcore/libchcore.vc90.vcproj	(.../libchcore.vc90.vcproj)	(revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f)
+++ src/libchcore/libchcore.vc90.vcproj	(.../libchcore.vc90.vcproj)	(revision f18d23588f370de68d37adb285dcf5e046a8d37c)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="windows-1250"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="9,00"
+	Version="9.00"
 	Name="libchcore"
 	ProjectGUID="{CBBF380B-7B16-4A1E-8194-758DAD7D8011}"
 	RootNamespace="libchcore"
@@ -1367,6 +1367,42 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Tests\TestsTSmartPath.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Tests\TestsTSpeedTracker.cpp"
 				>
 				<FileConfiguration