DPL Path fix
authorTomasz Iwanek <t.iwanek@samsung.com>
Thu, 4 Apr 2013 06:58:01 +0000 (08:58 +0200)
committerGerrit Code Review <gerrit2@kim11>
Mon, 8 Apr 2013 08:22:34 +0000 (17:22 +0900)
[Issue#] LINUXWRT-149
[Feature] new method for Path class
[Cause] N/A
[Solution] N/A
[Verification] Run tests: wrt-commons-tests-utils --output=text --regexp='path'

Change-Id: I1f65a1d3f324b5b8ce0d217e511f320337e0866b

modules/utils/include/dpl/utils/path.h
modules/utils/src/path.cpp
tests/utils/path_tests.cpp

index 6e025db..de8840b 100644 (file)
@@ -48,17 +48,29 @@ namespace Utils {
  *
  * Class for expressing paths not limited not existing ones.
  * It's possible to check if path exists, remove it or iterate it if it's directory
+ *
+ * Created Path object allways contains absolute path, never relative path.
+ * Simplifies common usage cases:
+ * - path construction (with /= and / operators)
+ * - directory iterator (begin(), end(), iterator construction)
+ * - receiving filenames and directory names of given paths
+ * - checking what is pointed by path (Exists(), IsFile(), IsDir())
+ *
+             * Check tests for details of usage.
  */
 class Path
 {
 public:
     DECLARE_EXCEPTION_TYPE(DPL::Exception, BaseException)
-    DECLARE_EXCEPTION_TYPE(BaseException, AlreadyExists)
-    DECLARE_EXCEPTION_TYPE(BaseException, NotExists)
-    DECLARE_EXCEPTION_TYPE(BaseException, NotDirectory)
-    DECLARE_EXCEPTION_TYPE(BaseException, OperationFailed)
-    DECLARE_EXCEPTION_TYPE(BaseException, EmptyPath)
-    DECLARE_EXCEPTION_TYPE(BaseException, InternalError)
+    DECLARE_EXCEPTION_TYPE(BaseException, AlreadyExists)            //path already exists
+    DECLARE_EXCEPTION_TYPE(BaseException, NotPrefix)                //given path is not prefix of this path
+    DECLARE_EXCEPTION_TYPE(BaseException, NotExists)                //file not exists
+    DECLARE_EXCEPTION_TYPE(BaseException, NotDirectory)             //directory nto exists
+    DECLARE_EXCEPTION_TYPE(BaseException, OperationFailed)          //operation failed due to system error(permission etc..)
+    DECLARE_EXCEPTION_TYPE(BaseException, EmptyPath)                //object cannot be constructed with empty path
+    DECLARE_EXCEPTION_TYPE(BaseException, InternalError)            //internal error / wrong path usage
+    DECLARE_EXCEPTION_TYPE(BaseException, CannotCopy)               //cannot make copy
+    DECLARE_EXCEPTION_TYPE(BaseException, RootDirectoryError)       //operation cannot be done with root diretory
 
     class Iterator : public std::iterator<std::input_iterator_tag, Path>
     {
@@ -82,8 +94,14 @@ public:
     explicit Path(const DPL::String & str);
     explicit Path(const std::string & str);
     explicit Path(const char * str);
+    Path();
 
     /**
+     * @brief DirectoryPath shell's dirname equivalent as path
+     * @return directory path
+     */
+    Path DirectoryPath() const;
+    /**
      * @brief DirectoryName shell's dirname equivalent
      * @return directory name of given path
      */
@@ -92,7 +110,7 @@ public:
      * @brief Basename shell's basename equivalent
      * @return base name of given path
      */
-    std::string Basename() const;
+    std::string Filename() const;
     /**
      * @brief Fullpath fullpath based on current working diretory
      * @return full path
@@ -103,6 +121,15 @@ public:
     bool IsDir() const;
     bool IsFile() const;
     bool IsSymlink() const;
+    std::size_t Size() const;
+    /**
+     * @brief isSubPath Returns relative path to given base
+     * @param prefix base path
+     * @return reltive path
+     *
+     * @throws If prefix does not match to this path object
+     */
+    bool isSubPath(const Path & other) const;
 
     bool operator==(const Path & other) const;
     bool operator!=(const Path & other) const;
@@ -120,8 +147,10 @@ public:
     Iterator begin() const;
     Iterator end() const;
 
+    //root error - throws error on root directory
+    void RootGuard() const;
+
 private:
-    Path();
 
     void Append(const std::string& part);
     void Construct(const std::string & src);
@@ -151,6 +180,12 @@ void MakeEmptyFile(const Path & path);
 void Remove(const Path & path);
 
 /**
+ * @brief TryRemove tries to remvoe path
+ * @param path returns status of removal
+ */
+bool TryRemove(const Path & path);
+
+/**
  * @brief Rename renames(moves) current path
  *
  * If you uses this method string to path is internally change
@@ -167,6 +202,22 @@ void Rename(const Path & from, const Path & to);
  */
 bool Exists(const Path & path);
 
+/**
+ * @brief Copy file
+ *
+ * @param from source path
+ * @param to target path
+ */
+void CopyFile(const Path & from, const Path & to);
+
+/**
+ * @brief Copy directory recursively
+ *
+ * @param from source directory path
+ * @param to target directory path
+ */
+void CopyDir(const Path & from, const Path & to);
+
 }
 
 }
index d2867d4..5f36011 100644 (file)
@@ -28,6 +28,8 @@
 #include <dpl/file_input.h>
 #include <dpl/file_output.h>
 #include <dpl/copy.h>
+#include <dpl/log/log.h>
+#include <dpl/foreach.h>
 #include <unistd.h>
 #include <sys/stat.h>
 
@@ -138,7 +140,7 @@ void Path::Construct(const std::string & src)
     Tokenize(src, "\\/", std::inserter(m_parts, m_parts.end()), true);
 }
 
-Path::Path() //for private usage
+Path::Path()
 {
 }
 
@@ -149,7 +151,7 @@ std::string Path::DirectoryName() const
     return std::string("/") + ret;
 }
 
-std::string Path::Basename() const
+std::string Path::Filename() const
 {
     if(m_parts.empty()) return "";
     else return m_parts.back();
@@ -179,16 +181,22 @@ Path::Iterator Path::end() const
     return Iterator();
 }
 
+void Path::RootGuard() const
+{
+    if(m_parts.empty()) Throw(RootDirectoryError);
+}
 
 bool Path::Exists() const
 {
     struct stat tmp;
+    memset(&tmp, 0, sizeof(struct stat));
     return (0 == lstat(Fullpath().c_str(), &tmp));
 }
 
 bool Path::IsDir() const
 {
     struct stat tmp;
+    memset(&tmp, 0, sizeof(struct stat));
     if (-1 == lstat(Fullpath().c_str(), &tmp))
     {
         ThrowMsg(NotExists, DPL::GetErrnoString());
@@ -199,6 +207,7 @@ bool Path::IsDir() const
 bool Path::IsFile() const
 {
     struct stat tmp;
+    memset(&tmp, 0, sizeof(struct stat));
     if (-1 == lstat(Fullpath().c_str(), &tmp))
     {
         ThrowMsg(NotExists, DPL::GetErrnoString());
@@ -209,6 +218,7 @@ bool Path::IsFile() const
 bool Path::IsSymlink() const
 {
     struct stat tmp;
+    memset(&tmp, 0, sizeof(struct stat));
     if (-1 == lstat(Fullpath().c_str(), &tmp))
     {
         ThrowMsg(NotExists, DPL::GetErrnoString());
@@ -228,14 +238,14 @@ bool Path::operator!=(const Path & other) const
 
 Path Path::operator/(const DPL::String& part) const
 {
-    Path newOne;
+    Path newOne(*this);
     newOne.Append(ToUTF8String(part));
     return newOne;
 }
 
 Path Path::operator/(const std::string& part) const
 {
-    Path newOne;
+    Path newOne(*this);
     newOne.Append(part);
     return newOne;
 }
@@ -272,18 +282,53 @@ void Path::Append(const std::string& part)
     std::copy(tokens.begin(), tokens.end(), std::inserter(m_parts, m_parts.end()));
 }
 
+Path Path::DirectoryPath() const
+{
+    Path npath;
+    if(m_parts.empty()) ThrowMsg(InternalError, "Asking DirectoryPath for root directory");
+    std::copy(m_parts.begin(), --m_parts.end(), std::back_inserter(npath.m_parts));
+    return npath;
+}
+
+std::size_t Path::Size() const
+{
+    struct stat tmp;
+    memset(&tmp, 0, sizeof(struct stat));
+    if (-1 == lstat(Fullpath().c_str(), &tmp))
+    {
+        ThrowMsg(NotExists, DPL::GetErrnoString());
+    }
+    return tmp.st_size;
+}
+
+bool Path::isSubPath(const Path & other) const
+{
+    typedef std::vector<std::string>::const_iterator Iter;
+    Iter otherIter = other.m_parts.begin();
+    for(Iter iter = m_parts.begin(); iter != m_parts.end(); iter++)
+    {
+        if(otherIter == other.m_parts.end()) return false;
+        if(*iter != *otherIter) return false;
+        otherIter++;
+    }
+    return true;
+}
+
 void MakeDir(const Path & path, mode_t mode)
 {
+    path.RootGuard();
     if(!WrtUtilMakeDir(path.Fullpath(), mode)) ThrowMsg(Path::OperationFailed, "Cannot make directory");
 }
 
 void MakeEmptyFile(const Path & path)
 {
+    path.RootGuard();
     std::string fp = path.Fullpath();
     FILE* fd = fopen(fp.c_str(), "wx");
     if(!fd)
     {
         struct stat st;
+        memset(&st, 0, sizeof(struct stat));
         if(lstat(fp.c_str(), &st) == 0)
         {
             ThrowMsg(Path::AlreadyExists, "File already exists");
@@ -298,33 +343,42 @@ void MakeEmptyFile(const Path & path)
 
 void Remove(const Path & path)
 {
+    path.RootGuard();
     if(!WrtUtilRemove(path.Fullpath())) ThrowMsg(Path::OperationFailed, "Cannot remove path");
 }
 
+bool TryRemove(const Path & path)
+{
+    path.RootGuard();
+    if(!WrtUtilRemove(path.Fullpath())) return false;
+    return true;
+}
+
 void Rename(const Path & from, const Path & to)
 {
+    from.RootGuard();
+    to.RootGuard();
     if(from == to)
     {
         return;
     }
-    int code = 0;
-    if( (code = rename(from.Fullpath().c_str(), to.Fullpath().c_str())) )
+    if(0 != rename(from.Fullpath().c_str(), to.Fullpath().c_str()))
     {
-        if(code == EXDEV)
+        if(errno == EXDEV)
         {
-            Try
+            if(from.IsDir())
             {
-                DPL::FileInput in(from.Fullpath());
-                DPL::FileOutput out(to.Fullpath());
-                DPL::Copy(&in, &out);
+                CopyDir(from, to);
+                Remove(from);
             }
-            Catch(DPL::FileInput::Exception::Base)
+            else if(from.IsFile() || from.IsSymlink())
             {
-                ThrowMsg(Path::OperationFailed, "Cannot open input file " << from.Fullpath());
+                CopyFile(from, to);
+                Remove(from);
             }
-            Catch(DPL::FileOutput::Exception::Base)
+            else
             {
-                ThrowMsg(Path::OperationFailed, "Cannot open output file " << to.Fullpath());
+                 ThrowMsg(Path::OperationFailed, DPL::GetErrnoString());
             }
         }
         else
@@ -334,6 +388,59 @@ void Rename(const Path & from, const Path & to)
     }
 }
 
+void CopyFile(const Path & from, const Path & to)
+{
+    from.RootGuard();
+    to.RootGuard();
+    Try
+    {
+        DPL::FileInput input(from.Fullpath());
+        DPL::FileOutput output(to.Fullpath());
+        DPL::Copy(&input, &output);
+    }
+    Catch(DPL::FileInput::Exception::Base)
+    {
+        LogError("File input error");
+        ReThrowMsg(DPL::CopyFailed, std::string("File input error") + from.Fullpath());
+    }
+    Catch(DPL::FileOutput::Exception::Base)
+    {
+        LogError("File output error");
+        ReThrowMsg(DPL::CopyFailed, std::string("File output error") + to.Fullpath());
+    }
+    Catch(DPL::CopyFailed)
+    {
+        LogError("File copy error");
+        ReThrowMsg(DPL::CopyFailed, std::string("File copy error") + from.Fullpath());
+    }
+}
+
+void CopyDir(const Path & from, const Path & to)
+{
+    from.RootGuard();
+    to.RootGuard();
+    if(from.isSubPath(to))
+    {
+        ThrowMsg(Path::CannotCopy, "Cannot copy content of directory to it's sub directory");
+    }
+    MakeDir(to);
+    FOREACH(item, from)
+    {
+        if(item->IsDir())
+        {
+            CopyDir(*item, to / item->Filename());
+        }
+        else if(item->IsFile() || item->IsSymlink())
+        {
+            CopyFile(*item, to / item->Filename());
+        }
+        else
+        {
+            Throw(Path::OperationFailed);
+        }
+    }
+}
+
 bool Exists(const Path & path)
 {
     return path.Exists();
index 1a86a21..4e957e2 100644 (file)
@@ -28,6 +28,9 @@
 #include <dpl/utils/path.h>
 #include <dpl/foreach.h>
 #include <dpl/log/log.h>
+#include <dpl/binary_queue.h>
+#include <dpl/file_input.h>
+#include <dpl/file_output.h>
 
 #include <sys/stat.h>
 #include <unistd.h>
@@ -39,6 +42,17 @@ namespace {
 std::string rootTest = "/tmp/wrttest/";
 }
 
+#define ROOTGUARD_TESTMETHOD(FUNC)                                                         \
+{                                                                                          \
+    bool catched = false;                                                                  \
+    Try {                                                                                  \
+        FUNC;                                                                              \
+    } Catch(Path::RootDirectoryError) {                                                    \
+        catched = true;                                                                    \
+    }                                                                                      \
+    RUNNER_ASSERT_MSG(catched, "Use of method should be protected against root diretory"); \
+}                                                                                          \
+
 RUNNER_TEST_GROUP_INIT(DPL_Path)
 
 /*
@@ -51,6 +65,7 @@ RUNNER_TEST(path_mkfile)
     DPL::ScopedDir sd(rootTest);
 
     struct stat st;
+    memset(&st, 0, sizeof(struct stat));
     Path path = Path(rootTest) / "touch.txt";
     RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) != 0, "File should not be created");
     RUNNER_ASSERT(!path.Exists());
@@ -118,6 +133,7 @@ RUNNER_TEST(path_mkdir)
     DPL::ScopedDir sd(rootTest);
 
     struct stat st;
+    memset(&st, 0, sizeof(struct stat));
     Path path = Path(rootTest) / "touchDir";
     RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) != 0, "Directory should not be created");
     RUNNER_ASSERT(!path.Exists());
@@ -139,6 +155,7 @@ RUNNER_TEST(path_symlink)
     DPL::ScopedDir sd(rootTest);
 
     struct stat st;
+    memset(&st, 0, sizeof(struct stat));
     Path path = Path(rootTest) / "symlink";
     RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) != 0, "Symlink should not be created");
     RUNNER_ASSERT(!path.Exists());
@@ -178,7 +195,7 @@ RUNNER_TEST(path_construction_root)
 {
     Path path1(std::string("/"));
     RUNNER_ASSERT(path1.Fullpath() == "/");
-    RUNNER_ASSERT(path1.Basename() == "");
+    RUNNER_ASSERT(path1.Filename() == "");
     bool passed = false;
     Try
     {
@@ -202,7 +219,7 @@ RUNNER_TEST(path_construction_1)
 
     Path path1(std::string("/test/bin/file"));
     RUNNER_ASSERT(path1.Fullpath() == "/test/bin/file");
-    RUNNER_ASSERT(path1.Basename() == "file");
+    RUNNER_ASSERT(path1.Filename() == "file");
     RUNNER_ASSERT(path1.DirectoryName() == "/test/bin");
 }
 
@@ -218,7 +235,7 @@ RUNNER_TEST(path_construction_2)
 
     Path path2(std::string("test/bin/file.eas"));
     RUNNER_ASSERT(path2.Fullpath() == cwd + "/test/bin/file.eas");
-    RUNNER_ASSERT(path2.Basename() == "file.eas");
+    RUNNER_ASSERT(path2.Filename() == "file.eas");
     RUNNER_ASSERT(path2.DirectoryName() == cwd + "/test/bin");
 }
 
@@ -234,7 +251,7 @@ RUNNER_TEST(path_construction_3)
 
     Path path3("test/23/abc");
     RUNNER_ASSERT(path3.Fullpath() == cwd + "/test/23/abc");
-    RUNNER_ASSERT(path3.Basename() == "abc");
+    RUNNER_ASSERT(path3.Filename() == "abc");
     RUNNER_ASSERT(path3.DirectoryName() == cwd + "/test/23");
 }
 
@@ -249,7 +266,7 @@ RUNNER_TEST(path_construction_4)
 
     Path path4("/test/bin/abc");
     RUNNER_ASSERT(path4.Fullpath() == "/test/bin/abc");
-    RUNNER_ASSERT(path4.Basename() == "abc");
+    RUNNER_ASSERT(path4.Filename() == "abc");
     RUNNER_ASSERT(path4.DirectoryName() == "/test/bin");
 }
 
@@ -265,7 +282,7 @@ RUNNER_TEST(path_construction_5)
 
     Path path5(DPL::String(L"test/bin/file.st.exe"));
     RUNNER_ASSERT(path5.Fullpath() == cwd + "/test/bin/file.st.exe");
-    RUNNER_ASSERT(path5.Basename() == "file.st.exe");
+    RUNNER_ASSERT(path5.Filename() == "file.st.exe");
     RUNNER_ASSERT(path5.DirectoryName() == cwd + "/test/bin");
 }
 
@@ -280,7 +297,7 @@ RUNNER_TEST(path_construction_6)
 
     Path path6(DPL::String(L"/test/bin/file"));
     RUNNER_ASSERT(path6.Fullpath() == "/test/bin/file");
-    RUNNER_ASSERT(path6.Basename() == "file");
+    RUNNER_ASSERT(path6.Filename() == "file");
     RUNNER_ASSERT(path6.DirectoryName() == "/test/bin");
 }
 
@@ -296,7 +313,7 @@ RUNNER_TEST(path_construction_7)
 
     Path path7 = Path("test") / "a///23/lol";
     RUNNER_ASSERT(path7.Fullpath() == cwd + "/test/a/23/lol");
-    RUNNER_ASSERT(path7.Basename() == "lol");
+    RUNNER_ASSERT(path7.Filename() == "lol");
     RUNNER_ASSERT(path7.DirectoryName() == cwd + "/test/a/23");
 }
 
@@ -311,7 +328,7 @@ RUNNER_TEST(path_construction_8)
 
     Path path8 = Path("/test/bin/") / "123" / "dir1.dll";
     RUNNER_ASSERT(path8.Fullpath() == "/test/bin/123/dir1.dll");
-    RUNNER_ASSERT(path8.Basename() == "dir1.dll");
+    RUNNER_ASSERT(path8.Filename() == "dir1.dll");
     RUNNER_ASSERT(path8.DirectoryName() ==  "/test/bin/123");
 }
 
@@ -326,7 +343,7 @@ RUNNER_TEST(path_construction_9)
 
     Path path9 = Path("/test/bin/file.txt//");
     RUNNER_ASSERT(path9.Fullpath() == "/test/bin/file.txt");
-    RUNNER_ASSERT(path9.Basename() == "file.txt");
+    RUNNER_ASSERT(path9.Filename() == "file.txt");
     RUNNER_ASSERT(path9.DirectoryName() ==  "/test/bin");
 }
 
@@ -342,7 +359,7 @@ RUNNER_TEST(path_construction_10)
     path10 /= std::string("two");
     path10 /= DPL::String(L"three");
     RUNNER_ASSERT(path10.Fullpath() == "/test/one/two/three");
-    RUNNER_ASSERT(path10.Basename() == "three");
+    RUNNER_ASSERT(path10.Filename() == "three");
     RUNNER_ASSERT(path10.DirectoryName() ==  "/test/one/two");
 }
 
@@ -356,6 +373,7 @@ RUNNER_TEST(path_remove_valid)
     DPL::ScopedDir sd(rootTest);
 
     struct stat st;
+    memset(&st, 0, sizeof(struct stat));
     Path path = Path(rootTest) / "touchDir";
     RUNNER_ASSERT(!path.Exists());
 
@@ -377,6 +395,39 @@ RUNNER_TEST(path_remove_valid)
 }
 
 /*
+Name: path_try_remove
+Description: tests removing paths
+Expected: successfull path remove once
+*/
+RUNNER_TEST(path_try_remove_valid)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    struct stat st;
+    memset(&st, 0, sizeof(struct stat));
+    Path path = Path(rootTest) / "touchDir";
+    RUNNER_ASSERT(!path.Exists());
+
+    MakeDir(path);
+    RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) == 0, "Directory should be created");
+    RUNNER_ASSERT(path.Exists());
+
+    RUNNER_ASSERT(TryRemove(path));
+    RUNNER_ASSERT(!TryRemove(path));
+    RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) != 0, "Directory should not be created");
+    RUNNER_ASSERT(!path.Exists());
+
+    MakeEmptyFile(path);
+    RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) == 0, "File should be created");
+    RUNNER_ASSERT(path.Exists());
+
+    RUNNER_ASSERT(TryRemove(path));
+    RUNNER_ASSERT(!TryRemove(path));
+    RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) != 0, "File should not be created");
+    RUNNER_ASSERT(!path.Exists());
+}
+
+/*
 Name: path_remove_invalid
 Description: tests removing invalid paths
 Expected: failure at path remove
@@ -409,6 +460,7 @@ RUNNER_TEST(path_rename)
     DPL::ScopedDir sd(rootTest);
 
     struct stat st;
+    memset(&st, 0, sizeof(struct stat));
     Path path = Path(rootTest) / "touchDir";
     Path dirpath = Path(rootTest) / "directory";
     Path path2 = dirpath / "touchDir2";
@@ -427,8 +479,220 @@ RUNNER_TEST(path_rename)
     Rename(path2, path);
     RUNNER_ASSERT(path.Exists());
     RUNNER_ASSERT(!path2.Exists());
+}
+
+/*
+Name: path_rename_xdev
+Description: tests path renaming between devices
+Expected: path is successfully renamed
+*/
+RUNNER_TEST(path_rename_xdev)
+{
+    //assuming /opt/usr and /usr is normally on other partitions on device
+    //TODO: better
+    Path path = Path("/opt/usr") / "touchDir";
+    Path dirpath = path / "directory";
+    Path filepath = path / "file.txt";
+
+    Path path2 = Path("/usr") / "touchDir2";
+    Path dirpath2 = path2 / "directory";
+    Path filepath2 = path2 / "file.txt";
+
+    TryRemove(path);
+
+    MakeDir(path);
+    MakeDir(dirpath);
+    MakeEmptyFile(filepath);
+
+    RUNNER_ASSERT(path.Exists());
+    RUNNER_ASSERT(dirpath.Exists());
+    RUNNER_ASSERT(filepath.Exists());
+    RUNNER_ASSERT(!path2.Exists());
+    RUNNER_ASSERT(!dirpath2.Exists());
+    RUNNER_ASSERT(!filepath2.Exists());
+
+    Rename(path, path2);
+    RUNNER_ASSERT(!path.Exists());
+    RUNNER_ASSERT(!dirpath.Exists());
+    RUNNER_ASSERT(!filepath.Exists());
+    RUNNER_ASSERT(path2.Exists());
+    RUNNER_ASSERT(dirpath2.Exists());
+    RUNNER_ASSERT(filepath2.Exists());
+
+    Rename(path2, path);
+    RUNNER_ASSERT(path.Exists());
+    RUNNER_ASSERT(dirpath.Exists());
+    RUNNER_ASSERT(filepath.Exists());
+    RUNNER_ASSERT(!path2.Exists());
+    RUNNER_ASSERT(!dirpath2.Exists());
+    RUNNER_ASSERT(!filepath2.Exists());
+
+    Remove(path);
+}
 
-    //TODO: test for different devices
+/**
+ * Name: path_basename
+ * Description: check basename equivalents
+ * Expected: failure
+ */
+RUNNER_TEST(path_basename)
+{
+    DPL::ScopedDir sd(rootTest);
+    Path path = Path(rootTest) / "directory" / "touch.txt";
+    RUNNER_ASSERT(path.DirectoryName() == path.DirectoryPath().Fullpath());
+    RUNNER_ASSERT(path.DirectoryPath().DirectoryName() == path.DirectoryPath().DirectoryPath().Fullpath());
+}
+
+/**
+ * Name: path_safe
+ * Description: check if operations cannot be executed on root directory
+ *
+ * This is check because of default path is root and it should not be used usually
+ * Default constructor is unfortnatelly easier to use
+ *
+ * Expected: failure
+ */
+RUNNER_TEST(path_safe)
+{
+    DPL::ScopedDir sd(rootTest);
+    Path normal = Path(rootTest) / "directory" / "touch.txt";
+    Path root("/");
+    ROOTGUARD_TESTMETHOD( Rename(normal, root) );
+    ROOTGUARD_TESTMETHOD( Rename(root, root) );
+    ROOTGUARD_TESTMETHOD( Rename(root, normal) );
+    ROOTGUARD_TESTMETHOD( CopyDir(normal, root) );
+    ROOTGUARD_TESTMETHOD( CopyDir(root, root) );
+    ROOTGUARD_TESTMETHOD( CopyDir(root, normal) );
+    ROOTGUARD_TESTMETHOD( CopyFile(normal, root) );
+    ROOTGUARD_TESTMETHOD( CopyFile(root, root) );
+    ROOTGUARD_TESTMETHOD( CopyFile(root, normal) );
+    ROOTGUARD_TESTMETHOD( Remove(root) );
+    ROOTGUARD_TESTMETHOD( MakeEmptyFile(root) );
+    ROOTGUARD_TESTMETHOD( MakeDir(root) );
+}
+
+/**
+ * Name: path_size
+ * Description: check testing size of file
+ * Expected: correct size
+ */
+RUNNER_TEST(path_size)
+{
+    DPL::ScopedDir sd(rootTest);
+    Path path = Path(rootTest) / "touch.txt";
+    DPL::Utils::MakeEmptyFile(path);
+    RUNNER_ASSERT(path.Size() == 0);
+
+    {
+        DPL::FileOutput out(path.Fullpath());
+        DPL::BinaryQueue bq;
+        bq.AppendCopy("123456789", 9);
+        out.Write(bq, bq.Size());
+        out.Close();
+        RUNNER_ASSERT(path.Size() == 9);
+    }
+
+    {
+        DPL::FileOutput out(path.Fullpath());
+        DPL::BinaryQueue bq;
+        bq.AppendCopy("123456789", 4);
+        out.Write(bq, bq.Size());
+        out.Close();
+        RUNNER_ASSERT(path.Size() == 4);
+    }
+}
+
+/**
+Name: path_copy
+Description: tests path coping directory andfiles
+Expected: coping should be done
+*/
+RUNNER_TEST(path_copy_directory)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path path = Path(rootTest) / "sourceDir";
+    Path innerPath = Path(rootTest) / "sourceDir" / "level1" ;
+    Path innerPath2 = Path(rootTest) / "sourceDir" / "level1" / "level2";
+    Path file1 = Path(rootTest) / "sourceDir" / "level1" / "level2" / "file1.txt";
+    Path file2 = Path(rootTest) / "sourceDir" / "level1" / "level2" / "file2.txt";
+    Path file3 = Path(rootTest) / "sourceDir" / "level1" / "file3.txt";
+    Path file4 = Path(rootTest) / "sourceDir" /  "file4.txt";
+
+    Path tfile1 = Path(rootTest) / "targetDir" / "level1" / "level2" / "file1.txt";
+    Path tfile2 = Path(rootTest) / "targetDir" / "level1" / "level2" / "file2.txt";
+    Path tfile3 = Path(rootTest) / "targetDir" / "level1" / "file3.txt";
+    Path tfile4 = Path(rootTest) / "targetDir" /  "file4.txt";
+
+    Path target = Path(rootTest) / "targetDir";
+
+    DPL::Utils::MakeDir(path);
+    DPL::Utils::MakeDir(innerPath);
+    DPL::Utils::MakeDir(innerPath2);
+    DPL::Utils::MakeEmptyFile(file1);
+    DPL::Utils::MakeEmptyFile(file2);
+    DPL::Utils::MakeEmptyFile(file3);
+    DPL::Utils::MakeEmptyFile(file4);
+
+    DPL::Utils::CopyDir(path, target);
+
+    RUNNER_ASSERT_MSG(tfile1.Exists(), tfile1.Fullpath() + " not exists");
+    RUNNER_ASSERT_MSG(tfile1.IsFile(), tfile1.Fullpath() + " is not file");
+    RUNNER_ASSERT_MSG(tfile2.Exists(), tfile2.Fullpath() + " not exists");
+    RUNNER_ASSERT_MSG(tfile2.IsFile(), tfile2.Fullpath() + " is not file");
+    RUNNER_ASSERT_MSG(tfile3.Exists(), tfile3.Fullpath() + " not exists");
+    RUNNER_ASSERT_MSG(tfile3.IsFile(), tfile3.Fullpath() + " is not file");
+    RUNNER_ASSERT_MSG(tfile4.Exists(), tfile4.Fullpath() + " not exists");
+    RUNNER_ASSERT_MSG(tfile4.IsFile(), tfile4.Fullpath() + " is not file");
+}
+
+/*
+Name: path_copy_inner
+Description: tests path coping to subdirectory
+Expected: coping shoudl fail
+*/
+RUNNER_TEST(path_copy_inner)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path path = Path(rootTest) / "touchDir";
+    Path inner = Path(rootTest) / "touchDir" / "innerDirectory";
+
+    bool exceptionCatched = false;
+    Try
+    {
+        DPL::Utils::CopyDir(path, inner);
+    }
+    Catch(DPL::Utils::Path::CannotCopy)
+    {
+        exceptionCatched = true;
+    }
+    RUNNER_ASSERT_MSG(exceptionCatched, "Copy should fail");
+}
+
+/*
+Name: issubpath
+Description: tests method compare if one path is subpath of another
+Expected: correct results
+*/
+RUNNER_TEST(path_issubpath)
+{
+    Path path1 = Path(rootTest) / "touchDir/asd/sdf";
+    Path path2 = Path(rootTest) / "touchDir/asd/sdf/123";
+    Path path3 = Path(rootTest) / "touchDir/asd/sdno";
+    Path path4 = Path("/");
+
+    RUNNER_ASSERT(path1.isSubPath(path2));
+    RUNNER_ASSERT(!path1.isSubPath(path3));
+    RUNNER_ASSERT(!path1.isSubPath(path4));
+
+    RUNNER_ASSERT(!path2.isSubPath(path1));
+    RUNNER_ASSERT(!path2.isSubPath(path3));
+    RUNNER_ASSERT(!path2.isSubPath(path4));
+
+    RUNNER_ASSERT(path4.isSubPath(path1));
+    RUNNER_ASSERT(path4.isSubPath(path2));
+    RUNNER_ASSERT(path4.isSubPath(path3));
 }
 
 /*
@@ -441,6 +705,7 @@ RUNNER_TEST(path_rename_same)
     DPL::ScopedDir sd(rootTest);
 
     struct stat st;
+    memset(&st, 0, sizeof(struct stat));
     Path path = Path(rootTest) / "touchDir";
 
     MakeDir(path);