diff --git a/tdd_intro/homework/06_bank_ocr/06_bank_ocr.pro b/tdd_intro/homework/05_bank_ocr/05_bank_ocr.pro similarity index 100% rename from tdd_intro/homework/06_bank_ocr/06_bank_ocr.pro rename to tdd_intro/homework/05_bank_ocr/05_bank_ocr.pro diff --git a/tdd_intro/homework/05_bank_ocr/test.cpp b/tdd_intro/homework/05_bank_ocr/test.cpp new file mode 100644 index 0000000..e7852dc --- /dev/null +++ b/tdd_intro/homework/05_bank_ocr/test.cpp @@ -0,0 +1,187 @@ +/*### Bank OCR + +Your manager has recently purchased a machine that assists in reading letters and faxes sent in by branch offices. The machine scans the paper documents, and produces a file with a number of entries. You will write a program to parse this file. + +#### Specification +#### User Story 1 + +The following format is created by the machine: +``` + _ _ _ _ _ _ _ + | _| _||_||_ |_ ||_||_| + ||_ _| | _||_| ||_| _| +``` +Each entry is 3 lines long, and each line has 27 characters. 3 lines of each entry contain an account number written using pipes and underscores. + +Each account number should have 9 digits, all of which should be in the range 0-9. A normal file contains around 500 entries. + +Write a program that can take this file and parse it into actual account numbers. + +Example input and output +``` + _ _ _ _ _ _ _ _ _ +| || || || || || || || || | +|_||_||_||_||_||_||_||_||_| + +=> 000000000 + + | | | | | | | | | + | | | | | | | | | + +=> 111111111 + + _ _ _ _ _ _ _ _ _ + _| _| _| _| _| _| _| _| _| +|_ |_ |_ |_ |_ |_ |_ |_ |_ + +=> 222222222 + + _ _ _ _ _ _ _ _ _ + _| _| _| _| _| _| _| _| _| + _| _| _| _| _| _| _| _| _| + +=> 333333333 + +|_||_||_||_||_||_||_||_||_| + | | | | | | | | | + +=> 444444444 + + _ _ _ _ _ _ _ _ _ +|_ |_ |_ |_ |_ |_ |_ |_ |_ + _| _| _| _| _| _| _| _| _| + +=> 555555555 + + _ _ _ _ _ _ _ _ _ +|_ |_ |_ |_ |_ |_ |_ |_ |_ +|_||_||_||_||_||_||_||_||_| + +=> 666666666 + + _ _ _ _ _ _ _ _ _ + | | | | | | | | | + | | | | | | | | | + +=> 777777777 + + _ _ _ _ _ _ _ _ _ +|_||_||_||_||_||_||_||_||_| +|_||_||_||_||_||_||_||_||_| + +=> 888888888 + + _ _ _ _ _ _ _ _ _ +|_||_||_||_||_||_||_||_||_| + _| _| _| _| _| _| _| _| _| + +=> 999999999 + + _ _ _ _ _ _ _ + | _| _||_||_ |_ ||_||_| + ||_ _| | _||_| ||_| _| + +=> 123456789 +``` +*/ +#include + +// check matrix for one digit 3x3 +// parse one digit + // - parse 1 + // - parse 2 + // - parse 0-9 + // - check invalid one digit +// parse several digits (27x3) +// parse 27x3 (9 digits) + // - check matrix 27x3 + // - parse +// parse several lines + +using Digit = std::vector; + +const Digit s_1({" ", + " |", + " |"}); + +const Digit s_2({" _ ", + " _|", + "|_ "}); + +std::vector s_digits({ + +}); + +bool CheckMatrixDimension(const Digit& digit) +{ + const size_t prefferedSize = 3; + + if (digit.size() != prefferedSize) + { + return false; + } + + for (const std::string& line : digit) + { + if (line.size() != prefferedSize) + { + return false; + } + } + + return true; +} + +std::string ParseDigit(const Digit& digit) +{ + if (digit == Digit({" ", + " |", + " |"})) + { + return "1"; + } + else if (digit == Digit({" _ ", + " _|", + "|_ "})) + { + return "2"; + } + + return "8"; +} + +TEST(BankOCRTests, Check_Matrix_dimension_true) +{ + Digit digit = {" ", " ", " "}; + EXPECT_TRUE(CheckMatrixDimension(digit)); +} + +TEST(BankOCRTests, Check_Matrix_dimension_false) +{ + Digit digit = {" ", "! ", " "}; + EXPECT_FALSE(CheckMatrixDimension(digit)); +} + +TEST(BankOCRTests, ParseDigit_1) +{ + Digit digit = {" ", + " |", + " |"}; + EXPECT_EQ("1", ParseDigit(digit)); +} + +TEST(BankOCRTests, ParseDigit_2) +{ + Digit digit = {" _ ", + " _|", + "|_ "}; + EXPECT_EQ("2", ParseDigit(digit)); +} + +TEST(BankOCRTests, ParseDigit_8) +{ + Digit digit = {" _ ", + "|_|", + "|_|"}; + EXPECT_EQ("8", ParseDigit(digit)); +} diff --git a/tdd_intro/workshops/03_anagram/03_anagram.pro b/tdd_intro/homework/06_allergies/06_allergies.pro similarity index 100% rename from tdd_intro/workshops/03_anagram/03_anagram.pro rename to tdd_intro/homework/06_allergies/06_allergies.pro diff --git a/tdd_intro/homework/06_allergies/test.cpp b/tdd_intro/homework/06_allergies/test.cpp new file mode 100644 index 0000000..72943fb --- /dev/null +++ b/tdd_intro/homework/06_allergies/test.cpp @@ -0,0 +1,209 @@ +/* +Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies. +An allergy test produces a single numeric score which contains the information about all the allergies the person has (that they were tested for). +The list of items (and their value) that were tested are: + eggs (1) + peanuts (2) + shellfish (4) + strawberries (8) + tomatoes (16) + chocolate (32) + pollen (64) + cats (128) +So if Tom is allergic to peanuts and chocolate, he gets a score of 34. + +Now, given just that score of 34, your program should be able: + To say have Tom allergic to specific product or not. + To give list of all allergens Tom is allergic to. + +E.g. it can be class with methods IsAllergicTo(string), List() and receiving allergyScore in constructor + +Note: a given score may include allergens not listed above (i.e. allergens that score 256, 512, 1024, etc.). +Your program should ignore those components of the score. +For example, if the allergy score is 257, your program should only report the eggs (1) allergy. +*/ +#include +#include + +/* + - AllergyIndexTests + - Compare allergy index with correct number + - Compare allergy index with incorrect number + - Compare with complex number + - AllergyNameTests + - Find allergy index for correct name + - Throw exceprion for incorrect name + - PersonAllergiesTests + - check with unexistent allergy + - List() returns empty list + - IsAllergicTo() returns false + - check with one allergy + - List() returns name of allergy + - IsAllergicTo() returns true if allergy score = index of allergy name + - IsAllergicTo() returns false if allergy score != index of allergy name + - check with two allergies + - List() returns names of allergies + - IsAllergicTo() returns true if allergy score contains index of allergy name + - IsAllergicTo() returns false if allergy score not contains index of allergy name + - check with existent and unexistent allergies + - List() returns name of existent allergy +*/ + +enum AllergyIndex : uint64_t +{ + AllergyIndexFirst = 0, + AllergyIndexEggs = AllergyIndexFirst, + AllergyIndexPeanuts, + AllergyIndexShellfish, + AllergyIndexStrawberries, + AllergyIndexTomatoes, + AllergyIndexChocolate, + AllergyIndexPollen, + AllergyIndexCats, + AllergyIndexLast = AllergyIndexCats +}; + +static const std::map s_allergies({ + {"eggs", AllergyIndexEggs}, + {"peanuts", AllergyIndexPeanuts}, + {"shellfish", AllergyIndexShellfish}, + {"strawberries", AllergyIndexStrawberries}, + {"tomatoes", AllergyIndexTomatoes}, + {"chocolate", AllergyIndexChocolate}, + {"pollen", AllergyIndexPollen}, + {"cats", AllergyIndexCats} }); + +bool HaveAllergy(uint64_t allergyScore, AllergyIndex alergyIndex) +{ + return (allergyScore & uint64_t(1) << alergyIndex) != 0; +} + +using AllergiesList = std::set; + +AllergyIndex GetAllergyIndex(const std::string& allergyName) +{ + auto allergy = s_allergies.find(allergyName); + + if (allergy == s_allergies.end()) + { + throw std::out_of_range("Allergy has no index."); + } + + return allergy->second; +} + +class PersonAllergies +{ +public: + explicit PersonAllergies(uint64_t allergyScore) + : m_allergyScore(allergyScore) + {} + + AllergiesList List() + { + AllergiesList allergiesList; + + for (auto allergy : s_allergies) + { + if (HaveAllergy(m_allergyScore, allergy.second)) + { + allergiesList.insert(allergy.first); + } + } + + return allergiesList; + } + + bool IsAllergicTo(const std::string& allergyName) + { + return HaveAllergy(m_allergyScore, GetAllergyIndex(allergyName)); + } + +private: + uint64_t m_allergyScore; +}; + +const uint64_t s_unexistentAllergyIndex(256); +const std::string s_tomatoes("tomatoes"); +const std::string s_eggs("eggs"); +const uint64_t s_tomatoesIndex(16); + +TEST(HaveAllergyTests, CompareWithCorrectNumber) +{ + EXPECT_TRUE(HaveAllergy(1, AllergyIndexEggs)); +} + +TEST(HaveAllergyTests, CompareWithIncorrectNumber) +{ + EXPECT_FALSE(HaveAllergy(2, AllergyIndexEggs)); +} + +TEST(HaveAllergyTests, CompareWithComplexNumber) +{ + EXPECT_TRUE(HaveAllergy(5, AllergyIndexEggs)); + EXPECT_TRUE(HaveAllergy(5, AllergyIndexShellfish)); +} + +TEST(GetAllergyIndexTests, WithCorrectName) +{ + EXPECT_EQ(AllergyIndexEggs, GetAllergyIndex(s_eggs)); +} + +TEST(GetAllergyIndexTests, WithIncorrectName) +{ + EXPECT_THROW(GetAllergyIndex(""), std::out_of_range); +} + +TEST(GetAllergyIndexTests, WithCorrectName_tomatoes) +{ + EXPECT_EQ(AllergyIndexTomatoes, GetAllergyIndex(s_tomatoes)); +} + +TEST(PersonAllergiesTests, UnexistentAllergy_EmptyList) +{ + PersonAllergies personAllergies(s_unexistentAllergyIndex); + EXPECT_EQ(AllergiesList(), personAllergies.List()); +} + +TEST(PersonAllergiesTests, IsAllergicTo_UnexistentAllergy) +{ + PersonAllergies personAllergies(s_unexistentAllergyIndex); + EXPECT_FALSE(personAllergies.IsAllergicTo(s_tomatoes)); +} + +TEST(PersonAllergiesTests, List_OneAllergy) +{ + PersonAllergies personAllergies(s_tomatoesIndex); + EXPECT_EQ(AllergiesList({s_tomatoes}), personAllergies.List()); +} + +TEST(PersonAllergiesTests, List_TwoAllergy) +{ + PersonAllergies personAllergies(s_tomatoesIndex + 1); + EXPECT_EQ(AllergiesList({s_tomatoes, s_eggs}), personAllergies.List()); +} + +TEST(PersonAllergiesTests, IsAllergicTo_ExistentAllergy) +{ + PersonAllergies personAllergies(s_tomatoesIndex); + EXPECT_TRUE(personAllergies.IsAllergicTo(s_tomatoes)); +} + +TEST(PersonAllergiesTests, IsAllergicTo_ExistentAllergy_WrongIndex) +{ + PersonAllergies personAllergies(s_tomatoesIndex); + EXPECT_FALSE(personAllergies.IsAllergicTo(s_eggs)); +} + +TEST(PersonAllergiesTests, IsAllergicTo_TwoAllergy) +{ + PersonAllergies personAllergies(s_tomatoesIndex + 1); + EXPECT_TRUE(personAllergies.IsAllergicTo(s_tomatoes)); + EXPECT_TRUE(personAllergies.IsAllergicTo(s_eggs)); +} + +TEST(PersonAllergiesTests, List_ExistentAndUnexistentAllergy) +{ + PersonAllergies personAllergies(s_tomatoesIndex + s_unexistentAllergyIndex); + EXPECT_EQ(AllergiesList({s_tomatoes}), personAllergies.List()); +} diff --git a/tdd_intro/homework/06_bank_ocr/test.cpp b/tdd_intro/homework/06_bank_ocr/test.cpp deleted file mode 100644 index a4dfe1f..0000000 --- a/tdd_intro/homework/06_bank_ocr/test.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/*### Bank OCR - -Your manager has recently purchased a machine that assists in reading letters and faxes sent in by branch offices. The machine scans the paper documents, and produces a file with a number of entries. You will write a program to parse this file. - -#### Specification -#### User Story 1 - -The following format is created by the machine: -``` - _ _ _ _ _ _ _ - | _| _||_||_ |_ ||_||_| - ||_ _| | _||_| ||_| _| -``` -Each entry is 3 lines long, and each line has 27 characters. 3 lines of each entry contain an account number written using pipes and underscores. - -Each account number should have 9 digits, all of which should be in the range 0-9. A normal file contains around 500 entries. - -Write a program that can take this file and parse it into actual account numbers. - -Example input and output -``` - _ _ _ _ _ _ _ _ _ -| || || || || || || || || | -|_||_||_||_||_||_||_||_||_| - -=> 000000000 - - | | | | | | | | | - | | | | | | | | | - -=> 111111111 - - _ _ _ _ _ _ _ _ _ - _| _| _| _| _| _| _| _| _| -|_ |_ |_ |_ |_ |_ |_ |_ |_ - -=> 222222222 - - _ _ _ _ _ _ _ _ _ - _| _| _| _| _| _| _| _| _| - _| _| _| _| _| _| _| _| _| - -=> 333333333 - -|_||_||_||_||_||_||_||_||_| - | | | | | | | | | - -=> 444444444 - - _ _ _ _ _ _ _ _ _ -|_ |_ |_ |_ |_ |_ |_ |_ |_ - _| _| _| _| _| _| _| _| _| - -=> 555555555 - - _ _ _ _ _ _ _ _ _ -|_ |_ |_ |_ |_ |_ |_ |_ |_ -|_||_||_||_||_||_||_||_||_| - -=> 666666666 - - _ _ _ _ _ _ _ _ _ - | | | | | | | | | - | | | | | | | | | - -=> 777777777 - - _ _ _ _ _ _ _ _ _ -|_||_||_||_||_||_||_||_||_| -|_||_||_||_||_||_||_||_||_| - -=> 888888888 - - _ _ _ _ _ _ _ _ _ -|_||_||_||_||_||_||_||_||_| - _| _| _| _| _| _| _| _| _| - -=> 999999999 - - _ _ _ _ _ _ _ - | _| _||_||_ |_ ||_||_| - ||_ _| | _||_| ||_| _| - -=> 123456789 -``` -*/ -#include - diff --git a/tdd_intro/homework/07_filecopier/test.cpp b/tdd_intro/homework/07_filecopier/test.cpp index be20cab..67e1b87 100644 --- a/tdd_intro/homework/07_filecopier/test.cpp +++ b/tdd_intro/homework/07_filecopier/test.cpp @@ -20,3 +20,306 @@ You can start with GMock from https://goo.gl/j7EkQX, good luck! #include #include +/* + - Check if file/directory exist + - Get list of files in direcroty + - Check if file is directory + - Get relative path + - Create directory + - Copy file + + - Pass not existent src + - Copy one file + - Copy two files + - Copy folder with file + - Check empty folder is not copying + - Copy file and folder with file + - Copy file hierarchy +*/ + +using FilesList = std::vector; +const std::string s_srcFolder("C:\\Folder"); +const std::string s_dstFolder("D:\\Folder"); +const std::string s_fileName("file.name"); +const std::string s_fileName1(s_fileName + "1"); +const std::string s_subFolder("Subfolder"); + +std::string ConcatPath(const std::string& left, const std::string& right) +{ + if (left.empty()) + { + return right; + } + if (right.empty()) + { + return left; + } + + return left + "\\" + right; +} + +const std::string s_srcFilePath(ConcatPath(s_srcFolder, s_fileName)); +const std::string s_dstFilePath(ConcatPath(s_dstFolder, s_fileName)); +const std::string s_srcFilePath1(ConcatPath(s_srcFolder, s_fileName1)); +const std::string s_dstFilePath1(ConcatPath(s_dstFolder, s_fileName1)); +const std::string s_srcFolderPath(ConcatPath(s_srcFolder, s_subFolder)); +const std::string s_dstFolderPath(ConcatPath(s_dstFolder, s_subFolder)); +const std::string s_srcFolderFilePath(ConcatPath(s_srcFolderPath, s_fileName)); +const std::string s_dstFolderFilePath(ConcatPath(s_dstFolderPath, s_fileName)); + +class IFileSystem +{ +public: + virtual bool IsFileExist(const std::string& path) const = 0; + virtual FilesList GetFilesList(const std::string& dirPath) const = 0; + virtual bool IsDirectory(const std::string& path) const = 0; + virtual std::string GetRelativePath(const std::string& fullPath, const std::string& relativeToPath) const = 0; + virtual bool CreateDirectory(const std::string& dirPath) const = 0; + virtual bool CopyFile(const std::string& srcFilePath, const std::string& dstFilePath) const = 0; +}; + +class MockFileSystem : public IFileSystem +{ +public: + MOCK_CONST_METHOD1(IsFileExist, bool(const std::string& path)); + MOCK_CONST_METHOD1(GetFilesList, FilesList(const std::string& dirPath)); + MOCK_CONST_METHOD1(IsDirectory, bool(const std::string& path)); + MOCK_CONST_METHOD2(GetRelativePath, std::string(const std::string& fullPath, const std::string& relativeToPath)); + MOCK_CONST_METHOD1(CreateDirectory, bool(const std::string& dirPath)); + MOCK_CONST_METHOD2(CopyFile, bool(const std::string& srcFilePath, const std::string& dstFilePath)); +}; + +class IFileCopier +{ +public: + virtual void Copy(const std::string& src, const std::string& dst) = 0; +}; + +class FileCopier : public IFileCopier +{ +public: + FileCopier(IFileSystem* fileSystem) + : m_fileSystem(fileSystem) + { + } + + virtual void Copy(const std::string& src, const std::string& dst) override + { + if (!m_fileSystem->IsFileExist(src)) + { + throw std::runtime_error("Source path not exist"); + } + + FilesList files(m_fileSystem->GetFilesList(src)); + if (files.empty()) + { + return; + } + + m_fileSystem->CreateDirectory(dst); + + for (const std::string& srcFilePath : files) + { + const std::string relativePath(m_fileSystem->GetRelativePath(srcFilePath, src)); + const std::string dstPath(ConcatPath(dst, relativePath)); + if (m_fileSystem->IsDirectory(srcFilePath)) + { + Copy(srcFilePath, dstPath); + } + else + { + m_fileSystem->CopyFile(srcFilePath, dstPath); + } + } + } + +private: + IFileSystem* m_fileSystem; +}; + +void CopyFileTest(const std::string& srcFolder, + const std::string& srcFilePath, + const std::string& fileName, + const std::string& dstFilePath, + MockFileSystem& fileSystem) +{ + EXPECT_CALL(fileSystem, GetRelativePath(srcFilePath, srcFolder)) + .WillOnce(testing::Return(fileName)); + EXPECT_CALL(fileSystem, IsDirectory(srcFilePath)) + .WillOnce(testing::Return(false)); + EXPECT_CALL(fileSystem, CopyFile(srcFilePath, dstFilePath)) + .WillOnce(testing::Return(true)); +} + +void CopyFolderTest(const std::string& srcFolder, + const std::string& srcFilePath, + const std::string& fileName, + MockFileSystem& fileSystem) +{ + EXPECT_CALL(fileSystem, GetRelativePath(srcFilePath, srcFolder)) + .WillOnce(testing::Return(fileName)); + EXPECT_CALL(fileSystem, IsDirectory(srcFilePath)) + .WillOnce(testing::Return(true)); +} + +void BeforeCopyFileTest(const std::string& srcFolder, + const std::string& dstFolder, + const FilesList& filesList, + MockFileSystem& fileSystem) +{ + EXPECT_CALL(fileSystem, IsFileExist(srcFolder)) + .WillOnce(testing::Return(true)); + EXPECT_CALL(fileSystem, GetFilesList(srcFolder)) + .WillOnce(testing::Return(filesList)); + EXPECT_CALL(fileSystem, CreateDirectory(dstFolder)) + .WillOnce(testing::Return(true)); +} + +void EmptyFolderTest(const std::string& srcFolder, MockFileSystem& fileSystem) +{ + EXPECT_CALL(fileSystem, IsFileExist(srcFolder)) + .WillOnce(testing::Return(true)); + EXPECT_CALL(fileSystem, GetFilesList(srcFolder)) + .WillOnce(testing::Return(FilesList())); + EXPECT_CALL(fileSystem, CreateDirectory(srcFolder)).Times(0); + EXPECT_CALL(fileSystem, CopyFile(testing::_, testing::_)).Times(0); +} +TEST(FileCopierTests, Copy_NotExistentSrc) +{ + MockFileSystem fileSystem; + + const std::string notExistentSrc("NotExistentSrc"); + EXPECT_CALL(fileSystem, IsFileExist(notExistentSrc)).WillOnce(testing::Return(false)); + + FileCopier fileCopier(&fileSystem); + EXPECT_THROW(fileCopier.Copy(notExistentSrc, s_dstFolder), std::runtime_error); +} + +TEST(FileCopierTests, Copy_GetFilesListEmpty) +{ + MockFileSystem fileSystem; + testing::InSequence copySequence; + + EmptyFolderTest(s_srcFolder, fileSystem); + + FileCopier fileCopier(&fileSystem); + EXPECT_NO_THROW(fileCopier.Copy(s_srcFolder, s_dstFolder)); +} + +TEST(FileCopierTests, Copy_OneFile) +{ + MockFileSystem fileSystem; + testing::InSequence copySequence; + + BeforeCopyFileTest(s_srcFolder, + s_dstFolder, + FilesList({s_srcFilePath}), + fileSystem); + + CopyFileTest(s_srcFolder, s_srcFilePath, s_fileName, s_dstFilePath, fileSystem); + + FileCopier fileCopier(&fileSystem); + EXPECT_NO_THROW(fileCopier.Copy(s_srcFolder, s_dstFolder)); +} + +TEST(FileCopierTests, Copy_TwoFiles) +{ + MockFileSystem fileSystem; + testing::InSequence copySequence; + + BeforeCopyFileTest(s_srcFolder, + s_dstFolder, + FilesList({s_srcFilePath, s_srcFilePath1}), + fileSystem); + + CopyFileTest(s_srcFolder, s_srcFilePath, s_fileName, s_dstFilePath, fileSystem); + CopyFileTest(s_srcFolder, s_srcFilePath1, s_fileName1, s_dstFilePath1, fileSystem); + + FileCopier fileCopier(&fileSystem); + EXPECT_NO_THROW(fileCopier.Copy(s_srcFolder, s_dstFolder)); +} + +TEST(FileCopierTests, Copy_FolderWithFile) +{ + MockFileSystem fileSystem; + testing::InSequence copySequence; + + BeforeCopyFileTest(s_srcFolder, + s_dstFolder, + FilesList({s_srcFolderPath}), + fileSystem); + + CopyFolderTest(s_srcFolder, s_srcFolderPath, s_subFolder, fileSystem); + + BeforeCopyFileTest(s_srcFolderPath, + s_dstFolderPath, + FilesList({s_srcFolderFilePath}), + fileSystem); + + CopyFileTest(s_srcFolderPath, s_srcFolderFilePath, s_fileName, s_dstFolderFilePath, fileSystem); + + FileCopier fileCopier(&fileSystem); + EXPECT_NO_THROW(fileCopier.Copy(s_srcFolder, s_dstFolder)); +} + +TEST(FileCopierTests, Copy_FolderWithoutFiles) +{ + MockFileSystem fileSystem; + testing::InSequence copySequence; + + BeforeCopyFileTest(s_srcFolder, + s_dstFolder, + FilesList({s_srcFolderPath}), + fileSystem); + + CopyFolderTest(s_srcFolder, s_srcFolderPath, s_subFolder, fileSystem); + + EmptyFolderTest(s_srcFolderPath, fileSystem); + + FileCopier fileCopier(&fileSystem); + EXPECT_NO_THROW(fileCopier.Copy(s_srcFolder, s_dstFolder)); +} + +TEST(FileCopierTests, Copy_FileAndFolderWithFile) +{ + MockFileSystem fileSystem; + testing::InSequence copySequence; + + BeforeCopyFileTest(s_srcFolder, + s_dstFolder, + FilesList({s_srcFolderPath, s_srcFilePath}), + fileSystem); + + CopyFolderTest(s_srcFolder, s_srcFolderPath, s_subFolder, fileSystem); + + BeforeCopyFileTest(s_srcFolderPath, + s_dstFolderPath, + FilesList({s_srcFolderFilePath}), + fileSystem); + + CopyFileTest(s_srcFolderPath, s_srcFolderFilePath, s_fileName, s_dstFolderFilePath, fileSystem); + CopyFileTest(s_srcFolder, s_srcFilePath, s_fileName, s_dstFilePath, fileSystem); + + FileCopier fileCopier(&fileSystem); + EXPECT_NO_THROW(fileCopier.Copy(s_srcFolder, s_dstFolder)); +} + +TEST(FileCopierTests, ConcatPath_ConcatLeftWithRight) +{ + EXPECT_EQ("C:\\Folder\\file.name", ConcatPath(s_srcFolder, s_fileName)); +} + +TEST(FileCopierTests, ConcatPath_ConcatLeftWithoutRight) +{ + EXPECT_EQ(s_srcFolder, ConcatPath(s_srcFolder, "")); +} + +TEST(FileCopierTests, ConcatPath_ConcatRightWithoutLeft) +{ + EXPECT_EQ(s_fileName, ConcatPath("", s_fileName)); +} + +TEST(FileCopierTests, ConcatPath_ConcatEmpty) +{ + EXPECT_EQ("", ConcatPath("", "")); +} diff --git a/tdd_intro/homework/README.MD b/tdd_intro/homework/README.MD index 7457706..fc7a47c 100644 --- a/tdd_intro/homework/README.MD +++ b/tdd_intro/homework/README.MD @@ -86,6 +86,29 @@ It should be wrapped by length of 30 into this sequence of lines (ommiting quote If your language provides a method in the standard library to perform the conversion, pretend it doesn't exist and implement it yourself. +### Allergies + +Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies. +An allergy test produces a single numeric score which contains the information about all the allergies the person has (that they were tested for). +The list of items (and their value) that were tested are: + eggs (1) + peanuts (2) + shellfish (4) + strawberries (8) + tomatoes (16) + chocolate (32) + pollen (64) + cats (128) +So if Tom is allergic to peanuts and chocolate, he gets a score of 34. + +Now, given just that score of 34, your program should be able: +1. To say have Tom allergic to specific product or not. +2. To give list of all allergens Tom is allergic to. + +Note: a given score may include allergens not listed above (i.e. allergens that score 256, 512, 1024, etc.). Your program should ignore those components of the score. For example, if the allergy score is 257, your program should only report the eggs (1) allergy. + +_from http://exercism.io/_ + ## Functionality decomposition training: ### Bank OCR diff --git a/tdd_intro/homework/homework.pro b/tdd_intro/homework/homework.pro index dd4d892..92bc4f7 100644 --- a/tdd_intro/homework/homework.pro +++ b/tdd_intro/homework/homework.pro @@ -6,6 +6,7 @@ SUBDIRS += \ 03_anagram \ 04_trinary_numbers \ 05_word_wrapp \ - 06_bank_ocr \ + 05_bank_ocr \ + 06_allergies \ 07_filecopier \ 08_timer diff --git a/tdd_intro/tdd_intro.pro.user b/tdd_intro/tdd_intro.pro.user index a2f1674..e4cdef8 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} + {f70a0dd6-3871-4c73-bc87-e473c39bca7a} ProjectExplorer.Project.ActiveTarget @@ -59,14 +59,14 @@ ProjectExplorer.Project.Target.0 - Qt 5.7.0 (windows) - Qt 5.7.0 (windows) - {bb54e87c-a17e-4f34-bfa2-da2794ff8a10} + 5.7.0 + 5.7.0 + {1d82d85e-e2b0-49a5-8ca5-1516886ad9e7} 0 0 - 11 + 0 - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug + D:/Study/tdd-course-2/build-tdd_intro-5_7_0-Debug true @@ -120,7 +120,7 @@ true - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Release + D:/Study/tdd-course-2/build-tdd_intro-5_7_0-Release true @@ -174,7 +174,7 @@ true - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Profile + D:/Study/tdd-course-2/build-tdd_intro-5_7_0-Profile true @@ -292,7 +292,7 @@ cleanroom/chatclient/chatclient.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/cleanroom/chatclient + 3768 false true @@ -350,7 +350,7 @@ 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 @@ -408,7 +408,7 @@ 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 @@ -458,15 +458,15 @@ 2 - 03_anagram - 03_anagram2 - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/03_anagram/03_anagram.pro + 03_armstrong_number + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/03_armstrong_number/03_armstrong_number.pro true - workshops/03_anagram/03_anagram.pro + workshops/03_armstrong_number/03_armstrong_number.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/03_anagram + 3768 false true @@ -516,15 +516,15 @@ 2 - 04_trinary_numbers - 04_trinary_numbers2 - Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/04_trinary_numbers/04_trinary_numbers.pro + 04_roman_numerals + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/04_roman_numerals/04_roman_numerals.pro true - workshops/04_trinary_numbers/04_trinary_numbers.pro + workshops/04_roman_numerals/04_roman_numerals.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/04_trinary_numbers + 3768 false true @@ -582,7 +582,7 @@ workshops/05_word_wrapp/05_word_wrapp.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/05_word_wrapp + 3768 false true @@ -640,7 +640,7 @@ homework/02_leap_year/02_leap_year.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/02_leap_year + 3768 false true @@ -698,7 +698,7 @@ homework/03_anagram/03_anagram.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/03_anagram + 3768 false true @@ -756,7 +756,7 @@ homework/04_trinary_numbers/04_trinary_numbers.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/04_trinary_numbers + 3768 false true @@ -814,7 +814,7 @@ homework/05_word_wrapp/05_word_wrapp.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/05_word_wrapp + 3768 false true @@ -872,7 +872,7 @@ homework/06_bank_ocr/06_bank_ocr.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/06_bank_ocr + 3768 false true @@ -930,7 +930,7 @@ 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 @@ -988,7 +988,7 @@ 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 @@ -1046,7 +1046,7 @@ workshops/01_fizz_buzz/01_fizz_buzz.pro false - D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/01_fizz_buzz + 3768 false true diff --git a/tdd_intro/tdd_intro.pro.user.a9e7f68 b/tdd_intro/tdd_intro.pro.user.a9e7f68 new file mode 100644 index 0000000..d2e0159 --- /dev/null +++ b/tdd_intro/tdd_intro.pro.user.a9e7f68 @@ -0,0 +1,1072 @@ + + + + + + EnvironmentId + {a9e7f687-ac9f-466e-a5b0-c81b575a0a1d} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + true + 4 + false + 80 + true + false + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Qt 5.7.0 (windows) + Qt 5.7.0 (windows) + {bb54e87c-a17e-4f34-bfa2-da2794ff8a10} + 0 + 0 + 13 + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + 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 + + chatclient + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/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 + 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_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 + + 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 + + 05_word_wrapp + 05_word_wrapp2 + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/05_word_wrapp/05_word_wrapp.pro + true + + workshops/05_word_wrapp/05_word_wrapp.pro + false + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/05_word_wrapp + 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_armstrong_number + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/03_armstrong_number/03_armstrong_number.pro + true + + workshops/03_armstrong_number/03_armstrong_number.pro + false + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/03_armstrong_number + 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_roman_numerals + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/workshops/04_roman_numerals/04_roman_numerals.pro + true + + workshops/04_roman_numerals/04_roman_numerals.pro + false + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/04_roman_numerals + 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_leap_year + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/02_leap_year/02_leap_year.pro + true + + homework/02_leap_year/02_leap_year.pro + false + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/02_leap_year + 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 + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/03_anagram/03_anagram.pro + true + + homework/03_anagram/03_anagram.pro + false + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/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 + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/04_trinary_numbers/04_trinary_numbers.pro + true + + homework/04_trinary_numbers/04_trinary_numbers.pro + false + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/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 + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/05_word_wrapp/05_word_wrapp.pro + true + + homework/05_word_wrapp/05_word_wrapp.pro + false + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/05_word_wrapp + 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 + + 06_bank_ocr + + Qt4ProjectManager.Qt4RunConfiguration:D:/Study/tdd-course-2/tdd_intro/homework/06_bank_ocr/06_bank_ocr.pro + true + + homework/06_bank_ocr/06_bank_ocr.pro + false + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/homework/06_bank_ocr + 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 + + 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 + true + + workshops/01_fizz_buzz/01_fizz_buzz.pro + false + + D:/Study/tdd-course-2/build-tdd_intro-Qt_5_7_0_windows-Debug/workshops/01_fizz_buzz + 3768 + false + true + false + false + true + + 14 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/tdd_intro/workshops/02_word_count/test.cpp b/tdd_intro/workshops/02_word_count/test.cpp index 82612fe..572b8a2 100644 --- a/tdd_intro/workshops/02_word_count/test.cpp +++ b/tdd_intro/workshops/02_word_count/test.cpp @@ -12,3 +12,117 @@ free: 1 #include #include +#include +#include + +using MyMap = std::map; + +MyMap WordsCount(const std::string& str) +{ + if (str.empty()) + { + return {}; + } + + MyMap result; + + std::istringstream f(str); + std::string s; + + while(std::getline(f, s, ' ')) + { + if (!s.empty()) + { + ++result[s]; + } + } + + + return result; +} + + +TEST(WordsCountTests, TakeEmptyString_ReturnEmptyMap) +{ + EXPECT_EQ(MyMap(), WordsCount("")); +} + +TEST(WordsCountTests, TakeOneWord_ReturnOneOccurForThisWord) +{ + const std::string word = "Word"; + MyMap myMap; + myMap[word] = 1; + EXPECT_EQ(myMap, WordsCount(word)); +} + +TEST(WordsCountTests, TakeOneWord_Hello_ReturnOneOccurForThisWord) +{ + const std::string word = "Hello"; + MyMap myMap; + myMap[word] = 1; + EXPECT_EQ(myMap, WordsCount(word)); +} + +TEST(WordsCountTests, TakeOneWithSpaceInTheEnd_ReturnOneOccur) +{ + const std::string word = "word "; + MyMap myMap; + myMap["word"] = 1; + EXPECT_EQ(myMap, WordsCount(word)); +} + +TEST(WordsCountTests, TakeOneWithSpace_ReturnOneOccur) +{ + const std::string word = " word"; + MyMap myMap; + myMap["word"] = 1; + EXPECT_EQ(myMap, WordsCount(word)); +} + +TEST(WordsCountTests, TakeTwoDiffWords_ReturnOneOccurForEach) +{ + const std::string word = "Hello word"; + MyMap myMap; + myMap["word"] = 1; + myMap["Hello"] = 1; + EXPECT_EQ(myMap, WordsCount(word)); +} + +TEST(WordsCountTests, TakeALotOfDifferentWords_ReturnOneOccurForEach) +{ + const std::string word = "qwerty qwerty1 qwerty2 qwerty3 qwerty4 qwerty5"; + EXPECT_EQ(1, WordsCount(word).at("qwerty")); + EXPECT_EQ(1, WordsCount(word).at("qwerty1")); + EXPECT_EQ(1, WordsCount(word).at("qwerty2")); + EXPECT_EQ(1, WordsCount(word).at("qwerty3")); + EXPECT_EQ(1, WordsCount(word).at("qwerty4")); + EXPECT_EQ(1, WordsCount(word).at("qwerty5")); +} + +TEST(WordsCountTests, TakeTwoEqualWords_ReturnTwoOccurForIt) +{ + const std::string phrase = "qwerty qwerty"; + MyMap myMap; + myMap["qwerty"] = 2; + EXPECT_EQ(myMap, WordsCount(phrase)); +} + +TEST(WordsCountTests, AcceptanceTest) +{ + const std::string phrase = "olly olly in come free"; + MyMap myMap; + myMap["olly"] = 2; + myMap["in"] = 1; + myMap["come"] = 1; + myMap["free"] = 1; + + EXPECT_EQ(myMap, WordsCount(phrase)); +} + +TEST(WordsCountTests, TakeTwoWordsWithManuSpaces_ReturnTwoOccurForIt) +{ + const std::string phrase = " qwerty qwerty "; + MyMap myMap; + myMap["qwerty"] = 2; + EXPECT_EQ(myMap, WordsCount(phrase)); +} diff --git a/tdd_intro/workshops/03_anagram/test.cpp b/tdd_intro/workshops/03_anagram/test.cpp deleted file mode 100644 index 2fea6eb..0000000 --- a/tdd_intro/workshops/03_anagram/test.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* -Given a word and a list of possible anagrams, select the correct sublist. - -Given "listen" and a list of candidates like "enlists" "google" "inlets" "banana" the program should return a list containing "inlets". - -_from http://exercism.io/_ -*/ -#include \ No newline at end of file diff --git a/tdd_intro/workshops/04_trinary_numbers/04_trinary_numbers.pro b/tdd_intro/workshops/03_armstrong_number/03_armstrong_number.pro similarity index 100% rename from tdd_intro/workshops/04_trinary_numbers/04_trinary_numbers.pro rename to tdd_intro/workshops/03_armstrong_number/03_armstrong_number.pro diff --git a/tdd_intro/workshops/03_armstrong_number/test.cpp b/tdd_intro/workshops/03_armstrong_number/test.cpp new file mode 100644 index 0000000..78a9291 --- /dev/null +++ b/tdd_intro/workshops/03_armstrong_number/test.cpp @@ -0,0 +1,134 @@ +/* +An Armstrong number is a number that is the sum of its own digits each raised to the power of the number of digits. + +For example: + +9 is an Armstrong number, because 9 = 9^1 = 9 +10 is not an Armstrong number, because 10 != 1^2 + 0^2 = 1 +153 is an Armstrong number, because: 153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153 +154 is not an Armstrong number, because: 154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190 +9474 is an Armstrong number + +Write some code to determine whether a number is an Armstrong number. + +Acceptance test +5 - true +100 - false +9475 - false +9926315 - true +9926314 - false + +_from http://exercism.io/_ +*/ +#include +#include + +using Digits = std::multiset; + +Digits GetDidgitList(unsigned int num) +{ + Digits res; + + if (num == 0) + { + res.insert(0); + } + + while (num > 0) + { + res.insert(num % 10); + num /= 10; + } + + return res; +} + +bool IsArmstrongNumber(unsigned int num) +{ + Digits digits = GetDidgitList(num); + unsigned int sum = 0; + size_t digits_size = digits.size(); + + for (auto digit : digits) + { + sum += static_cast(std::pow(digit, digits_size )); + } + + return num == sum; +} + +TEST(IsArmstrongNumberTest, Input_9_Return_True) +{ + EXPECT_TRUE(IsArmstrongNumber(9)); +} + +TEST(IsArmstrongNumberTest, Input_10_Return_False) +{ + EXPECT_FALSE(IsArmstrongNumber(10)); +} + +TEST(IsArmstrongNumberTest, Input_7_Return_True) +{ + EXPECT_TRUE(IsArmstrongNumber(7)); +} + +TEST(IsArmstrongNumberTest, Input_153_Return_True) +{ + EXPECT_TRUE(IsArmstrongNumber(153)); +} + +TEST(IsArmstrongNumberTest, Input_370_Return_True) +{ + EXPECT_TRUE(IsArmstrongNumber(370)); +} + +TEST(IsArmstrongNumberTest, Input_1634_Return_True) +{ + EXPECT_TRUE(IsArmstrongNumber(1634)); +} + +TEST(IsArmstrongNumberTest, Input_9926315_Return_True) +{ + EXPECT_TRUE(IsArmstrongNumber(9926315)); +} + +TEST(IsArmstrongNumberTest, Input_9926314_Return_False) +{ + EXPECT_FALSE(IsArmstrongNumber(9926314)); +} + +TEST(IsArmstrongNumberTest, AcceptanceTest) +{ + EXPECT_TRUE(IsArmstrongNumber(5)); + EXPECT_TRUE(IsArmstrongNumber(9926315)); + EXPECT_FALSE(IsArmstrongNumber(100)); + EXPECT_FALSE(IsArmstrongNumber(9475)); + EXPECT_FALSE(IsArmstrongNumber(9926314)); +} + +TEST(GetDidgitListTest, Input_0) +{ + Digits res; + res.insert(0); + EXPECT_EQ(res, GetDidgitList(0)); +} + +TEST(GetDidgitListTest, Input_35) +{ + Digits res; + res.insert(3); + res.insert(5); + EXPECT_EQ(res, GetDidgitList(35)); +} + +TEST(GetDidgitListTest, Input_945) +{ + Digits res; + res.insert(9); + res.insert(4); + res.insert(5); + EXPECT_EQ(res, GetDidgitList(945)); +} + + + diff --git a/tdd_intro/workshops/04_roman_numerals/04_roman_numerals.pro b/tdd_intro/workshops/04_roman_numerals/04_roman_numerals.pro new file mode 100644 index 0000000..c7fec38 --- /dev/null +++ b/tdd_intro/workshops/04_roman_numerals/04_roman_numerals.pro @@ -0,0 +1,9 @@ +include(../../gtest.pri) + +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt + +SOURCES += \ + test.cpp diff --git a/tdd_intro/workshops/04_roman_numerals/test.cpp b/tdd_intro/workshops/04_roman_numerals/test.cpp new file mode 100644 index 0000000..69756ab --- /dev/null +++ b/tdd_intro/workshops/04_roman_numerals/test.cpp @@ -0,0 +1,94 @@ +#include +#include +/* +Write a function to convert from normal numbers to Roman Numerals. + +The Romans wrote numbers using letters - I, V, X, L, C, D, M. (converter http://www.novaroma.org/via_romana/numbers.html) + +There is no need to be able to convert numbers larger than about 3000. (The Romans themselves didn't tend to go any higher) + +Wikipedia says: Modern Roman numerals ... are written by expressing each digit separately starting with the left most digit and skipping any digit with a value of zero. + +To see this in practice, consider the example of 1990. +In Roman numerals 1990 is MCMXC: +1000=M 900=CM 90=XC + +2008 is written as MMVIII: +2000=MM 8=VIII + +1998 is written as MCMXCVIII. +*/ + +std::string ConvertToRoman(unsigned short num) +{ + if(num == 10) + { + return std::string("X"); + } + else if (num == 0) + { + return std::string(); + } + + std::string result; + if (num / 5 > 0) + { + result = "V"; + num -= 5; + } + + if (num == 4) + { + result = "IV"; + } + else if (num == 9) + { + result = "IX"; + } + else + { + while (num--) + { + result += "I"; + } + } + return result; +} + +TEST(ConvertToRomanTest, insert_zero_return_empty_string) +{ + EXPECT_EQ("", ConvertToRoman(0)); +} + +TEST(ConvertToRomanTest, insert_one_return_I) +{ + EXPECT_EQ("I", ConvertToRoman(1)); +} + +TEST(ConvertToRomanTest, insert_2_return_II) +{ + EXPECT_EQ("II", ConvertToRoman(2)); +} + +TEST(ConvertToRomanTest, insert_5_return_V) +{ + EXPECT_EQ("V", ConvertToRoman(5)); +} + +TEST(ConvertToRomanTest, insert_4_return_IV) +{ + EXPECT_EQ("IV", ConvertToRoman(4)); +} + +TEST(ConvertToRomanTest, insert_10_return_X) +{ + EXPECT_EQ("X", ConvertToRoman(10)); +} + +TEST(ConvertToRomanTest, AcceptanceLess10) +{ + EXPECT_EQ("III", ConvertToRoman(3)); + EXPECT_EQ("VI", ConvertToRoman(6)); + EXPECT_EQ("VII", ConvertToRoman(7)); + EXPECT_EQ("VIII", ConvertToRoman(8)); +} diff --git a/tdd_intro/workshops/04_trinary_numbers/test.cpp b/tdd_intro/workshops/04_trinary_numbers/test.cpp deleted file mode 100644 index c35967c..0000000 --- a/tdd_intro/workshops/04_trinary_numbers/test.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include - -/* -Convert a trinary number, represented as a string (e.g. '102012'), to its decimal equivalent using first principles. - -The program should consider strings specifying an invalid trinary as the value 0. - -Trinary numbers contain three symbols: 0, 1, and 2. - -The last place in a trinary number is the 1's place. The second to last is the 3's place, the third to last is the 9's place, etc. - -# "102012" - 1 0 2 0 1 2 # the number -1*3^5 + 0*3^4 + 2*3^3 + 0*3^2 + 1*3^1 + 2*3^0 # the value - 243 + 0 + 54 + 0 + 3 + 2 = 302 - -If your language provides a method in the standard library to perform the conversion, pretend it doesn't exist and implement it yourself. -*/ diff --git a/tdd_intro/workshops/05_bank_ocr/05_bank_ocr.pro b/tdd_intro/workshops/05_bank_ocr/05_bank_ocr.pro new file mode 100644 index 0000000..c7fec38 --- /dev/null +++ b/tdd_intro/workshops/05_bank_ocr/05_bank_ocr.pro @@ -0,0 +1,9 @@ +include(../../gtest.pri) + +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt + +SOURCES += \ + test.cpp diff --git a/tdd_intro/workshops/05_bank_ocr/test.cpp b/tdd_intro/workshops/05_bank_ocr/test.cpp new file mode 100644 index 0000000..e7852dc --- /dev/null +++ b/tdd_intro/workshops/05_bank_ocr/test.cpp @@ -0,0 +1,187 @@ +/*### Bank OCR + +Your manager has recently purchased a machine that assists in reading letters and faxes sent in by branch offices. The machine scans the paper documents, and produces a file with a number of entries. You will write a program to parse this file. + +#### Specification +#### User Story 1 + +The following format is created by the machine: +``` + _ _ _ _ _ _ _ + | _| _||_||_ |_ ||_||_| + ||_ _| | _||_| ||_| _| +``` +Each entry is 3 lines long, and each line has 27 characters. 3 lines of each entry contain an account number written using pipes and underscores. + +Each account number should have 9 digits, all of which should be in the range 0-9. A normal file contains around 500 entries. + +Write a program that can take this file and parse it into actual account numbers. + +Example input and output +``` + _ _ _ _ _ _ _ _ _ +| || || || || || || || || | +|_||_||_||_||_||_||_||_||_| + +=> 000000000 + + | | | | | | | | | + | | | | | | | | | + +=> 111111111 + + _ _ _ _ _ _ _ _ _ + _| _| _| _| _| _| _| _| _| +|_ |_ |_ |_ |_ |_ |_ |_ |_ + +=> 222222222 + + _ _ _ _ _ _ _ _ _ + _| _| _| _| _| _| _| _| _| + _| _| _| _| _| _| _| _| _| + +=> 333333333 + +|_||_||_||_||_||_||_||_||_| + | | | | | | | | | + +=> 444444444 + + _ _ _ _ _ _ _ _ _ +|_ |_ |_ |_ |_ |_ |_ |_ |_ + _| _| _| _| _| _| _| _| _| + +=> 555555555 + + _ _ _ _ _ _ _ _ _ +|_ |_ |_ |_ |_ |_ |_ |_ |_ +|_||_||_||_||_||_||_||_||_| + +=> 666666666 + + _ _ _ _ _ _ _ _ _ + | | | | | | | | | + | | | | | | | | | + +=> 777777777 + + _ _ _ _ _ _ _ _ _ +|_||_||_||_||_||_||_||_||_| +|_||_||_||_||_||_||_||_||_| + +=> 888888888 + + _ _ _ _ _ _ _ _ _ +|_||_||_||_||_||_||_||_||_| + _| _| _| _| _| _| _| _| _| + +=> 999999999 + + _ _ _ _ _ _ _ + | _| _||_||_ |_ ||_||_| + ||_ _| | _||_| ||_| _| + +=> 123456789 +``` +*/ +#include + +// check matrix for one digit 3x3 +// parse one digit + // - parse 1 + // - parse 2 + // - parse 0-9 + // - check invalid one digit +// parse several digits (27x3) +// parse 27x3 (9 digits) + // - check matrix 27x3 + // - parse +// parse several lines + +using Digit = std::vector; + +const Digit s_1({" ", + " |", + " |"}); + +const Digit s_2({" _ ", + " _|", + "|_ "}); + +std::vector s_digits({ + +}); + +bool CheckMatrixDimension(const Digit& digit) +{ + const size_t prefferedSize = 3; + + if (digit.size() != prefferedSize) + { + return false; + } + + for (const std::string& line : digit) + { + if (line.size() != prefferedSize) + { + return false; + } + } + + return true; +} + +std::string ParseDigit(const Digit& digit) +{ + if (digit == Digit({" ", + " |", + " |"})) + { + return "1"; + } + else if (digit == Digit({" _ ", + " _|", + "|_ "})) + { + return "2"; + } + + return "8"; +} + +TEST(BankOCRTests, Check_Matrix_dimension_true) +{ + Digit digit = {" ", " ", " "}; + EXPECT_TRUE(CheckMatrixDimension(digit)); +} + +TEST(BankOCRTests, Check_Matrix_dimension_false) +{ + Digit digit = {" ", "! ", " "}; + EXPECT_FALSE(CheckMatrixDimension(digit)); +} + +TEST(BankOCRTests, ParseDigit_1) +{ + Digit digit = {" ", + " |", + " |"}; + EXPECT_EQ("1", ParseDigit(digit)); +} + +TEST(BankOCRTests, ParseDigit_2) +{ + Digit digit = {" _ ", + " _|", + "|_ "}; + EXPECT_EQ("2", ParseDigit(digit)); +} + +TEST(BankOCRTests, ParseDigit_8) +{ + Digit digit = {" _ ", + "|_|", + "|_|"}; + EXPECT_EQ("8", ParseDigit(digit)); +} diff --git a/tdd_intro/workshops/05_word_wrapp/test.cpp b/tdd_intro/workshops/05_word_wrapp/test.cpp index f29c0fa..7281e37 100644 --- a/tdd_intro/workshops/05_word_wrapp/test.cpp +++ b/tdd_intro/workshops/05_word_wrapp/test.cpp @@ -1,8 +1,89 @@ /* Write a function, that is given a string and a length limit, splits provided string into sequence of string, where length of each string is not more, than provided limit. If there are spaces under provided limit - -last space should be used to wrapp this line. If there are no spaces - wrapp it on provided length limit. +last space should be used to Wrappp this line. If there are no spaces - Wrappp it on provided length limit. + +When pos is specified, the search only includes sequences of characters that begin at or before position pos, ignoring any possible match beginning after pos. + +"When pos is specified, the", +"search only includes sequences", +"of characters that begin at or", +"before position pos, ignoring", +"any possible match beginning", +"after pos." */ #include #include +#include +//1. Empty test. +//2. Short word and big limit. +//3. Big word and short limit. +//4. Input string with all spaces. +//5. String with 2 words and space before limit. +//6. String with 2 words and space after limit. +//7. String with 2 words and space on limit. +//8. String with 2 words and several spaces before limit. +//9. String with words and different count of spaces. +//10. + +using Strings_vt = std::vector; +std::vector WordWrapp(std::string data, unsigned int limit) +{ + Strings_vt result; + if (data.empty()) + { + return result; + } + + for (int pos = 0; pos < data.size(); pos += limit) + { + + std::string word(data.substr(pos, limit)); + if (word != " ") + { + if (word.back() == ' ') + { + word.pop_back(); + } + result.push_back(word); + } + } + + return result; +} + +TEST(WordWrappTests, Put_empty_get_empty) +{ + EXPECT_EQ(Strings_vt{}, WordWrapp("", 5)); +} + +TEST(WordWrappTests, Put_ShortWord_with_BigLimit) +{ + EXPECT_EQ(Strings_vt{"Word"}, WordWrapp("Word", 5)); +} + +TEST(WordWrappTests, Put_ShortWord_with_space) +{ + EXPECT_EQ(Strings_vt{"Word"}, WordWrapp("Word ", 4)); +} + +TEST(WordWrappTests, BigWord_ShortLimit) +{ + EXPECT_EQ(Strings_vt({"01234", "56789"}), WordWrapp("0123456789", 5)); +} + +TEST(WordWrappTests, BigWord_ShortLimit_ThreeWords) +{ + EXPECT_EQ(Strings_vt({"01234", "56789", "01234"}), WordWrapp("012345678901234", 5)); +} + +TEST(WordWrappTests, TwoWordWithSpace) +{ + EXPECT_EQ(Strings_vt({"0123", "4567"}), WordWrapp("0123 4567", 5)); +} + +TEST(WordWrappTests, ThreeWordWithSingleSpaces) +{ + EXPECT_EQ(Strings_vt({"012 3", "45678"}), WordWrapp("012 3 45678", 5)); +} diff --git a/tdd_intro/workshops/README.MD b/tdd_intro/workshops/README.MD index 85013db..765c8f8 100644 --- a/tdd_intro/workshops/README.MD +++ b/tdd_intro/workshops/README.MD @@ -37,31 +37,135 @@ Example declaration of function required can be something like this: std::map WordsCount(std::string) ``` -### Anagram +### Armstrong number -Given a word and a list of possible anagrams, select the correct sublist. +An Armstrong number is a number that is the sum of its own digits each raised to the power of the number of digits. -Given "listen" and a list of candidates like "enlists" "google" "inlets" "banana" the program should return a list containing "inlets". +For example: + +9 is an Armstrong number, because 9 = 9^1 = 9 +10 is not an Armstrong number, because 10 != 1^2 + 0^2 = 1 +153 is an Armstrong number, because: 153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153 +154 is not an Armstrong number, because: 154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190 +9474 is an Armstrong number + +Write some code to determine whether a number is an Armstrong number. + +Acceptance test +5 - true +100 - false +9475 - false +9926315 - true +9926314 - false _from http://exercism.io/_ -### Trinary +### Roman numerals + +Write a function to convert from normal numbers to Roman Numerals. + +The Romans wrote numbers using letters - I, V, X, L, C, D, M. (converter http://www.novaroma.org/via_romana/numbers.html) + +There is no need to be able to convert numbers larger than about 3000. (The Romans themselves didn't tend to go any higher) + +Wikipedia says: Modern Roman numerals ... are written by expressing each digit separately starting with the left most digit and skipping any digit with a value of zero. + +To see this in practice, consider the example of 1990. +In Roman numerals 1990 is MCMXC: +1000=M 900=CM 90=XC + +2008 is written as MMVIII: +2000=MM 8=VIII -Convert a trinary number, represented as a string (e.g. '102012'), to its decimal equivalent using first principles. +1998 is written as MCMXCVIII. -The program should consider strings specifying an invalid trinary as the value 0. +## Functionality decomposition training: -Trinary numbers contain three symbols: 0, 1, and 2. +### Bank OCR -The last place in a trinary number is the 1's place. The second to last is the 3's place, the third to last is the 9's place, etc. +Your manager has recently purchased a machine that assists in reading letters and faxes sent in by branch offices. The machine scans the paper documents, and produces a file with a number of entries. You will write a program to parse this file. + +#### Specification +#### User Story 1 + +The following format is created by the machine: ``` -# "102012" - 1 0 2 0 1 2 # the number -1*3^5 + 0*3^4 + 2*3^3 + 0*3^2 + 1*3^1 + 2*3^0 # the value - 243 + 0 + 54 + 0 + 3 + 2 = 302 + _ _ _ _ _ _ _ + | _| _||_||_ |_ ||_||_| + ||_ _| | _||_| ||_| _| ``` +Each entry is 3 lines long, and each line has 27 characters. 3 lines of each entry contain an account number written using pipes and underscores. + +Each account number should have 9 digits, all of which should be in the range 0-9. A normal file contains around 500 entries. + +Write a program that can take this file and parse it into actual account numbers. + +Example input and output +``` + _ _ _ _ _ _ _ _ _ +| || || || || || || || || | +|_||_||_||_||_||_||_||_||_| + +=> 000000000 + + | | | | | | | | | + | | | | | | | | | + +=> 111111111 -If your language provides a method in the standard library to perform the conversion, pretend it doesn't exist and implement it yourself. + _ _ _ _ _ _ _ _ _ + _| _| _| _| _| _| _| _| _| +|_ |_ |_ |_ |_ |_ |_ |_ |_ + +=> 222222222 + + _ _ _ _ _ _ _ _ _ + _| _| _| _| _| _| _| _| _| + _| _| _| _| _| _| _| _| _| + +=> 333333333 + +|_||_||_||_||_||_||_||_||_| + | | | | | | | | | + +=> 444444444 + + _ _ _ _ _ _ _ _ _ +|_ |_ |_ |_ |_ |_ |_ |_ |_ + _| _| _| _| _| _| _| _| _| + +=> 555555555 + + _ _ _ _ _ _ _ _ _ +|_ |_ |_ |_ |_ |_ |_ |_ |_ +|_||_||_||_||_||_||_||_||_| + +=> 666666666 + + _ _ _ _ _ _ _ _ _ + | | | | | | | | | + | | | | | | | | | + +=> 777777777 + + _ _ _ _ _ _ _ _ _ +|_||_||_||_||_||_||_||_||_| +|_||_||_||_||_||_||_||_||_| + +=> 888888888 + + _ _ _ _ _ _ _ _ _ +|_||_||_||_||_||_||_||_||_| + _| _| _| _| _| _| _| _| _| + +=> 999999999 + + _ _ _ _ _ _ _ + | _| _||_||_ |_ ||_||_| + ||_ _| | _||_| ||_| _| + +=> 123456789 +``` ### Word Wrapp diff --git a/tdd_intro/workshops/workshops.pro b/tdd_intro/workshops/workshops.pro index 3bcc2e2..e5f4d28 100644 --- a/tdd_intro/workshops/workshops.pro +++ b/tdd_intro/workshops/workshops.pro @@ -3,6 +3,7 @@ TEMPLATE = subdirs SUBDIRS += \ 01_fizz_buzz \ 02_word_count \ - 03_anagram \ - 04_trinary_numbers \ - 05_word_wrapp + 03_armstrong_number \ + 04_roman_numerals \ + 05_word_wrapp \ + 05_bank_ocr