From ab056bb69bc6a222ec57251c6a950d324de0e6f7 Mon Sep 17 00:00:00 2001 From: jwilken <7515971+jsbwilken@users.noreply.github.com> Date: Tue, 8 Aug 2023 18:51:59 +0200 Subject: [PATCH] Added iban support for missing eu members (#74) * Added iban support for missing eu members * Added missing tests based on regex Added gmock neccessary for ASSERT_THAT * Added macro to match regex using std::regex Link gmock for tests --- CMakeLists.txt | 5 +- include/faker-cxx/types/IbanCountry.h | 58 +++++++- src/modules/finance/FinanceTest.cpp | 175 ++++++++++++++----------- src/modules/finance/data/IbanFormats.h | 28 +++- 4 files changed, 180 insertions(+), 86 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 55c86097..8aaedbe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,7 @@ if (BUILD_FAKER_TESTS) add_subdirectory(externals/googletest) set(GTEST_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/googletest/googletest/include") + set(GMOCK_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/googletest/googlemock/include") enable_testing() @@ -84,9 +85,9 @@ if (BUILD_FAKER_TESTS) add_executable(${LIBRARY_NAME}-UT ${FAKER_UT_SOURCES}) - target_link_libraries(${LIBRARY_NAME}-UT PRIVATE gtest_main faker-cxx) + target_link_libraries(${LIBRARY_NAME}-UT PRIVATE gtest_main gmock_main faker-cxx) - target_include_directories(${LIBRARY_NAME}-UT PRIVATE ${GTEST_INCLUDE_DIR} ${CMAKE_CURRENT_LIST_DIR}) + target_include_directories(${LIBRARY_NAME}-UT PRIVATE ${GTEST_INCLUDE_DIR} ${GMOCK_INCLUDE_DIR} ${CMAKE_CURRENT_LIST_DIR}) add_test(NAME ${LIBRARY_NAME}-UT COMMAND ${LIBRARY_NAME}-UT WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) diff --git a/include/faker-cxx/types/IbanCountry.h b/include/faker-cxx/types/IbanCountry.h index 60dbcd2b..204c77ac 100644 --- a/include/faker-cxx/types/IbanCountry.h +++ b/include/faker-cxx/types/IbanCountry.h @@ -6,13 +6,63 @@ namespace faker { enum class IbanCountry { - Poland, + Austria, + Belgium, + Bulgaria, + Croatia, + Cyprus, + Czechia, + Denmark, + Estonia, + Finland, France, Germany, - Italy + Greece, + Hungary, + Ireland, + Italy, + Latvia, + Lithuania, + Luxembourg, + Malta, + Netherlands, + Poland, + Portugal, + Romania, + Slovakia, + Slovenia, + Spain, + Sweden }; -const std::vector supportedIbanCountries{IbanCountry::Poland, IbanCountry::France, IbanCountry::Germany, - IbanCountry::Italy}; +const std::vector supportedIbanCountries{ + IbanCountry::Austria, + IbanCountry::Belgium, + IbanCountry::Bulgaria, + IbanCountry::Croatia, + IbanCountry::Cyprus, + IbanCountry::Czechia, + IbanCountry::Denmark, + IbanCountry::Estonia, + IbanCountry::Finland, + IbanCountry::France, + IbanCountry::Germany, + IbanCountry::Greece, + IbanCountry::Hungary, + IbanCountry::Ireland, + IbanCountry::Italy, + IbanCountry::Latvia, + IbanCountry::Lithuania, + IbanCountry::Luxembourg, + IbanCountry::Malta, + IbanCountry::Netherlands, + IbanCountry::Poland, + IbanCountry::Portugal, + IbanCountry::Romania, + IbanCountry::Slovakia, + IbanCountry::Slovenia, + IbanCountry::Spain, + IbanCountry::Sweden, +}; } diff --git a/src/modules/finance/FinanceTest.cpp b/src/modules/finance/FinanceTest.cpp index 937b007b..c2d30f9d 100644 --- a/src/modules/finance/FinanceTest.cpp +++ b/src/modules/finance/FinanceTest.cpp @@ -1,8 +1,11 @@ #include "faker-cxx/Finance.h" #include +#include +#include #include "gtest/gtest.h" +#include "gmock/gmock.h" #include "../../common/LuhnCheck.h" #include "../../common/StringHelper.h" @@ -11,15 +14,75 @@ #include "data/BankIndentifiersCodes.h" #include "data/Currencies.h" + using namespace ::testing; using namespace faker; namespace { const std::string creditCardCharacters = "0123456789-"; +const std::map expectedRegex { + {IbanCountry::Austria, "^(AT)([0-9]{2})([0-9]{5})([0-9]{11})$"}, + {IbanCountry::Belgium, "^(BE)([0-9]{2})([0-9]{3})([0-9]{7})([0-9]{2})$"}, + {IbanCountry::Bulgaria, "^(BG)([0-9]{2})([A-Z]{4})([0-9]{4})([0-9]{2})([a-zA-Z0-9]{8})$"}, + {IbanCountry::Croatia, "^(HR)([0-9]{2})([0-9]{7})([0-9]{10})$"}, + {IbanCountry::Cyprus, "^(CY)([0-9]{2})([0-9]{3})([0-9]{5})([a-zA-Z0-9]{16})$"}, + {IbanCountry::Czechia, "^(CZ)([0-9]{2})([0-9]{4})([0-9]{6})([0-9]{10})$"}, + {IbanCountry::Denmark, "^(DK)([0-9]{2})([0-9]{4})([0-9]{9})([0-9]{1})$"}, + {IbanCountry::Estonia, "^(EE)([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{11})([0-9]{1})$"}, + {IbanCountry::Finland, "^(FI)([0-9]{2})([0-9]{6})([0-9]{7})([0-9]{1})$"}, + {IbanCountry::France, "^(FR)([0-9]{2})([0-9]{5})([0-9]{5})([a-zA-Z0-9]{11})([0-9]{2})$"}, + {IbanCountry::Germany, "^(DE)([0-9]{2})([0-9]{8})([0-9]{10})$"}, + {IbanCountry::Greece, "^(GR)([0-9]{2})([0-9]{3})([0-9]{4})([a-zA-Z0-9]{16})$"}, + {IbanCountry::Hungary, "^(HU)([0-9]{2})([0-9]{3})([0-9]{4})([0-9]{1})([0-9]{15})([0-9]{1})$"}, + {IbanCountry::Ireland, "^(IE)([0-9]{2})([A-Z]{4})([0-9]{6})([0-9]{8})$"}, + {IbanCountry::Italy, "^(IT)([0-9]{2})([A-Z]{1})([0-9]{5})([0-9]{5})([a-zA-Z0-9]{12})$"}, + {IbanCountry::Latvia, "^(LV)([0-9]{2})([A-Z]{4})([a-zA-Z0-9]{13})$"}, + {IbanCountry::Lithuania, "^(LT)([0-9]{2})([0-9]{5})([0-9]{11})$"}, + {IbanCountry::Luxembourg, "^(LU)([0-9]{2})([0-9]{3})([a-zA-Z0-9]{13})$"}, + {IbanCountry::Malta, "^(MT)([0-9]{2})([A-Z]{4})([0-9]{5})([a-zA-Z0-9]{18})$"}, + {IbanCountry::Netherlands, "^(NL)([0-9]{2})([A-Z]{4})([0-9]{10})$"}, + {IbanCountry::Poland, "^(PL)([0-9]{2})([0-9]{3})([0-9]{4})([0-9]{1})([0-9]{16})$"}, + {IbanCountry::Portugal, "^(PT)([0-9]{2})([0-9]{4})([0-9]{4})([0-9]{11})([0-9]{2})$"}, + {IbanCountry::Romania, "^(RO)([0-9]{2})([A-Z]{4})([a-zA-Z0-9]{16})$"}, + {IbanCountry::Slovakia, "^(SK)([0-9]{2})([0-9]{4})([0-9]{6})([0-9]{10})$"}, + {IbanCountry::Slovenia, "^(SI)([0-9]{2})([0-9]{2})([0-9]{3})([0-9]{8})([0-9]{2})$"}, + {IbanCountry::Spain, "^(ES)([0-9]{2})([0-9]{4})([0-9]{4})([0-9]{2})([0-9]{10})$"}, + {IbanCountry::Sweden, "^(SE)([0-9]{2})([0-9]{3})([0-9]{17})$"}, +}; + +const std::map generatedTestName { + {IbanCountry::Austria, "shouldGenerateAustriaIban"}, + {IbanCountry::Belgium, "shouldGenerateBelgiumIban"}, + {IbanCountry::Bulgaria, "shouldGenerateBulgariaIban"}, + {IbanCountry::Croatia, "shouldGenerateCroatiaIban"}, + {IbanCountry::Cyprus, "shouldGenerateCyprusIban"}, + {IbanCountry::Czechia, "shouldGenerateCzechiaIban"}, + {IbanCountry::Denmark, "shouldGenerateDenmarkIban"}, + {IbanCountry::Estonia, "shouldGenerateEstoniaIban"}, + {IbanCountry::Finland, "shouldGenerateFinlandIban"}, + {IbanCountry::France, "shouldGenerateFranceIban"}, + {IbanCountry::Germany, "shouldGenerateGermanyIban"}, + {IbanCountry::Greece, "shouldGenerateGreeceIban"}, + {IbanCountry::Hungary, "shouldGenerateHungaryIban"}, + {IbanCountry::Ireland, "shouldGenerateIrelandIban"}, + {IbanCountry::Italy, "shouldGenerateItalyIban"}, + {IbanCountry::Latvia, "shouldGenerateLatviaIban"}, + {IbanCountry::Lithuania, "shouldGenerateLithuaniaIban"}, + {IbanCountry::Luxembourg, "shouldGenerateLuxembourgIban"}, + {IbanCountry::Malta, "shouldGenerateMaltaIban"}, + {IbanCountry::Netherlands, "shouldGenerateNetherlandsIban"}, + {IbanCountry::Poland, "shouldGeneratePolandIban"}, + {IbanCountry::Portugal, "shouldGeneratePortugalIban"}, + {IbanCountry::Romania, "shouldGenerateRomaniaIban"}, + {IbanCountry::Slovakia, "shouldGenerateSlovakiaIban"}, + {IbanCountry::Slovenia, "shouldGenerateSloveniaIban"}, + {IbanCountry::Spain, "shouldGenerateSpainIban"}, + {IbanCountry::Sweden, "shouldGenerateSwedenIban"}, +}; } -class FinanceTest : public Test +class FinanceTest : public TestWithParam { public: static bool checkIfAllCharactersAreNumeric(const std::string& data) @@ -100,6 +163,32 @@ TEST_F(FinanceTest, shouldGenerateAmount) ASSERT_LE(amountAsFloat, 1000); } +/* + * The default GTest macro "MatchesRegex" has only minimal support on + * windows. Hence, we define our own macro which uses the c++ default + * implementation of the used compiler. + */ +MATCHER_P(MatchesRegexCpp, value, "") { + return std::regex_match(arg, std::regex(value)); +} + +TEST_P(FinanceTest, CheckIbanGenerator) { + auto ibanCountry = GetParam(); + + ASSERT_THAT(Finance::iban(ibanCountry), MatchesRegexCpp(expectedRegex.at(ibanCountry))); +} + +INSTANTIATE_TEST_SUITE_P( + TestIbanGenerator, + FinanceTest, + ValuesIn( + std::views::keys(expectedRegex).begin(), + std::views::keys(expectedRegex).end() + ), + [](const TestParamInfo &info) { + return generatedTestName.at(info.param); + }); + TEST_F(FinanceTest, shouldGenerateAmountWithSymbol) { const auto min = 150; @@ -125,83 +214,13 @@ TEST_F(FinanceTest, shouldGenerateIban) const auto iban = Finance::iban(); // TODO: implement more detailed checks for iban with default argument - ASSERT_TRUE(iban.starts_with("PL") || iban.starts_with("IT") || iban.starts_with("FR") || iban.starts_with("DE")); -} - -TEST_F(FinanceTest, shouldGeneratePolishIban) -{ - const auto iban = Finance::iban(IbanCountry::Poland); - - const auto countryCode = iban.substr(0, 2); - const auto checksum = iban.substr(2, 2); - const auto bankCode = iban.substr(4, 3); - const auto branchCode = iban.substr(7, 4); - const auto checkDigit = iban.substr(11, 1); - const auto accountNumber = iban.substr(12, 16); - - ASSERT_EQ(iban.size(), 28); - ASSERT_EQ(countryCode, "PL"); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(checksum)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(bankCode)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(branchCode)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(checkDigit)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(accountNumber)); -} - -TEST_F(FinanceTest, shouldGenerateFranceIban) -{ - const auto iban = Finance::iban(IbanCountry::France); - - const auto countryCode = iban.substr(0, 2); - const auto checksum = iban.substr(2, 2); - const auto bankCode = iban.substr(4, 5); - const auto branchCode = iban.substr(9, 5); - const auto accountNumber = iban.substr(14, 11); - const auto checkDigit = iban.substr(25, 2); - - ASSERT_EQ(iban.size(), 27); - ASSERT_EQ(countryCode, "FR"); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(checksum)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(bankCode)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(branchCode)); - ASSERT_TRUE(checkIfAllCharactersAreAlphanumeric(accountNumber)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(checkDigit)); -} - -TEST_F(FinanceTest, shouldGenerateItalyIban) -{ - const auto iban = Finance::iban(IbanCountry::Italy); - - const auto countryCode = iban.substr(0, 2); - const auto checksum = iban.substr(2, 2); - const auto checkDigit = iban.substr(4, 1); - const auto bankCode = iban.substr(5, 5); - const auto branchCode = iban.substr(10, 5); - const auto accountNumber = iban.substr(15, 12); - - ASSERT_EQ(iban.size(), 27); - ASSERT_EQ(countryCode, "IT"); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(checksum)); - ASSERT_TRUE(checkIfAllCharactersAreAlpha(checkDigit)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(bankCode)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(branchCode)); - ASSERT_TRUE(checkIfAllCharactersAreAlphanumeric(accountNumber)); -} - -TEST_F(FinanceTest, shouldGenerateGermanyIban) -{ - const auto iban = Finance::iban(IbanCountry::Germany); - - const auto countryCode = iban.substr(0, 2); - const auto checksum = iban.substr(2, 2); - const auto blz = iban.substr(4, 8); - const auto accountNumber = iban.substr(12, 10); - - ASSERT_EQ(iban.size(), 22); - ASSERT_EQ(countryCode, "DE"); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(checksum)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(blz)); - ASSERT_TRUE(checkIfAllCharactersAreNumeric(accountNumber)); + ASSERT_TRUE(iban.starts_with("AT") || iban.starts_with("BE") || iban.starts_with("BG") || iban.starts_with("HR") || + iban.starts_with("CY") || iban.starts_with("CZ") || iban.starts_with("DK") || iban.starts_with("EE") || + iban.starts_with("FI") || iban.starts_with("FR") || iban.starts_with("DE") || iban.starts_with("GR") || + iban.starts_with("HU") || iban.starts_with("IE") || iban.starts_with("IT") || iban.starts_with("LV") || + iban.starts_with("LT") || iban.starts_with("LU") || iban.starts_with("MT") || iban.starts_with("NL") || + iban.starts_with("PL") || iban.starts_with("PT") || iban.starts_with("RO") || iban.starts_with("SK") || + iban.starts_with("SI") || iban.starts_with("ES") || iban.starts_with("SE")); } TEST_F(FinanceTest, shouldGenerateBic) diff --git a/src/modules/finance/data/IbanFormats.h b/src/modules/finance/data/IbanFormats.h index 0f4ccf0a..14c97ca9 100644 --- a/src/modules/finance/data/IbanFormats.h +++ b/src/modules/finance/data/IbanFormats.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "faker-cxx/types/IbanCountry.h" @@ -11,9 +12,32 @@ namespace faker // Iban format structure from https://bank.codes/iban/structure/ // Note: a - alphabets (letters only), c - characters (letters & numbers), n - numbers (numbers only) const std::map> ibanFormats{ - {IbanCountry::Poland, {"PL", "2n", "3n", "4n", "1n", "16n"}}, + {IbanCountry::Austria, {"AT", "2n", "5n", "11n"}}, + {IbanCountry::Belgium, {"BE", "2n", "3n", "7n", "2n"}}, + {IbanCountry::Bulgaria, {"BG", "2n", "4a", "4n", "2n", "8c"}}, + {IbanCountry::Croatia, {"HR", "2n", "7n", "10n"}}, + {IbanCountry::Cyprus, {"CY", "2n", "3n", "5n", "16c"}}, + {IbanCountry::Czechia, {"CZ", "2n", "4n", "6n", "10n"}}, + {IbanCountry::Denmark, {"DK", "2n", "4n", "9n", "1n"}}, + {IbanCountry::Estonia, {"EE", "2n", "2n", "2n", "11n", "1n"}}, + {IbanCountry::Finland, {"FI", "2n", "6n", "7n", "1n"}}, {IbanCountry::France, {"FR", "2n", "5n", "5n", "11c", "2n"}}, - {IbanCountry::Italy, {"IT", "2n", "1a", "5n", "5n", "12c"}}, {IbanCountry::Germany, {"DE", "2n", "8n", "10n"}}, + {IbanCountry::Greece, {"GR", "2n", "3n", "4n", "16c"}}, + {IbanCountry::Hungary, {"HU", "2n", "3n", "4n", "1n", "15n", "1n"}}, + {IbanCountry::Ireland, {"IE", "2n", "4a", "6n", "8n"}}, + {IbanCountry::Italy, {"IT", "2n", "1a", "5n", "5n", "12c"}}, + {IbanCountry::Latvia, {"LV", "2n", "4a", "13n"}}, + {IbanCountry::Lithuania, {"LT", "2n", "5n", "11n"}}, + {IbanCountry::Luxembourg, {"LU", "2n", "3n", "13c"}}, + {IbanCountry::Malta, {"MT", "2n", "4a", "5n", "18c"}}, + {IbanCountry::Netherlands, {"NL", "2n", "4a", "10n"}}, + {IbanCountry::Poland, {"PL", "2n", "3n", "4n", "1n", "16n"}}, + {IbanCountry::Portugal, {"PT", "2n", "4n", "4n", "11n", "2n"}}, + {IbanCountry::Romania, {"RO", "2n", "4a", "16c"}}, + {IbanCountry::Slovakia, {"SK", "2n", "4n", "6n", "10n"}}, + {IbanCountry::Slovenia, {"SI", "2n", "2n", "3n", "8n", "2n"}}, + {IbanCountry::Spain, {"ES", "2n", "4n", "4n", "2n", "10n"}}, + {IbanCountry::Sweden, {"SE", "2n", "3n", "16n", "1n"}}, }; }