diff --git a/CMakeLists.txt b/CMakeLists.txt index c3f883db3..40128f457 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ set(FAKER_SOURCES src/modules/database/Database.cpp src/modules/music/Music.cpp src/modules/movie/Movie.cpp + src/modules/git/Git.cpp src/modules/hacker/Hacker.cpp src/modules/sport/Sport.cpp src/modules/videoGame/VideoGame.cpp @@ -72,6 +73,7 @@ set(FAKER_UT_SOURCES src/modules/database/DatabaseTest.cpp src/modules/music/MusicTest.cpp src/modules/movie/MovieTest.cpp + src/modules/git/GitTest.cpp src/modules/hacker/HackerTest.cpp src/modules/sport/SportTest.cpp src/modules/videoGame/VideoGameTest.cpp diff --git a/include/faker-cxx/Git.h b/include/faker-cxx/Git.h new file mode 100644 index 000000000..587eacf49 --- /dev/null +++ b/include/faker-cxx/Git.h @@ -0,0 +1,79 @@ +#pragma once + +#include +#include + +#include "faker-cxx/types/Language.h" + +namespace faker +{ +class Git +{ +public: + /** + * @brief Returns a random branch name. + * + * @param maxIssueNum The maximum issue number in branch name. Defaults to `100`. + * @returns Branch name. + * + * @code + * Git::branch() // "capitalize-bus" + * @endcode + */ + static std::string branch(unsigned maxIssueNum = 100); + + /** + * @brief Generates a random date in form of string. + * + * @param years The range of years the date may be in the past. Defaults to `15`. + * @returns Commit date. + * + * @code + * Git::commitDate() // "Mon Jan 17 15:05:53 2022 +1100" + * @endcode + */ + static std::string commitDate(unsigned years = 15); + + /** + * @brief Generates a random commit entry in form of string. + * + * @param dateYears The range of years the date may be in the past. Defaults to `15`. + * @param shaLength The length of output SHA hash. Defaults to `40`. + * @param language The language set for name generating. Defaults to `English` (could be random, if there was a random language generator). + * @returns Commit entry. + * + * @code + * Git::commitEntry() // "commit 9cbc41bb8ce0438c8de9cb25a1c6ad33441d8aca + Author: Rachel McLaughlin Rachel_McLaughlin@gmail.com + Date: Mon Jan 17 15:05:53 2022 +1100 + + spawn polyp" + * @endcode + */ + static std::string commitEntry(std::optional dateYears = std::nullopt, std::optional shaLength = std::nullopt, Language language = Language::English); + + /** + * @brief Generates a random commit message. + * + * @returns Commit message. + * + * @code + * Git::commitMessage() // "spawn polyp" + * @endcode + */ + static std::string commitMessage(); + + /** + * @brief Returns a random SHA hash. + * + * @param length The length of output SHA hash. Defaults to `40`. + * + * @returns SHA hash. + * + * @code + * Git::commitSha() // "9cbc41bb8ce0438c8de9cb25a1c6ad33441d8aca" + * @endcode + */ + static std::string commitSha(unsigned length = 40); +}; +} \ No newline at end of file diff --git a/src/modules/git/Git.cpp b/src/modules/git/Git.cpp new file mode 100644 index 000000000..4fdec0453 --- /dev/null +++ b/src/modules/git/Git.cpp @@ -0,0 +1,120 @@ +#include "faker-cxx/Git.h" + +#include + +#include "faker-cxx/Word.h" +#include "faker-cxx/Number.h" +#include "faker-cxx/Date.h" +#include "faker-cxx/String.h" +#include "faker-cxx/Person.h" +#include "faker-cxx/Internet.h" +#include "faker-cxx/types/Language.h" +#include "../../common/StringHelper.h" +#include "../date/data/MonthNames.h" +#include "fmt/format.h" + +namespace faker +{ + +std::string Git::branch(unsigned maxIssueNum) +{ + switch (Number::integer(1, 3)) + { + case 1: + return fmt::format("{}-{}", Word::verb(), Word::noun()); + case 2: + return fmt::format("{}-{}-{}", Word::verb(), Word::adjective(), Word::noun()); + default: + return fmt::format("{}-{}-{}-{}", Number::integer(unsigned (1), maxIssueNum), Word::verb(), Word::adjective(), Word::noun()); + } +} + +std::string Git::commitDate(unsigned years) +{ + std::string date = Date::pastDate(int(years)); + std::string outputDate = Date::weekdayAbbreviatedName(); + + std::vector dateSplit = StringHelper::split(date, "-"); + std::string year = dateSplit[0]; + std::string month = dateSplit[1]; + std::string rest = dateSplit[2]; + + std::vector restSplit = StringHelper::split(rest, "T"); + std::string day = restSplit[0]; + + std::string time = StringHelper::split(restSplit[1], "Z")[0]; + + int timeZone = Number::integer(0, 12); + std::string timeZoneString; + if (Number::integer(0, 1)) + { + timeZoneString += "-"; + } + else + { + timeZoneString += "+"; + } + + if (timeZone <= 9) + { + timeZoneString += "0"; + } + + timeZoneString += std::to_string(timeZone * 100); + if (!timeZone) + { + timeZoneString += "00"; + } + + + return fmt::format("{} {} {} {} {} {}", Date::weekdayAbbreviatedName(), monthAbbreviatedNames[size_t(std::stoi(month)-1)], day, time, year, timeZoneString); +} + +std::string Git::commitEntry(std::optional dateYears, std::optional shaLength, Language language) +{ + std::string entry = "commit "; + if (shaLength) + { + entry += commitSha(shaLength.emplace()); + } + else + { + entry += commitSha(); + } + + std::string firstName = Person::firstName(language); + std::string lastName = Person::lastName(language); + entry += "\nAuthor: " + firstName + " " + lastName + " " + Internet::email(firstName, lastName) + "\nDate: "; + if (dateYears) + { + entry += commitDate(dateYears.emplace()); + } + else + { + entry += commitDate(); + } + + entry += "\n\n\t" + commitMessage(); + return entry; +} + +std::string Git::commitMessage() +{ + switch (Number::integer(1, 4)) + { + case 1: + return fmt::format("{} {}", Word::verb(), Word::noun()); + case 2: + return fmt::format("{} {} {}", Word::verb(), Word::adjective(), Word::noun()); + case 3: + return fmt::format("{} {} {}", Word::verb(), Word::noun(), Word::adverb()); + default: + return fmt::format("{} {} {} {}", Word::verb(), Word::adjective(), Word::noun(), Word::adverb()); + } +} + +std::string Git::commitSha(unsigned length) +{ + return faker::String::hexadecimal(length, HexCasing::Lower, HexPrefix::None); +} +} \ No newline at end of file diff --git a/src/modules/git/GitTest.cpp b/src/modules/git/GitTest.cpp new file mode 100644 index 000000000..63387c566 --- /dev/null +++ b/src/modules/git/GitTest.cpp @@ -0,0 +1,101 @@ +#include "faker-cxx/Git.h" + +#include + +#include "gtest/gtest.h" + +#include +#include +#include + +#include "faker-cxx/Word.h" +#include "faker-cxx/Number.h" +#include "faker-cxx/Date.h" +#include "faker-cxx/String.h" +#include "faker-cxx/Person.h" +#include "faker-cxx/Internet.h" +#include "faker-cxx/types/Language.h" +#include "../../common/StringHelper.h" +#include "../date/data/MonthNames.h" + +using namespace ::testing; +using namespace faker; + +class GitTest : public Test +{ +public: + inline static const std::string DATE_REGEX = "[A-Z][a-z]{2} [A-Z][a-z]{2,3} (([0-2][0-9])|(3[0-1])) (([0-1][0-9])|(2[0-4])):[0-5][0-9]:[0-5][0-9] [1-2][0-9]{3} (-|\\+)((0[0-9])|(1[0-2]))00"; + inline static const std::string MESSAGE_REGEX = R"([a-zA-Z]+(\-[a-zA-Z]+)* ([a-zA-Z\-]+(\-[a-zA-Z]+)*\s)*[a-zA-Z\-]+(\-[a-zA-Z]+)*)"; + + static std::string generateShaRegex(unsigned length) ; + static std::string generateShaRegex(); +}; + +std::string GitTest::generateShaRegex(unsigned length) { + return "[0-9a-fA-F]{" + std::to_string(length) + "}"; +} + +std::string GitTest::generateShaRegex() { + return "[0-9a-fA-F]+"; +} + +TEST_F(GitTest, shouldGenerateBranch) +{ + const auto branch = Git::branch(); + unsigned long branchSplit = faker::StringHelper::split(branch, "-").size(); + std::cout << branch << " | " << branchSplit << std::endl; + + ASSERT_TRUE(2 <= branchSplit && branchSplit <= 7); +} + +TEST_F(GitTest, branchIssueNumTest) +{ + unsigned testValue = unsigned (faker::Number::integer(2, 100)); + std::vector branch = faker::StringHelper::split(Git::branch(testValue), "-"); + bool numberAtFront = false; + int number; + while (!numberAtFront) + { + branch = faker::StringHelper::split(Git::branch(testValue), "-"); + try + { + number = std::stoi(branch[0]); + numberAtFront = true; + } + catch (...) + { + continue; + } + } + + ASSERT_TRUE(1 <= number && number <= int(testValue)); +} + +TEST_F(GitTest, shouldGenerateCommitDate) +{ + const std::regex dateRegex("^" + GitTest::DATE_REGEX + "$"); + ASSERT_TRUE(std::regex_match(Git::commitDate(), dateRegex)); +} + +TEST_F(GitTest, shouldGenerateCommitEntry) +{ + const std::regex entryRegex("^commit " + GitTest::generateShaRegex() + + "\nAuthor: [A-Z][a-zA-Z]+ [A-Z][a-zA-Z]+ .+@[0-9a-zA-Z]+\\.[0-9a-zA-Z]+\nDate: " + + GitTest::DATE_REGEX + "\n\n\t" + GitTest::MESSAGE_REGEX + "$"); + ASSERT_TRUE(std::regex_match(Git::commitEntry(), entryRegex)); +} + +TEST_F(GitTest, shouldGenerateCommitMessage) +{ + const std::regex messageRegex("^" + GitTest::MESSAGE_REGEX + "$"); + std::string temp = Git::commitMessage(); + std::cout << temp << std::endl; + ASSERT_TRUE(std::regex_match(temp, messageRegex)); +} + +TEST_F(GitTest, shouldGenerateCommitSha) +{ + unsigned length = 40; + const std::regex shaRegex("^" + GitTest::generateShaRegex(length) + "$"); + ASSERT_TRUE(std::regex_match(Git::commitSha(length), shaRegex)); +} \ No newline at end of file