Path class for DPL + tests
authorTomasz Iwanek <t.iwanek@samsung.com>
Mon, 25 Feb 2013 15:36:11 +0000 (16:36 +0100)
committerGerrit Code Review <gerrit2@kim11>
Thu, 7 Mar 2013 09:54:01 +0000 (18:54 +0900)
[Issue#]       LINUXWRT-86
[Feature]      There is no utility for encapsulate paths
[Cause]        Path is constructed manually
[Solution]     Path abstarction
[Verification] Build repository. Run:
   wrt-commons-tests-utils --output=text --regexp='path_'

Change-Id: Iede9100de7a3c94e7f45256d94599c4114281c04

modules/utils/config.cmake
modules/utils/include/dpl/utils/path.h [new file with mode: 0644]
modules/utils/src/path.cpp [new file with mode: 0644]
tests/utils/CMakeLists.txt
tests/utils/path_tests.cpp [new file with mode: 0644]

index aac2fce..828ca6c 100644 (file)
@@ -27,6 +27,7 @@ SET(DPL_UTILS_SOURCES
     ${PROJECT_SOURCE_DIR}/modules/utils/src/widget_version.cpp
     ${PROJECT_SOURCE_DIR}/modules/utils/src/wrt_global_settings.cpp
     ${PROJECT_SOURCE_DIR}/modules/utils/src/wrt_utility.cpp
+    ${PROJECT_SOURCE_DIR}/modules/utils/src/path.cpp
     PARENT_SCOPE
 )
 
@@ -38,6 +39,7 @@ SET(DPL_UTILS_HEADERS
     ${PROJECT_SOURCE_DIR}/modules/utils/include/dpl/utils/widget_version.h
     ${PROJECT_SOURCE_DIR}/modules/utils/include/dpl/utils/wrt_global_settings.h
     ${PROJECT_SOURCE_DIR}/modules/utils/include/dpl/utils/wrt_utility.h
+    ${PROJECT_SOURCE_DIR}/modules/utils/include/dpl/utils/path.h
     PARENT_SCOPE
 )
 
diff --git a/modules/utils/include/dpl/utils/path.h b/modules/utils/include/dpl/utils/path.h
new file mode 100644 (file)
index 0000000..6e025db
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file    path.h
+ * @author  Tomasz Iwanek (t.iwanek@samsung.com)
+ * @version 1.0
+ */
+#ifndef PATH_H
+#define PATH_H
+
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include <string>
+#include <sstream>
+#include <iterator>
+#include <memory>
+#include <vector>
+
+#include <dpl/exception.h>
+#include <dpl/string.h>
+
+namespace DPL {
+namespace Utils {
+class Path;
+}
+}
+
+std::ostream & operator<<(std::ostream & str, const DPL::Utils::Path & path);
+
+namespace DPL {
+namespace Utils {
+/**
+ * @brief The Path class path abstraction
+ *
+ * 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
+ */
+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)
+
+    class Iterator : public std::iterator<std::input_iterator_tag, Path>
+    {
+    public:
+        Iterator();
+        Iterator(const char *);
+        Iterator& operator++();
+        Iterator operator++(int);
+        bool operator==(const Iterator& rhs) const;
+        bool operator!=(const Iterator& rhs) const;
+        const Path & operator*();
+        const Path * operator->();
+    private:
+        void ReadNext();
+
+        std::shared_ptr<DIR> m_dir;
+        std::shared_ptr<Path> m_path;
+        std::shared_ptr<Path> m_root;
+    };
+
+    explicit Path(const DPL::String & str);
+    explicit Path(const std::string & str);
+    explicit Path(const char * str);
+
+    /**
+     * @brief DirectoryName shell's dirname equivalent
+     * @return directory name of given path
+     */
+    std::string DirectoryName() const;
+    /**
+     * @brief Basename shell's basename equivalent
+     * @return base name of given path
+     */
+    std::string Basename() const;
+    /**
+     * @brief Fullpath fullpath based on current working diretory
+     * @return full path
+     */
+    std::string Fullpath() const;
+
+    bool Exists() const;
+    bool IsDir() const;
+    bool IsFile() const;
+    bool IsSymlink() const;
+
+    bool operator==(const Path & other) const;
+    bool operator!=(const Path & other) const;
+
+    //appending to path
+    Path operator/(const DPL::String& part) const;
+    Path operator/(const std::string& part) const;
+    Path operator/(const char * part) const;
+
+    Path & operator/=(const DPL::String& part);
+    Path & operator/=(const std::string& part);
+    Path & operator/=(const char * part);
+
+    //foreach
+    Iterator begin() const;
+    Iterator end() const;
+
+private:
+    Path();
+
+    void Append(const std::string& part);
+    void Construct(const std::string & src);
+
+    std::vector<std::string> m_parts;
+
+    friend std::ostream & ::operator<<(std::ostream & str, const DPL::Utils::Path & path);
+};
+
+/**
+ * @brief MkDir creates 'current path' as directory
+ * @param path path
+ * @param mode mode
+ */
+void MakeDir(const Path & path, mode_t mode = 0755);
+
+/**
+ * @brief MkFile creates 'current path' as empty file
+ * @param path path
+ */
+void MakeEmptyFile(const Path & path);
+
+/**
+ * @brief Remove removes 'current path'
+ * @param path path to remove
+ */
+void Remove(const Path & path);
+
+/**
+ * @brief Rename renames(moves) current path
+ *
+ * If you uses this method string to path is internally change
+ * and this object will store new path not only anymore
+ * @param from source path
+ * @param to target path
+ */
+void Rename(const Path & from, const Path & to);
+
+/**
+ * @brief Exists Checks if given path exists
+ * @param path path
+ * @return true if path exists
+ */
+bool Exists(const Path & path);
+
+}
+
+}
+
+//TODO: uncomment when user defiend literals are supported
+///Path operator"" p(const char * str);
+
+#endif // PATH_H
diff --git a/modules/utils/src/path.cpp b/modules/utils/src/path.cpp
new file mode 100644 (file)
index 0000000..5ce44a1
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file    path.h
+ * @author  Tomasz Iwanek (t.iwanek@samsung.com)
+ * @version 1.0
+ */
+
+#include "dpl/utils/path.h"
+
+#include <dpl/utils/wrt_utility.h>
+
+#include <dpl/scoped_free.h>
+#include <dpl/errno_string.h>
+#include <dpl/file_input.h>
+#include <dpl/file_output.h>
+#include <dpl/copy.h>
+
+#include <sys/stat.h>
+
+namespace DPL {
+
+namespace Utils {
+
+Path::Iterator::Iterator() //end iterator by default
+{
+}
+
+Path::Iterator::Iterator(const char * str)
+{
+    m_root = std::shared_ptr<Path>(new Path(str));
+    m_dir = std::shared_ptr<DIR>(opendir(str), [](DIR * d){ if(d)closedir(d); }); //custom delete
+    if(m_dir.get() == NULL)
+    {
+        ThrowMsg(NotDirectory, "Not directory");
+    }
+    ReadNext();
+}
+
+Path::Iterator& Path::Iterator::operator++()
+{
+    ReadNext();
+    return *this;
+}
+
+Path::Iterator Path::Iterator::operator++(int)
+{
+    Path::Iterator copy(*this);
+    ReadNext();
+    return copy;
+}
+
+void Path::Iterator::ReadNext()
+{
+    struct dirent * entry = readdir(m_dir.get());
+    while(entry && (strcmp(entry->d_name, ".") == 0 ||
+          strcmp(entry->d_name, "..") == 0))
+    {
+        entry = readdir(m_dir.get());
+    }
+    if(entry)
+    {
+        m_path = std::shared_ptr<Path>(new Path(*m_root));
+        m_path->Append(entry->d_name);
+    }
+    else //transform into end iterator
+    {
+        m_path.reset();
+        m_dir.reset();
+    }
+}
+
+bool Path::Iterator::operator==(const Path::Iterator& rhs) const
+{
+    if(m_dir.get() == NULL)
+    {
+        if(rhs.m_dir.get() == NULL) return true;
+        else return false;
+    }
+    else
+    {
+        if(rhs.m_dir.get() == NULL) return false;
+    }
+    return *m_path == *rhs.m_path;
+}
+
+bool Path::Iterator::operator!=(const Path::Iterator& rhs) const
+{
+    return !this->operator==(rhs);
+}
+
+const Path & Path::Iterator::operator*()
+{
+    return *m_path;
+}
+
+const Path * Path::Iterator::operator->()
+{
+    return m_path.get();
+}
+
+Path::Path(const DPL::String & str)
+{
+    Construct(ToUTF8String(str));
+}
+
+Path::Path(const std::string & str)
+{
+    Construct(str);
+}
+
+Path::Path(const char * str)
+{
+    Construct(std::string(str));
+}
+
+void Path::Construct(const std::string & src)
+{
+    if(src.empty()) ThrowMsg(EmptyPath, "Path cannot be empty");
+    if(src[0] != '/')
+    {
+        DPL::ScopedFree<char> root(getcwd(NULL,0));
+        Tokenize(std::string(root.Get()), "\\/", std::inserter(m_parts, m_parts.begin()), true);
+    }
+    Tokenize(src, "\\/", std::inserter(m_parts, m_parts.end()), true);
+}
+
+Path::Path() //for private usage
+{
+}
+
+std::string Path::DirectoryName() const
+{
+    if(m_parts.empty()) ThrowMsg(InternalError, "Asking DirectoryName for root directory");
+    std::string ret = Join(m_parts.begin(), --m_parts.end(), "/");
+    return std::string("/") + ret;
+}
+
+std::string Path::Basename() const
+{
+    if(m_parts.empty()) return "";
+    else return m_parts.back();
+}
+
+std::string Path::Fullpath() const
+{
+    std::string ret = Join(m_parts.begin(), m_parts.end(), "/");
+    return std::string ("/") + ret;
+}
+
+//foreach
+Path::Iterator Path::begin() const
+{
+    if(IsDir())
+    {
+        return Iterator(Fullpath().c_str());
+    }
+    else
+    {
+        ThrowMsg(NotDirectory, "Cannot iterate not a directory");
+    }
+}
+
+Path::Iterator Path::end() const
+{
+    return Iterator();
+}
+
+
+bool Path::Exists() const
+{
+    struct stat tmp;
+    return (0 == lstat(Fullpath().c_str(), &tmp));
+}
+
+bool Path::IsDir() const
+{
+    struct stat tmp;
+    if (-1 == lstat(Fullpath().c_str(), &tmp))
+    {
+        ThrowMsg(NotExists, DPL::GetErrnoString());
+    }
+    return S_ISDIR(tmp.st_mode);
+}
+
+bool Path::IsFile() const
+{
+    struct stat tmp;
+    if (-1 == lstat(Fullpath().c_str(), &tmp))
+    {
+        ThrowMsg(NotExists, DPL::GetErrnoString());
+    }
+    return S_ISREG(tmp.st_mode);
+}
+
+bool Path::IsSymlink() const
+{
+    struct stat tmp;
+    if (-1 == lstat(Fullpath().c_str(), &tmp))
+    {
+        ThrowMsg(NotExists, DPL::GetErrnoString());
+    }
+    return S_ISLNK(tmp.st_mode);
+}
+
+bool Path::operator==(const Path & other) const
+{
+    return m_parts == other.m_parts;
+}
+
+bool Path::operator!=(const Path & other) const
+{
+    return m_parts != other.m_parts;
+}
+
+Path Path::operator/(const DPL::String& part) const
+{
+    Path newOne;
+    newOne.Append(ToUTF8String(part));
+    return newOne;
+}
+
+Path Path::operator/(const std::string& part) const
+{
+    Path newOne;
+    newOne.Append(part);
+    return newOne;
+}
+
+Path Path::operator/(const char * part) const
+{
+    Path newOne(*this);
+    newOne.Append(std::string(part));
+    return newOne;
+}
+
+Path & Path::operator/=(const DPL::String& part)
+{
+    Append(ToUTF8String(part));
+}
+
+Path & Path::operator/=(const std::string& part)
+{
+    Append(part);
+}
+
+Path & Path::operator/=(const char * part)
+{
+    Append(std::string(part));
+}
+
+void Path::Append(const std::string& part)
+{
+    std::vector<std::string> tokens;
+    Tokenize(part, "\\/", std::inserter(tokens, tokens.end()), true);
+    std::copy(tokens.begin(), tokens.end(), std::inserter(m_parts, m_parts.end()));
+}
+
+void MakeDir(const Path & path, mode_t mode)
+{
+    if(!WrtUtilMakeDir(path.Fullpath(), mode)) ThrowMsg(Path::OperationFailed, "Cannot make directory");
+}
+
+void MakeEmptyFile(const Path & path)
+{
+    std::string fp = path.Fullpath();
+    FILE* fd = fopen(fp.c_str(), "wx");
+    if(!fd)
+    {
+        struct stat st;
+        if(lstat(fp.c_str(), &st) == 0)
+        {
+            ThrowMsg(Path::AlreadyExists, "File already exists");
+        }
+        else
+        {
+            ThrowMsg(Path::OperationFailed, "Operation failed");
+        }
+    }
+    fclose(fd);
+}
+
+void Remove(const Path & path)
+{
+    if(!WrtUtilRemove(path.Fullpath())) ThrowMsg(Path::OperationFailed, "Cannot remove path");
+}
+
+void Rename(const Path & from, const Path & to)
+{
+    if(from == to)
+    {
+        return;
+    }
+    int code = 0;
+    if( (code = rename(from.Fullpath().c_str(), to.Fullpath().c_str())) )
+    {
+        if(code == EXDEV)
+        {
+            Try
+            {
+                DPL::FileInput in(from.Fullpath());
+                DPL::FileOutput out(to.Fullpath());
+                DPL::Copy(&in, &out);
+            }
+            Catch(DPL::FileInput::Exception::Base)
+            {
+                ThrowMsg(Path::OperationFailed, "Cannot open input file " << from.Fullpath());
+            }
+            Catch(DPL::FileOutput::Exception::Base)
+            {
+                ThrowMsg(Path::OperationFailed, "Cannot open output file " << to.Fullpath());
+            }
+        }
+        else
+        {
+            ThrowMsg(Path::OperationFailed, DPL::GetErrnoString());
+        }
+    }
+}
+
+bool Exists(const Path & path)
+{
+    return path.Exists();
+}
+
+}
+
+}
+
+std::ostream & operator<<(std::ostream & str, const DPL::Utils::Path & path)
+{
+    str << path.Fullpath();
+    return str;
+}
+
+//TODO: uncomment when used defiend literals are supported
+///DPL::Utils::Path operator""p(const char * str, size_t)
+//{
+//    return DPL::Utils::Path(str);
+//}
index 9898084..f17421b 100644 (file)
@@ -26,6 +26,7 @@ SET(DPL_TESTS_UTIL_SOURCES
     ${TESTS_DIR}/utils/widget_version.cpp
     ${TESTS_DIR}/utils/bash_utils.cpp
     ${TESTS_DIR}/utils/wrt_utility.cpp
+    ${TESTS_DIR}/utils/path_tests.cpp
 )
 
 #WRT_TEST_ADD_INTERNAL_DEPENDENCIES(${TARGET_NAME} ${TARGET_DPL_UTILS_EFL})
diff --git a/tests/utils/path_tests.cpp b/tests/utils/path_tests.cpp
new file mode 100644 (file)
index 0000000..1a86a21
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file    path.h
+ * @author  Tomasz Iwanek (t.iwanek@samsung.com)
+ * @version 1.0
+ */
+
+#include <set>
+#include <memory>
+
+#include <dpl/test/test_runner.h>
+#include <dpl/scoped_dir.h>
+#include <dpl/scoped_free.h>
+#include <dpl/utils/path.h>
+#include <dpl/foreach.h>
+#include <dpl/log/log.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+using namespace DPL::Utils;
+
+namespace {
+//do not used path here we test it
+std::string rootTest = "/tmp/wrttest/";
+}
+
+RUNNER_TEST_GROUP_INIT(DPL_Path)
+
+/*
+Name: path_touch
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_mkfile)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    struct stat st;
+    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());
+    MakeEmptyFile(path);
+    RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) == 0, "File should be created");
+    RUNNER_ASSERT(path.Exists());
+    RUNNER_ASSERT(path.IsFile());
+    RUNNER_ASSERT(!path.IsDir());
+    RUNNER_ASSERT(!path.IsSymlink());
+}
+
+/*
+Name: path_touch
+Description: tries to craete file when it exists
+Expected: failure
+*/
+RUNNER_TEST(path_mkfile_exists)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path path = Path(rootTest) / "touch.txt";
+    MakeEmptyFile(path);
+    RUNNER_ASSERT(path.Exists());
+    bool cannotCreate2ndTime = false;
+    Try
+    {
+        MakeEmptyFile(path);
+    }
+    Catch(Path::AlreadyExists)
+    {
+        cannotCreate2ndTime = true;
+    }
+    RUNNER_ASSERT_MSG(cannotCreate2ndTime, "File created should not be able to be created second time");
+}
+
+/*
+Name: path_mkfile_invalid_path
+Description: tries to create file in not exisitng directory
+Expected: failure at creation
+*/
+RUNNER_TEST(path_mkfile_invalid_path)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path path = Path(rootTest) / "not_existing" / "touch.txt";
+    bool cannotCreate = false;
+    Try
+    {
+        MakeEmptyFile(path);
+    }
+    Catch(Path::OperationFailed)
+    {
+        cannotCreate = true;
+    }
+    RUNNER_ASSERT_MSG(cannotCreate, "File created should not be able to be created");
+}
+
+/*
+Name: path_mkdir
+Description: creates valid directory
+Expected: success direcotry creation
+*/
+RUNNER_TEST(path_mkdir)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    struct stat st;
+    Path path = Path(rootTest) / "touchDir";
+    RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) != 0, "Directory should not be created");
+    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(!path.IsFile());
+    RUNNER_ASSERT(path.IsDir());
+    RUNNER_ASSERT(!path.IsSymlink());
+}
+
+/*
+Name: path_symlink
+Description: chekc if symlink is correctly recognized
+Expected: method isSymlink returns true
+*/
+RUNNER_TEST(path_symlink)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    struct stat st;
+    Path path = Path(rootTest) / "symlink";
+    RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) != 0, "Symlink should not be created");
+    RUNNER_ASSERT(!path.Exists());
+    (void)symlink("/nonexistisfile/file/file/file ", path.Fullpath().c_str());
+    RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) == 0, "Symlink should be created");
+    RUNNER_ASSERT(path.Exists());
+    RUNNER_ASSERT(!path.IsFile());
+    RUNNER_ASSERT(!path.IsDir());
+    RUNNER_ASSERT(path.IsSymlink());
+}
+
+/*
+Name: path_construction_empty
+Description: tries to construct empty path
+Expected: failure
+*/
+RUNNER_TEST(path_construction_empty)
+{
+    bool passed = false;
+    Try
+    {
+        Path path1(std::string(""));
+    }
+    Catch(Path::EmptyPath)
+    {
+        passed = true;
+    }
+    RUNNER_ASSERT_MSG(passed, "Construction with empty path do not fails");
+}
+
+/*
+Name: path_construction_root
+Description: tries to construct root path
+Expected: success
+*/
+RUNNER_TEST(path_construction_root)
+{
+    Path path1(std::string("/"));
+    RUNNER_ASSERT(path1.Fullpath() == "/");
+    RUNNER_ASSERT(path1.Basename() == "");
+    bool passed = false;
+    Try
+    {
+        RUNNER_ASSERT(path1.DirectoryName() == "/");
+    }
+    Catch(Path::InternalError)
+    {
+        passed = true;
+    }
+    RUNNER_ASSERT_MSG(passed, "Directory name for root should be an error");
+}
+
+/*
+Name: path_construction_1
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_1)
+{
+    DPL::ScopedFree<char> sf(getcwd(NULL, 0));
+
+    Path path1(std::string("/test/bin/file"));
+    RUNNER_ASSERT(path1.Fullpath() == "/test/bin/file");
+    RUNNER_ASSERT(path1.Basename() == "file");
+    RUNNER_ASSERT(path1.DirectoryName() == "/test/bin");
+}
+
+/*
+Name: path_construction_2
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_2)
+{
+    DPL::ScopedFree<char> sf(getcwd(NULL, 0));
+    std::string cwd(sf.Get());
+
+    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.DirectoryName() == cwd + "/test/bin");
+}
+
+/*
+Name: path_construction_3
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_3)
+{
+    DPL::ScopedFree<char> sf(getcwd(NULL, 0));
+    std::string cwd(sf.Get());
+
+    Path path3("test/23/abc");
+    RUNNER_ASSERT(path3.Fullpath() == cwd + "/test/23/abc");
+    RUNNER_ASSERT(path3.Basename() == "abc");
+    RUNNER_ASSERT(path3.DirectoryName() == cwd + "/test/23");
+}
+
+/*
+Name: path_construction_4
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_4)
+{
+    DPL::ScopedFree<char> sf(getcwd(NULL, 0));
+
+    Path path4("/test/bin/abc");
+    RUNNER_ASSERT(path4.Fullpath() == "/test/bin/abc");
+    RUNNER_ASSERT(path4.Basename() == "abc");
+    RUNNER_ASSERT(path4.DirectoryName() == "/test/bin");
+}
+
+/*
+Name: path_construction_5
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_5)
+{
+    DPL::ScopedFree<char> sf(getcwd(NULL, 0));
+    std::string cwd(sf.Get());
+
+    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.DirectoryName() == cwd + "/test/bin");
+}
+
+/*
+Name: path_construction_6
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_6)
+{
+    DPL::ScopedFree<char> sf(getcwd(NULL, 0));
+
+    Path path6(DPL::String(L"/test/bin/file"));
+    RUNNER_ASSERT(path6.Fullpath() == "/test/bin/file");
+    RUNNER_ASSERT(path6.Basename() == "file");
+    RUNNER_ASSERT(path6.DirectoryName() == "/test/bin");
+}
+
+/*
+Name: path_construction_7
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_7)
+{
+    DPL::ScopedFree<char> sf(getcwd(NULL, 0));
+    std::string cwd(sf.Get());
+
+    Path path7 = Path("test") / "a///23/lol";
+    RUNNER_ASSERT(path7.Fullpath() == cwd + "/test/a/23/lol");
+    RUNNER_ASSERT(path7.Basename() == "lol");
+    RUNNER_ASSERT(path7.DirectoryName() == cwd + "/test/a/23");
+}
+
+/*
+Name: path_construction_8
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_8)
+{
+    DPL::ScopedFree<char> sf(getcwd(NULL, 0));
+
+    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.DirectoryName() ==  "/test/bin/123");
+}
+
+/*
+Name: path_construction_9
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_9)
+{
+    DPL::ScopedFree<char> sf(getcwd(NULL, 0));
+
+    Path path9 = Path("/test/bin/file.txt//");
+    RUNNER_ASSERT(path9.Fullpath() == "/test/bin/file.txt");
+    RUNNER_ASSERT(path9.Basename() == "file.txt");
+    RUNNER_ASSERT(path9.DirectoryName() ==  "/test/bin");
+}
+
+/*
+Name: path_construction_10
+Description: constructs paths by appending
+Expected: success full constrution
+*/
+RUNNER_TEST(path_construction_10)
+{
+    Path path10 = Path("/test/");
+    path10 /= "one";
+    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.DirectoryName() ==  "/test/one/two");
+}
+
+/*
+Name: path_remove
+Description: tests removing paths
+Expected: successfull path remove
+*/
+RUNNER_TEST(path_remove_valid)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    struct stat st;
+    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());
+
+    Remove(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());
+
+    Remove(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
+*/
+RUNNER_TEST(path_remove_invalid)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path path = Path(rootTest) / "touchDir";
+
+    bool removedNotExisting = true;
+    Try
+    {
+        Remove(path);
+    }
+    Catch(Path::OperationFailed)
+    {
+        removedNotExisting = false;
+    }
+    RUNNER_ASSERT_MSG(!removedNotExisting, "Removing not existing file");
+}
+
+/*
+Name: path_rename
+Description: tests path renaming
+Expected: path is successfully renamed
+*/
+RUNNER_TEST(path_rename)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    struct stat st;
+    Path path = Path(rootTest) / "touchDir";
+    Path dirpath = Path(rootTest) / "directory";
+    Path path2 = dirpath / "touchDir2";
+
+    MakeDir(dirpath);
+
+    MakeEmptyFile(path);
+    RUNNER_ASSERT_MSG(lstat(path.Fullpath().c_str(), &st) == 0, "File should be created");
+    RUNNER_ASSERT(path.Exists());
+    RUNNER_ASSERT(!path2.Exists());
+
+    Rename(path, path2);
+    RUNNER_ASSERT(!path.Exists());
+    RUNNER_ASSERT(path2.Exists());
+
+    Rename(path2, path);
+    RUNNER_ASSERT(path.Exists());
+    RUNNER_ASSERT(!path2.Exists());
+
+    //TODO: test for different devices
+}
+
+/*
+Name: path_rename_same
+Description: tests if renam does not brokens file if target location is equal to source location
+Expected: path is avaliable
+*/
+RUNNER_TEST(path_rename_same)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    struct stat st;
+    Path path = Path(rootTest) / "touchDir";
+
+    MakeDir(path);
+    Rename(path, path);
+    RUNNER_ASSERT(path.Exists());
+}
+
+/*
+Name: path_iterate_not_directory
+Description: iterates not a directory
+Expected: success full constrution
+*/
+RUNNER_TEST(path_iterate_not_directory)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path fileTest = Path(rootTest) / "file.txt";
+    MakeEmptyFile(fileTest);
+
+    bool passed = false;
+    Try
+    {
+        FOREACH(file, fileTest)
+        {
+
+        }
+    }
+    Catch(Path::NotDirectory)
+    {
+        passed = true;
+    }
+    RUNNER_ASSERT(passed);
+}
+
+/*
+Name: path_construction
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_iterate_empty_directory)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path dirTest = Path(rootTest) / "directory";
+    MakeDir(dirTest);
+
+    bool passed = true;
+    Try
+    {
+        FOREACH(file, dirTest)
+        {
+            passed = false;
+            LogError("Directory should be empty");
+        }
+    }
+    Catch(Path::NotDirectory)
+    {
+        passed = false;
+        LogError("Directory should exists");
+    }
+    RUNNER_ASSERT(passed);
+}
+
+/*
+Name: path_construction
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_iterate_notempty_directory)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path dirTest = Path(rootTest) / "directory";
+
+    Path path1 = Path(rootTest) / "directory" / "file1";
+    Path path2 = Path(rootTest) / "directory" / "file2";
+    Path path3 = Path(rootTest) / "directory" / "file3";
+
+    std::set<std::string> resultSet;
+    std::set<std::string> testSet;
+    testSet.insert(path1.Fullpath());
+    testSet.insert(path2.Fullpath());
+    testSet.insert(path3.Fullpath());
+
+    MakeDir(dirTest);
+    MakeEmptyFile(path1);
+    MakeEmptyFile(path2);
+    MakeEmptyFile(path3);
+
+    FOREACH(file, dirTest)
+    {
+        resultSet.insert(file->Fullpath());
+    }
+
+    RUNNER_ASSERT_MSG(testSet == resultSet, "Testing");
+}
+
+/*
+Name: path_construction
+Description: constructs paths in many ways
+Expected: success full constrution
+*/
+RUNNER_TEST(path_iterator_copy_constructor)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path dirTest = Path(rootTest) / "directory";
+
+    Path path1 = Path(rootTest) / "directory" / "file1";
+    Path path2 = Path(rootTest) / "directory" / "file2";
+    Path path3 = Path(rootTest) / "directory" / "file3";
+
+    MakeDir(dirTest);
+    MakeEmptyFile(path1);
+    MakeEmptyFile(path2);
+    MakeEmptyFile(path3);
+
+    std::shared_ptr<Path::Iterator> iter1(new Path::Iterator((Path(rootTest) / "directory").Fullpath().c_str()));
+
+    //as it's input iterator it's guaranteed for one element to be iterate only once
+    (*iter1)++;
+    std::shared_ptr<Path::Iterator> iter2(new Path::Iterator( (*iter1)));
+    iter1.reset();
+    (*iter2)++;
+    ++(*iter2);
+    RUNNER_ASSERT_MSG(*iter2 == dirTest.end(), "Iterator is in broken state");
+    iter2.reset();
+}