diff --git a/tdd_intro/cleanroom/chatclient/test.cpp b/tdd_intro/cleanroom/chatclient/test.cpp index 599f292a..7bf393a1 100644 --- a/tdd_intro/cleanroom/chatclient/test.cpp +++ b/tdd_intro/cleanroom/chatclient/test.cpp @@ -40,134 +40,3 @@ Implement chat application, that communicates via TCP sockets. #include "mocks.h" using namespace ::testing; - -bool TryToBind(ISocketWrapper& socket) -{ - try - { - socket.Bind("", 0); - } - catch (const std::exception& ex) - { - return false; - } - - return true; -} - -ISocketWrapperPtr EstablishConnection(ISocketWrapper& socket) -{ - if (TryToBind(socket)) - { - socket.Listen(); - return socket.Accept(); - } - else - { - return socket.Connect("", 0); - } -} - -void WriteToSocket(ISocketWrapper& socket, std::string data) -{ - data.push_back('\0'); - socket.Write(data); -} - -void ReadFromSocket(ISocketWrapper& socket, std::string& data) -{ - socket.Read(data); -} - -TEST(Chat, StartAsServer) -{ - StrictMock socketMock; - EXPECT_CALL(socketMock, Bind(_, _)); - ASSERT_TRUE(TryToBind(socketMock)); -} - -TEST(Chat, StartAsClient) -{ - StrictMock socketMock; - EXPECT_CALL(socketMock, Bind(_, _)).WillOnce(Throw(std::runtime_error(""))); - ASSERT_FALSE(TryToBind(socketMock)); -} - -TEST(Chat, StartConnection) -{ - StrictMock socketMock; - EXPECT_CALL(socketMock, Bind(_, _)).WillOnce(Throw(std::runtime_error(""))); - EXPECT_CALL(socketMock, Connect(_, _)).WillOnce(Return(ISocketWrapperPtr())); - EstablishConnection(socketMock); -} - -TEST(Chat, AcceptAfterListen) -{ - StrictMock listener; - StrictMock client; - InSequence sequence; - EXPECT_CALL(listener, Bind(_, _)); - EXPECT_CALL(listener, Listen()); - EXPECT_CALL(listener, Accept()).WillOnce(Return(ISocketWrapperPtr())); - EXPECT_CALL(client, Bind(_, _)).WillOnce(Throw(std::runtime_error(""))); - EXPECT_CALL(client, Connect(_, _)).WillOnce(Return(ISocketWrapperPtr())); - - EstablishConnection(listener); - EstablishConnection(client); -} - -TEST(Chat, ReturnsClientSocket) -{ - SocketWrapperMock listener; - EXPECT_CALL(listener, Accept()).WillOnce(Return(std::make_shared())); - ASSERT_NE(nullptr, EstablishConnection(listener)); -} - -TEST(Chat, ReturnsServerSocket) -{ - SocketWrapperMock server; - EXPECT_CALL(server, Bind(_, _)).WillOnce(Throw(std::runtime_error(""))); - EXPECT_CALL(server, Connect(_, _)).WillOnce(Return(std::make_shared())); - ASSERT_NE(nullptr, EstablishConnection(server)); -} - -TEST(Chat, WriteSomethingToSocket) -{ - SocketWrapperMock server; - EXPECT_CALL(server, Write(_)).Times(1); - WriteToSocket(server,"Hello"); -} - -TEST(Chat, WriteDataToSocket) -{ - std::string expected("Hello", sizeof("Hello")); - - SocketWrapperMock server; - EXPECT_CALL(server, Write(expected)).Times(1); - WriteToSocket(server,"Hello"); -} - -TEST(Chat, ReadSomethingFromSocket) -{ - SocketWrapperMock server; - std::string data; - EXPECT_CALL(server, Read(data)).Times(1); - ReadFromSocket(server, data); -} - -TEST(Chat, ReadDataFromSocket) -{ - SocketWrapperMock server; - std::string data; - EXPECT_CALL(server, Read(data)).WillOnce(::SetArgReferee<0>("Hello")); - ReadFromSocket(server, data); - ASSERT_EQ("Hello", data); -} - -TEST(Chat, ClientHandshakeStart) -{ - SocketWrapperMock socket; - std::string nickname = "client"; - EXPECT_CALL(socket, Write("client:HELLO!")).Times(1); - ClientHandshake(socket, nickname); -} diff --git a/tdd_intro/homework/04_weather_client/test.cpp b/tdd_intro/homework/04_weather_client/test.cpp index 346ea809..04fdd57c 100644 --- a/tdd_intro/homework/04_weather_client/test.cpp +++ b/tdd_intro/homework/04_weather_client/test.cpp @@ -79,3 +79,229 @@ class IWeatherClient virtual double GetAverageWindDirection(IWeatherServer& server, const std::string& date) = 0; virtual double GetMaximumWindSpeed(IWeatherServer& server, const std::string& date) = 0; }; + +// Test list +// done: 1. request creating(look from inside server if client call server with correct request +// done: 2. responce parsing. separate function +// 3. Minium temperature. For different days + +using StringContainer = std::vector; +using WeatherContainer = std::vector; + +const std::string s_testDate = "31.08.2018"; +const std::string s_3hours = "03:00"; +const std::string s_9hours = "09:00"; +const std::string s_15hours = "15:00"; +const std::string s_21hour = "21:00"; + +std::string RemoveFirstToken(std::string& str, const std::string& separator) +{ + size_t offset = str.find(separator); + std::string result = str.substr(0, offset); + str.erase(0, offset+1); + return result; +} + +Weather ParseWeather(const std::string& response) +{ + Weather weather; + std::string tmpResponse = response; + weather.temperature = std::atoi(RemoveFirstToken(tmpResponse, ";").c_str()); + weather.windDirection = std::atoi(RemoveFirstToken(tmpResponse, ";").c_str()); + weather.windSpeed = std::atof(RemoveFirstToken(tmpResponse, ";").c_str()); + return weather; +} + +class FakeWeatherServer : public IWeatherServer +{ + std::map m_data; + StringContainer m_requests; +public: + FakeWeatherServer() + { + m_data = + { + {"31.08.2018;03:00", "20;181;5.1"}, + {"31.08.2018;09:00", "23;204;4.9"}, + {"31.08.2018;15:00", "33;193;4.3"}, + {"31.08.2018;21:00", "26;179;4.5"}, + {"01.09.2018;03:00", "19;176;4.2"}, + {"01.09.2018;09:00", "22;131;4.1"}, + {"01.09.2018;15:00", "31;109;4.0"}, + {"01.09.2018;21:00", "24;127;4.1"}, + {"02.09.2018;03:00", "21;158;3.8"}, + {"02.09.2018;09:00", "25;201;3.5"}, + {"02.09.2018;15:00", "34;258;3.7"}, + {"02.09.2018;21:00", "27;299;4.0"} + }; + } + std::string GetWeather(const std::string &request) + { + m_requests.push_back(request); + auto it = m_data.find(request); + if(it == m_data.end()) + { + return ""; + } + return it->second; + } + + StringContainer GetRequests() + { + StringContainer result; + result.swap(m_requests); + return result; + } +}; + +std::string CreateRequest(const std::string& date, const std::string& time) +{ + return date+";"+time; +} +class WeatherClient : public IWeatherClient +{ +public: + virtual double GetAverageTemperature(IWeatherServer& server, const std::string& date) + { + WeatherContainer weatherArray = GetWeatherForADay(server, date); + double sum = 0; + for(size_t i = 0; i < weatherArray.size(); ++i) + { + sum += weatherArray[i].temperature; + } + return sum/weatherArray.size(); + } + virtual double GetMinimumTemperature(IWeatherServer& server, const std::string& date) + { + WeatherContainer weatherArray = GetWeatherForADay(server, date); + short min = weatherArray[0].temperature; + for(size_t i = 1; i < weatherArray.size(); ++i) + { + min = std::min(min, weatherArray[i].temperature); + } + return min; + } + virtual double GetMaximumTemperature(IWeatherServer& server, const std::string& date) + { + WeatherContainer weatherArray = GetWeatherForADay(server, date); + short max = weatherArray[0].temperature; + for(size_t i = 1; i < weatherArray.size(); ++i) + { + max = std::max(max, weatherArray[i].temperature); + } + return max; + } + virtual double GetAverageWindDirection(IWeatherServer& server, const std::string& date) + { + GetWeatherForADay(server, date); + return 0.0; + } + virtual double GetMaximumWindSpeed(IWeatherServer& server, const std::string& date) + { + GetWeatherForADay(server, date); + return 0.0; + } +private: + WeatherContainer GetWeatherForADay(IWeatherServer& server, const std::string& date) + { + WeatherContainer weatherContainer; + const StringContainer timePoints = {s_3hours, s_9hours, s_15hours, s_21hour}; + for(size_t i = 0; i < timePoints.size(); ++i) + { + std::string request = CreateRequest(date, timePoints[i]); + std::string response = server.GetWeather(request); + weatherContainer.push_back(ParseWeather(response)); + } + return weatherContainer; + } +}; + +StringContainer GenerateExpectedRequests(const std::string& date) +{ + return + { + CreateRequest(date,s_3hours), + CreateRequest(date,s_9hours), + CreateRequest(date,s_15hours), + CreateRequest(date,s_21hour) + }; +} + +TEST(WeatherClient, ClientCallsServerWith3hoursTimeForAvrTemperature) +{ + WeatherClient client; + FakeWeatherServer server; + client.GetAverageTemperature(server, s_testDate); + ASSERT_EQ(CreateRequest(s_testDate,s_3hours), server.GetRequests().at(0)); +} + +TEST(WeatherClient, ClientSends4TimesForMinTemp) +{ + StringContainer expectedRequests = GenerateExpectedRequests(s_testDate); + FakeWeatherServer server; + WeatherClient client; + client.GetMinimumTemperature(server, s_testDate); + ASSERT_EQ(expectedRequests, server.GetRequests()); +} +TEST(WeatherClient, FourRequestsForAnyClientCall) +{ + StringContainer expectedRequests = GenerateExpectedRequests(s_testDate); + WeatherClient client; + FakeWeatherServer server; + + client.GetAverageTemperature(server, s_testDate); + ASSERT_EQ(expectedRequests, server.GetRequests()); + + client.GetMaximumTemperature(server, s_testDate); + ASSERT_EQ(expectedRequests, server.GetRequests()); + + client.GetAverageWindDirection(server, s_testDate); + ASSERT_EQ(expectedRequests, server.GetRequests()); + + client.GetAverageWindDirection(server, s_testDate); + ASSERT_EQ(expectedRequests, server.GetRequests()); + + client.GetMaximumWindSpeed(server, s_testDate); + ASSERT_EQ(expectedRequests, server.GetRequests()); +} + +TEST(RemoveFirstToken, FirstIs10For10_180_5) +{ + std::string str("10;180;5"); + std::string first = RemoveFirstToken(str, ";"); + ASSERT_EQ("10", first); + ASSERT_EQ("180;5", str); +} + +TEST(ParseResponce, TemperatureIs10For10_180_5) +{ + Weather response = ParseWeather("10;180;5"); + ASSERT_EQ(10, response.temperature); +} + +TEST(ParseResponce, WeatherFieldsFor10_180_5) +{ + Weather response = ParseWeather("10;180;5"); + ASSERT_EQ(180, response.windDirection); + ASSERT_EQ(5, response.windSpeed); +} + +TEST(WeatherClient, MinTemperatureIs21For02_09_2018) +{ + FakeWeatherServer server; + WeatherClient client; + ASSERT_EQ(21, client.GetMinimumTemperature(server, "02.09.2018")); +} + +TEST(WeatherClient, AverageTemperatureIs24For01_09_2018) +{ + FakeWeatherServer server; + WeatherClient client; + ASSERT_EQ(24, client.GetAverageTemperature(server, "01.09.2018")); +} +TEST(WeatherClient, MaxTemperatureIs33For31_08_2018) +{ + FakeWeatherServer server; + WeatherClient client; + ASSERT_EQ(33, client.GetMaximumTemperature(server, "31.08.2018")); +}