#pragma once #include // for ipv4-ipv6 platform-specific stuff #include #include #include "utils.h" #include #include inline in_addr MakeIPv4(uint32_t ip) { static_assert(sizeof(in_addr) == sizeof(ip)); in_addr result; memcpy(&result, &ip, sizeof(ip)); return result; } inline in6_addr MakeIPv6(uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15) { return in6_addr{{{v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}}}; } inline in6_addr MakeIPv6(uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15) { return in6_addr{{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, v10, v11, v12, v13, v14, v15}}}; } std::vector MakeNumbers(); std::vector MakeBools(); std::vector MakeFixedStrings(size_t string_size); std::vector MakeStrings(); std::vector MakeDateTime64s(size_t scale, size_t values_size = 200); std::vector MakeDates32(); std::vector MakeDateTimes(); std::vector MakeIPv4s(); std::vector MakeIPv6s(); std::vector MakeUUIDs(); std::vector MakeInt128s(); std::vector MakeUInt128s(); std::vector MakeDecimals(size_t precision, size_t scale); template ::value, bool> = true> inline std::vector MakeNumbers() { std::vector result; result.reserve(32); // to reach from in to max in 32 steps, it also has to be lower than 7 to work for int8 values. const T step = static_cast(1) << (sizeof(T)*8 - 5); // `- step` to avoid accidential overflow for (T i = std::numeric_limits::min(); i <= std::numeric_limits::max() - step; i += step) { result.push_back(i); } result.push_back(std::numeric_limits::max()); return result; } template ::value, bool> = true> inline std::vector MakeNumbers() { std::vector result { std::numeric_limits::min(), std::numeric_limits::max(), std::numeric_limits::quiet_NaN(), std::numeric_limits::infinity(), -std::numeric_limits::infinity(), static_cast(0), static_cast(0) + std::numeric_limits::epsilon(), static_cast(0) - std::numeric_limits::epsilon() }; const auto total_steps = 100; const auto step = std::pow(10, (std::numeric_limits::max_exponent - std::numeric_limits::min_exponent) / total_steps); const auto min_value = std::pow(10, std::numeric_limits::min_exponent10); // cover most of the precision ranges for (T i = std::numeric_limits::max(); i >= min_value * step; i /= step) { result.push_back(i); result.push_back(-1 * i); } result.push_back(min_value); result.push_back(-min_value); return result; } template inline std::vector MakeFixedStrings() { return MakeFixedStrings(size); } template inline std::vector MakeDateTime64s() { return MakeDateTime64s(scale); } template inline std::vector MakeDecimals() { return MakeDecimals(precision, scale); } template inline auto MakeDates() { std::vector result {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 - 1}; if constexpr (std::is_same_v) { // in CH Date internally a UInt16 and stores a day number // ColumnDate expects values to be seconds, which is then // converted to day number internally, hence the `* 86400`. std::for_each(result.begin(), result.end(), [](auto& value) { value *= 86400; }); } return result; } template (*Generator)()> inline auto MakeArrays() { const auto nested_values = Generator(); std::vector> result; result.reserve(nested_values.size()); for (size_t i = 0; i < nested_values.size(); ++i) { result.emplace_back(nested_values.begin(), nested_values.begin() + i); } return result; } std::string FooBarGenerator(size_t i); template auto GenerateVector(size_t items, Generator && gen) { using ActualValueType = std::conditional_t, my_result_of_t, ValueType>; std::vector result; result.reserve(items); for (size_t i = 0; i < items; ++i) { result.push_back(std::move(gen(i))); } return result; } template auto SameValueGenerator(const U & value) { return [&value](size_t) -> T { return value; }; } template auto AlternateGenerators(Generator1 && gen1, Generator2 && gen2) { return [&gen1, &gen2](size_t i) -> ResultType { if (i % 2 == 0) return gen1(i/2); else return gen2(i/2); }; } template struct RandomGenerator { using uniform_distribution = typename std::conditional_t, std::uniform_real_distribution, typename std::conditional_t, std::uniform_int_distribution, void>>; explicit RandomGenerator(T seed = 0, T value_min = std::numeric_limits::min(), T value_max = std::numeric_limits::max()) : random_engine(seed) , distribution(value_min, value_max) { } template T operator()(U) { return distribution(random_engine); } private: std::default_random_engine random_engine; uniform_distribution distribution; }; template std::vector ConcatSequences(std::vector && vec1, std::vector && vec2) { std::vector result(vec1); result.reserve(vec1.size() + vec2.size()); result.insert(result.end(), vec2.begin(), vec2.end()); return result; } template struct FromVectorGenerator { const std::vector data; RandomGenerator random_generator; FromVectorGenerator(std::vector data_) : data(std::move(data_)), random_generator(0, 0, data.size() - 1) { if (data.size() == 0) throw std::runtime_error("can't generate values from empty vector"); } auto operator()(size_t pos) { return data[random_generator(pos)]; } };