From d6e65a373533ee4b407df56e3ee9249f72561a4c Mon Sep 17 00:00:00 2001 From: Konstantin Osipov Date: Sat, 5 Dec 2020 00:11:31 +0300 Subject: [PATCH] test: add a test case for monotonicity of timeuuid least significant bits Ensure that timeuuid least significant bits are compared correctly. --- test/boost/UUID_test.cc | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/boost/UUID_test.cc b/test/boost/UUID_test.cc index ad707ec202..a24dc677c7 100644 --- a/test/boost/UUID_test.cc +++ b/test/boost/UUID_test.cc @@ -96,6 +96,44 @@ BOOST_AUTO_TEST_CASE(test_get_time_uuid) { BOOST_CHECK(unix_timestamp == millis); } +BOOST_AUTO_TEST_CASE(test_timeuuid_submicro_is_monotonic) { + const int64_t PAD6 = 0xFFFF'FFFF'FFFF; + using namespace std::chrono; + using utils::UUID, utils::UUID_gen; + UUID current_timeuuid = UUID_gen::get_time_UUID(); + // Node identifier must be set to avoid collisions + BOOST_CHECK((current_timeuuid.get_least_significant_bits() & PAD6) != 0); + int64_t micros = UUID_gen::micros_timestamp(current_timeuuid); + int maxsubmicro = (1 << 17) - 1; + int step = 1 + (random() % 169); + auto prev = UUID_gen::get_time_UUID_bytes_from_micros_and_submicros(micros, 0); + auto prev_timeuuid = UUID_gen::get_UUID(prev.data()); + // Check prev_timeuuid node identifier is set. It uses + // a spoof MAC address, not the same as a standard UUID. + BOOST_CHECK((prev_timeuuid.get_least_significant_bits() & PAD6) != 0); + auto check_is_valid_timeuuid = [&](UUID uuid) { + // UUID is version 1 + BOOST_CHECK(uuid.is_timestamp()); + // UUID preserves the original microsecond time + BOOST_CHECK(UUID_gen::micros_timestamp(uuid) == micros); + // UUID 100nsec time grows monotonically + BOOST_CHECK(uuid.timestamp() >= prev_timeuuid.timestamp()); + // UUID node is the same for all generated UUIDs + BOOST_CHECK((prev_timeuuid.get_least_significant_bits() & PAD6) == + (uuid.get_least_significant_bits() & PAD6)); + }; + for (int i = 1; i <= maxsubmicro; i += step) { + auto uuid = UUID_gen::get_time_UUID_bytes_from_micros_and_submicros( + micros, i); + check_is_valid_timeuuid(UUID_gen::get_UUID(uuid.data())); + // UUID submicro part grows monotonically + BOOST_CHECK(utils::timeuuid_tri_compare({uuid.data(), 16}, {prev.data(), 16}) > 0); + prev = uuid; + } + BOOST_CHECK_EXCEPTION(UUID_gen::get_time_UUID_bytes_from_micros_and_submicros(micros, 2 * maxsubmicro), + utils::timeuuid_submicro_out_of_range, [](auto& x) -> bool { return true; }); +} + BOOST_AUTO_TEST_CASE(test_min_time_uuid) { using namespace std::chrono;