diff --git a/include/faker-cxx/string.h b/include/faker-cxx/string.h index 279cec0c..be6c2e78 100644 --- a/include/faker-cxx/string.h +++ b/include/faker-cxx/string.h @@ -1,6 +1,10 @@ #pragma once +#include +#include #include +#include +#include #include #include #include @@ -112,6 +116,34 @@ std::string uuidV1(RandomGenerator gen = RandomGenerator{}) return ss.str(); } +template +std::string uuidV3(RandomGenerator gen = RandomGenerator{}) +{ + // FAking MD5 hash with random data from the generator is enough for this purpose + std::array hash; + std::uniform_int_distribution dist(0, 255); + + for (auto& byte : hash) + { + byte = gen(dist); + } + + hash[6] = (hash[6] & 0x0F) | 0x30; // Set the version to 3 + hash[8] = (hash[8] & 0x3F) | 0x80; // Set the variant to '10' + + std::ostringstream ss; + ss << std::hex << std::setfill('0'); + for (size_t i = 0; i < hash.size(); ++i) + { + ss << std::setw(2) << static_cast(hash[i]); + // Add hyphens at the appropriate positions + if (i == 3 || i == 5 || i == 7 || i == 9) + ss << '-'; + } + + return ss.str(); +} + template std::string uuidV4(RandomGenerator gen = RandomGenerator{}) { @@ -167,7 +199,7 @@ std::string uuidV4(RandomGenerator gen = RandomGenerator{}) * @returns UUID. * * @code - * faker::string::uuid() // "27666229-cedb-4a45-8018-98b1e1d921e2" + * faker::string::uuid() // V4: "27666229-cedb-4a45-8018-98b1e1d921e2" * @endcode */ template @@ -184,7 +216,14 @@ std::string uuid(RandomGenerator gen) * @returns UUID. * * @code - * faker::string::uuid() // "27666229-cedb-4a45-8018-98b1e1d921e2" + * faker::string::uuid() // "27666229-cedb-4a45-8018-98b1e1d921e2" // V4 + * faker::string::uuid(Uuid::V1) // "04f916a0-af32-11ef-9cd2-0242ac120002" + * faker::string::uuid(Uuid::V3) // "a3bb189e-8bf9-3888-9912-ace4e6543002" + * faker::string::uuid(Uuid::V4) // "27666229-cedb-4a45-8018-98b1e1d921e2" + * faker::string::uuid(Uuid::V5) // "27666229-cedb-4a45-8018-98b1e1d921e2" + * faker::string::uuid(Uuid::V6) // "27666229-cedb-4a45-8018-98b1e1d921e2" + * faker::string::uuid(Uuid::V7) // "27666229-cedb-4a45-8018-98b1e1d921e2" + * faker::string::uuid(Uuid::V8) // "27666229-cedb-4a45-8018-98b1e1d921e2" * @endcode */ template @@ -195,7 +234,7 @@ std::string uuid(Uuid uuid = Uuid::V4, RandomGenerator gen = RandomGenerator< case Uuid::V1: return uuidV1(gen); case Uuid::V3: - return uuidV4(gen); + return uuidV3(gen); case Uuid::V4: return uuidV4(gen); case Uuid::V5: diff --git a/tests/modules/string_test.cpp b/tests/modules/string_test.cpp index 353b1286..e4cb2cc8 100644 --- a/tests/modules/string_test.cpp +++ b/tests/modules/string_test.cpp @@ -52,16 +52,44 @@ TEST_F(StringTest, shouldGenerateUuid1) ASSERT_EQ(generatedUuid[18], '-'); ASSERT_EQ(generatedUuid[23], '-'); - // Check the version number ASSERT_EQ(generatedUuid[14], '1'); +} + +TEST_F(StringTest, shouldUseCustomRandomGeneratorForUuid3) +{ + RandomGenerator gen1{}; + const auto generatedUuid1 = uuid(Uuid::V3, gen1); + + ASSERT_EQ(generatedUuid1.size(), 36); + ASSERT_EQ(generatedUuid1[8], '-'); + ASSERT_EQ(generatedUuid1[13], '-'); + ASSERT_EQ(generatedUuid1[18], '-'); + ASSERT_EQ(generatedUuid1[23], '-'); + ASSERT_EQ(generatedUuid1[14], '3'); // Check for version 3 - // Check that the variant bits are '10' - char clock_seq_hi_and_reserved_char = generatedUuid[19]; - int cshr_value = (clock_seq_hi_and_reserved_char >= '0' && clock_seq_hi_and_reserved_char <= '9') ? - clock_seq_hi_and_reserved_char - '0' : - clock_seq_hi_and_reserved_char - 'a' + 10; - ASSERT_TRUE((cshr_value & 0x8) != 0); // Bit 7 should be 1 - ASSERT_TRUE((cshr_value & 0x4) == 0); // Bit 6 should be 0 + RandomGenerator gen2{}; + const auto generatedUuid2 = uuid(Uuid::V3, gen2); + + ASSERT_EQ(generatedUuid2.size(), 36); + ASSERT_EQ(generatedUuid2[8], '-'); + ASSERT_EQ(generatedUuid2[13], '-'); + ASSERT_EQ(generatedUuid2[18], '-'); + ASSERT_EQ(generatedUuid2[23], '-'); + ASSERT_EQ(generatedUuid2[14], '3'); +} + +TEST_F(StringTest, shouldGenerateUuid3) +{ + const auto generatedUuid = uuid(Uuid::V3); + + ASSERT_EQ(generatedUuid.size(), 36); + ASSERT_EQ(generatedUuid[8], '-'); + ASSERT_EQ(generatedUuid[13], '-'); + ASSERT_EQ(generatedUuid[18], '-'); + ASSERT_EQ(generatedUuid[23], '-'); + + // Check the version number + ASSERT_EQ(generatedUuid[14], '3'); } TEST_F(StringTest, shouldUseCustomRandomGeneratorForUuid4)