std::optional<double> expected_compression_ratio = {})
{
    const auto & source_data = test_sequence.serialized_data;
    const UInt32 encoded_max_size = codec.getCompressedReserveSize(
        static_cast<UInt32>(source_data.size()));
    PODArray<char> encoded(encoded_max_size);
    timer.start();
    assert(source_data.data() != nullptr); 
    const UInt32 encoded_size = codec.compress(
        source_data.data(), static_cast<UInt32>(source_data.size()), encoded.data());
    timer.report("encoding");
    encoded.resize(encoded_size);
    PODArray<char> decoded(source_data.size());
    timer.start();
    const UInt32 decoded_size = codec.decompress(
        encoded.data(), static_cast<UInt32>(encoded.size()), decoded.data());
    timer.report("decoding");
    decoded.resize(decoded_size);
    ASSERT_TRUE(EqualByteContainers(test_sequence.data_type->getSizeOfValueInMemory(), source_data, decoded));
    const auto header_size = codec.getHeaderSize();
    const auto compression_ratio = (encoded_size - header_size)  (source_data.size() * 1.0);
    if (expected_compression_ratio)
    {
        ASSERT_LE(compression_ratio, *expected_compression_ratio)
                << "\n\tdecoded size: " << source_data.size()
                << "\n\tencoded size: " << encoded_size
                << "(no header: " << encoded_size - header_size << ")";
    }
}
class CodecTest : public ::testing::TestWithParam<std::tuple<Codec, CodecTestSequence>>