From b0f48bd1cfbf586170570d98f956af4097a151c5 Mon Sep 17 00:00:00 2001 From: snandasena Date: Wed, 22 Jun 2022 23:01:15 +0530 Subject: [PATCH] Imoproved --- app/common/CMakeLists.txt | 2 +- app/common/include/constants/Constants.h | 9 ++- .../include/parsers/ValidatedReportParser.h | 17 +++++ app/parsers/include/parsers/XmlParser.h | 2 + app/parsers/src/ValidatedReportParser.cpp | 49 +++++++++++- app/parsers/test/CMakeLists.txt | 2 + .../test/ValidatedReportParser_tests.cpp | 53 +++++++++++++ app/parsers/test/XmlParser_test.cpp | 75 +++++++++++++++++++ 8 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 app/parsers/test/ValidatedReportParser_tests.cpp create mode 100644 app/parsers/test/XmlParser_test.cpp diff --git a/app/common/CMakeLists.txt b/app/common/CMakeLists.txt index 89b01d2..a7d9901 100644 --- a/app/common/CMakeLists.txt +++ b/app/common/CMakeLists.txt @@ -17,4 +17,4 @@ set(SOURCES add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) -target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/inc;include) \ No newline at end of file +target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include) \ No newline at end of file diff --git a/app/common/include/constants/Constants.h b/app/common/include/constants/Constants.h index 33c121a..3210406 100644 --- a/app/common/include/constants/Constants.h +++ b/app/common/include/constants/Constants.h @@ -10,10 +10,10 @@ namespace constants { - std::string OK{"OK"}; - std::string NOK{"NOK"}; - - const std::unordered_set validTaxNames{ + const std::string OK{"OK"}; + const std::string NOK{"NOK"}; +// clang-format off + const std::unordered_set validTaxNames = { "corporate income tax", "individual income tax", "value added tax", @@ -21,6 +21,7 @@ namespace constants "property tax", "exit tax" }; +// clang-format on } #endif //DESIGN_PATTERNS_CONSTANTS_H diff --git a/app/parsers/include/parsers/ValidatedReportParser.h b/app/parsers/include/parsers/ValidatedReportParser.h index ffe471b..e9113a1 100644 --- a/app/parsers/include/parsers/ValidatedReportParser.h +++ b/app/parsers/include/parsers/ValidatedReportParser.h @@ -5,4 +5,21 @@ #ifndef DESIGN_PATTERNS_VALIDATEDREPORTPARSER_H #define DESIGN_PATTERNS_VALIDATEDREPORTPARSER_H +#include "parsers/IReportParser.h" + +#include + + +namespace parsers +{ + template + class ValidatedReportParser : public BaseReportParser + { + public: + static_assert(std::is_base_of::value); + + std::optional parseReport(const std::string &) const override; + }; +} + #endif //DESIGN_PATTERNS_VALIDATEDREPORTPARSER_H diff --git a/app/parsers/include/parsers/XmlParser.h b/app/parsers/include/parsers/XmlParser.h index 67a1637..77f66b8 100644 --- a/app/parsers/include/parsers/XmlParser.h +++ b/app/parsers/include/parsers/XmlParser.h @@ -14,6 +14,8 @@ namespace parsers { class XmlParser : public IReportParser, public ICredentialsParser { + public: + std::optional parseReport(const std::string &) const override; std::optional parseCredentials(const std::string &) const override; diff --git a/app/parsers/src/ValidatedReportParser.cpp b/app/parsers/src/ValidatedReportParser.cpp index 6ec2143..a913028 100644 --- a/app/parsers/src/ValidatedReportParser.cpp +++ b/app/parsers/src/ValidatedReportParser.cpp @@ -13,4 +13,51 @@ #include "constants/Constants.h" #include "parsers/JsonParser.h" -#include "parsers/XmlParser.h" \ No newline at end of file +#include "parsers/XmlParser.h" + +namespace +{ + bool validateTaxYear(const types::Report &report) + { + using Clock = std::chrono::system_clock; + + const auto now = Clock::now(); + const std::time_t now_c = Clock::to_time_t(now); + const struct tm *parts = std::localtime(&now_c); + + const auto currentyear = 1900 + parts->tm_year; + return report.year <= currentyear; + } +} + +namespace parsers +{ + template + std::optional ValidatedReportParser::parseReport(const std::string &rawReport) + const try + { + if (const auto report = BaseReportParser::parseReport(rawReport)) + { + if (report->amount > 0.0 && validateTaxYear(*report)) + { + std::string tax = report->tax; + boost::algorithm::to_lower(tax); + if (constants::validTaxNames.count(tax)) + { + return report; + } + } + } + return std::nullopt; + } catch (const std::exception &e) + { + std::cerr << __FILE__ << ' ' << e.what() << '\n'; + return std::nullopt; + } + + template + class ValidatedReportParser; + + template + class ValidatedReportParser; +} \ No newline at end of file diff --git a/app/parsers/test/CMakeLists.txt b/app/parsers/test/CMakeLists.txt index b61b7ee..c902dba 100644 --- a/app/parsers/test/CMakeLists.txt +++ b/app/parsers/test/CMakeLists.txt @@ -6,6 +6,8 @@ include_directories(${GTEST_INCLUDE_DIR}) set(SOURCES JsonParser_test.cpp + XmlParser_test.cpp + ValidatedReportParser_tests.cpp ) add_executable(${PROJECT_NAME} ${SOURCES}) diff --git a/app/parsers/test/ValidatedReportParser_tests.cpp b/app/parsers/test/ValidatedReportParser_tests.cpp new file mode 100644 index 0000000..243fa04 --- /dev/null +++ b/app/parsers/test/ValidatedReportParser_tests.cpp @@ -0,0 +1,53 @@ +// +// Created by sajith on 6/22/22. +// + +#include "parsers/ValidatedReportParser.h" + +#include +#include +#include +#include + +#include "constants/Constants.h" +#include "nlohmann/json.hpp" +#include "parsers/JsonParser.h" +#include "parsers/XmlParser.h" +#include "types/Report.h" + +using json = nlohmann::json; + +namespace parsers +{ + struct ValidatedReportParserTest : testing::Test + { + const ValidatedReportParser sut; + const std::string taxName = *constants::validTaxNames.begin(); + + const std::string validReport = + nlohmann::to_string(json{{"payer", 1}, + {"tax", taxName}, + {"amount", 1000}, + {"year", 2020}}); + + const std::vector invalidReports = { + to_string(json{{"payer", 1}, + {"tax", taxName}, + {"amount", 0.0}, + {"year", 2020}}), + to_string(json{{"payer", 1}, + {"tax", taxName}, + {"amount", 1000}, + {"year", 2222}}), + to_string(json{{"payer", 1}, + {"tax", "Unknown tax"}, + {"amount", 0}, + {"year", 2020}}), + }; + }; + + TEST_F(ValidatedReportParserTest, reportValidationSucceeds) + { +// ASSERT_NE(sut.parseReport(validReport), std::nullopt); + } +} \ No newline at end of file diff --git a/app/parsers/test/XmlParser_test.cpp b/app/parsers/test/XmlParser_test.cpp new file mode 100644 index 0000000..2fa16b1 --- /dev/null +++ b/app/parsers/test/XmlParser_test.cpp @@ -0,0 +1,75 @@ +// +// Created by sajith on 6/22/22. +// + +#include "parsers/XmlParser.h" + +#include +#include +#include + +#include "types/Report.h" + +struct XmlParserTest : testing::Test +{ + parsers::XmlParser sut; +}; + +TEST_F(XmlParserTest, whenValidData_parseReportReturnsReport) +{ + const std::string xmlRequest{"" + "2" + "VAT" + "10" + "2020" + ""}; + + const std::optional parserReport = sut.parseReport(xmlRequest); + const types::Report expectedReport{2, "VAT", 10, 2020}; + ASSERT_TRUE(parserReport); + ASSERT_EQ(parserReport, expectedReport); +} + + + +TEST_F(XmlParserTest, whenMissingFields_parseReportReturnsNull) +{ + const std::string xmlReport = "22020"; + ASSERT_EQ(sut.parseReport(xmlReport), std::nullopt); +} + +TEST_F(XmlParserTest, whenEmptyReport_parseReportReturnsNull) +{ + const std::string xmlReport = ""; + ASSERT_EQ(sut.parseReport(xmlReport), std::nullopt); +} + +TEST_F(XmlParserTest, whenInvalidXml_parseReportReturnsNull) +{ + const std::string xmlReport = "<>"; + ASSERT_EQ(sut.parseReport(xmlReport), std::nullopt); +} + +TEST_F(XmlParserTest, whenNumericDataInvalid_parseReportReturnsNull) +{ + const std::string xmlReport = "TwoVATOne" + "Three"; + ASSERT_EQ(sut.parseReport(xmlReport), std::nullopt); +} + +TEST_F(XmlParserTest, whenValidData_parseCredentialsReturnsUser) +{ + const std::string xmlReport = "Jhon Doe" + "123"; + const std::optional parsedUser = sut.parseCredentials(xmlReport); + ASSERT_TRUE(parsedUser); + ASSERT_EQ(parsedUser->login.value, std::string("Jhon Doe")); + ASSERT_EQ(parsedUser->password.value, std::string("123")); +} + +TEST_F(XmlParserTest, whenMissingFields_parseCredentialsReturnsNull) +{ + const std::string xmlReport = "Jhon Doe"; + const std::optional parsedUser = sut.parseCredentials(xmlReport); + ASSERT_EQ(parsedUser, std::nullopt); +} \ No newline at end of file