*
* 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>
{
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
*/
* @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
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;
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);
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
*/
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);
+
}
}
#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>
Tokenize(src, "\\/", std::inserter(m_parts, m_parts.end()), true);
}
-Path::Path() //for private usage
+Path::Path()
{
}
return std::string("/") + ret;
}
-std::string Path::Basename() const
+std::string Path::Filename() const
{
if(m_parts.empty()) return "";
else return m_parts.back();
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());
bool Path::IsFile() const
{
struct stat tmp;
+ memset(&tmp, 0, sizeof(struct stat));
if (-1 == lstat(Fullpath().c_str(), &tmp))
{
ThrowMsg(NotExists, DPL::GetErrnoString());
bool Path::IsSymlink() const
{
struct stat tmp;
+ memset(&tmp, 0, sizeof(struct stat));
if (-1 == lstat(Fullpath().c_str(), &tmp))
{
ThrowMsg(NotExists, DPL::GetErrnoString());
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;
}
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");
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
}
}
+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();
#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>
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)
/*
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());
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());
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());
{
Path path1(std::string("/"));
RUNNER_ASSERT(path1.Fullpath() == "/");
- RUNNER_ASSERT(path1.Basename() == "");
+ RUNNER_ASSERT(path1.Filename() == "");
bool passed = false;
Try
{
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");
}
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");
}
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");
}
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");
}
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");
}
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");
}
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");
}
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");
}
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");
}
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");
}
DPL::ScopedDir sd(rootTest);
struct stat st;
+ memset(&st, 0, sizeof(struct stat));
Path path = Path(rootTest) / "touchDir";
RUNNER_ASSERT(!path.Exists());
}
/*
+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
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";
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));
}
/*
DPL::ScopedDir sd(rootTest);
struct stat st;
+ memset(&st, 0, sizeof(struct stat));
Path path = Path(rootTest) / "touchDir";
MakeDir(path);