From 77dcb2bcda7d0bca509dff10ffe2f35029b6f944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chojnowski?= Date: Thu, 4 Sep 2025 14:21:24 +0200 Subject: [PATCH] test/lib/random_schema: add some constraints for generated uuid and time/date values I want to write a test which generates a random table (random schema, random data) and uses the Python driver to query it. But it turns out that some values generated by test/lib/random_schema can't be deserialized by the Python driver. For example, it doesn't unknown uuid versions, dates before year 1 of after year 9999, or `time` values greater or equal to the number of nanoseconds in a day. AFAIK those "driver-illegal" values aren't particularly interesting for tests which use `random_schema`, so we can just not generate them. --- test/lib/random_schema.cc | 36 +++++++++++++++++++++++++++--------- test/lib/random_schema.hh | 2 +- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/test/lib/random_schema.cc b/test/lib/random_schema.cc index 4213d982e1..a030775e82 100644 --- a/test/lib/random_schema.cc +++ b/test/lib/random_schema.cc @@ -471,28 +471,46 @@ data_value generate_boolean_value(std::mt19937& engine, size_t, size_t) { } data_value generate_date_value(std::mt19937& engine, size_t, size_t) { - return data_value(date_type_native_type{db_clock::time_point(db_clock::duration(random::get_int>(engine)))}); + using pt = db_clock::time_point; + // Python driver can't tolerate dates above year 9999. + constexpr auto max_day = std::chrono::sys_days(std::chrono::year{10000}/1/1); + constexpr auto max = std::chrono::sys_time(max_day).time_since_epoch().count() - 1; + auto x = random::get_int>(0, max, engine); + return data_value(date_type_native_type{pt(pt::duration(x))}); } data_value generate_timeuuid_value(std::mt19937&, size_t, size_t) { - return data_value(timeuuid_native_type{utils::UUID_gen::get_time_UUID()}); + // FIXME: respect the passed engine. + auto b = tests::random::get_bytes(16); + b[6] = (b[6] & 0x0F) | 0x10; // version 1 + return timeuuid_type->deserialize(b); } data_value generate_timestamp_value(std::mt19937& engine, size_t, size_t) { using pt = db_clock::time_point; - return data_value(pt(pt::duration(random::get_int(engine)))); + // Python driver can't tolerate dates above year 9999 or below year 1. + constexpr auto min_day = std::chrono::sys_days(std::chrono::year{1}/1/1); + constexpr auto max_day = std::chrono::sys_days(std::chrono::year{10000}/1/1); + constexpr auto min = std::chrono::sys_time(min_day).time_since_epoch().count(); + constexpr auto max = std::chrono::sys_time(max_day).time_since_epoch().count() - 1; + auto x = random::get_int(min, max, engine); + return data_value(pt(pt::duration(x))); } - + data_value generate_simple_date_value(std::mt19937& engine, size_t, size_t) { return data_value(simple_date_native_type{random::get_int(engine)}); } data_value generate_time_value(std::mt19937& engine, size_t, size_t) { - return data_value(time_native_type{random::get_int(engine)}); + // A legal `time` is smaller than the number of nanoseconds in a day. + auto max = std::chrono::nanoseconds(std::chrono::days(1)).count() - 1; + return data_value(time_native_type{random::get_int(0, max, engine)}); } data_value generate_uuid_value(std::mt19937& engine, size_t, size_t) { - return data_value(utils::make_random_uuid()); + auto b = tests::random::get_bytes(16, engine); + b[6] = (b[6] & 0x0F) | 0x40; // version 4 + return data_value(uuid_type->deserialize(b)); } data_value generate_inet_addr_value(std::mt19937& engine, size_t, size_t) { @@ -769,7 +787,7 @@ timestamp_generator default_timestamp_generator() { }; } -timestamp_generator uncompactible_timestamp_generator(uint32_t seed) { +timestamp_generator uncompactible_timestamp_generator(uint32_t seed, api::timestamp_type min_timestamp) { auto engine = std::mt19937(seed); const auto rank = [] (timestamp_destination dest) -> api::timestamp_type { @@ -791,7 +809,7 @@ timestamp_generator uncompactible_timestamp_generator(uint32_t seed) { const auto max_rank = rank(timestamp_destination::collection_cell_timestamp); const auto margin = 1000; std::vector points; - points.push_back(api::min_timestamp); + points.push_back(min_timestamp); for (api::timestamp_type i = 0; i < max_rank; ++i) { const auto remaining_ranks = max_rank - i; const auto point = std::uniform_int_distribution(points.back() + margin, api::max_timestamp - (remaining_ranks * margin))(engine); @@ -799,7 +817,7 @@ timestamp_generator uncompactible_timestamp_generator(uint32_t seed) { } points.push_back(api::max_timestamp); - return [rank, points] (std::mt19937& engine, timestamp_destination destination, api::timestamp_type min_timestamp) { + return [rank, points] (std::mt19937& engine, timestamp_destination destination, api::timestamp_type curr_min_ts) { const auto r = rank(destination); auto ts_dist = std::uniform_int_distribution(points.at(r), points.at(r + 1) - 1); return ts_dist(engine); diff --git a/test/lib/random_schema.hh b/test/lib/random_schema.hh index c6a63cccee..41a45cf57b 100644 --- a/test/lib/random_schema.hh +++ b/test/lib/random_schema.hh @@ -139,7 +139,7 @@ timestamp_generator default_timestamp_generator(); /// Use this to generate mutations that cannot be compacted /// /// Tombstones will not cover lower level tombstones, or data. -timestamp_generator uncompactible_timestamp_generator(uint32_t seed); +timestamp_generator uncompactible_timestamp_generator(uint32_t seed, api::timestamp_type min_timestamp = api::min_timestamp); struct expiry_info { gc_clock::duration ttl;