Files
cpputils/tests/test_uuid.cpp

146 lines
3.7 KiB
C++

#include "catch.hpp"
#include <cpputils/uuid.h>
#include <array>
#include <chrono>
#include <cstddef>
#include <string>
#include <thread>
#include <unordered_set>
using namespace cpputils::uuid;
TEST_CASE("uuidToString formats UUIDs correctly", "[uuid]") {
struct TestVector {
std::array<uint8_t, 16> uuid;
char const* expected;
};
constexpr TestVector tests[] = {
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00},
"00000000-0000-0000-0000-000000000000"},
{{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67,
0x89, 0xab, 0xcd, 0xef},
"01234567-89ab-cdef-0123-456789abcdef"},
{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff},
"ffffffff-ffff-ffff-ffff-ffffffffffff"},
{{0x55, 0x0e, 0x84, 0x00, 0xe2, 0x9b, 0x41, 0xd4, 0xa7, 0x16, 0x44, 0x66,
0x55, 0x44, 0x00, 0x00},
"550e8400-e29b-41d4-a716-446655440000"},
{{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe, 0x80, 0x00, 0x01, 0x23,
0x45, 0x67, 0x89, 0xab},
"deadbeef-cafe-babe-8000-0123456789ab"},
{{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f},
"00010203-0405-0607-0809-0a0b0c0d0e0f"},
};
for (auto const& t : tests) {
REQUIRE(uuidToString(t.uuid) == t.expected);
}
}
TEST_CASE("V4 generates unique UUIDs", "[uuid][v4]") {
V4 generator;
constexpr int N = 1000;
std::unordered_set<std::string> uuids;
for (int i = 0; i < N; ++i) {
auto uuid = generator.generate();
auto str = uuidToString(uuid);
REQUIRE(uuids.find(str) == uuids.end());
uuids.insert(str);
}
}
TEST_CASE("V7 generates increasing timestamps", "[uuid][v7]") {
V7 generator;
constexpr int N = 1000;
int64_t prev_ts = 0;
for (int i = 0; i < N; ++i) {
auto uuid = generator.generate();
auto ts = V7::get_timestamp_from_uuid(uuid);
REQUIRE(ts >= prev_ts);
prev_ts = ts;
}
}
TEST_CASE("V7 sequence increments on same timestamp", "[uuid][v7][!mayfail]") {
INFO("info message");
V7 generator;
size_t count = 0;
size_t i = 1000;
for (; i > 0;) {
auto uuid1 = generator.generate();
auto uuid2 = generator.generate();
auto ts1 = V7::get_timestamp_from_uuid(uuid1);
auto ts2 = V7::get_timestamp_from_uuid(uuid2);
if (ts1 == ts2) {
REQUIRE(uuid1 != uuid2);
count++;
if (count >= 10) {
break;
}
} else {
i--;
}
}
INFO(
"Testing that V7 UUIDs with the same timestamp produce unique UUIDs. "
"Tries up to 1000 pairs to avoid long runtime if UUID generation is "
"slow. "
"(Test fails with 0 > 0 if no same-timestamp UUIDs could be generated)");
REQUIRE(i > 0);
}
TEST_CASE("UUID string formatting consistency", "[uuid]") {
V4 v4;
V7 v7;
auto uuid4 = v4.generate();
auto uuid7 = v7.generate();
auto str4 = uuidToString(uuid4);
auto str7 = uuidToString(uuid7);
REQUIRE(str4.size() == 36);
REQUIRE(str7.size() == 36);
auto is_hex_or_dash = [](char c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c == '-');
};
REQUIRE(std::all_of(str4.begin(), str4.end(), is_hex_or_dash));
REQUIRE(std::all_of(str7.begin(), str7.end(), is_hex_or_dash));
}
TEST_CASE("V4 and V7 generate large number of UUIDs without collision",
"[uuid][stress]") {
V4 v4;
V7 v7;
constexpr int N = 5000;
std::unordered_set<std::string> uuids;
for (int i = 0; i < N; ++i) {
uuids.insert(uuidToString(v4.generate()));
uuids.insert(uuidToString(v7.generate()));
}
REQUIRE(uuids.size() == 2 * N);
}