From 3995d83b6bf39c9d0d50386b1eb5a40fc12dd97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Cie=C5=9Blar?= Date: Thu, 4 Jul 2024 18:22:22 +0100 Subject: [PATCH] docs: refresh readme (#779) * feat: improve generating username * docs: add introduction section to readme * fix: fix tests --- README.md | 55 ++- examples/basic/main.cpp | 9 +- examples/person/main.cpp | 8 +- include/faker-cxx/Internet.h | 569 ++++++++++++------------ src/common/StringHelper.cpp | 5 + src/common/StringHelper.h | 17 +- src/modules/internet/Internet.cpp | 21 +- src/modules/internet/InternetData.h | 104 +++-- tests/modules/internet/InternetTest.cpp | 130 +++--- 9 files changed, 479 insertions(+), 439 deletions(-) diff --git a/README.md b/README.md index 93bfc34aa..e94db17b7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@
C++ Faker, a powerful tool for generating realistic and randomized fake data in C++ programming, enhancing data testing and development workflows

Faker C++

-

Generate fake (but realistic) data for testing and development

[![clang++](https://github.com/cieslarmichal/faker-cxx/actions/workflows/linux-clang-build.yml/badge.svg?branch=main)](https://github.com/cieslarmichal/faker-cxx/actions/workflows/linux-clang-build.yml?query=branch%3Amain) [![apple clang++](https://github.com/cieslarmichal/faker-cxx/actions/workflows/macos-clang-build.yml/badge.svg?branch=main)](https://github.com/cieslarmichal/faker-cxx/actions/workflows/macos-clang-build.yml?query=branch%3Amain) @@ -15,26 +14,37 @@ ## Table of Contents -- [🎯 Goal](#-goal) -- [📖 Usage and Documentation](#usage-and-documentation) +- [Introduction](#introduction) +- [Key Features](#key-features) +- [📖 Usage and Documentation](#-usage-and-documentation) - [💎 Modules](#-modules) -- [Consuming library with CMake](#consuming-library-with-cmake-cmake-322-or-newer) -- [⚒️ Compiler support](#%EF%B8%8F-compiler-support) +- [Consuming the library with CMake](#consuming-the-library-with-cmake) +- [⚒️ Compiler support](#-compiler-support) - [Dependencies](#dependencies) -- [📦 Building the library with Conan](#building-the-library-with-conan) +- [📦 Building the library with Conan](#-building-the-library-with-conan) - [Installing the library with Conan](#installing-the-library-with-conan) -- [Building the Project with Bazel](#building-the-project-with-bazel) +- [Building the library with Bazel](#building-the-library-with-bazel) - [✨ Contributing](#-contributing) - [📘 Credits](#-credits) - [Examples](#examples) - [📝 Changelog](#-changelog) - [🔑 License](#-license) -## 🎯 Goal +## Introduction -The goal of Faker C++ is to provide a library similar to [Faker.js](https://github.com/faker-js/faker) for C++ -community. Faker C++ helps with the creation of realistic and customizable fake data for testing and development -purposes within C++ applications. +Faker C++ is a C++ library inspired by the popular [Faker.js](https://github.com/faker-js/faker), +aimed at providing developers with a robust tool for generating fake (but realistic) data. +Whether you're building test suites, populating databases, or creating demos, Faker C++ has got you covered. + +## Key Features + +📚 Realistic Data Generation: Generate various types of data including names, addresses, emails, dates, and more. + +🛠 Modular Design: Choose from a wide range of modules like Internet, Location, String, Date, and more to generate +specific types of data. + +🚀 Easy Integration: Seamlessly integrate with CMake, and it supports major compilers like MSVC, GCC, Clang, and Apple +Clang. ## 📖 Usage and Documentation @@ -48,12 +58,7 @@ Below is an example of how to use Faker C++ in your code. ```cpp #include -#include "faker-cxx/Date.h" -#include "faker-cxx/Internet.h" -#include "faker-cxx/Location.h" -#include "faker-cxx/String.h" - -// or #include "faker-cxx/Faker.h" for all modules +#include "faker-cxx/Faker.h" // or include specific module int main() { @@ -62,12 +67,14 @@ int main() const auto password = faker::internet::password(); const auto city = faker::location::city(); const auto streetAddress = faker::location::streetAddress(); + const auto bornDate = faker::date::birthdateByYear(1970, 2000); - std::cout << id << std::endl; // 58018063-ce5a-4fa7-adfd-327eb2e2d9a5 - std::cout << email << std::endl; // Lois_Hauck@hotmail.com - std::cout << password << std::endl; // @cWLwgM#Knalxeb - std::cout << city << std::endl; // Sayre ville - std::cout << streetAddress << std::endl; // 1716 Harriet Alley + std::cout << id << std::endl; // 59990db5-3a5f-40bf-8af0-7834c29ee884 + std::cout << email << std::endl; // hills.rita@gmail.com + std::cout << password << std::endl; // Mf+*[(_'lHfM.$v{ + std::cout << city << std::endl; // Rochester + std::cout << streetAddress << std::endl; // 643 Ricardo Creek + std::cout << bornDate << std::endl; // 1973-12-03T11:07:02Z return 0; } @@ -110,7 +117,7 @@ int main() - 🌤️ Weather - temperature, pressure, humidity, weather description - 💬 Word - sample words, nouns, verbs -## Consuming library with CMake (CMake 3.22 or newer) +## Consuming the library with CMake 1. Add faker to git submodules (execute in project root): @@ -177,7 +184,7 @@ The faker-cxx Conan recipe is kept up to date by Conan maintainers and community If the version is out of date, please [create an issue or pull request](https://github.com/conan-io/conan-center-index) on the ConanCenterIndex repository. -## Building the Project with [Bazel](https://bazel.build/) +## Building the library with [Bazel](https://bazel.build/) As alternative, this project can be built using [Bazel](https://bazel.build/). The dependencies are managed directly by Bazel modules, downloading and building all external dependencies. Follow the steps below to build the project: diff --git a/examples/basic/main.cpp b/examples/basic/main.cpp index cad6f1643..c3efa034b 100644 --- a/examples/basic/main.cpp +++ b/examples/basic/main.cpp @@ -1,9 +1,6 @@ -#include #include -#include "faker-cxx/Internet.h" -#include "faker-cxx/Location.h" -#include "faker-cxx/String.h" +#include "faker-cxx/Faker.h" int main() { @@ -12,12 +9,14 @@ int main() const auto password = faker::internet::password(); const auto city = faker::location::city(); const auto streetAddress = faker::location::streetAddress(); + const auto bornDate = faker::date::birthdateByYear(1970, 2000); std::cout << id << std::endl; std::cout << email << std::endl; std::cout << password << std::endl; std::cout << city << std::endl; std::cout << streetAddress << std::endl; + std::cout << bornDate << std::endl; - return EXIT_SUCCESS; + return 0; } diff --git a/examples/person/main.cpp b/examples/person/main.cpp index d834e78c4..539516600 100644 --- a/examples/person/main.cpp +++ b/examples/person/main.cpp @@ -1,9 +1,9 @@ -#include #include #include "faker-cxx/Person.h" -int main() { +int main() +{ const auto personFullName = faker::person::fullName(); std::cout << "Person full name: " << personFullName << std::endl; @@ -25,5 +25,5 @@ int main() { const auto passport = faker::person::passport(); std::cout << "Person passport: " << passport << std::endl; - return EXIT_SUCCESS; -} \ No newline at end of file + return 0; +} diff --git a/include/faker-cxx/Internet.h b/include/faker-cxx/Internet.h index 23348c645..9139d16c5 100644 --- a/include/faker-cxx/Internet.h +++ b/include/faker-cxx/Internet.h @@ -40,310 +40,311 @@ struct FAKER_CXX_EXPORT PasswordOptions bool symbols = true; }; - /** - * @brief Generates a username using the given person's name as base. - * - * @param firstName The optional first name to include in username. - * @param lastName The optional last name to include in username. - * - * @returns Username including neither, one or both of the provided names. - * - * @code - * faker::internet::username() // "Richardson.Jeffrey1997" - * faker::internet::username("Michael") // "Michael_Allen29" - * faker::internet::username(std::nullopt, "Cieslar") // "Phillip_Cieslar20" - * faker::internet::username("Andrew", "Cieslar") // "Andrew.Cieslar" - * @endcode - */ - FAKER_CXX_EXPORT std::string username(std::optional firstName = std::nullopt, - std::optional lastName = std::nullopt, Country country = Country::Usa); +/** + * @brief Generates a username using the given person's name as base. + * + * @param firstName The optional first name to include in username. + * @param lastName The optional last name to include in username. + * + * @returns Username including neither, one or both of the provided names. + * + * @code + * faker::internet::username() // "Richardson.Jeffrey1997" + * faker::internet::username("Michael") // "Michael_Allen29" + * faker::internet::username(std::nullopt, "Cieslar") // "Phillip_Cieslar20" + * faker::internet::username("Andrew", "Cieslar") // "Andrew.Cieslar" + * @endcode + */ +FAKER_CXX_EXPORT std::string username(std::optional firstName = std::nullopt, + std::optional lastName = std::nullopt, + Country country = Country::Usa); - /** - * @brief Generates an email address using the given person's name as base. - * - * @param firstName The optional first name to use. If not specified, a random one will be chosen. - * @param lastName The optional last name to use. If not specified, a random one will be chosen. - * @param emailHost The optional email host name to use. If not specified, a random one will be chosen. - * - * @returns Email including neither, one or both of the provided names, with random/provided email host. - * - * @code - * faker::internet::email() // "Jimenez.Clyde@gmail.com" - * faker::internet::email("Tom") // "TomRichardson79@outlook.com" - * faker::internet::email(std::nullopt, "Howard") // "FreddieHoward@hotmail.com" - * faker::internet::email("Cindy", "Young") // "Young_Cindy@gmail.com" - * faker::internet::email(std::nullopt, std::nullopt, "example.com") // "Wright.Edna1973@code.com" - * @endcode - */ - FAKER_CXX_EXPORT std::string email(std::optional firstName = std::nullopt, - std::optional lastName = std::nullopt, - std::optional emailHost = std::nullopt); +/** + * @brief Generates an email address using the given person's name as base. + * + * @param firstName The optional first name to use. If not specified, a random one will be chosen. + * @param lastName The optional last name to use. If not specified, a random one will be chosen. + * @param emailHost The optional email host name to use. If not specified, a random one will be chosen. + * + * @returns Email including neither, one or both of the provided names, with random/provided email host. + * + * @code + * faker::internet::email() // "Jimenez.Clyde@gmail.com" + * faker::internet::email("Tom") // "TomRichardson79@outlook.com" + * faker::internet::email(std::nullopt, "Howard") // "FreddieHoward@hotmail.com" + * faker::internet::email("Cindy", "Young") // "Young_Cindy@gmail.com" + * faker::internet::email(std::nullopt, std::nullopt, "example.com") // "Wright.Edna1973@code.com" + * @endcode + */ +FAKER_CXX_EXPORT std::string email(std::optional firstName = std::nullopt, + std::optional lastName = std::nullopt, + std::optional emailHost = std::nullopt); - /** - * @brief Generates an email address using the given person's name as base with example domain. - * - * @param firstName The optional first name to use. If not specified, a random one will be chosen. - * @param lastName The optional last name to use. If not specified, a random one will be chosen. - * - * @returns Email including neither, one or both of the provided names, with example email host. - * - * @code - * faker::internet::exampleEmail() // "Jimenez.Clyde@example.com" - * @endcode - */ - FAKER_CXX_EXPORT std::string exampleEmail(std::optional firstName = std::nullopt, - std::optional lastName = std::nullopt); +/** + * @brief Generates an email address using the given person's name as base with example domain. + * + * @param firstName The optional first name to use. If not specified, a random one will be chosen. + * @param lastName The optional last name to use. If not specified, a random one will be chosen. + * + * @returns Email including neither, one or both of the provided names, with example email host. + * + * @code + * faker::internet::exampleEmail() // "Jimenez.Clyde@example.com" + * @endcode + */ +FAKER_CXX_EXPORT std::string exampleEmail(std::optional firstName = std::nullopt, + std::optional lastName = std::nullopt); - /** - * @brief Generates a random password-like string. Do not use this method for generating actual passwords for users. - * Since the source of the randomness is not cryptographically secure, neither is this generator. - * - * @param length The length of the password to generate. Defaults to `15`. - * - * @returns Random password-like string. - * - * @code - * faker::internet::password() // "gXGpe9pKfFcKy9R" - * faker::internet::password(25) // "xv8vDu*wM!Rg0$zd0kH%8p!WY" - * @endcode - */ - FAKER_CXX_EXPORT std::string password(int length = 15, const PasswordOptions& options = {}); +/** + * @brief Generates a random password-like string. Do not use this method for generating actual passwords for users. + * Since the source of the randomness is not cryptographically secure, neither is this generator. + * + * @param length The length of the password to generate. Defaults to `16`. + * + * @returns Random password-like string. + * + * @code + * faker::internet::password() // "gXGpe9pKfFcKy9R" + * faker::internet::password(25) // "xv8vDu*wM!Rg0$zd0kH%8p!WY" + * @endcode + */ +FAKER_CXX_EXPORT std::string password(int length = 16, const PasswordOptions& options = {}); - enum class EmojiType - { - Activity, - Body, - Flag, - Food, - Nature, - Object, - Person, - Smiley, - Symbol, - Travel, - }; +enum class EmojiType +{ + Activity, + Body, + Flag, + Food, + Nature, + Object, + Person, + Smiley, + Symbol, + Travel, +}; - /** - * @brief Returns a random emoji. - * - * @param type The optional type of them emoji to be generated. - * - * @returns Emoji. - * - * @code - * faker::internet::emoji() // "👑" - * faker::internet::emoji(EmojiType::Food) // "🍕" - * @endcode - */ - FAKER_CXX_EXPORT std::string_view emoji(std::optional type = std::nullopt); +/** + * @brief Returns a random emoji. + * + * @param type The optional type of them emoji to be generated. + * + * @returns Emoji. + * + * @code + * faker::internet::emoji() // "👑" + * faker::internet::emoji(EmojiType::Food) // "🍕" + * @endcode + */ +FAKER_CXX_EXPORT std::string_view emoji(std::optional type = std::nullopt); - /** - * @brief Verify that a given emoji is valid. - * - * @param emojiToCheck the emoji to check. - * - * @returns true if emojiToCheck is found in one of the vectors, false otherwise. - * - * @code - * faker::internet::checkIfEmojiIsValid("👑") // true - * @endcode - */ - FAKER_CXX_EXPORT bool checkIfEmojiIsValid(const std::string& emojiToCheck); +/** + * @brief Verify that a given emoji is valid. + * + * @param emojiToCheck the emoji to check. + * + * @returns true if emojiToCheck is found in one of the vectors, false otherwise. + * + * @code + * faker::internet::checkIfEmojiIsValid("👑") // true + * @endcode + */ +FAKER_CXX_EXPORT bool checkIfEmojiIsValid(const std::string& emojiToCheck); - /** - * @brief Returns a random web protocol. Either `http` or `https`. - * - * @returns Web protocol. - * - * @code - * faker::internet::protocol() // "https" - * @endcode - */ - FAKER_CXX_EXPORT std::string_view protocol(); +/** + * @brief Returns a random web protocol. Either `http` or `https`. + * + * @returns Web protocol. + * + * @code + * faker::internet::protocol() // "https" + * @endcode + */ +FAKER_CXX_EXPORT std::string_view protocol(); - /** - * @brief Generates a random http method name. - * - * @returns Http method name. - * - * @code - * faker::internet::httpMethod() // "POST" - * @endcode - */ - FAKER_CXX_EXPORT std::string_view httpMethod(); +/** + * @brief Generates a random http method name. + * + * @returns Http method name. + * + * @code + * faker::internet::httpMethod() // "POST" + * @endcode + */ +FAKER_CXX_EXPORT std::string_view httpMethod(); - /** - * @brief Returns a random http status code. - * - * @param responseType The type of the http response. - * - * @returns Http status code. - * - * @code - * faker::internet::httpStatusCode() // 500 - * faker::internet::httpStatusCode(HttpStatusCodeType::success) // 201 - * @endcode - */ - FAKER_CXX_EXPORT unsigned httpStatusCode(std::optional responseType = std::nullopt); +/** + * @brief Returns a random http status code. + * + * @param responseType The type of the http response. + * + * @returns Http status code. + * + * @code + * faker::internet::httpStatusCode() // 500 + * faker::internet::httpStatusCode(HttpStatusCodeType::success) // 201 + * @endcode + */ +FAKER_CXX_EXPORT unsigned httpStatusCode(std::optional responseType = std::nullopt); - /** - * @brief Generates a random http request header. - * - * @returns Http request header. - * - * @code - * faker::internet::httpRequestHeader() // "Authorization" - * @endcode - */ - FAKER_CXX_EXPORT std::string_view httpRequestHeader(); +/** + * @brief Generates a random http request header. + * + * @returns Http request header. + * + * @code + * faker::internet::httpRequestHeader() // "Authorization" + * @endcode + */ +FAKER_CXX_EXPORT std::string_view httpRequestHeader(); - /** - * @brief Generates a random http response header. - * - * @returns Http response header. - * - * @code - * faker::internet::httpResponseHeader() // "Location" - * @endcode - */ - FAKER_CXX_EXPORT std::string_view httpResponseHeader(); +/** + * @brief Generates a random http response header. + * + * @returns Http response header. + * + * @code + * faker::internet::httpResponseHeader() // "Location" + * @endcode + */ +FAKER_CXX_EXPORT std::string_view httpResponseHeader(); - /** - * @brief Generates a random http media type. - * - * @returns Http media type. - * - * @code - * faker::internet::httpMediaType() // "application/json" - * @endcode - */ - FAKER_CXX_EXPORT std::string_view httpMediaType(); +/** + * @brief Generates a random http media type. + * + * @returns Http media type. + * + * @code + * faker::internet::httpMediaType() // "application/json" + * @endcode + */ +FAKER_CXX_EXPORT std::string_view httpMediaType(); - /** - * @brief Returns a string containing randomized ipv4 address of the given class. - * - * @param ipv4class Address class to be generated. - * - * @return String representation of the ipv4 address. - * - * @code - * faker::internet::ipv4() // "192.168.0.1" - * faker::internet::ipv4(IPv4Class::classA) // "10.0.0.1" - * @endcode - */ - FAKER_CXX_EXPORT std::string ipv4(const IPv4Class& ipv4class = IPv4Class::C); +/** + * @brief Returns a string containing randomized ipv4 address of the given class. + * + * @param ipv4class Address class to be generated. + * + * @return String representation of the ipv4 address. + * + * @code + * faker::internet::ipv4() // "192.168.0.1" + * faker::internet::ipv4(IPv4Class::classA) // "10.0.0.1" + * @endcode + */ +FAKER_CXX_EXPORT std::string ipv4(const IPv4Class& ipv4class = IPv4Class::C); - /** - * @brief Returns a string containing randomized ipv4 address based on given base address and mask. - * - * Generated result is compliant with the ipv4 classes. Bits of the baseIpv4Address not covered by the - * generationMask will be ignored and replaced during generation. Bits covered by the mask will be kept in the - * result. Mask should be provided in the same format as regular ipv4 mask. - * - * @param generationMask Mask deciding which bits of the base address should be kept during randomization. - * @param baseIpv4Address Address to randomize from. - * - * @return std::string representation of the ipv4 address. - * - * @code - * faker::internet::ipv4({255.0.0.0}, {10.100.100.100}) // "10.128.17.1" - * faker::internet::ipv4({255.255.128.0}, {129.168.255.0}) // "192.168.128.10" - * @endcode - */ - FAKER_CXX_EXPORT std::string ipv4(const std::array& baseIpv4Address, - const std::array& generationMask); +/** + * @brief Returns a string containing randomized ipv4 address based on given base address and mask. + * + * Generated result is compliant with the ipv4 classes. Bits of the baseIpv4Address not covered by the + * generationMask will be ignored and replaced during generation. Bits covered by the mask will be kept in the + * result. Mask should be provided in the same format as regular ipv4 mask. + * + * @param generationMask Mask deciding which bits of the base address should be kept during randomization. + * @param baseIpv4Address Address to randomize from. + * + * @return std::string representation of the ipv4 address. + * + * @code + * faker::internet::ipv4({255.0.0.0}, {10.100.100.100}) // "10.128.17.1" + * faker::internet::ipv4({255.255.128.0}, {129.168.255.0}) // "192.168.128.10" + * @endcode + */ +FAKER_CXX_EXPORT std::string ipv4(const std::array& baseIpv4Address, + const std::array& generationMask); - /** - * @brief Returns a string containing randomized ipv6 address. - * - * @return String representation of the ipv6 address. - * - * @code - * faker::internet::ipv6() // "269f:1230:73e3:318d:842b:daab:326d:897b" - * @endcode - */ - FAKER_CXX_EXPORT std::string ipv6(); +/** + * @brief Returns a string containing randomized ipv6 address. + * + * @return String representation of the ipv6 address. + * + * @code + * faker::internet::ipv6() // "269f:1230:73e3:318d:842b:daab:326d:897b" + * @endcode + */ +FAKER_CXX_EXPORT std::string ipv6(); - /** - * @brief Returns a generated random mac address. - * - * @param sep Separator to use. Defaults to ":". Also can be "-" or "". - * - * @return A generated random mac address. - * - * @code - * faker::internet::mac() // "2d:10:34:2f:ac:ac" - * @endcode - */ - FAKER_CXX_EXPORT std::string mac(const std::string& sep = ":"); +/** + * @brief Returns a generated random mac address. + * + * @param sep Separator to use. Defaults to ":". Also can be "-" or "". + * + * @return A generated random mac address. + * + * @code + * faker::internet::mac() // "2d:10:34:2f:ac:ac" + * @endcode + */ +FAKER_CXX_EXPORT std::string mac(const std::string& sep = ":"); - /** - * @brief Generates a random port. - * - * @return Port. - * - * @code - * faker::internet::port() // 5432 - * @endcode - */ - FAKER_CXX_EXPORT unsigned port(); +/** + * @brief Generates a random port. + * + * @return Port. + * + * @code + * faker::internet::port() // 5432 + * @endcode + */ +FAKER_CXX_EXPORT unsigned port(); - /** - * @brief Generates a random url. - * - * @param webProtocol Web protocol to generate url with. Defaults to `WebProtocol::Https`. - * - * @return Http(s) url. - * - * @code - * faker::internet::url() // "https://slow-timer.info" - * @endcode - */ - FAKER_CXX_EXPORT std::string url(const WebProtocol& webProtocol = WebProtocol::Https); +/** + * @brief Generates a random url. + * + * @param webProtocol Web protocol to generate url with. Defaults to `WebProtocol::Https`. + * + * @return Http(s) url. + * + * @code + * faker::internet::url() // "https://slow-timer.info" + * @endcode + */ +FAKER_CXX_EXPORT std::string url(const WebProtocol& webProtocol = WebProtocol::Https); - /** - * @brief Generates a random domain name. - * - * @return Domain name. - * - * @code - * faker::internet::domainName() // "slow-timer.info" - * @endcode - */ - FAKER_CXX_EXPORT std::string domainName(); +/** + * @brief Generates a random domain name. + * + * @return Domain name. + * + * @code + * faker::internet::domainName() // "slow-timer.info" + * @endcode + */ +FAKER_CXX_EXPORT std::string domainName(); - /** - * @brief Generates a random domain word. - * - * @return Domain word. - * - * @code - * faker::internet::domainWord() // "close-reality" - * @endcode - */ - FAKER_CXX_EXPORT std::string domainWord(); +/** + * @brief Generates a random domain word. + * + * @return Domain word. + * + * @code + * faker::internet::domainWord() // "close-reality" + * @endcode + */ +FAKER_CXX_EXPORT std::string domainWord(); - /** - * @brief Generates a random domain suffix. - * - * @return Domain suffix. - * - * @code - * faker::internet::domainSuffix() // "com" - * @endcode - */ - FAKER_CXX_EXPORT std::string_view domainSuffix(); +/** + * @brief Generates a random domain suffix. + * + * @return Domain suffix. + * + * @code + * faker::internet::domainSuffix() // "com" + * @endcode + */ +FAKER_CXX_EXPORT std::string_view domainSuffix(); - /** - * @brief Generates a random username. - * - * @param maxLength maxLength of the generated username. - * - * @return Username. - * - * @code - * faker::internet::anonymousUsername() // "profusebrother", "richad", "powerfuldifferential" - * @endcode - */ - FAKER_CXX_EXPORT std::string anonymousUsername(unsigned maxLength); +/** + * @brief Generates a random username. + * + * @param maxLength maxLength of the generated username. + * + * @return Username. + * + * @code + * faker::internet::anonymousUsername() // "profusebrother", "richad", "powerfuldifferential" + * @endcode + */ +FAKER_CXX_EXPORT std::string anonymousUsername(unsigned maxLength); } diff --git a/src/common/StringHelper.cpp b/src/common/StringHelper.cpp index c4e52dfb2..6590e4b2a 100644 --- a/src/common/StringHelper.cpp +++ b/src/common/StringHelper.cpp @@ -97,6 +97,11 @@ std::string toLower(const std::string& data) return lowerData; } +std::string toLower(const std::string_view& data) +{ + return toLower(std::string{data}); +} + bool isPunctuation(char c) { return (c == '.' || c == ',' || c == '!' || c == '?' || c == ';' || c == ':'); diff --git a/src/common/StringHelper.h b/src/common/StringHelper.h index 22c21ada7..c3585c709 100644 --- a/src/common/StringHelper.h +++ b/src/common/StringHelper.h @@ -1,16 +1,19 @@ #pragma once #include +#include #include + #include "faker-cxx/Export.h" namespace faker::common { - FAKER_CXX_EXPORT std::vector split(const std::string& data, const std::string& separator = " "); - FAKER_CXX_EXPORT std::string joinString(const std::vector& data, const std::string& separator = " "); - FAKER_CXX_EXPORT std::string join(const std::vector& data, const std::string& separator = " "); - FAKER_CXX_EXPORT std::string repeat(const std::string& data, int repetition); - FAKER_CXX_EXPORT std::string toLower(const std::string& data); - FAKER_CXX_EXPORT bool isPunctuation(char c); - FAKER_CXX_EXPORT std::string removePunctuation(const std::string& word); +FAKER_CXX_EXPORT std::vector split(const std::string& data, const std::string& separator = " "); +FAKER_CXX_EXPORT std::string joinString(const std::vector& data, const std::string& separator = " "); +FAKER_CXX_EXPORT std::string join(const std::vector& data, const std::string& separator = " "); +FAKER_CXX_EXPORT std::string repeat(const std::string& data, int repetition); +FAKER_CXX_EXPORT std::string toLower(const std::string& data); +FAKER_CXX_EXPORT std::string toLower(const std::string_view& data); +FAKER_CXX_EXPORT bool isPunctuation(char c); +FAKER_CXX_EXPORT std::string removePunctuation(const std::string& word); } diff --git a/src/modules/internet/Internet.cpp b/src/modules/internet/Internet.cpp index 6c5b10158..7946ddabe 100644 --- a/src/modules/internet/Internet.cpp +++ b/src/modules/internet/Internet.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -77,29 +78,29 @@ std::vector getAllEmojis() emojis.insert(emojis.end(), objectEmojis.begin(), objectEmojis.end()); emojis.insert(emojis.end(), symbolEmojis.begin(), symbolEmojis.end()); emojis.insert(emojis.end(), flagEmojis.begin(), flagEmojis.end()); + return emojis; } std::string username(std::optional firstNameInit, std::optional lastNameInit, Country country) { - const auto firstName = firstNameInit ? *firstNameInit : person::firstName(country); - const auto lastName = lastNameInit ? *lastNameInit : person::lastName(country); + const auto firstName = common::toLower(std::string{firstNameInit ? *firstNameInit : person::firstName(country)}); + const auto lastName = common::toLower(std::string{lastNameInit ? *lastNameInit : person::lastName(country)}); std::string username; switch (number::integer(2)) { case 0: - username = common::format("{}{}{}", firstName, lastName, number::integer(999)); + username = common::format("{}{}{}", firstName, lastName, number::integer(1970, 2005)); break; case 1: - username = common::format("{}{}{}", firstName, - helper::arrayElement(std::vector{".", "_", ""}), lastName); + username = + common::format("{}{}{}", firstName, helper::arrayElement(std::vector{".", "_", ""}), lastName); break; case 2: username = - common::format("{}{}{}{}", firstName, helper::arrayElement(std::vector{".", "_", ""}), - lastName, number::integer(99)); + common::format("{}{}{}", lastName, helper::arrayElement(std::vector{".", "_", ""}), firstName); break; } @@ -110,13 +111,13 @@ std::string email(std::optional firstName, std::optional emailHost) { return common::format("{}@{}", username(std::move(firstName), std::move(lastName)), - emailHost ? *emailHost : helper::arrayElement(emailHosts)); + emailHost ? *emailHost : helper::arrayElement(emailHosts)); } std::string exampleEmail(std::optional firstName, std::optional lastName) { return common::format("{}@{}", username(std::move(firstName), std::move(lastName)), - helper::arrayElement(emailExampleHosts)); + helper::arrayElement(emailExampleHosts)); } std::string password(int length, const PasswordOptions& options) @@ -163,12 +164,14 @@ std::string_view emoji(std::optional type) } const auto emojis = getAllEmojis(); + return helper::arrayElement(emojis); } bool checkIfEmojiIsValid(const std::string& emojiToCheck) { const auto emojis = getAllEmojis(); + return std::find(emojis.begin(), emojis.end(), emojiToCheck) != emojis.end(); } diff --git a/src/modules/internet/InternetData.h b/src/modules/internet/InternetData.h index 551040fcf..c8b4eeefe 100644 --- a/src/modules/internet/InternetData.h +++ b/src/modules/internet/InternetData.h @@ -6,11 +6,19 @@ namespace faker::internet { const auto domainSuffixes = std::to_array({ - "biz", "com", "info", "name", "net", "org", + "biz", + "com", + "info", + "name", + "net", + "org", }); const auto emailHosts = std::to_array({ - "gmail.com", "hotmail.com", "outlook.com", "proton.me", "yahoo.com", + "gmail.com", + "hotmail.com", + "outlook.com", + "yahoo.com", }); const auto emailExampleHosts = std::to_array({ @@ -731,53 +739,51 @@ const auto flagEmojis = std::to_array({ "🚩", }); -const auto httpMediaTypes = std::to_array({ - "application/gzip", - "application/java-archive", - "application/json", - "application/octet-stream", - "application/pdf", - "application/rtf", - "application/vnd.amazon.ebook", - "application/vnd.mozilla.xul+xml", - "application/x-7z-compressed", - "application/x-abiword", - "application/x-bzip", - "application/x-bzip2", - "application/x-csh", - "application/x-freearc", - "application/xml", - "application/zip", - "audio/3gpp", - "audio/3gpp2", - "audio/aac", - "audio/mpeg", - "audio/wav", - "audio/webm", - "font/otf", - "font/ttf", - "font/woff", - "font/woff2", - "image/bmp", - "image/gif", - "image/jpeg", - "image/png", - "image/tiff", - "image/webp", - "text/calendar", - "text/css", - "text/csv", - "text/html", - "text/javascript", - "text/plain", - "text/xml", - "video/3gpp", - "video/3gpp2", - "video/mp2t", - "video/mpeg", - "video/webm", - "video/x-msvideo" -}); +const auto httpMediaTypes = std::to_array({"application/gzip", + "application/java-archive", + "application/json", + "application/octet-stream", + "application/pdf", + "application/rtf", + "application/vnd.amazon.ebook", + "application/vnd.mozilla.xul+xml", + "application/x-7z-compressed", + "application/x-abiword", + "application/x-bzip", + "application/x-bzip2", + "application/x-csh", + "application/x-freearc", + "application/xml", + "application/zip", + "audio/3gpp", + "audio/3gpp2", + "audio/aac", + "audio/mpeg", + "audio/wav", + "audio/webm", + "font/otf", + "font/ttf", + "font/woff", + "font/woff2", + "image/bmp", + "image/gif", + "image/jpeg", + "image/png", + "image/tiff", + "image/webp", + "text/calendar", + "text/css", + "text/csv", + "text/html", + "text/javascript", + "text/plain", + "text/xml", + "video/3gpp", + "video/3gpp2", + "video/mp2t", + "video/mpeg", + "video/webm", + "video/x-msvideo"}); const auto httpRequestHeaders = std::to_array({ "A-IM", diff --git a/tests/modules/internet/InternetTest.cpp b/tests/modules/internet/InternetTest.cpp index eef940120..2ee76927b 100644 --- a/tests/modules/internet/InternetTest.cpp +++ b/tests/modules/internet/InternetTest.cpp @@ -106,21 +106,24 @@ TEST_F(InternetTest, shouldGenerateUsername) const auto generatedUsername = username(); - ASSERT_TRUE(std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) - { return generatedUsername.find(firstName) != std::string::npos; })); - ASSERT_TRUE(std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) - { return generatedUsername.find(lastName) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) + { return generatedUsername.find(common::toLower(firstName)) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) + { return generatedUsername.find(common::toLower(lastName)) != std::string::npos; })); } TEST_F(InternetTest, shouldGenerateUsernameWithFirstNameProvided) { - const auto firstName = "Michael"; + const std::string firstName = "Michael"; const auto generatedUsername = username(firstName); - ASSERT_TRUE(generatedUsername.find(firstName) != std::string::npos); - ASSERT_TRUE(std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) - { return generatedUsername.find(lastName) != std::string::npos; })); + ASSERT_TRUE(generatedUsername.find(common::toLower(firstName)) != std::string::npos); + ASSERT_TRUE( + std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) + { return generatedUsername.find(common::toLower(lastName)) != std::string::npos; })); } TEST_F(InternetTest, shouldGenerateUsernameWithLastNameProvided) @@ -129,25 +132,26 @@ TEST_F(InternetTest, shouldGenerateUsernameWithLastNameProvided) person::englishMaleFirstNames.end()); firstNames.insert(firstNames.end(), person::englishFemaleFirstNames.begin(), person::englishFemaleFirstNames.end()); - const auto lastName = "Cieslar"; + const std::string lastName = "Cieslar"; const auto generatedUsername = username(std::nullopt, lastName); - ASSERT_TRUE(std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) - { return generatedUsername.find(firstName) != std::string::npos; })); - ASSERT_TRUE(generatedUsername.find(lastName) != std::string::npos); + ASSERT_TRUE( + std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) + { return generatedUsername.find(common::toLower(firstName)) != std::string::npos; })); + ASSERT_TRUE(generatedUsername.find(common::toLower(lastName)) != std::string::npos); } TEST_F(InternetTest, shouldGenerateUsernameWithFullNameProvided) { - const auto firstName = "Andrew"; + const std::string firstName = "Andrew"; - const auto lastName = "Cieslar"; + const std::string lastName = "Cieslar"; const auto generatedUsername = username(firstName, lastName); - ASSERT_TRUE(generatedUsername.find(firstName) != std::string::npos); - ASSERT_TRUE(generatedUsername.find(lastName) != std::string::npos); + ASSERT_TRUE(generatedUsername.find(common::toLower(firstName)) != std::string::npos); + ASSERT_TRUE(generatedUsername.find(common::toLower(lastName)) != std::string::npos); } TEST_F(InternetTest, shouldGenerateInternationalUsernames) @@ -157,11 +161,13 @@ TEST_F(InternetTest, shouldGenerateInternationalUsernames) const auto generatedUsername = username(std::nullopt, std::nullopt, Country::Poland); - ASSERT_TRUE(std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) - { return generatedUsername.find(firstName) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) + { return generatedUsername.find(common::toLower(firstName)) != std::string::npos; })); - ASSERT_TRUE(std::ranges::any_of(person::polishLastNames, [generatedUsername](const std::string_view& lastName) - { return generatedUsername.find(lastName) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(person::polishLastNames, [generatedUsername](const std::string_view& lastName) + { return generatedUsername.find(common::toLower(lastName)) != std::string::npos; })); } TEST_F(InternetTest, shouldGenerateEmail) @@ -181,15 +187,17 @@ TEST_F(InternetTest, shouldGenerateEmail) ASSERT_TRUE(std::ranges::any_of(emailHosts, [generatedEmailHost](const std::string_view& emailHost) { return generatedEmailHost == emailHost; })); - ASSERT_TRUE(std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) - { return generatedUsername.find(firstName) != std::string::npos; })); - ASSERT_TRUE(std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) - { return generatedUsername.find(lastName) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) + { return generatedUsername.find(common::toLower(firstName)) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) + { return generatedUsername.find(common::toLower(lastName)) != std::string::npos; })); } TEST_F(InternetTest, shouldGenerateEmailWithFirstName) { - const auto firstName = "Tom"; + const std::string firstName = "Tom"; const auto generatedEmail = email(firstName); @@ -202,9 +210,10 @@ TEST_F(InternetTest, shouldGenerateEmailWithFirstName) ASSERT_TRUE(std::ranges::any_of(emailHosts, [generatedEmailHost](const std::string_view& emailHost) { return generatedEmailHost == emailHost; })); - ASSERT_TRUE(generatedUsername.find(firstName) != std::string::npos); - ASSERT_TRUE(std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) - { return generatedUsername.find(lastName) != std::string::npos; })); + ASSERT_TRUE(generatedUsername.find(common::toLower(firstName)) != std::string::npos); + ASSERT_TRUE( + std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) + { return generatedUsername.find(common::toLower(lastName)) != std::string::npos; })); } TEST_F(InternetTest, shouldGenerateEmailWithLastName) @@ -213,7 +222,7 @@ TEST_F(InternetTest, shouldGenerateEmailWithLastName) person::englishMaleFirstNames.end()); firstNames.insert(firstNames.end(), person::englishFemaleFirstNames.begin(), person::englishFemaleFirstNames.end()); - const auto lastName = "Howard"; + const std::string lastName = "Howard"; const auto generatedEmail = email(std::nullopt, lastName); @@ -226,16 +235,17 @@ TEST_F(InternetTest, shouldGenerateEmailWithLastName) ASSERT_TRUE(std::ranges::any_of(emailHosts, [generatedEmailHost](const std::string_view& emailHost) { return generatedEmailHost == emailHost; })); - ASSERT_TRUE(std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) - { return generatedUsername.find(firstName) != std::string::npos; })); - ASSERT_TRUE(generatedUsername.find(lastName) != std::string::npos); + ASSERT_TRUE( + std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) + { return generatedUsername.find(common::toLower(firstName)) != std::string::npos; })); + ASSERT_TRUE(generatedUsername.find(common::toLower(lastName)) != std::string::npos); } TEST_F(InternetTest, shouldGenerateEmailWithFullName) { - const auto firstName = "Cindy"; + const std::string firstName = "Cindy"; - const auto lastName = "Young"; + const std::string lastName = "Young"; const auto generatedEmail = email(firstName, lastName); @@ -248,8 +258,8 @@ TEST_F(InternetTest, shouldGenerateEmailWithFullName) ASSERT_TRUE(std::ranges::any_of(emailHosts, [generatedEmailHost](const std::string_view& emailHost) { return generatedEmailHost == emailHost; })); - ASSERT_TRUE(generatedUsername.find(firstName) != std::string::npos); - ASSERT_TRUE(generatedUsername.find(lastName) != std::string::npos); + ASSERT_TRUE(generatedUsername.find(common::toLower(firstName)) != std::string::npos); + ASSERT_TRUE(generatedUsername.find(common::toLower(lastName)) != std::string::npos); } TEST_F(InternetTest, shouldGenerateEmailWithSpecifiedEmailHost) @@ -270,10 +280,12 @@ TEST_F(InternetTest, shouldGenerateEmailWithSpecifiedEmailHost) const auto& generatedEmailHost = emailParts[1]; ASSERT_EQ(generatedEmailHost, emailHost); - ASSERT_TRUE(std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) - { return generatedUsername.find(firstName) != std::string::npos; })); - ASSERT_TRUE(std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) - { return generatedUsername.find(lastName) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) + { return generatedUsername.find(common::toLower(firstName)) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) + { return generatedUsername.find(common::toLower(lastName)) != std::string::npos; })); } TEST_F(InternetTest, shouldGenerateExampleEmail) @@ -293,15 +305,17 @@ TEST_F(InternetTest, shouldGenerateExampleEmail) ASSERT_TRUE(std::ranges::any_of(emailExampleHosts, [generatedEmailHost](const std::string_view& emailHost) { return generatedEmailHost == emailHost; })); - ASSERT_TRUE(std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) - { return generatedUsername.find(firstName) != std::string::npos; })); - ASSERT_TRUE(std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) - { return generatedUsername.find(lastName) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) + { return generatedUsername.find(common::toLower(firstName)) != std::string::npos; })); + ASSERT_TRUE( + std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) + { return generatedUsername.find(common::toLower(lastName)) != std::string::npos; })); } TEST_F(InternetTest, shouldGenerateExampleEmailWithFirstName) { - const auto firstName = "Barry"; + const std::string firstName = "Barry"; const auto email = exampleEmail(firstName); @@ -314,9 +328,10 @@ TEST_F(InternetTest, shouldGenerateExampleEmailWithFirstName) ASSERT_TRUE(std::ranges::any_of(emailExampleHosts, [generatedEmailHost](const std::string_view& emailHost) { return generatedEmailHost == emailHost; })); - ASSERT_TRUE(generatedUsername.find(firstName) != std::string::npos); - ASSERT_TRUE(std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) - { return generatedUsername.find(lastName) != std::string::npos; })); + ASSERT_TRUE(generatedUsername.find(common::toLower(firstName)) != std::string::npos); + ASSERT_TRUE( + std::ranges::any_of(person::englishLastNames, [generatedUsername](const std::string_view& lastName) + { return generatedUsername.find(common::toLower(lastName)) != std::string::npos; })); } TEST_F(InternetTest, shouldGenerateExampleEmailWithLastName) @@ -325,7 +340,7 @@ TEST_F(InternetTest, shouldGenerateExampleEmailWithLastName) person::englishMaleFirstNames.end()); firstNames.insert(firstNames.end(), person::englishFemaleFirstNames.begin(), person::englishFemaleFirstNames.end()); - const auto lastName = "Wilkinson"; + const std::string lastName = "Wilkinson"; const auto email = exampleEmail(std::nullopt, lastName); @@ -338,16 +353,17 @@ TEST_F(InternetTest, shouldGenerateExampleEmailWithLastName) ASSERT_TRUE(std::ranges::any_of(emailExampleHosts, [generatedEmailHost](const std::string_view& emailHost) { return generatedEmailHost == emailHost; })); - ASSERT_TRUE(std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) - { return generatedUsername.find(firstName) != std::string::npos; })); - ASSERT_TRUE(generatedUsername.find(lastName) != std::string::npos); + ASSERT_TRUE( + std::ranges::any_of(firstNames, [generatedUsername](const std::string_view& firstName) + { return generatedUsername.find(common::toLower(firstName)) != std::string::npos; })); + ASSERT_TRUE(generatedUsername.find(common::toLower(lastName)) != std::string::npos); } TEST_F(InternetTest, shouldGenerateExampleEmailWithFullName) { - const auto firstName = "Walter"; + const std::string firstName = "Walter"; - const auto lastName = "Brown"; + const std::string lastName = "Brown"; const auto email = exampleEmail(firstName, lastName); @@ -360,15 +376,15 @@ TEST_F(InternetTest, shouldGenerateExampleEmailWithFullName) ASSERT_TRUE(std::ranges::any_of(emailExampleHosts, [generatedEmailHost](const std::string_view& emailHost) { return generatedEmailHost == emailHost; })); - ASSERT_TRUE(generatedUsername.find(firstName) != std::string::npos); - ASSERT_TRUE(generatedUsername.find(lastName) != std::string::npos); + ASSERT_TRUE(generatedUsername.find(common::toLower(firstName)) != std::string::npos); + ASSERT_TRUE(generatedUsername.find(common::toLower(lastName)) != std::string::npos); } TEST_F(InternetTest, shouldGeneratePassword) { const auto generatedPassword = password(); - ASSERT_EQ(generatedPassword.size(), 15); + ASSERT_EQ(generatedPassword.size(), 16); ASSERT_TRUE(std::ranges::all_of(generatedPassword, [&](char passwordCharacter) { return passwordCharacters.find(passwordCharacter) != std::string::npos; })); }