/* vim:set ts=2 sw=2 sts=2 et: */ /** * \author Marcus Holland-Moritz (github@mhxnet.de) * \copyright Copyright (c) Marcus Holland-Moritz * * This file is part of ricepp. * * ricepp is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ricepp is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ricepp. If not, see . */ #include #include #include #include #include #include #include namespace { template std::vector generate_random_data(size_t count, unsigned unused_lsb_count = 0, std::endian byteorder = std::endian::big, unsigned full_chance = 50) { std::mt19937_64 rng(42); std::uniform_int_distribution dist(0, full_chance); std::uniform_int_distribution noise(20000, 21000); std::uniform_int_distribution full( 0, std::numeric_limits::max()); std::vector data(count); ValueType mask = static_cast(std::numeric_limits::max() << unused_lsb_count); std::generate(data.begin(), data.end(), [&]() { return ricepp::byteswap( (dist(rng) == 0 ? full(rng) : noise(rng)) & mask, byteorder); }); return data; } } // namespace TEST(ricepp, codec_basic_test) { auto codec = ricepp::create_codec({ .block_size = 16, .component_stream_count = 1, .byteorder = std::endian::big, .unused_lsb_count = 0, }); auto data = generate_random_data(12345); auto encoded = codec->encode(data); std::vector decoded(data.size()); codec->decode(decoded, encoded); EXPECT_THAT(decoded, ::testing::ContainerEq(data)); } TEST(ricepp, codec_unused_lsb_test) { auto codec = ricepp::create_codec({ .block_size = 13, // because why not? .component_stream_count = 1, .byteorder = std::endian::big, .unused_lsb_count = 4, }); auto data = generate_random_data(4321, 4); auto encoded = codec->encode(data); std::vector decoded(data.size()); codec->decode(decoded, encoded); EXPECT_THAT(decoded, ::testing::ContainerEq(data)); } TEST(ricepp, codec_mixed_data_test) { auto codec = ricepp::create_codec({ .block_size = 32, .component_stream_count = 1, .byteorder = std::endian::big, .unused_lsb_count = 0, }); auto data1 = generate_random_data(500, 0); auto data2 = std::vector(500, 25000); auto data3 = generate_random_data(500, 0, std::endian::big, 0); auto data = ranges::views::concat(data1, data2, data3) | ranges::to_vector; auto encoded = codec->encode(data); std::vector decoded(data.size()); codec->decode(decoded, encoded); EXPECT_THAT(decoded, ::testing::ContainerEq(data)); } TEST(ricepp, codec_multi_component_test) { auto codec = ricepp::create_codec({ .block_size = 29, .component_stream_count = 2, .byteorder = std::endian::big, .unused_lsb_count = 2, }); auto data = generate_random_data(23456, 2); auto encoded = codec->encode(data); std::vector decoded(data.size()); codec->decode(decoded, encoded); EXPECT_THAT(decoded, ::testing::ContainerEq(data)); } TEST(ricepp, codec_preallocated_buffer_test) { auto codec = ricepp::create_codec({ .block_size = 29, .component_stream_count = 1, .byteorder = std::endian::big, .unused_lsb_count = 0, }); static constexpr size_t const kDataLen = 14443; auto data = generate_random_data(kDataLen, 0, std::endian::big, 0); auto worst_case_bytes = codec->worst_case_encoded_bytes(data); static constexpr size_t const kWorstCaseBytes = 29138; EXPECT_EQ(kWorstCaseBytes, worst_case_bytes); std::vector encoded(worst_case_bytes); auto span = codec->encode(encoded, data); EXPECT_EQ(kWorstCaseBytes, span.size()); encoded.resize(span.size()); encoded.shrink_to_fit(); std::vector decoded(data.size()); codec->decode(decoded, encoded); EXPECT_THAT(decoded, ::testing::ContainerEq(data)); } TEST(ricepp, codec_worst_case_bytes_test) { auto codec = ricepp::create_codec({ .block_size = 29, .component_stream_count = 2, .byteorder = std::endian::big, .unused_lsb_count = 0, }); static constexpr size_t const kDataLen = 28886; auto worst_case_bytes = codec->worst_case_encoded_bytes(kDataLen); static constexpr size_t const kWorstCaseBytes = 58275; EXPECT_EQ(kWorstCaseBytes, worst_case_bytes); } TEST(ricepp, codec_error_test) { EXPECT_THAT( [] { auto codec = ricepp::create_codec({ .block_size = 513, .component_stream_count = 2, .byteorder = std::endian::big, .unused_lsb_count = 0, }); }, ::testing::ThrowsMessage( "Unsupported configuration")); EXPECT_THAT( [] { auto codec = ricepp::create_codec({ .block_size = 128, .component_stream_count = 3, .byteorder = std::endian::big, .unused_lsb_count = 0, }); }, ::testing::ThrowsMessage( "Unsupported configuration")); }