diff --git a/tdd_intro/homework/01_leap_year/test.cpp b/tdd_intro/homework/01_leap_year/test.cpp index 4f186c8b..9f60fafd 100644 --- a/tdd_intro/homework/01_leap_year/test.cpp +++ b/tdd_intro/homework/01_leap_year/test.cpp @@ -13,3 +13,47 @@ If your language provides a method in the standard library that does this look-u */ #include + +bool LeapYear(int year) +{ + if (year%400 == 0) + { + return true; + } + if (year%100 == 0) + { + return false; + } + if (year%4 == 0) + { + return true; + } + return false; +} + +TEST(LeapYear, DevidedBy4) +{ + ASSERT_TRUE(LeapYear(4)); +} + +TEST(LeapYear, DevidedBy100) +{ + ASSERT_FALSE(LeapYear(100)); +} + +TEST(LeapYear, DevidedBy400) +{ + ASSERT_TRUE(LeapYear(400)); +} + +TEST(LeapYear, RandomYearsTest) +{ + ASSERT_TRUE(LeapYear(2000)); + ASSERT_FALSE(LeapYear(1000)); + ASSERT_TRUE(LeapYear(1996)); + ASSERT_FALSE(LeapYear(1997)); + ASSERT_TRUE(LeapYear(2020)); + ASSERT_FALSE(LeapYear(2018)); + ASSERT_TRUE(LeapYear(-2000)); + ASSERT_FALSE(LeapYear(-1000)); +} diff --git a/tdd_intro/homework/02_ternary_numbers/test.cpp b/tdd_intro/homework/02_ternary_numbers/test.cpp index 17503028..8ab93634 100644 --- a/tdd_intro/homework/02_ternary_numbers/test.cpp +++ b/tdd_intro/homework/02_ternary_numbers/test.cpp @@ -16,3 +16,61 @@ The last place in a ternary number is the 1's place. The second to last is the 3 If your language provides a method in the standard library to perform the conversion, pretend it doesn't exist and implement it yourself. */ + +#include + +int OneSignDemicalView(const std::string& oneSign) +{ + if (oneSign == "1" || oneSign == "2" || oneSign == "0") + { + + return std::stoi( oneSign ); + } + return -1; +} + +int DemicalView(const std::string& str) +{ + if (str.empty()) + { + return 0; + } + int answer = 0; + for(size_t i = 1; i <= str.size(); ++i) + { + answer += OneSignDemicalView(str.substr(str.size() - i , 1)) * pow(3, i - 1) ; + } + return (answer > 0) ? answer : 0; +} + +TEST(TernaryNumbers, EmptyString) +{ + ASSERT_EQ(0, DemicalView("")); +} + +TEST(TernaryNumbers, EqualOne) +{ + ASSERT_EQ(1, DemicalView("1")); +} + +TEST(TernaryNumbers, EqualTwo) +{ + ASSERT_EQ(2, DemicalView("2")); +} + +TEST(TernaryNumbers, TwoSignString01) +{ + ASSERT_EQ(1, DemicalView("01")); +} + + +TEST(TernaryNumbers, TwoSignString11) +{ + ASSERT_EQ(4, DemicalView("11")); +} + + +TEST(TernaryNumbers, SpecifcationTest) +{ + ASSERT_EQ(302, DemicalView("102012")); +} diff --git a/tdd_intro/homework/03_bank_ocr/test.cpp b/tdd_intro/homework/03_bank_ocr/test.cpp index cb4b28cb..06d3f3cc 100644 --- a/tdd_intro/homework/03_bank_ocr/test.cpp +++ b/tdd_intro/homework/03_bank_ocr/test.cpp @@ -86,6 +86,8 @@ Example input and output */ #include #include +#include +#include const unsigned short g_linesInDigit = 3; struct Digit @@ -139,6 +141,10 @@ const Digit s_digit9 = { " _ ", "|_|", " _|" }; +const Digit s_noDigit = { " _ ", + "|_|", + " _ " + }; const Display s_displayAll0 = { " _ _ _ _ _ _ _ _ _ ", "| || || || || || || || || |", @@ -194,3 +200,195 @@ const Display s_display123456789 = { " _ _ _ _ _ _ _ ", " | _| _||_||_ |_ ||_||_|", " ||_ _| | _||_| ||_| _|" }; +const Display s_wrongDisplay = { " _ _ _ _ _ _ _ _ _ ", + "|_||_||_||_||_||_||_||_||_|", + " _| _| _| _ _| _| _| _| _|" +}; + +// parse 1 number 0-9 +// right numbers +// wrong numbers +// empty digit + +// parse line +// more than 27 symbols in string +// less than 27 symbols in string +// 27 symbols in string + +// parse several structs + + + +// assumptions: +// one function, take vector of Display and return vector of string +// second function, take 1 Display and return one string with 9 digit. +// third function, take 1 Digit and return one int. +// No information about wrong entry* + +bool CompareDigits(const Digit& left, const Digit& right) +{ + return left.lines[0] == right.lines[0] && left.lines[1] == right.lines[1] && left.lines[2] == right.lines[2]; +} + +int ZipNumberParser(const Digit& digit) +{ + std::vector allNumbers; + allNumbers.reserve(10); + allNumbers.push_back(s_digit0); + allNumbers.push_back(s_digit1); + allNumbers.push_back(s_digit2); + allNumbers.push_back(s_digit3); + allNumbers.push_back(s_digit4); + allNumbers.push_back(s_digit5); + allNumbers.push_back(s_digit6); + allNumbers.push_back(s_digit7); + allNumbers.push_back(s_digit8); + allNumbers.push_back(s_digit9); + + for (int i = 0; i < allNumbers.size(); ++i) + { + if ( CompareDigits(digit, allNumbers[i]) ) + { + return i; + } + } + return -1; +} + +std::string ZipLineParser(const Display& display) +{ + if (display.lines[0].size() != 27 || display.lines[1].size() != 27 || display.lines[2].size() != 27) + { + return "-1"; + } + std::string answer=""; + for(int i = 0; i < 27; i+=3) + { + Digit tempDigit{ std::string(display.lines[0].begin() + i,display.lines[0].begin()+3 + i), + std::string(display.lines[1].begin() + i,display.lines[1].begin()+3 + i), + std::string(display.lines[2].begin() + i,display.lines[2].begin()+3 + i)}; + int temp = ZipNumberParser(tempDigit); + if(temp == -1) + { + return "-1"; + } + else + { + answer = answer + std::to_string(temp); + } + } + return answer; +} + +std::vector ZipVectorParser(std::vector displays) +{ + std::vector answer; + for(auto disp:displays) + { + answer.push_back(ZipLineParser(disp)); + } + return answer; +} + + +TEST(Bank, NumberZero) +{ + ASSERT_EQ(0, ZipNumberParser(s_digit0)); +} + +TEST(Bank, NumberOne) +{ + ASSERT_EQ(1, ZipNumberParser(s_digit1)); +} + +TEST(Bank, NumberThree) +{ + ASSERT_EQ(3, ZipNumberParser(s_digit3)); +} + +TEST(Bank, WrongNumber) +{ + ASSERT_EQ(-1, ZipNumberParser(s_noDigit)); +} + +TEST(Bank, EmptyDigit) +{ + const Digit emptyDigit{"", "", ""}; + ASSERT_EQ(-1, ZipNumberParser(emptyDigit)); +} + +TEST(Bank, LineOfZero) +{ + ASSERT_EQ("000000000", ZipLineParser(s_displayAll0)); +} + +TEST(Bank, emptyDisplay) +{ + Display emptyDisplay{"", "", ""}; + ASSERT_EQ("-1", ZipLineParser(emptyDisplay)); +} + +TEST(Bank, largeDisplay) +{ + Display largeDisplay{"______________________________", + "___________________________", + "___________________________"}; + ASSERT_EQ("-1", ZipLineParser(largeDisplay)); +} +TEST(Bank, LineOf1) +{ + ASSERT_EQ("111111111", ZipLineParser(s_displayAll1)); +} + +TEST(Bank, LineOf2) +{ + ASSERT_EQ("222222222", ZipLineParser(s_displayAll2)); +} + +TEST(Bank, Line123456789) +{ + ASSERT_EQ("123456789", ZipLineParser(s_display123456789)); +} + +TEST(Bank, WrongDispley) +{ + ASSERT_EQ("-1", ZipLineParser(s_wrongDisplay)); +} + +TEST(Bank, TwoLines) +{ + std::vector linesOfDisplay; + linesOfDisplay.push_back(s_displayAll0); + linesOfDisplay.push_back(s_displayAll1); + std::vector answer; + answer.push_back("000000000"); + answer.push_back("111111111"); + ASSERT_EQ(answer, ZipVectorParser(linesOfDisplay)); +} + +TEST(Bank, ThreeLines) +{ + std::vector linesOfDisplay; + linesOfDisplay.push_back(s_displayAll0); + linesOfDisplay.push_back(s_displayAll1); + linesOfDisplay.push_back(s_display123456789); + std::vector answer; + answer.push_back("000000000"); + answer.push_back("111111111"); + answer.push_back("123456789"); + ASSERT_EQ(answer, ZipVectorParser(linesOfDisplay)); +} + +TEST(Bank, ThreeLinesWithWrongDisplay) +{ + std::vector linesOfDisplay; + linesOfDisplay.push_back(s_displayAll0); + linesOfDisplay.push_back(s_wrongDisplay); + linesOfDisplay.push_back(s_display123456789); + std::vector answer; + answer.push_back("000000000"); + answer.push_back("-1"); + answer.push_back("123456789"); + ASSERT_EQ(answer, ZipVectorParser(linesOfDisplay)); +} + diff --git a/tdd_intro/homework/05_coffee/test.cpp b/tdd_intro/homework/05_coffee/test.cpp deleted file mode 100644 index 919530d9..00000000 --- a/tdd_intro/homework/05_coffee/test.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* -We have to develop a coffee machine with TDD. The machine uses the automated source of ingredients, which implements the interface ISourceOfIngredients. - -Our machine should be able to produce the coffee accordingly to the next receipts: -- americano: water & coffee 1:2 or 1:3. Water temp 60C -- cappuccino - milk & coffee & milk foam 1:3, 1:3, 1:3. Water temp 80C -- latte - milk & coffee & milk foam 1:4, 1:2, 1:4. Water temp 90C -- marochino - chocolate & coffee & milk foam, 1:4, 1:4, 1:4 and 1:4 is empty - -We have 2 possible sizes of the cup: -- little 100 gram -- big 140 gram - -Implement worked coffee machine using ISourceOfIngredients to controll the process of coffee production. -*/ - -#include -#include - -class ISourceOfIngredients -{ -public: - ~ISourceOfIngredients() {} - virtual void SetCupSize(int gram) = 0; - virtual void AddWater(int gram, int temperature) = 0; - virtual void AddSugar(int gram) = 0; - virtual void AddCoffee(int gram) = 0; - virtual void AddMilk(int gram) = 0; - virtual void AddMilkFoam(int gram) = 0; - virtual void AddChocolate(int gram) = 0; - virtual void AddCream(int gram) = 0; -}; diff --git a/tdd_intro/homework/05_word_wrapp/05_word_wrapp.pro b/tdd_intro/homework/05_word_wrapp/05_word_wrapp.pro new file mode 100644 index 00000000..c7fec38c --- /dev/null +++ b/tdd_intro/homework/05_word_wrapp/05_word_wrapp.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/homework/05_word_wrapp/test.cpp b/tdd_intro/homework/05_word_wrapp/test.cpp new file mode 100644 index 00000000..77e47210 --- /dev/null +++ b/tdd_intro/homework/05_word_wrapp/test.cpp @@ -0,0 +1,96 @@ +/* +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. + +Example: +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 + +// empty string +// string shorter than wrap number +// word longer than wrap number +// word much longer than wrap number (more than 2 strings) +// string longer than wrap number + +// string wrapped by several whitespaces (less than wrapLength) +// string wrapped by several whitespaces (more than wrapLength) +// only whitespaces in string + +using WrappedStrings = std::vector; + +WrappedStrings WrapString(const std::string& str, size_t wrapLength) +{ + WrappedStrings result; + for(size_t i = 0; i < str.length(); i += wrapLength) + { + std::string cur = str.substr(i, wrapLength); + if (cur.back() == ' ') + { + cur.pop_back(); + } + + if(!cur.empty() && cur.front() == ' ') + { + cur = cur.substr(1); + } + + if(!cur.empty()) + { + result.push_back(cur); + } + } + + return result; +} + +TEST(WrapString, EmptyString) +{ + ASSERT_EQ(WrappedStrings(), WrapString("", 25)); +} + +TEST(WrapString, StringShorterWrapNumber) +{ + ASSERT_EQ(WrappedStrings{"asdf"}, WrapString("asdf", 8)); +} + +TEST(WrapString, StringLongerThanWrapNumber) +{ + WrappedStrings expected = {"asd", "f"}; + ASSERT_EQ(expected, WrapString("asdf", 3)); +} + +TEST(WrapString, StringLongerThanWrapNumberSeveralParts) +{ + WrappedStrings expected = {"12", "34", "56"}; + ASSERT_EQ(expected, WrapString("123456", 2)); +} + +TEST(WrapString, MultipleWordsLonger) +{ + WrappedStrings expected = {"1", "2"}; + ASSERT_EQ(expected, WrapString("1 2", 1)); +} + +TEST(WrapString, SpaceStringEnd) +{ + WrappedStrings expected = {"1", "2"}; + ASSERT_EQ(expected, WrapString("1 2", 2)); +} + +TEST(WrapString, StringWrappedBySeveralWhitespace) +{ + WrappedStrings expected = {"12", "34"}; + ASSERT_EQ(expected, WrapString("12 34", 3)); +} diff --git a/tdd_intro/homework/05_coffee/05_coffee.pro b/tdd_intro/homework/06_coffee/05_coffee.pro similarity index 100% rename from tdd_intro/homework/05_coffee/05_coffee.pro rename to tdd_intro/homework/06_coffee/05_coffee.pro diff --git a/tdd_intro/homework/06_coffee/test.cpp b/tdd_intro/homework/06_coffee/test.cpp new file mode 100644 index 00000000..68118bf3 --- /dev/null +++ b/tdd_intro/homework/06_coffee/test.cpp @@ -0,0 +1,279 @@ +/* +We have to develop a coffee machine with TDD. The machine uses the automated source of ingredients, which implements the interface ISourceOfIngredients. +Our machine should be able to produce the coffee accordingly to the next receipts: +- americano: water & coffee 1:2 or 1:3. Water temp 60C +- cappuccino - milk & coffee & milk foam 1:3, 1:3, 1:3. Water temp 80C +- latte - milk & coffee & milk foam 1:4, 1:2, 1:4. Water temp 90C +- marochino - chocolate & coffee & milk foam, 1:4, 1:4, 1:4 and 1:4 is empty +We have 2 possible sizes of the cup: +- little 100 gram +- big 140 gram +Implement worked coffee machine using ISourceOfIngredients to controll the process of coffee production. +*/ + +#include +#include + +class ISourceOfIngredients +{ +public: + virtual ~ISourceOfIngredients() {} + virtual void SetCupSize(int gram) = 0; + virtual void AddWater(int gram, int temperature) = 0; + virtual void AddSugar(int gram) = 0; + virtual void AddCoffee(int gram) = 0; + virtual void AddMilk(int gram) = 0; + virtual void AddMilkFoam(int gram) = 0; + virtual void AddChocolate(int gram) = 0; + virtual void AddCream(int gram) = 0; +}; + + +enum Cup +{ + Normal = 100, + Big = 140 +}; + +enum Coffee +{ + Americano, + Cappuccino, + Latte, + Marochino +}; + +class MockSourceOfIngredients : public ISourceOfIngredients +{ +public: + MOCK_METHOD1(SetCupSize, void(int)); + MOCK_METHOD2(AddWater, void(int, int)); + MOCK_METHOD1(AddSugar, void(int)); + MOCK_METHOD1(AddCoffee, void(int)); + MOCK_METHOD1(AddMilk, void(int)); + MOCK_METHOD1(AddMilkFoam, void(int)); + MOCK_METHOD1(AddChocolate, void(int)); + MOCK_METHOD1(AddCream, void(int)); +}; + +class CoffeeMachine +{ +public: + CoffeeMachine(ISourceOfIngredients& source) : m_source(source) + { + + } + void CreateCoffee(const Cup cup, const Coffee coffee) + { + switch (coffee) { + case Americano: + { + MakeAmericano(cup); + break; + } + case Cappuccino: + { + MakeCappuccino(cup); + break; + } + case Latte: + { + MakeLatte(cup); + break; + } + case Marochino: + { + MakeMarochino(cup); + break; + } + default: + break; + } + } +private: + void MakeAmericano(int cupSize) + { + m_source.AddCoffee(cupSize/3); + m_source.SetCupSize(cupSize); + m_source.AddWater((cupSize/3)*2, 60); + } + void MakeCappuccino(int cupSize) + { + m_source.AddCoffee(cupSize/4); + m_source.SetCupSize(cupSize); + m_source.AddWater(cupSize/4, 80); + m_source.AddMilk(cupSize/4); + m_source.AddMilkFoam(cupSize/4); + } + void MakeLatte(int cupSize) + { + m_source.AddCoffee(cupSize/2); + m_source.SetCupSize(cupSize); + m_source.AddWater(cupSize/4, 90); + m_source.AddMilk(cupSize/8); + m_source.AddMilkFoam(cupSize/8); + } + void MakeMarochino(int cupSize) + { + m_source.AddCoffee(cupSize/4); + m_source.SetCupSize(cupSize); + m_source.AddMilk(cupSize/4); + m_source.AddMilkFoam(cupSize/4); + } +private: + ISourceOfIngredients& m_source; +}; + + +// Architecture +// Class CoffeMachine +// Class-Mock SourceOfIngredients + +// - americano: water & coffee 1:2 or 1:3. Water temp 60C + +// Tests list: +// 1. americano + 100 gram = 1 coffe +// 2. americano + 140 gram = 1 large coffee +// 3. AddCoffee, SetCupSize and AddWater calls once +// 4. Check parameters +// 5. Same for each recipe + +TEST(CoffeeMachine, CoffemachineIsHere) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); +} + +TEST(CoffeeMachine, CallsImportantThings) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); + + EXPECT_CALL(si, AddCoffee(::testing::_)).Times(1); + EXPECT_CALL(si, SetCupSize(::testing::_)).Times(1); + EXPECT_CALL(si, AddWater(::testing::_, ::testing::_)).Times(1); + + cm.CreateCoffee(Cup::Normal, Coffee::Americano); +} + +//- americano: water & coffee 2:3, 1:3. Water temp 60C +// cup size = 100 ml: 33 coffee + 66 water with 60C +TEST(CoffeeMachine, Americano100ml) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); + + EXPECT_CALL(si, AddCoffee(33)).Times(1); + EXPECT_CALL(si, SetCupSize(100)).Times(1); + EXPECT_CALL(si, AddWater(66, 60)).Times(1); + + cm.CreateCoffee(Cup::Normal, Coffee::Americano); +} + +// cappuccino - milk & coffee & milk foam & water 1:4, 1:4, 1:4 , 1:4. Water temp 80C +// cup size = 100 ml: 25 milk + 25 coffee + 25 milk foam + 25 water 80C +TEST(CoffeeMachine, Cappuccino100ml) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); + + EXPECT_CALL(si, AddCoffee(25)).Times(1); + EXPECT_CALL(si, SetCupSize(100)).Times(1); + EXPECT_CALL(si, AddWater(25, 80)).Times(1); + EXPECT_CALL(si, AddMilk(25)).Times(1); + EXPECT_CALL(si, AddMilkFoam(25)).Times(1); + + cm.CreateCoffee(Cup::Normal, Coffee::Cappuccino); +} + +//- latte - milk & coffee & milk foam 1:8, 1:2, 1:8. 1:4 Water temp 90C +// cup size = 100 ml: 12 milk + 50 coffee + 12 milk foam + 25 water 90C +TEST(CoffeeMachine, Latte100ml) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); + + EXPECT_CALL(si, AddCoffee(50)).Times(1); + EXPECT_CALL(si, SetCupSize(100)).Times(1); + EXPECT_CALL(si, AddWater(25, 90)).Times(1); + EXPECT_CALL(si, AddMilk(12)).Times(1); + EXPECT_CALL(si, AddMilkFoam(12)).Times(1); + + cm.CreateCoffee(Cup::Normal, Coffee::Latte); +} + +// - marochino - chocolate & coffee & milk foam, 1:4, 1:4, 1:4 and 1:4 is empty +// cup size = 100 ml: 25 chocolate + 25 coffee + 25 milk foam +TEST(CoffeeMachine, Marochino100ml) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); + + EXPECT_CALL(si, AddCoffee(25)).Times(1); + EXPECT_CALL(si, SetCupSize(100)).Times(1); + EXPECT_CALL(si, AddMilk(25)).Times(1); + EXPECT_CALL(si, AddMilkFoam(25)).Times(1); + + cm.CreateCoffee(Cup::Normal, Coffee::Marochino); +} + +//- americano: water & coffee 1:3 Water temp 60C +// cup size = 140 ml: 140/3 = 46 coffee + 92 water with 60C +TEST(CoffeeMachine, Americano140ml) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); + + EXPECT_CALL(si, AddCoffee(46)).Times(1); + EXPECT_CALL(si, SetCupSize(140)).Times(1); + EXPECT_CALL(si, AddWater(92, 60)).Times(1); + + cm.CreateCoffee(Cup::Big, Coffee::Americano); +} + +// cappuccino - milk & coffee & milk foam & water 1:4, 1:4, 1:4 , 1:4. Water temp 80C +// cup size = 140 ml: 35 milk + 35 coffee + 35 milk foam + 35 water 80C +TEST(CoffeeMachine, Cappuccino140ml) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); + + EXPECT_CALL(si, AddCoffee(35)).Times(1); + EXPECT_CALL(si, SetCupSize(140)).Times(1); + EXPECT_CALL(si, AddWater(35, 80)).Times(1); + EXPECT_CALL(si, AddMilk(35)).Times(1); + EXPECT_CALL(si, AddMilkFoam(35)).Times(1); + + cm.CreateCoffee(Cup::Big, Coffee::Cappuccino); +} + +//- latte - milk & coffee & milk foam 1:8, 1:2, 1:8. 1:4 Water temp 90C +// cup size = 140 ml: 17 milk + 70 coffee + 17 milk foam + 35 water 90C +TEST(CoffeeMachine, Latte140ml) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); + + EXPECT_CALL(si, AddCoffee(70)).Times(1); + EXPECT_CALL(si, SetCupSize(140)).Times(1); + EXPECT_CALL(si, AddWater(35, 90)).Times(1); + EXPECT_CALL(si, AddMilk(17)).Times(1); + EXPECT_CALL(si, AddMilkFoam(17)).Times(1); + + cm.CreateCoffee(Cup::Big, Coffee::Latte); +} + +// - marochino - chocolate & coffee & milk foam, 1:4, 1:4, 1:4 and 1:4 is empty +// cup size = 140 ml: 35 chocolate + 35 coffee + 35 milk foam +TEST(CoffeeMachine, Marochino140ml) +{ + MockSourceOfIngredients si; + CoffeeMachine cm(si); + + EXPECT_CALL(si, AddCoffee(35)).Times(1); + EXPECT_CALL(si, SetCupSize(140)).Times(1); + EXPECT_CALL(si, AddMilk(35)).Times(1); + EXPECT_CALL(si, AddMilkFoam(35)).Times(1); + + cm.CreateCoffee(Cup::Big, Coffee::Marochino); +} diff --git a/tdd_intro/homework/07_sqlite_header_parser/07_sqlite_header_parser.pro b/tdd_intro/homework/07_sqlite_header_parser/07_sqlite_header_parser.pro new file mode 100644 index 00000000..9cc4c620 --- /dev/null +++ b/tdd_intro/homework/07_sqlite_header_parser/07_sqlite_header_parser.pro @@ -0,0 +1,12 @@ +include(../../gmock.pri) + +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt + +SOURCES += \ + test.cpp +HEADERS += \ + Interfaces.h\ + Mocks.h diff --git a/tdd_intro/homework/07_sqlite_header_parser/Interfaces.h b/tdd_intro/homework/07_sqlite_header_parser/Interfaces.h new file mode 100644 index 00000000..942da7aa --- /dev/null +++ b/tdd_intro/homework/07_sqlite_header_parser/Interfaces.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include + +struct SqliteHeader +{ + std::string head; + int pageSize; + int fileFormatWriteVersion; + int fileFormatReadVersion; + int bytesOfUnused; + int maximumEmbeddedPayloadFraction; + int minimumEmbeddedPayloadFraction; + int leafPayloadFraction; + int fileChangeCounter; + int pageCount; + int firstFreelistPage; + int freelistPageCount; +// 40 4 The schema cookie. + int schemaFormat; // Supported schema formats are 1, 2, 3, and 4. + int defaultPageCacheSize; + int numberOfLargestRootPage; + int databaseTextEncoding; // A value of 1 means UTF-8. A value of 2 means UTF-16le. A value of 3 means UTF-16be. + int userVersion; + int incrementalVacuumMode; + int applicationId; +// 72 20 Reserved for expansion. Must be zero. + int versionValidNumber; + int sqliteVersionNumber; +}; + +class IGui +{ +public: + virtual ~IGui(){} + virtual void DisplayHeader(const std::vector& header) = 0; +}; + +class IDbReader +{ +public: + virtual ~IDbReader(){} + virtual bool ReadFilePath(const std::string& filePath) = 0; + virtual bool CheckHeader() = 0; + virtual std::string GetHeaderString() = 0; + virtual int GetPageSize() = 0; + virtual int GetFormatWriteVersion() = 0; + virtual int GetFormatReadVersion() = 0; + virtual int GetUnsedBytes() = 0; + virtual int GetMaximumEmbeddedPayloadFraction() = 0; + virtual int GetMinimumEmbeddedPayloadFraction() = 0; + virtual int GetLeafPayloadFraction() = 0; + virtual int GetFileChangeCounter() = 0; + virtual int GetPageCount() = 0; + virtual int GetFirstFreelistPage() = 0; + virtual int GetFreelistPageCount() = 0; +// 40 4 The schema cookie. + virtual int GetSchemaFormat() = 0; // Supported schema formats are 1, 2, 3, and 4. + virtual int GetDefaultPageCacheSize() = 0; + virtual int GetNumberOfLargestRootPage() = 0; + virtual int GetDatabaseTextEncoding() = 0; // A value of 1 means UTF-8. A value of 2 means UTF-16le. A value of 3 means UTF-16be. + virtual int GetUserVersion() = 0; + virtual int GetIncrementalVacuumMode() = 0; + virtual int GetApplicationId() = 0; +// 72 20 Reserved for expansion. Must be zero. + virtual int GetVersionValidNumber() = 0; + virtual int GetSqliteVersionNumber() = 0; + virtual bool IsEmpty() = 0; +}; diff --git a/tdd_intro/homework/07_sqlite_header_parser/Mocks.h b/tdd_intro/homework/07_sqlite_header_parser/Mocks.h new file mode 100644 index 00000000..00c13c93 --- /dev/null +++ b/tdd_intro/homework/07_sqlite_header_parser/Mocks.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include "Interfaces.h" + +class GuiMock: public IGui +{ +public: + ~GuiMock(){} + MOCK_METHOD1(DisplayHeader, void(const std::vector& header)); +}; + +class DbReaderMock: public IDbReader +{ +public: + ~DbReaderMock(){} + MOCK_METHOD1(ReadFilePath, bool(const std::string& filePath)); + MOCK_METHOD0(CheckHeader, bool()); + MOCK_METHOD0(GetHeaderString, std::string()); + MOCK_METHOD0(GetPageSize, int()); + MOCK_METHOD0(GetFormatWriteVersion, int()); + MOCK_METHOD0(GetFormatReadVersion, int()); + MOCK_METHOD0(GetUnsedBytes, int()); + MOCK_METHOD0(GetMaximumEmbeddedPayloadFraction, int()); + MOCK_METHOD0(GetMinimumEmbeddedPayloadFraction, int()); + MOCK_METHOD0(GetLeafPayloadFraction, int()); + MOCK_METHOD0(GetFileChangeCounter, int()); + MOCK_METHOD0(GetPageCount, int()); + MOCK_METHOD0(GetFirstFreelistPage, int()); + MOCK_METHOD0(GetFreelistPageCount, int()); +// 40 4 The schema cookie. + MOCK_METHOD0(GetSchemaFormat, int()); + MOCK_METHOD0(GetDefaultPageCacheSize, int()); + MOCK_METHOD0(GetNumberOfLargestRootPage, int()); + MOCK_METHOD0(GetDatabaseTextEncoding, int()); + MOCK_METHOD0(GetUserVersion, int()); + MOCK_METHOD0(GetIncrementalVacuumMode, int()); + MOCK_METHOD0(GetApplicationId, int()); +// 72 20 Reserved for expansion. Must be zero. + MOCK_METHOD0(GetVersionValidNumber, int()); + MOCK_METHOD0(GetSqliteVersionNumber, int()); + MOCK_METHOD0(IsEmpty, bool()); +}; diff --git a/tdd_intro/homework/07_sqlite_header_parser/test.cpp b/tdd_intro/homework/07_sqlite_header_parser/test.cpp new file mode 100644 index 00000000..841211b1 --- /dev/null +++ b/tdd_intro/homework/07_sqlite_header_parser/test.cpp @@ -0,0 +1,463 @@ +/* +Implement application for display sqlite header structure of given file. +Application takes path to file and displays header structure +Sqlite header is described here https://www.sqlite.org/fileformat.html + +Offset Size Description +0 16 The header string: "SQLite format 3\000" +16 2 The database page size in bytes. Must be a power of two between 512 and 32768 inclusive, or the value 1 representing a page size of 65536. +18 1 File format write version. 1 for legacy; 2 for WAL. +19 1 File format read version. 1 for legacy; 2 for WAL. +20 1 Bytes of unused "reserved" space at the end of each page. Usually 0. +21 1 Maximum embedded payload fraction. Must be 64. +22 1 Minimum embedded payload fraction. Must be 32. +23 1 Leaf payload fraction. Must be 32. +24 4 File change counter. +28 4 Size of the database file in pages. The "in-header database size". +32 4 Page number of the first freelist trunk page. +36 4 Total number of freelist pages. +40 4 The schema cookie. +44 4 The schema format number. Supported schema formats are 1, 2, 3, and 4. +48 4 Default page cache size. +52 4 The page number of the largest root b-tree page when in auto-vacuum or incremental-vacuum modes, or zero otherwise. +56 4 The database text encoding. A value of 1 means UTF-8. A value of 2 means UTF-16le. A value of 3 means UTF-16be. +60 4 The "user version" as read and set by the user_version pragma. +64 4 True (non-zero) for incremental-vacuum mode. False (zero) otherwise. +68 4 The "Application ID" set by PRAGMA application_id. +72 20 Reserved for expansion. Must be zero. +92 4 The version-valid-for number. +96 4 SQLITE_VERSION_NUMBER +*/ + +/* + * Read file that not exist + * Read file that have header less than 100 + * Read file with normal first 16 byte + * ... read another parameters + * + * + * */ + +#include +#include + +#include "Mocks.h" +using namespace testing; + +const SqliteHeader g_testHeader{"SQLite format 3", + 512, + 1, + 1, + 0, + 64, + 32, + 32, + 1, + 30, + 20, + 5, + // 40 4 The schema cookie. + 1, + 32, + 0, + 1, + 2, + 0, + 33, + // 72 20 Reserved for expansion. Must be zero. + 3, + 22}; + + +void DysplayHeaderStructure(IGui* gui, IDbReader* dbReader) +{ + if (gui == nullptr || dbReader->IsEmpty() || !dbReader->CheckHeader()) + { + throw std::exception(); + } + std::vector messagesForOutput; + messagesForOutput.push_back("Type - " + dbReader->GetHeaderString()); + messagesForOutput.push_back("DB page size - " + std::to_string(dbReader->GetPageSize())); + messagesForOutput.push_back("File format write version - " + std::to_string(dbReader->GetFormatWriteVersion())); + messagesForOutput.push_back("File format read version - " + std::to_string(dbReader->GetFormatReadVersion())); + messagesForOutput.push_back("Unused bytes - " + std::to_string(dbReader->GetUnsedBytes())); + messagesForOutput.push_back("Maximum embedded payload fraction - " + std::to_string(dbReader->GetMaximumEmbeddedPayloadFraction())); + messagesForOutput.push_back("Minimum embedded payload fraction - " + std::to_string(dbReader->GetMinimumEmbeddedPayloadFraction())); + messagesForOutput.push_back("Leaf payload fraction - " + std::to_string(dbReader->GetLeafPayloadFraction())); + messagesForOutput.push_back("File change counter - " + std::to_string(dbReader->GetFileChangeCounter())); + messagesForOutput.push_back("Size of the database file in pages - " + std::to_string(dbReader->GetPageCount())); + messagesForOutput.push_back("Page number of the first freelist trunk page - " + std::to_string(dbReader->GetFirstFreelistPage())); + messagesForOutput.push_back("Total number of freelist pages - " + std::to_string(dbReader->GetFreelistPageCount())); + messagesForOutput.push_back("The schema format number - " + std::to_string(dbReader->GetSchemaFormat())); + messagesForOutput.push_back("Default page cache size - " + std::to_string(dbReader->GetDefaultPageCacheSize())); + messagesForOutput.push_back("The page number of the largest root b-tree page - " + std::to_string(dbReader->GetNumberOfLargestRootPage())); + messagesForOutput.push_back("The database text encoding - " + std::to_string(dbReader->GetDatabaseTextEncoding())); + messagesForOutput.push_back("The \"user version\" - " + std::to_string(dbReader->GetUserVersion())); + messagesForOutput.push_back("The vacuum mode - " + std::to_string(dbReader->GetIncrementalVacuumMode())); + messagesForOutput.push_back("The \"Application ID\" - " + std::to_string(dbReader->GetApplicationId())); + messagesForOutput.push_back("The version-valid-for number - " + std::to_string(dbReader->GetVersionValidNumber())); + messagesForOutput.push_back("The SQLITE_VERSION_NUMBER - " + std::to_string(dbReader->GetSqliteVersionNumber())); + + gui->DisplayHeader(messagesForOutput); +} + +TEST(SqliteHeaderReader, NoGui) +{ + DbReaderMock dbReader; + ASSERT_THROW(DysplayHeaderStructure(nullptr, &dbReader), std::exception); +} + +TEST(SqliteHeaderReader, EmptyReader) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(true)); + ASSERT_THROW(DysplayHeaderStructure(&gui, &dbReader), std::exception); +} + +TEST(SqliteHeaderReader, ReadFileLessThan100Byte) +{ + DbReaderMock dbReader; + EXPECT_CALL(dbReader, ReadFilePath("somePath")).WillOnce(Return(true)); + dbReader.ReadFilePath("somePath"); + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(false)); + ASSERT_THROW(DysplayHeaderStructure(&gui, &dbReader), std::exception); +} + +TEST(SqliteHeaderReader, ReadHeadString) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetHeaderString()).WillOnce(Return(g_testHeader.head)); + + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadDbPageSize) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetPageSize()).WillOnce(Return(g_testHeader.pageSize)); + + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadFileWriteFormatVersion) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetFormatWriteVersion()).WillOnce(Return(g_testHeader.fileFormatWriteVersion)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadFileReadFormatVersion) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetFormatReadVersion()).WillOnce(Return(g_testHeader.fileFormatReadVersion)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadUnusedBytes) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetFormatReadVersion()).WillOnce(Return(g_testHeader.bytesOfUnused)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadMaximumEmbeddedPayloadFraction) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetMaximumEmbeddedPayloadFraction()).WillOnce(Return(g_testHeader.maximumEmbeddedPayloadFraction)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadMinimumEmbeddedPayloadFraction) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetMinimumEmbeddedPayloadFraction()).WillOnce(Return(g_testHeader.minimumEmbeddedPayloadFraction)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadLeafPayloadFraction) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetLeafPayloadFraction()).WillOnce(Return(g_testHeader.leafPayloadFraction)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadFileChangeCounter) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetFileChangeCounter()).WillOnce(Return(g_testHeader.fileChangeCounter)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadPageCount) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetPageCount()).WillOnce(Return(g_testHeader.pageCount)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadFirstFreelistPage) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetFirstFreelistPage()).WillOnce(Return(g_testHeader.firstFreelistPage)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadFreelistPageCount) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetFreelistPageCount()).WillOnce(Return(g_testHeader.freelistPageCount)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadSchemaFormat) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetSchemaFormat()).WillOnce(Return(g_testHeader.schemaFormat)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadDefaultPageCacheSize) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetDefaultPageCacheSize()).WillOnce(Return(g_testHeader.defaultPageCacheSize)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadNumberOfLargestRootPage) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetNumberOfLargestRootPage()).WillOnce(Return(g_testHeader.numberOfLargestRootPage)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadDatabaseTextEncoding) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetDatabaseTextEncoding()).WillOnce(Return(g_testHeader.databaseTextEncoding)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadUserVersion) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetUserVersion()).WillOnce(Return(g_testHeader.userVersion)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadIncrementalVacuumMode) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetIncrementalVacuumMode()).WillOnce(Return(g_testHeader.incrementalVacuumMode)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadApplicationId) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetApplicationId()).WillOnce(Return(g_testHeader.applicationId)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadVersionValidNumber) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetVersionValidNumber()).WillOnce(Return(g_testHeader.versionValidNumber)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, ReadSqliteVersionNumber) +{ + DbReaderMock dbReader; + GuiMock gui; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetSqliteVersionNumber()).WillOnce(Return(g_testHeader.sqliteVersionNumber)); + EXPECT_CALL(gui, DisplayHeader(_)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} + +TEST(SqliteHeaderReader, SummaryTest) +{ + DbReaderMock dbReader; + EXPECT_CALL(dbReader, ReadFilePath("somePath")).WillOnce(Return(true)); + dbReader.ReadFilePath("somePath"); + GuiMock gui; + + std::vector expectedData{ + std::string("Type - SQLite format 3"), + std::string("DB page size - 512"), + std::string("File format write version - 1"), + std::string("File format read version - 1"), + std::string("Unused bytes - 0"), + std::string("Maximum embedded payload fraction - 64"), + std::string("Minimum embedded payload fraction - 32"), + std::string("Leaf payload fraction - 32"), + std::string("File change counter - 1"), + std::string("Size of the database file in pages - 30"), + std::string("Page number of the first freelist trunk page - 20"), + std::string("Total number of freelist pages - 5"), + std::string("The schema format number - 1"), + std::string("Default page cache size - 32"), + std::string("The page number of the largest root b-tree page - 0"), + std::string("The database text encoding - 1"), + std::string("The \"user version\" - 2"), + std::string("The vacuum mode - 0"), + std::string("The \"Application ID\" - 33"), + std::string("The version-valid-for number - 3"), + std::string("The SQLITE_VERSION_NUMBER - 22")}; + + EXPECT_CALL(dbReader, IsEmpty()).WillOnce(Return(false)); + EXPECT_CALL(dbReader, CheckHeader()).WillOnce(Return(true)); + EXPECT_CALL(dbReader, GetHeaderString()).WillOnce(Return(g_testHeader.head)); + EXPECT_CALL(dbReader, GetPageSize()).WillOnce(Return(g_testHeader.pageSize)); + EXPECT_CALL(dbReader, GetFormatWriteVersion()).WillOnce(Return(g_testHeader.fileFormatWriteVersion)); + EXPECT_CALL(dbReader, GetFormatReadVersion()).WillOnce(Return(g_testHeader.fileFormatReadVersion)); + EXPECT_CALL(dbReader, GetFormatReadVersion()).WillOnce(Return(g_testHeader.bytesOfUnused)); + EXPECT_CALL(dbReader, GetMaximumEmbeddedPayloadFraction()).WillOnce(Return(g_testHeader.maximumEmbeddedPayloadFraction)); + EXPECT_CALL(dbReader, GetMinimumEmbeddedPayloadFraction()).WillOnce(Return(g_testHeader.minimumEmbeddedPayloadFraction)); + EXPECT_CALL(dbReader, GetLeafPayloadFraction()).WillOnce(Return(g_testHeader.leafPayloadFraction)); + EXPECT_CALL(dbReader, GetFileChangeCounter()).WillOnce(Return(g_testHeader.fileChangeCounter)); + EXPECT_CALL(dbReader, GetPageCount()).WillOnce(Return(g_testHeader.pageCount)); + EXPECT_CALL(dbReader, GetFirstFreelistPage()).WillOnce(Return(g_testHeader.firstFreelistPage)); + EXPECT_CALL(dbReader, GetFreelistPageCount()).WillOnce(Return(g_testHeader.freelistPageCount)); + EXPECT_CALL(dbReader, GetSchemaFormat()).WillOnce(Return(g_testHeader.schemaFormat)); + EXPECT_CALL(dbReader, GetDefaultPageCacheSize()).WillOnce(Return(g_testHeader.defaultPageCacheSize)); + EXPECT_CALL(dbReader, GetNumberOfLargestRootPage()).WillOnce(Return(g_testHeader.numberOfLargestRootPage)); + EXPECT_CALL(dbReader, GetDatabaseTextEncoding()).WillOnce(Return(g_testHeader.databaseTextEncoding)); + EXPECT_CALL(dbReader, GetUserVersion()).WillOnce(Return(g_testHeader.userVersion)); + EXPECT_CALL(dbReader, GetIncrementalVacuumMode()).WillOnce(Return(g_testHeader.incrementalVacuumMode)); + EXPECT_CALL(dbReader, GetApplicationId()).WillOnce(Return(g_testHeader.applicationId)); + EXPECT_CALL(dbReader, GetVersionValidNumber()).WillOnce(Return(g_testHeader.versionValidNumber)); + EXPECT_CALL(dbReader, GetSqliteVersionNumber()).WillOnce(Return(g_testHeader.sqliteVersionNumber)); + + EXPECT_CALL(gui, DisplayHeader(expectedData)).Times(1); + + ASSERT_NO_THROW(DysplayHeaderStructure(&gui, &dbReader)); +} diff --git a/tdd_intro/homework/homework.pro b/tdd_intro/homework/homework.pro index 5824b2ae..2198c02c 100644 --- a/tdd_intro/homework/homework.pro +++ b/tdd_intro/homework/homework.pro @@ -5,4 +5,6 @@ SUBDIRS += \ 02_ternary_numbers \ 03_bank_ocr \ 04_weather_client \ - 05_coffee + 05_word_wrapp \ + 06_coffee \ + 07_sqlite_header_parser