| 1 | #include <Compression/CompressionFactory.h> |
| 2 | |
| 3 | #include <Common/PODArray.h> |
| 4 | #include <Core/Types.h> |
| 5 | #include <DataTypes/DataTypesNumber.h> |
| 6 | #include <DataTypes/IDataType.h> |
| 7 | #include <IO/ReadBufferFromMemory.h> |
| 8 | #include <IO/WriteHelpers.h> |
| 9 | #include <Parsers/ExpressionElementParsers.h> |
| 10 | #include <Parsers/IParser.h> |
| 11 | #include <Parsers/TokenIterator.h> |
| 12 | |
| 13 | #include <boost/format.hpp> |
| 14 | |
| 15 | #include <bitset> |
| 16 | #include <cmath> |
| 17 | #include <initializer_list> |
| 18 | #include <iomanip> |
| 19 | #include <iostream> |
| 20 | #include <iterator> |
| 21 | #include <memory> |
| 22 | #include <typeinfo> |
| 23 | #include <vector> |
| 24 | |
| 25 | #include <string.h> |
| 26 | |
| 27 | /// For the expansion of gtest macros. |
| 28 | #if defined(__clang__) |
| 29 | #pragma clang diagnostic ignored "-Wdeprecated" |
| 30 | #elif defined (__GNUC__) && __GNUC__ >= 9 |
| 31 | #pragma GCC diagnostic ignored "-Wdeprecated-copy" |
| 32 | #endif |
| 33 | |
| 34 | #include <gtest/gtest.h> |
| 35 | |
| 36 | using namespace DB; |
| 37 | |
| 38 | namespace std |
| 39 | { |
| 40 | template <typename T> |
| 41 | std::ostream & operator<<(std::ostream & ostr, const std::optional<T> & opt) |
| 42 | { |
| 43 | if (!opt) |
| 44 | { |
| 45 | return ostr << "<empty optional>" ; |
| 46 | } |
| 47 | |
| 48 | return ostr << *opt; |
| 49 | } |
| 50 | |
| 51 | template <typename T> |
| 52 | std::vector<T> operator+(std::vector<T> && left, std::vector<T> && right) |
| 53 | { |
| 54 | std::vector<T> result(std::move(left)); |
| 55 | std::move(std::begin(right), std::end(right), std::back_inserter(result)); |
| 56 | |
| 57 | return result; |
| 58 | } |
| 59 | |
| 60 | } |
| 61 | |
| 62 | namespace |
| 63 | { |
| 64 | |
| 65 | template <typename T> |
| 66 | std::string bin(const T & value, size_t bits = sizeof(T)*8) |
| 67 | { |
| 68 | static const UInt8 MAX_BITS = sizeof(T)*8; |
| 69 | assert(bits <= MAX_BITS); |
| 70 | |
| 71 | return std::bitset<sizeof(T) * 8>(static_cast<unsigned long long>(value)) |
| 72 | .to_string().substr(MAX_BITS - bits, bits); |
| 73 | } |
| 74 | |
| 75 | template <typename T> |
| 76 | const char* type_name() |
| 77 | { |
| 78 | #define MAKE_TYPE_NAME(TYPE) \ |
| 79 | if constexpr (std::is_same_v<TYPE, T>) return #TYPE |
| 80 | |
| 81 | MAKE_TYPE_NAME(UInt8); |
| 82 | MAKE_TYPE_NAME(UInt16); |
| 83 | MAKE_TYPE_NAME(UInt32); |
| 84 | MAKE_TYPE_NAME(UInt64); |
| 85 | MAKE_TYPE_NAME(Int8); |
| 86 | MAKE_TYPE_NAME(Int16); |
| 87 | MAKE_TYPE_NAME(Int32); |
| 88 | MAKE_TYPE_NAME(Int64); |
| 89 | MAKE_TYPE_NAME(Float32); |
| 90 | MAKE_TYPE_NAME(Float64); |
| 91 | |
| 92 | #undef MAKE_TYPE_NAME |
| 93 | |
| 94 | return typeid(T).name(); |
| 95 | } |
| 96 | |
| 97 | template <typename T> |
| 98 | DataTypePtr makeDataType() |
| 99 | { |
| 100 | #define MAKE_DATA_TYPE(TYPE) \ |
| 101 | if constexpr (std::is_same_v<T, TYPE>) return std::make_shared<DataType ## TYPE>() |
| 102 | |
| 103 | MAKE_DATA_TYPE(UInt8); |
| 104 | MAKE_DATA_TYPE(UInt16); |
| 105 | MAKE_DATA_TYPE(UInt32); |
| 106 | MAKE_DATA_TYPE(UInt64); |
| 107 | MAKE_DATA_TYPE(Int8); |
| 108 | MAKE_DATA_TYPE(Int16); |
| 109 | MAKE_DATA_TYPE(Int32); |
| 110 | MAKE_DATA_TYPE(Int64); |
| 111 | MAKE_DATA_TYPE(Float32); |
| 112 | MAKE_DATA_TYPE(Float64); |
| 113 | |
| 114 | #undef MAKE_DATA_TYPE |
| 115 | |
| 116 | assert(false && "unsupported size" ); |
| 117 | return nullptr; |
| 118 | } |
| 119 | |
| 120 | |
| 121 | template <typename T, typename ContainerLeft, typename ContainerRight> |
| 122 | ::testing::AssertionResult EqualByteContainersAs(const ContainerLeft & left, const ContainerRight & right) |
| 123 | { |
| 124 | static_assert(sizeof(typename ContainerLeft::value_type) == 1, "Expected byte-container" ); |
| 125 | static_assert(sizeof(typename ContainerRight::value_type) == 1, "Expected byte-container" ); |
| 126 | |
| 127 | ::testing::AssertionResult result = ::testing::AssertionSuccess(); |
| 128 | |
| 129 | ReadBufferFromMemory left_read_buffer(left.data(), left.size()); |
| 130 | ReadBufferFromMemory right_read_buffer(right.data(), right.size()); |
| 131 | |
| 132 | const auto l_size = left.size() / sizeof(T); |
| 133 | const auto r_size = right.size() / sizeof(T); |
| 134 | const auto size = std::min(l_size, r_size); |
| 135 | |
| 136 | if (l_size != r_size) |
| 137 | { |
| 138 | result = ::testing::AssertionFailure() << "size mismatch" << " expected: " << l_size << " got:" << r_size; |
| 139 | } |
| 140 | |
| 141 | const auto MAX_MISMATCHING_ITEMS = 5; |
| 142 | int mismatching_items = 0; |
| 143 | for (int i = 0; i < size; ++i) |
| 144 | { |
| 145 | T left_value{}; |
| 146 | left_read_buffer.readStrict(reinterpret_cast<char*>(&left_value), sizeof(left_value)); |
| 147 | |
| 148 | T right_value{}; |
| 149 | right_read_buffer.readStrict(reinterpret_cast<char*>(&right_value), sizeof(right_value)); |
| 150 | |
| 151 | if (left_value != right_value) |
| 152 | { |
| 153 | if (result) |
| 154 | { |
| 155 | result = ::testing::AssertionFailure(); |
| 156 | } |
| 157 | |
| 158 | if (++mismatching_items <= MAX_MISMATCHING_ITEMS) |
| 159 | { |
| 160 | result << "mismatching " << sizeof(T) << "-byte item #" << i |
| 161 | << "\nexpected: " << bin(left_value) << " (0x" << std::hex << left_value << ")" |
| 162 | << "\ngot : " << bin(right_value) << " (0x" << std::hex << right_value << ")" |
| 163 | << std::endl; |
| 164 | if (mismatching_items == MAX_MISMATCHING_ITEMS) |
| 165 | { |
| 166 | result << "..." << std::endl; |
| 167 | } |
| 168 | } |
| 169 | } |
| 170 | } |
| 171 | if (mismatching_items > 0) |
| 172 | { |
| 173 | result << "\ntotal mismatching items:" << mismatching_items << " of " << size; |
| 174 | } |
| 175 | |
| 176 | return result; |
| 177 | } |
| 178 | |
| 179 | struct Codec |
| 180 | { |
| 181 | std::string codec_statement; |
| 182 | std::optional<double> expected_compression_ratio; |
| 183 | |
| 184 | explicit Codec(std::string codec_statement_, std::optional<double> expected_compression_ratio_ = std::nullopt) |
| 185 | : codec_statement(std::move(codec_statement_)), |
| 186 | expected_compression_ratio(expected_compression_ratio_) |
| 187 | {} |
| 188 | |
| 189 | Codec() |
| 190 | : Codec(std::string()) |
| 191 | {} |
| 192 | }; |
| 193 | |
| 194 | |
| 195 | struct CodecTestSequence |
| 196 | { |
| 197 | std::string name; |
| 198 | std::vector<char> serialized_data; |
| 199 | DataTypePtr data_type; |
| 200 | |
| 201 | CodecTestSequence() |
| 202 | : name(), |
| 203 | serialized_data(), |
| 204 | data_type() |
| 205 | {} |
| 206 | |
| 207 | CodecTestSequence(std::string name_, std::vector<char> serialized_data_, DataTypePtr data_type_) |
| 208 | : name(name_), |
| 209 | serialized_data(serialized_data_), |
| 210 | data_type(data_type_) |
| 211 | {} |
| 212 | |
| 213 | CodecTestSequence(const CodecTestSequence &) = default; |
| 214 | CodecTestSequence & operator=(const CodecTestSequence &) = default; |
| 215 | CodecTestSequence(CodecTestSequence &&) = default; |
| 216 | CodecTestSequence & operator=(CodecTestSequence &&) = default; |
| 217 | }; |
| 218 | |
| 219 | CodecTestSequence operator+(CodecTestSequence && left, CodecTestSequence && right) |
| 220 | { |
| 221 | assert(left.data_type->equals(*right.data_type)); |
| 222 | |
| 223 | std::vector<char> data(std::move(left.serialized_data)); |
| 224 | data.insert(data.end(), right.serialized_data.begin(), right.serialized_data.end()); |
| 225 | |
| 226 | return CodecTestSequence{ |
| 227 | left.name + " + " + right.name, |
| 228 | std::move(data), |
| 229 | std::move(left.data_type) |
| 230 | }; |
| 231 | } |
| 232 | |
| 233 | template <typename T> |
| 234 | CodecTestSequence operator*(CodecTestSequence && left, T times) |
| 235 | { |
| 236 | std::vector<char> data(std::move(left.serialized_data)); |
| 237 | const size_t initial_size = data.size(); |
| 238 | const size_t final_size = initial_size * times; |
| 239 | |
| 240 | data.reserve(final_size); |
| 241 | |
| 242 | for (T i = 0; i < times; ++i) |
| 243 | { |
| 244 | data.insert(data.end(), data.begin(), data.begin() + initial_size); |
| 245 | } |
| 246 | |
| 247 | return CodecTestSequence{ |
| 248 | left.name + " x " + std::to_string(times), |
| 249 | std::move(data), |
| 250 | std::move(left.data_type) |
| 251 | }; |
| 252 | } |
| 253 | |
| 254 | std::ostream & operator<<(std::ostream & ostr, const Codec & codec) |
| 255 | { |
| 256 | return ostr << "Codec{" |
| 257 | << "name: " << codec.codec_statement |
| 258 | << ", expected_compression_ratio: " << codec.expected_compression_ratio |
| 259 | << "}" ; |
| 260 | } |
| 261 | |
| 262 | std::ostream & operator<<(std::ostream & ostr, const CodecTestSequence & seq) |
| 263 | { |
| 264 | return ostr << "CodecTestSequence{" |
| 265 | << "name: " << seq.name |
| 266 | << ", type name: " << seq.data_type->getName() |
| 267 | << ", data size: " << seq.serialized_data.size() << " bytes" |
| 268 | << "}" ; |
| 269 | } |
| 270 | |
| 271 | template <typename T, typename... Args> |
| 272 | CodecTestSequence makeSeq(Args && ... args) |
| 273 | { |
| 274 | std::initializer_list<T> vals{static_cast<T>(args)...}; |
| 275 | std::vector<char> data(sizeof(T) * std::size(vals)); |
| 276 | |
| 277 | char * write_pos = data.data(); |
| 278 | for (const auto & v : vals) |
| 279 | { |
| 280 | unalignedStore<T>(write_pos, v); |
| 281 | write_pos += sizeof(v); |
| 282 | } |
| 283 | |
| 284 | return CodecTestSequence{ |
| 285 | (boost::format("%1% values of %2%" ) % std::size(vals) % type_name<T>()).str(), |
| 286 | std::move(data), |
| 287 | makeDataType<T>() |
| 288 | }; |
| 289 | } |
| 290 | |
| 291 | template <typename T, typename Generator> |
| 292 | CodecTestSequence generateSeq(Generator gen, const char* gen_name, size_t Begin = 0, size_t End = 10000) |
| 293 | { |
| 294 | assert (End >= Begin); |
| 295 | |
| 296 | std::vector<char> data(sizeof(T) * (End - Begin)); |
| 297 | char * write_pos = data.data(); |
| 298 | |
| 299 | for (size_t i = Begin; i < End; ++i) |
| 300 | { |
| 301 | const T v = gen(static_cast<T>(i)); |
| 302 | unalignedStore<T>(write_pos, v); |
| 303 | write_pos += sizeof(v); |
| 304 | } |
| 305 | |
| 306 | return CodecTestSequence{ |
| 307 | (boost::format("%1% values of %2% from %3%" ) % (End - Begin) % type_name<T>() % gen_name).str(), |
| 308 | std::move(data), |
| 309 | makeDataType<T>() |
| 310 | }; |
| 311 | } |
| 312 | |
| 313 | |
| 314 | class CodecTest : public ::testing::TestWithParam<std::tuple<Codec, CodecTestSequence>> |
| 315 | { |
| 316 | public: |
| 317 | enum MakeCodecParam |
| 318 | { |
| 319 | CODEC_WITH_DATA_TYPE, |
| 320 | CODEC_WITHOUT_DATA_TYPE, |
| 321 | }; |
| 322 | |
| 323 | CompressionCodecPtr makeCodec(MakeCodecParam with_data_type) const |
| 324 | { |
| 325 | const auto & codec_string = std::get<0>(GetParam()).codec_statement; |
| 326 | const auto & data_type = with_data_type == CODEC_WITH_DATA_TYPE ? std::get<1>(GetParam()).data_type : nullptr; |
| 327 | |
| 328 | const std::string codec_statement = "(" + codec_string + ")" ; |
| 329 | Tokens tokens(codec_statement.begin().base(), codec_statement.end().base()); |
| 330 | IParser::Pos token_iterator(tokens); |
| 331 | |
| 332 | Expected expected; |
| 333 | ASTPtr codec_ast; |
| 334 | ParserCodec parser; |
| 335 | |
| 336 | parser.parse(token_iterator, codec_ast, expected); |
| 337 | |
| 338 | return CompressionCodecFactory::instance().get(codec_ast, data_type); |
| 339 | } |
| 340 | |
| 341 | void testTranscoding(ICompressionCodec & codec) |
| 342 | { |
| 343 | const auto & test_sequence = std::get<1>(GetParam()); |
| 344 | const auto & source_data = test_sequence.serialized_data; |
| 345 | |
| 346 | const UInt32 encoded_max_size = codec.getCompressedReserveSize(source_data.size()); |
| 347 | PODArray<char> encoded(encoded_max_size); |
| 348 | |
| 349 | const UInt32 encoded_size = codec.compress(source_data.data(), source_data.size(), encoded.data()); |
| 350 | encoded.resize(encoded_size); |
| 351 | |
| 352 | PODArray<char> decoded(source_data.size()); |
| 353 | const UInt32 decoded_size = codec.decompress(encoded.data(), encoded.size(), decoded.data()); |
| 354 | decoded.resize(decoded_size); |
| 355 | |
| 356 | switch (test_sequence.data_type->getSizeOfValueInMemory()) |
| 357 | { |
| 358 | case 1: |
| 359 | ASSERT_TRUE(EqualByteContainersAs<UInt8>(source_data, decoded)); |
| 360 | break; |
| 361 | case 2: |
| 362 | ASSERT_TRUE(EqualByteContainersAs<UInt16>(source_data, decoded)); |
| 363 | break; |
| 364 | case 4: |
| 365 | ASSERT_TRUE(EqualByteContainersAs<UInt32>(source_data, decoded)); |
| 366 | break; |
| 367 | case 8: |
| 368 | ASSERT_TRUE(EqualByteContainersAs<UInt64>(source_data, decoded)); |
| 369 | break; |
| 370 | default: |
| 371 | FAIL() << "Invalid test sequence data type: " << test_sequence.data_type->getName(); |
| 372 | } |
| 373 | const auto = codec.getHeaderSize(); |
| 374 | const auto compression_ratio = (encoded_size - header_size) / (source_data.size() * 1.0); |
| 375 | |
| 376 | const auto & codec_spec = std::get<0>(GetParam()); |
| 377 | if (codec_spec.expected_compression_ratio) |
| 378 | { |
| 379 | ASSERT_LE(compression_ratio, *codec_spec.expected_compression_ratio) |
| 380 | << "\n\tdecoded size: " << source_data.size() |
| 381 | << "\n\tencoded size: " << encoded_size |
| 382 | << "(no header: " << encoded_size - header_size << ")" ; |
| 383 | } |
| 384 | } |
| 385 | }; |
| 386 | |
| 387 | TEST_P(CodecTest, TranscodingWithDataType) |
| 388 | { |
| 389 | const auto codec = makeCodec(CODEC_WITH_DATA_TYPE); |
| 390 | testTranscoding(*codec); |
| 391 | } |
| 392 | |
| 393 | TEST_P(CodecTest, TranscodingWithoutDataType) |
| 394 | { |
| 395 | const auto codec = makeCodec(CODEC_WITHOUT_DATA_TYPE); |
| 396 | testTranscoding(*codec); |
| 397 | } |
| 398 | |
| 399 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 400 | // Here we use generators to produce test payload for codecs. |
| 401 | // Generator is a callable that can produce infinite number of values, |
| 402 | // output value MUST be of the same type input value. |
| 403 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 404 | |
| 405 | auto SameValueGenerator = [](auto value) |
| 406 | { |
| 407 | return [=](auto i) |
| 408 | { |
| 409 | return static_cast<decltype(i)>(value); |
| 410 | }; |
| 411 | }; |
| 412 | |
| 413 | auto SequentialGenerator = [](auto stride = 1) |
| 414 | { |
| 415 | return [=](auto i) |
| 416 | { |
| 417 | using ValueType = decltype(i); |
| 418 | return static_cast<ValueType>(stride * i); |
| 419 | }; |
| 420 | }; |
| 421 | |
| 422 | // Generator that helps debugging output of other generators |
| 423 | // by logging every output value alongside iteration index and input. |
| 424 | //auto LoggingProxyGenerator = [](auto other_generator, const char * name, std::ostream & ostr, const int limit = std::numeric_limits<int>::max()) |
| 425 | //{ |
| 426 | // ostr << "\n\nValues from " << name << ":\n"; |
| 427 | // auto count = std::make_shared<int>(0); |
| 428 | // return [&, count](auto i) |
| 429 | // { |
| 430 | // using ValueType = decltype(i); |
| 431 | // const auto ret = static_cast<ValueType>(other_generator(i)); |
| 432 | // if (++(*count) < limit) |
| 433 | // { |
| 434 | // ostr << "\t" << *count << " : " << i << " => " << ret << "\n"; |
| 435 | // } |
| 436 | |
| 437 | // return ret; |
| 438 | // }; |
| 439 | //}; |
| 440 | |
| 441 | template <typename T> |
| 442 | using uniform_distribution = |
| 443 | typename std::conditional_t<std::is_floating_point_v<T>, std::uniform_real_distribution<T>, |
| 444 | typename std::conditional_t<is_integral_v<T>, std::uniform_int_distribution<T>, void>>; |
| 445 | |
| 446 | |
| 447 | template <typename T = Int32> |
| 448 | struct MonotonicGenerator |
| 449 | { |
| 450 | MonotonicGenerator(T stride_ = 1, T max_step = 10) |
| 451 | : prev_value(0), |
| 452 | stride(stride_), |
| 453 | random_engine(0), |
| 454 | distribution(0, max_step) |
| 455 | {} |
| 456 | |
| 457 | template <typename U> |
| 458 | U operator()(U) |
| 459 | { |
| 460 | prev_value = prev_value + stride * distribution(random_engine); |
| 461 | return static_cast<U>(prev_value); |
| 462 | } |
| 463 | |
| 464 | private: |
| 465 | T prev_value; |
| 466 | const T stride; |
| 467 | std::default_random_engine random_engine; |
| 468 | uniform_distribution<T> distribution; |
| 469 | }; |
| 470 | |
| 471 | template <typename T> |
| 472 | struct RandomGenerator |
| 473 | { |
| 474 | RandomGenerator(T seed = 0, T value_min = std::numeric_limits<T>::min(), T value_max = std::numeric_limits<T>::max()) |
| 475 | : random_engine(seed), |
| 476 | distribution(value_min, value_max) |
| 477 | { |
| 478 | } |
| 479 | |
| 480 | template <typename U> |
| 481 | U operator()(U) |
| 482 | { |
| 483 | return static_cast<U>(distribution(random_engine)); |
| 484 | } |
| 485 | |
| 486 | private: |
| 487 | std::default_random_engine random_engine; |
| 488 | uniform_distribution<T> distribution; |
| 489 | }; |
| 490 | |
| 491 | auto RandomishGenerator = [](auto i) |
| 492 | { |
| 493 | return static_cast<decltype(i)>(sin(static_cast<double>(i * i)) * i); |
| 494 | }; |
| 495 | |
| 496 | auto MinMaxGenerator = []() |
| 497 | { |
| 498 | return [step = 0](auto i) mutable |
| 499 | { |
| 500 | if (step++ % 2 == 0) |
| 501 | { |
| 502 | return std::numeric_limits<decltype(i)>::min(); |
| 503 | } |
| 504 | else |
| 505 | { |
| 506 | return std::numeric_limits<decltype(i)>::max(); |
| 507 | } |
| 508 | }; |
| 509 | }; |
| 510 | |
| 511 | // Fill dest value with 0x00 or 0xFF |
| 512 | auto FFand0Generator = []() |
| 513 | { |
| 514 | return [step = 0](auto i) mutable |
| 515 | { |
| 516 | decltype(i) result; |
| 517 | if (step++ % 2 == 0) |
| 518 | { |
| 519 | memset(&result, 0, sizeof(result)); |
| 520 | } |
| 521 | else |
| 522 | { |
| 523 | memset(&result, 0xFF, sizeof(result)); |
| 524 | } |
| 525 | |
| 526 | return result; |
| 527 | }; |
| 528 | }; |
| 529 | |
| 530 | |
| 531 | // Makes many sequences with generator, first sequence length is 1, second is 2... up to `sequences_count`. |
| 532 | template <typename T, typename Generator> |
| 533 | std::vector<CodecTestSequence> generatePyramidOfSequences(const size_t sequences_count, Generator && generator, const char* generator_name) |
| 534 | { |
| 535 | std::vector<CodecTestSequence> sequences; |
| 536 | sequences.reserve(sequences_count); |
| 537 | for (size_t i = 1; i < sequences_count; ++i) |
| 538 | { |
| 539 | std::string name = generator_name + std::string(" from 0 to " ) + std::to_string(i); |
| 540 | sequences.push_back(generateSeq<T>(std::forward<decltype(generator)>(generator), name.c_str(), 0, i)); |
| 541 | } |
| 542 | |
| 543 | return sequences; |
| 544 | }; |
| 545 | |
| 546 | |
| 547 | // helper macro to produce human-friendly sequence name from generator |
| 548 | #define G(generator) generator, #generator |
| 549 | |
| 550 | const auto DefaultCodecsToTest = ::testing::Values( |
| 551 | Codec("DoubleDelta" ), |
| 552 | Codec("DoubleDelta, LZ4" ), |
| 553 | Codec("DoubleDelta, ZSTD" ), |
| 554 | Codec("Gorilla" ), |
| 555 | Codec("Gorilla, LZ4" ), |
| 556 | Codec("Gorilla, ZSTD" ) |
| 557 | ); |
| 558 | |
| 559 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 560 | // test cases |
| 561 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 562 | |
| 563 | INSTANTIATE_TEST_CASE_P(Simple, |
| 564 | CodecTest, |
| 565 | ::testing::Combine( |
| 566 | DefaultCodecsToTest, |
| 567 | ::testing::Values( |
| 568 | makeSeq<Float64>(1, 2, 3, 5, 7, 11, 13, 17, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97) |
| 569 | ) |
| 570 | ), |
| 571 | ); |
| 572 | |
| 573 | INSTANTIATE_TEST_CASE_P(SmallSequences, |
| 574 | CodecTest, |
| 575 | ::testing::Combine( |
| 576 | DefaultCodecsToTest, |
| 577 | ::testing::ValuesIn( |
| 578 | generatePyramidOfSequences<Int8 >(42, G(SequentialGenerator(1))) |
| 579 | + generatePyramidOfSequences<Int16 >(42, G(SequentialGenerator(1))) |
| 580 | + generatePyramidOfSequences<Int32 >(42, G(SequentialGenerator(1))) |
| 581 | + generatePyramidOfSequences<Int64 >(42, G(SequentialGenerator(1))) |
| 582 | + generatePyramidOfSequences<UInt8 >(42, G(SequentialGenerator(1))) |
| 583 | + generatePyramidOfSequences<UInt16>(42, G(SequentialGenerator(1))) |
| 584 | + generatePyramidOfSequences<UInt32>(42, G(SequentialGenerator(1))) |
| 585 | + generatePyramidOfSequences<UInt64>(42, G(SequentialGenerator(1))) |
| 586 | ) |
| 587 | ), |
| 588 | ); |
| 589 | |
| 590 | INSTANTIATE_TEST_CASE_P(Mixed, |
| 591 | CodecTest, |
| 592 | ::testing::Combine( |
| 593 | DefaultCodecsToTest, |
| 594 | ::testing::Values( |
| 595 | generateSeq<Int8>(G(MinMaxGenerator()), 1, 5) + generateSeq<Int8>(G(SequentialGenerator(1)), 1, 1001), |
| 596 | generateSeq<Int16>(G(MinMaxGenerator()), 1, 5) + generateSeq<Int16>(G(SequentialGenerator(1)), 1, 1001), |
| 597 | generateSeq<Int32>(G(MinMaxGenerator()), 1, 5) + generateSeq<Int32>(G(SequentialGenerator(1)), 1, 1001), |
| 598 | generateSeq<Int64>(G(MinMaxGenerator()), 1, 5) + generateSeq<Int64>(G(SequentialGenerator(1)), 1, 1001), |
| 599 | generateSeq<UInt8>(G(MinMaxGenerator()), 1, 5) + generateSeq<UInt8>(G(SequentialGenerator(1)), 1, 1001), |
| 600 | generateSeq<UInt16>(G(MinMaxGenerator()), 1, 5) + generateSeq<UInt16>(G(SequentialGenerator(1)), 1, 1001), |
| 601 | generateSeq<UInt32>(G(MinMaxGenerator()), 1, 5) + generateSeq<UInt32>(G(SequentialGenerator(1)), 1, 1001), |
| 602 | generateSeq<UInt64>(G(MinMaxGenerator()), 1, 5) + generateSeq<UInt64>(G(SequentialGenerator(1)), 1, 1001) |
| 603 | ) |
| 604 | ), |
| 605 | ); |
| 606 | |
| 607 | INSTANTIATE_TEST_CASE_P(SameValueInt, |
| 608 | CodecTest, |
| 609 | ::testing::Combine( |
| 610 | DefaultCodecsToTest, |
| 611 | ::testing::Values( |
| 612 | generateSeq<Int8 >(G(SameValueGenerator(1000))), |
| 613 | generateSeq<Int16 >(G(SameValueGenerator(1000))), |
| 614 | generateSeq<Int32 >(G(SameValueGenerator(1000))), |
| 615 | generateSeq<Int64 >(G(SameValueGenerator(1000))), |
| 616 | generateSeq<UInt8 >(G(SameValueGenerator(1000))), |
| 617 | generateSeq<UInt16>(G(SameValueGenerator(1000))), |
| 618 | generateSeq<UInt32>(G(SameValueGenerator(1000))), |
| 619 | generateSeq<UInt64>(G(SameValueGenerator(1000))) |
| 620 | ) |
| 621 | ), |
| 622 | ); |
| 623 | |
| 624 | INSTANTIATE_TEST_CASE_P(SameNegativeValueInt, |
| 625 | CodecTest, |
| 626 | ::testing::Combine( |
| 627 | DefaultCodecsToTest, |
| 628 | ::testing::Values( |
| 629 | generateSeq<Int8 >(G(SameValueGenerator(-1000))), |
| 630 | generateSeq<Int16 >(G(SameValueGenerator(-1000))), |
| 631 | generateSeq<Int32 >(G(SameValueGenerator(-1000))), |
| 632 | generateSeq<Int64 >(G(SameValueGenerator(-1000))), |
| 633 | generateSeq<UInt8 >(G(SameValueGenerator(-1000))), |
| 634 | generateSeq<UInt16>(G(SameValueGenerator(-1000))), |
| 635 | generateSeq<UInt32>(G(SameValueGenerator(-1000))), |
| 636 | generateSeq<UInt64>(G(SameValueGenerator(-1000))) |
| 637 | ) |
| 638 | ), |
| 639 | ); |
| 640 | |
| 641 | INSTANTIATE_TEST_CASE_P(SameValueFloat, |
| 642 | CodecTest, |
| 643 | ::testing::Combine( |
| 644 | ::testing::Values( |
| 645 | Codec("Gorilla" ), |
| 646 | Codec("Gorilla, LZ4" ) |
| 647 | ), |
| 648 | ::testing::Values( |
| 649 | generateSeq<Float32>(G(SameValueGenerator(M_E))), |
| 650 | generateSeq<Float64>(G(SameValueGenerator(M_E))) |
| 651 | ) |
| 652 | ), |
| 653 | ); |
| 654 | |
| 655 | INSTANTIATE_TEST_CASE_P(SameNegativeValueFloat, |
| 656 | CodecTest, |
| 657 | ::testing::Combine( |
| 658 | ::testing::Values( |
| 659 | Codec("Gorilla" ), |
| 660 | Codec("Gorilla, LZ4" ) |
| 661 | ), |
| 662 | ::testing::Values( |
| 663 | generateSeq<Float32>(G(SameValueGenerator(-1 * M_E))), |
| 664 | generateSeq<Float64>(G(SameValueGenerator(-1 * M_E))) |
| 665 | ) |
| 666 | ), |
| 667 | ); |
| 668 | |
| 669 | INSTANTIATE_TEST_CASE_P(SequentialInt, |
| 670 | CodecTest, |
| 671 | ::testing::Combine( |
| 672 | DefaultCodecsToTest, |
| 673 | ::testing::Values( |
| 674 | generateSeq<Int8 >(G(SequentialGenerator(1))), |
| 675 | generateSeq<Int16 >(G(SequentialGenerator(1))), |
| 676 | generateSeq<Int32 >(G(SequentialGenerator(1))), |
| 677 | generateSeq<Int64 >(G(SequentialGenerator(1))), |
| 678 | generateSeq<UInt8 >(G(SequentialGenerator(1))), |
| 679 | generateSeq<UInt16>(G(SequentialGenerator(1))), |
| 680 | generateSeq<UInt32>(G(SequentialGenerator(1))), |
| 681 | generateSeq<UInt64>(G(SequentialGenerator(1))) |
| 682 | ) |
| 683 | ), |
| 684 | ); |
| 685 | |
| 686 | // -1, -2, -3, ... etc for signed |
| 687 | // 0xFF, 0xFE, 0xFD, ... for unsigned |
| 688 | INSTANTIATE_TEST_CASE_P(SequentialReverseInt, |
| 689 | CodecTest, |
| 690 | ::testing::Combine( |
| 691 | DefaultCodecsToTest, |
| 692 | ::testing::Values( |
| 693 | generateSeq<Int8 >(G(SequentialGenerator(-1))), |
| 694 | generateSeq<Int16 >(G(SequentialGenerator(-1))), |
| 695 | generateSeq<Int32 >(G(SequentialGenerator(-1))), |
| 696 | generateSeq<Int64 >(G(SequentialGenerator(-1))), |
| 697 | generateSeq<UInt8 >(G(SequentialGenerator(-1))), |
| 698 | generateSeq<UInt16>(G(SequentialGenerator(-1))), |
| 699 | generateSeq<UInt32>(G(SequentialGenerator(-1))), |
| 700 | generateSeq<UInt64>(G(SequentialGenerator(-1))) |
| 701 | ) |
| 702 | ), |
| 703 | ); |
| 704 | |
| 705 | INSTANTIATE_TEST_CASE_P(SequentialFloat, |
| 706 | CodecTest, |
| 707 | ::testing::Combine( |
| 708 | ::testing::Values( |
| 709 | Codec("Gorilla" ), |
| 710 | Codec("Gorilla, LZ4" ) |
| 711 | ), |
| 712 | ::testing::Values( |
| 713 | generateSeq<Float32>(G(SequentialGenerator(M_E))), |
| 714 | generateSeq<Float64>(G(SequentialGenerator(M_E))) |
| 715 | ) |
| 716 | ), |
| 717 | ); |
| 718 | |
| 719 | INSTANTIATE_TEST_CASE_P(SequentialReverseFloat, |
| 720 | CodecTest, |
| 721 | ::testing::Combine( |
| 722 | ::testing::Values( |
| 723 | Codec("Gorilla" ), |
| 724 | Codec("Gorilla, LZ4" ) |
| 725 | ), |
| 726 | ::testing::Values( |
| 727 | generateSeq<Float32>(G(SequentialGenerator(-1 * M_E))), |
| 728 | generateSeq<Float64>(G(SequentialGenerator(-1 * M_E))) |
| 729 | ) |
| 730 | ), |
| 731 | ); |
| 732 | |
| 733 | INSTANTIATE_TEST_CASE_P(MonotonicInt, |
| 734 | CodecTest, |
| 735 | ::testing::Combine( |
| 736 | DefaultCodecsToTest, |
| 737 | ::testing::Values( |
| 738 | generateSeq<Int8 >(G(MonotonicGenerator(1, 5))), |
| 739 | generateSeq<Int16 >(G(MonotonicGenerator(1, 5))), |
| 740 | generateSeq<Int32 >(G(MonotonicGenerator(1, 5))), |
| 741 | generateSeq<Int64 >(G(MonotonicGenerator(1, 5))), |
| 742 | generateSeq<UInt8 >(G(MonotonicGenerator(1, 5))), |
| 743 | generateSeq<UInt16>(G(MonotonicGenerator(1, 5))), |
| 744 | generateSeq<UInt32>(G(MonotonicGenerator(1, 5))), |
| 745 | generateSeq<UInt64>(G(MonotonicGenerator(1, 5))) |
| 746 | ) |
| 747 | ), |
| 748 | ); |
| 749 | |
| 750 | INSTANTIATE_TEST_CASE_P(MonotonicReverseInt, |
| 751 | CodecTest, |
| 752 | ::testing::Combine( |
| 753 | DefaultCodecsToTest, |
| 754 | ::testing::Values( |
| 755 | generateSeq<Int8 >(G(MonotonicGenerator(-1, 5))), |
| 756 | generateSeq<Int16 >(G(MonotonicGenerator(-1, 5))), |
| 757 | generateSeq<Int32 >(G(MonotonicGenerator(-1, 5))), |
| 758 | generateSeq<Int64 >(G(MonotonicGenerator(-1, 5))), |
| 759 | generateSeq<UInt8 >(G(MonotonicGenerator(-1, 5))), |
| 760 | generateSeq<UInt16>(G(MonotonicGenerator(-1, 5))), |
| 761 | generateSeq<UInt32>(G(MonotonicGenerator(-1, 5))), |
| 762 | generateSeq<UInt64>(G(MonotonicGenerator(-1, 5))) |
| 763 | ) |
| 764 | ), |
| 765 | ); |
| 766 | |
| 767 | INSTANTIATE_TEST_CASE_P(MonotonicFloat, |
| 768 | CodecTest, |
| 769 | ::testing::Combine( |
| 770 | ::testing::Values( |
| 771 | Codec("Gorilla" ) |
| 772 | ), |
| 773 | ::testing::Values( |
| 774 | generateSeq<Float32>(G(MonotonicGenerator<Float32>(M_E, 5))), |
| 775 | generateSeq<Float64>(G(MonotonicGenerator<Float64>(M_E, 5))) |
| 776 | ) |
| 777 | ), |
| 778 | ); |
| 779 | |
| 780 | INSTANTIATE_TEST_CASE_P(MonotonicReverseFloat, |
| 781 | CodecTest, |
| 782 | ::testing::Combine( |
| 783 | ::testing::Values( |
| 784 | Codec("Gorilla" ) |
| 785 | ), |
| 786 | ::testing::Values( |
| 787 | generateSeq<Float32>(G(MonotonicGenerator<Float32>(-1 * M_E, 5))), |
| 788 | generateSeq<Float64>(G(MonotonicGenerator<Float64>(-1 * M_E, 5))) |
| 789 | ) |
| 790 | ), |
| 791 | ); |
| 792 | |
| 793 | INSTANTIATE_TEST_CASE_P(RandomInt, |
| 794 | CodecTest, |
| 795 | ::testing::Combine( |
| 796 | DefaultCodecsToTest, |
| 797 | ::testing::Values( |
| 798 | generateSeq<UInt8 >(G(RandomGenerator<UInt8>(0))), |
| 799 | generateSeq<UInt16>(G(RandomGenerator<UInt16>(0))), |
| 800 | generateSeq<UInt32>(G(RandomGenerator<UInt32>(0, 0, 1000'000'000))), |
| 801 | generateSeq<UInt64>(G(RandomGenerator<UInt64>(0, 0, 1000'000'000))) |
| 802 | ) |
| 803 | ), |
| 804 | ); |
| 805 | |
| 806 | INSTANTIATE_TEST_CASE_P(RandomishInt, |
| 807 | CodecTest, |
| 808 | ::testing::Combine( |
| 809 | DefaultCodecsToTest, |
| 810 | ::testing::Values( |
| 811 | generateSeq<Int32>(G(RandomishGenerator)), |
| 812 | generateSeq<Int64>(G(RandomishGenerator)), |
| 813 | generateSeq<UInt32>(G(RandomishGenerator)), |
| 814 | generateSeq<UInt64>(G(RandomishGenerator)), |
| 815 | generateSeq<Float32>(G(RandomishGenerator)), |
| 816 | generateSeq<Float64>(G(RandomishGenerator)) |
| 817 | ) |
| 818 | ), |
| 819 | ); |
| 820 | |
| 821 | INSTANTIATE_TEST_CASE_P(RandomishFloat, |
| 822 | CodecTest, |
| 823 | ::testing::Combine( |
| 824 | DefaultCodecsToTest, |
| 825 | ::testing::Values( |
| 826 | generateSeq<Float32>(G(RandomishGenerator)), |
| 827 | generateSeq<Float64>(G(RandomishGenerator)) |
| 828 | ) |
| 829 | ), |
| 830 | ); |
| 831 | |
| 832 | // Double delta overflow case, deltas are out of bounds for target type |
| 833 | INSTANTIATE_TEST_CASE_P(OverflowInt, |
| 834 | CodecTest, |
| 835 | ::testing::Combine( |
| 836 | ::testing::Values( |
| 837 | Codec("DoubleDelta" , 1.2), |
| 838 | Codec("DoubleDelta, LZ4" , 1.0) |
| 839 | ), |
| 840 | ::testing::Values( |
| 841 | generateSeq<UInt32>(G(MinMaxGenerator())), |
| 842 | generateSeq<Int32>(G(MinMaxGenerator())), |
| 843 | generateSeq<UInt64>(G(MinMaxGenerator())), |
| 844 | generateSeq<Int64>(G(MinMaxGenerator())) |
| 845 | ) |
| 846 | ), |
| 847 | ); |
| 848 | |
| 849 | INSTANTIATE_TEST_CASE_P(OverflowFloat, |
| 850 | CodecTest, |
| 851 | ::testing::Combine( |
| 852 | ::testing::Values( |
| 853 | Codec("Gorilla" , 1.1), |
| 854 | Codec("Gorilla, LZ4" , 1.0) |
| 855 | ), |
| 856 | ::testing::Values( |
| 857 | generateSeq<Float32>(G(MinMaxGenerator())), |
| 858 | generateSeq<Float64>(G(MinMaxGenerator())), |
| 859 | generateSeq<Float32>(G(FFand0Generator())), |
| 860 | generateSeq<Float64>(G(FFand0Generator())) |
| 861 | ) |
| 862 | ), |
| 863 | ); |
| 864 | |
| 865 | } |
| 866 | |