From: Tomasz Iwanek Date: Mon, 25 Feb 2013 15:36:11 +0000 (+0100) Subject: Path class for DPL + tests X-Git-Tag: 2.1b_release~6^2~11 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1ed4d742847fa973d40ed681deb67aa9f5374f19;p=framework%2Fweb%2Fwrt-commons.git Path class for DPL + tests [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 --- diff --git a/modules/utils/config.cmake b/modules/utils/config.cmake index aac2fce..828ca6c 100644 --- a/modules/utils/config.cmake +++ b/modules/utils/config.cmake @@ -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 index 0000000..6e025db --- /dev/null +++ b/modules/utils/include/dpl/utils/path.h @@ -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 +#include + +#include +#include +#include +#include +#include + +#include +#include + +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 + { + 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 m_dir; + std::shared_ptr m_path; + std::shared_ptr 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 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 index 0000000..5ce44a1 --- /dev/null +++ b/modules/utils/src/path.cpp @@ -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 + +#include +#include +#include +#include +#include + +#include + +namespace DPL { + +namespace Utils { + +Path::Iterator::Iterator() //end iterator by default +{ +} + +Path::Iterator::Iterator(const char * str) +{ + m_root = std::shared_ptr(new Path(str)); + m_dir = std::shared_ptr(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(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 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 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); +//} diff --git a/tests/utils/CMakeLists.txt b/tests/utils/CMakeLists.txt index 9898084..f17421b 100644 --- a/tests/utils/CMakeLists.txt +++ b/tests/utils/CMakeLists.txt @@ -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 index 0000000..1a86a21 --- /dev/null +++ b/tests/utils/path_tests.cpp @@ -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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +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 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 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 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 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 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 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 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 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 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 resultSet; + std::set 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 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 iter2(new Path::Iterator( (*iter1))); + iter1.reset(); + (*iter2)++; + ++(*iter2); + RUNNER_ASSERT_MSG(*iter2 == dirTest.end(), "Iterator is in broken state"); + iter2.reset(); +}