diff --git a/tdd_intro/homework/07_filecopier/07_filecopier.pro b/tdd_intro/homework/07_filecopier/07_filecopier.pro index dec9b6a..f9d210b 100644 --- a/tdd_intro/homework/07_filecopier/07_filecopier.pro +++ b/tdd_intro/homework/07_filecopier/07_filecopier.pro @@ -6,4 +6,9 @@ CONFIG -= app_bundle CONFIG -= qt SOURCES += \ - test.cpp + test.cpp \ + FakeFileSystem.cpp + +HEADERS += \ + FakeFileSystem.h + diff --git a/tdd_intro/homework/07_filecopier/FakeFileSystem.cpp b/tdd_intro/homework/07_filecopier/FakeFileSystem.cpp new file mode 100644 index 0000000..a817789 --- /dev/null +++ b/tdd_intro/homework/07_filecopier/FakeFileSystem.cpp @@ -0,0 +1,144 @@ +#include "FakeFileSystem.h" +#include + +FakeFileSystem::FakeFileSystem(const FileSystemObjects &rootObjects) + : m_root(root.string(), rootObjects) +{ } + +std::set FakeFileSystem::GetChildren(const path &dir) +{ + const auto& fsos = GoTo(dir).GetChildren(); + std::set children; + std::transform(fsos.begin(), fsos.end(), std::inserter(children, children.begin()), [](const auto& fso) { return fso.GetName(); }); + return children; +} + +bool FakeFileSystem::IsDir(const path &obj) +{ + return GoTo(obj).IsDir(); +} + +void FakeFileSystem::MakeDir(const path &dir) +{ + GoToDir(dir.parent_path()).AddChild(Folder(dir.filename().string())); +} + +void FakeFileSystem::CopyFile(const path &src, const path &dst) +{ + src; // unused + CreateFile(dst); +} + +bool FakeFileSystem::FileExists(const path &file) +{ + auto fso = GoToSafe(file); + return fso != nullptr && !fso->IsDir(); +} + +bool FakeFileSystem::DirExists(const path &dir) +{ + auto fso = GoToSafe(dir); + return fso != nullptr && fso->IsDir(); +} + +void FakeFileSystem::CreateFile(const path &file) +{ + GoToDir(file.parent_path()).AddChild(File(file.filename().string())); +} + +FileSystemObject &FakeFileSystem::GoTo(const path &obj) +{ + FileSystemObject* current = &m_root; + path::iterator it = obj.begin(); + if (it == obj.end()) + { + throw std::runtime_error("Path is empty"); + } + + for (++it; it != obj.end(); ++it) + { + auto child = std::find_if(current->GetChildren().begin(), current->GetChildren().end(), [&it](const auto& fso) + { return fso.GetName() == it->string(); } + ); + if (child == current->GetChildren().end()) + { + throw std::runtime_error("Path does not exist"); + } + current = (FileSystemObject*)&(*child); + } + return *current; +} + +Folder &FakeFileSystem::GoToDir(const path &dir) +{ + auto& target = GoTo(dir); + if (!target.IsDir()) + { + throw std::runtime_error("Target path is not a directory"); + } + return (Folder&)target; +} + +FileSystemObject *FakeFileSystem::GoToSafe(const path &path) +{ + FileSystemObject* fso = nullptr; + try + { + fso = &GoTo(path); + } + catch(const std::exception&) { } + return fso; +} + +FileSystemObject::FileSystemObject(const std::string& name, bool isDir) + : name(name) + , isDir(isDir) +{ } + +FileSystemObject::FileSystemObject(const std::string &name, const FileSystemObjects &children) + : name(name) + , children(children) + , isDir(true) +{ } + +const bool FileSystemObject::operator==(const FileSystemObject &other) const +{ + return name == other.name; +} + +const bool FileSystemObject::operator!=(const FileSystemObject &other) const +{ + return !operator==(other); +} + +const bool FileSystemObject::operator<(const FileSystemObject &other) const +{ + return name < other.name; +} + +const std::string &FileSystemObject::GetName() const +{ + return name; +} + +const FileSystemObjects &FileSystemObject::GetChildren() const +{ + return children; +} + +bool FileSystemObject::IsDir() const +{ + return isDir; +} + +void Folder::AddChild(const FileSystemObject &child, bool overwrite /*= false*/) +{ + FileSystemObjects::iterator existant = std::find_if(children.begin(), children.end(), [&child](const auto& fso) + { return fso.GetName() == child.GetName(); } + ); + if (existant != children.end() && overwrite) + { + throw std::runtime_error("Child with specified name is already exist"); + } + children.insert(child); +} diff --git a/tdd_intro/homework/07_filecopier/FakeFileSystem.h b/tdd_intro/homework/07_filecopier/FakeFileSystem.h new file mode 100644 index 0000000..e85f7af --- /dev/null +++ b/tdd_intro/homework/07_filecopier/FakeFileSystem.h @@ -0,0 +1,88 @@ +#include +#include +namespace std +{ + using namespace experimental; // for filesystem support +} + +using path = std::filesystem::path; +static path::value_type separator = path::preferred_separator; +static path root = std::basic_string(1, separator); + +class IFileSystem +{ +public: + virtual ~IFileSystem() { } + virtual std::set GetChildren(const path& dir) = 0; + virtual bool IsDir(const path& obj) = 0; + + virtual void MakeDir(const path& dir) = 0; + virtual void CopyFile(const path& src, const path& dst) = 0; + + virtual bool FileExists(const path& file) = 0; + virtual bool DirExists(const path& dir) = 0; +}; + +class FileSystemObject; +using FileSystemObjects = std::set; +class FileSystemObject +{ +public: + FileSystemObject(const std::string& name, bool isDir); + FileSystemObject(const std::string& name, const FileSystemObjects& children); + + bool const operator==(const FileSystemObject& other) const; + bool const operator!=(const FileSystemObject& other) const; + bool const operator<(const FileSystemObject& other) const; + + const std::string& GetName() const; + const FileSystemObjects& GetChildren() const; + bool IsDir() const; + +protected: + std::string name; + FileSystemObjects children; + +private: + bool isDir = true; +}; + +class File : public FileSystemObject +{ +public: + explicit File(const std::string& name): FileSystemObject(name, false) { } +}; + +class Folder : public FileSystemObject +{ +public: + explicit Folder(const std::string& name) : FileSystemObject(name, true) { } + Folder(const std::string& name, const FileSystemObjects& children) : FileSystemObject(name, children) { } + void AddChild(const FileSystemObject& child, bool overwrite = false); +}; + +class FakeFileSystem: public IFileSystem +{ +public: + explicit FakeFileSystem(const FileSystemObjects& rootObjects = { }); + + virtual std::set GetChildren(const path& dir); + virtual bool IsDir(const path& obj); + + virtual void MakeDir(const path& dir); + virtual void CopyFile(const path& src, const path& dst); + + virtual bool FileExists(const path& file); + virtual bool DirExists(const path& dir); + +private: + void CreateFile(const path& file); + void CreateDir(const path& dir); + + FileSystemObject& GoTo(const path& path); + Folder &GoToDir(const path& dir); + FileSystemObject* GoToSafe(const path& path); + +private: + FileSystemObject m_root; +}; diff --git a/tdd_intro/homework/07_filecopier/test.cpp b/tdd_intro/homework/07_filecopier/test.cpp index be20cab..3a27b75 100644 --- a/tdd_intro/homework/07_filecopier/test.cpp +++ b/tdd_intro/homework/07_filecopier/test.cpp @@ -17,6 +17,90 @@ You don't need to test filesystem functions. To work with a filesystem you shoul You can start with GMock from https://goo.gl/j7EkQX, good luck! */ + +/* + * Test plan: + * 1. Copy single file + * 2. Copy several files + * 3. Copy folder with files + * 4. Copy folder with folders and files +*/ + #include #include +#include "FakeFileSystem.h" + +class IFileCopier +{ +public: + virtual void CopyFolderRecursive(const path& src, const path& dst) = 0; +}; + + +TEST(FakeFileSystem, RootTest) +{ + FakeFileSystem fs; + EXPECT_TRUE(fs.DirExists(root)); + EXPECT_TRUE(fs.GetChildren(root).empty()); +} + +TEST(FakeFileSystem, SingleFileTest) +{ + File file("file"); + FileSystemObjects rootObjects = { file }; + FakeFileSystem fs(rootObjects); + + EXPECT_TRUE(fs.DirExists(root)); + EXPECT_TRUE(fs.FileExists(root / "file")); + ASSERT_EQ(1, fs.GetChildren(root).size()); + EXPECT_EQ("file", *fs.GetChildren(root).begin()); +} + +TEST(FakeFileSystem, SingleFolderTest) +{ + Folder folder("folder"); + FileSystemObjects rootObjects = { folder }; + FakeFileSystem fs(rootObjects); + + EXPECT_TRUE(fs.DirExists(root)); + EXPECT_TRUE(fs.DirExists(root / "folder")); + ASSERT_EQ(1, fs.GetChildren(root).size()); + EXPECT_EQ("folder", *fs.GetChildren(root).begin()); +} + +TEST(FakeFileSystem, FoldersWithNextedFolders) +{ + Folder folder1("folder1"); + Folder folder2("folder2", FileSystemObjects { folder1 }); + Folder folder3("folder3", FileSystemObjects { folder2 }); + FileSystemObjects rootObjects = { folder3 }; + FakeFileSystem fs(rootObjects); + + EXPECT_TRUE(fs.DirExists(root)); + ASSERT_EQ(1, fs.GetChildren(root).size()); + EXPECT_TRUE(fs.DirExists(root / "folder3")); + ASSERT_EQ(1, fs.GetChildren(root / "folder3").size()); + EXPECT_TRUE(fs.DirExists(root / "folder3" / "folder2")); + ASSERT_EQ(1, fs.GetChildren(root / "folder3" / "folder2").size()); + EXPECT_TRUE(fs.DirExists(root / "folder3" / "folder2" / "folder1")); + ASSERT_EQ(0, fs.GetChildren(root / "folder3" / "folder2" / "folder1").size()); +} + +TEST(FakeFileSystem, FoldersWithNestedFoldersAndFiles) +{ + File file2("nested_file"); + Folder folder2("nested_folder", FileSystemObjects { file2 } ); + File file1("root_file"); + Folder folder1("root_folder", FileSystemObjects { folder2 }); + + FileSystemObjects rootObjects = { file1, folder1 }; + FakeFileSystem fs(rootObjects); + EXPECT_TRUE(fs.DirExists(root)); + ASSERT_EQ(2, fs.GetChildren(root).size()); + EXPECT_TRUE(fs.DirExists(root / "root_folder")); + EXPECT_TRUE(fs.FileExists(root / "root_file")); + ASSERT_EQ(1, fs.GetChildren(root / "root_folder").size()); + EXPECT_TRUE(fs.DirExists(root / "nested_folder")); + EXPECT_TRUE(fs.FileExists(root / "nested_folder" / "nested_file")); +} diff --git a/tdd_intro/homework/homework.pro b/tdd_intro/homework/homework.pro index dd4d892..d875a0a 100644 --- a/tdd_intro/homework/homework.pro +++ b/tdd_intro/homework/homework.pro @@ -1,11 +1,11 @@ TEMPLATE = subdirs SUBDIRS += \ - 01_bob \ - 02_leap_year \ - 03_anagram \ - 04_trinary_numbers \ - 05_word_wrapp \ - 06_bank_ocr \ + #01_bob \ + #02_leap_year \ + #03_anagram \ + #04_trinary_numbers \ + #05_word_wrapp \ + #06_bank_ocr \ 07_filecopier \ 08_timer diff --git a/tdd_intro/tdd_intro.pro.user b/tdd_intro/tdd_intro.pro.user index a2f1674..6df942d 100644 --- a/tdd_intro/tdd_intro.pro.user +++ b/tdd_intro/tdd_intro.pro.user @@ -1,10 +1,10 @@ - + EnvironmentId - {a9e7f687-ac9f-466e-a5b0-c81b575a0a1d} + {0cec21e3-b32f-4f16-9337-d30f16ca07a8} ProjectExplorer.Project.ActiveTarget @@ -30,12 +30,12 @@ 2 UTF-8 - true + false 4 false 80 true - false + true 1 true false @@ -59,14 +59,14 @@ ProjectExplorer.Project.Target.0 - Qt 5.7.0 (windows) - Qt 5.7.0 (windows) - {bb54e87c-a17e-4f34-bfa2-da2794ff8a10} + Desktop Qt 5.10.1 MSVC2017 64bit + Desktop Qt 5.10.1 MSVC2017 64bit + qt.qt5.5101.win64_msvc2017_64_kit 0 0 - 11 + 0 - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug + D:/Projects/TDD/build-tdd_intro-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug true @@ -114,13 +114,13 @@ false Debug - + Debug Qt4ProjectManager.Qt4BuildConfiguration 2 true - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Release + D:/Projects/TDD/build-tdd_intro-Desktop_Qt_5_10_1_MSVC2017_64bit-Release true @@ -168,13 +168,13 @@ false Release - + Release Qt4ProjectManager.Qt4BuildConfiguration 0 true - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Profile + D:/Projects/TDD/build-tdd_intro-Desktop_Qt_5_10_1_MSVC2017_64bit-Profile true @@ -222,7 +222,7 @@ false Profile - + Profile Qt4ProjectManager.Qt4BuildConfiguration 0 true @@ -236,7 +236,7 @@ ProjectExplorer.BuildSteps.Deploy 1 - Deploy locally + Deploy Configuration ProjectExplorer.DefaultDeployConfiguration @@ -286,13 +286,13 @@ chatclient - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/cleanroom/chatclient/chatclient.pro + Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/TDD/tdd_intro/cleanroom/chatclient/chatclient.pro true cleanroom/chatclient/chatclient.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/cleanroom/chatclient + 3768 false true @@ -342,247 +342,15 @@ 2 - 01_bob - - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/01_bob/01_bob.pro - true - - homework/01_bob/01_bob.pro - false - - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/01_bob - 3768 - false - true - false - false - true - - - false - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - 02_word_count + 07_filecopier - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/02_word_count/02_word_count.pro - true - - workshops/02_word_count/02_word_count.pro - false - - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/02_word_count - 3768 - false - true - false - false - true - - - false - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - 03_anagram - 03_anagram2 - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/03_anagram/03_anagram.pro - true - - workshops/03_anagram/03_anagram.pro - false - - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/03_anagram - 3768 - false - true - false - false - true - - - false - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - 04_trinary_numbers - 04_trinary_numbers2 - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/04_trinary_numbers/04_trinary_numbers.pro - true - - workshops/04_trinary_numbers/04_trinary_numbers.pro - false - - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/04_trinary_numbers - 3768 - false - true - false - false - true - - - false - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - 05_word_wrapp - 05_word_wrapp2 - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/05_word_wrapp/05_word_wrapp.pro + Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/TDD/tdd_intro/homework/07_filecopier/07_filecopier.pro true - workshops/05_word_wrapp/05_word_wrapp.pro + homework/07_filecopier/07_filecopier.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/05_word_wrapp + 3768 false true @@ -632,15 +400,15 @@ 2 - 02_leap_year + 08_timer - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/02_leap_year/02_leap_year.pro + Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/TDD/tdd_intro/homework/08_timer/08_timer.pro true - homework/02_leap_year/02_leap_year.pro + homework/08_timer/08_timer.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/02_leap_year + 3768 false true @@ -690,15 +458,15 @@ 2 - 03_anagram + 01_fizz_buzz - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/03_anagram/03_anagram.pro + Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/TDD/tdd_intro/workshops/01_fizz_buzz/01_fizz_buzz.pro true - homework/03_anagram/03_anagram.pro + workshops/01_fizz_buzz/01_fizz_buzz.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/03_anagram + 3768 false true @@ -748,15 +516,15 @@ 2 - 04_trinary_numbers + 02_word_count - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/04_trinary_numbers/04_trinary_numbers.pro + Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/TDD/tdd_intro/workshops/02_word_count/02_word_count.pro true - homework/04_trinary_numbers/04_trinary_numbers.pro + workshops/02_word_count/02_word_count.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/04_trinary_numbers + 3768 false true @@ -806,15 +574,15 @@ 2 - 05_word_wrapp - - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/05_word_wrapp/05_word_wrapp.pro + 03_anagram + 03_anagram2 + Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/TDD/tdd_intro/workshops/03_anagram/03_anagram.pro true - homework/05_word_wrapp/05_word_wrapp.pro + workshops/03_anagram/03_anagram.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/05_word_wrapp + 3768 false true @@ -864,15 +632,15 @@ 2 - 06_bank_ocr - - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/06_bank_ocr/06_bank_ocr.pro + 04_trinary_numbers + 04_trinary_numbers2 + Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/TDD/tdd_intro/workshops/04_trinary_numbers/04_trinary_numbers.pro true - homework/06_bank_ocr/06_bank_ocr.pro + workshops/04_trinary_numbers/04_trinary_numbers.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/06_bank_ocr + 3768 false true @@ -922,131 +690,15 @@ 2 - 07_filecopier - - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/07_filecopier/07_filecopier.pro - true - - homework/07_filecopier/07_filecopier.pro - false - - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/07_filecopier - 3768 - false - true - false - false - true - - - false - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - 08_timer - - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/08_timer/08_timer.pro - true - - homework/08_timer/08_timer.pro - false - - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/08_timer - 3768 - false - true - false - false - true - - - false - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - 01_fizz_buzz - - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/01_fizz_buzz/01_fizz_buzz.pro + 05_word_wrapp + 05_word_wrapp2 + Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/TDD/tdd_intro/workshops/05_word_wrapp/05_word_wrapp.pro true - workshops/01_fizz_buzz/01_fizz_buzz.pro + workshops/05_word_wrapp/05_word_wrapp.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/01_fizz_buzz + 3768 false true @@ -1054,7 +706,7 @@ false true - 14 + 8