/* test_deflate.cc -- Test deflate/inflate round-trip with various levels, sizes, and strategies */ #include "zbuild.h" #ifdef ZLIB_COMPAT # include "zlib.h" #else # include "zlib-ng.h" #endif #include #include #include #include #include #include "compressible_data_p.h" #include "test_shared.h" #define MAX_SIZE (1024 * 1024) class deflate_variant : public testing::TestWithParam> { public: static void SetUpTestSuite() { inbuf = gen_compressible_data(MAX_SIZE); ASSERT_TRUE(inbuf != NULL); } static void TearDownTestSuite() { free(inbuf); inbuf = NULL; } void SetUp() override { compbuf = NULL; decompbuf = NULL; } void TearDown() override { free(compbuf); free(decompbuf); } static uint8_t *inbuf; uint8_t *compbuf; uint8_t *decompbuf; }; uint8_t *deflate_variant::inbuf = NULL; TEST_P(deflate_variant, round_trip) { size_t size = std::get<0>(GetParam()); int level = std::get<1>(GetParam()); int window_bits = std::get<2>(GetParam()); int strategy = std::get<3>(GetParam()); PREFIX3(stream) c_stream, d_stream; int err; /* Allocate output buffer */ unsigned long compbuf_size = PREFIX(deflateBound)(NULL, (unsigned long)size); compbuf = (uint8_t *)malloc((size_t)compbuf_size); ASSERT_TRUE(compbuf != NULL); /* Compress */ memset(&c_stream, 0, sizeof(c_stream)); err = PREFIX(deflateInit2)(&c_stream, level, Z_DEFLATED, window_bits, MAX_MEM_LEVEL, strategy); ASSERT_EQ(err, Z_OK) << "deflateInit2 failed"; c_stream.next_in = inbuf; c_stream.avail_in = (uint32_t)size; c_stream.next_out = compbuf; c_stream.avail_out = (uint32_t)compbuf_size; err = PREFIX(deflate)(&c_stream, Z_FINISH); ASSERT_EQ(err, Z_STREAM_END) << "size: " << size << "\n" << "level: " << level << "\n" << "window_bits: " << window_bits << "\n" << "strategy: " << strategy; size_t comp_size = (size_t)c_stream.total_out; err = PREFIX(deflateEnd)(&c_stream); EXPECT_EQ(err, Z_OK); /* Decompress and verify round-trip */ decompbuf = (uint8_t *)malloc(size); ASSERT_TRUE(decompbuf != NULL); memset(&d_stream, 0, sizeof(d_stream)); err = PREFIX(inflateInit2)(&d_stream, window_bits); ASSERT_EQ(err, Z_OK) << "inflateInit2 failed"; d_stream.next_in = compbuf; d_stream.avail_in = (uint32_t)comp_size; d_stream.next_out = decompbuf; d_stream.avail_out = (uint32_t)size; err = PREFIX(inflate)(&d_stream, Z_FINISH); ASSERT_EQ(err, Z_STREAM_END) << "size: " << size << "\n" << "level: " << level << "\n" << "window_bits: " << window_bits << "\n" << "strategy: " << strategy; EXPECT_EQ(d_stream.total_in, comp_size); EXPECT_EQ(d_stream.total_out, size); EXPECT_EQ(memcmp(inbuf, decompbuf, size), 0) << "round-trip data mismatch"; err = PREFIX(inflateEnd)(&d_stream); EXPECT_EQ(err, Z_OK); } static std::string deflate_test_name(const testing::TestParamInfo &info) { size_t size = std::get<0>(info.param); int level = std::get<1>(info.param); int window_bits = std::get<2>(info.param); int strategy = std::get<3>(info.param); char size_str[32]; if (size >= 1048576 && size % 1048576 == 0) snprintf(size_str, sizeof(size_str), "%zuM", size / 1048576); else if (size >= 1024 && size % 1024 == 0) snprintf(size_str, sizeof(size_str), "%zuK", size / 1024); else snprintf(size_str, sizeof(size_str), "%zu", size); const char *wrap_str = (window_bits < 0) ? "raw" : "zlib"; const char *strategy_str; switch (strategy) { case Z_FILTERED: strategy_str = "filtered"; break; case Z_HUFFMAN_ONLY: strategy_str = "huffman"; break; case Z_RLE: strategy_str = "rle"; break; case Z_FIXED: strategy_str = "fixed"; break; default: strategy_str = "default"; break; } char name[64]; snprintf(name, sizeof(name), "%s_level%d_%s_%s", size_str, level, wrap_str, strategy_str); return name; } INSTANTIATE_TEST_SUITE_P(deflate, deflate_variant, testing::Combine( testing::Values(1024, 16384, 131072, 1048576), /* size */ testing::Values(1, 3, 6, 9), /* level */ testing::Values(MAX_WBITS, -MAX_WBITS), /* window_bits */ testing::Values(Z_DEFAULT_STRATEGY, Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED) /* strategy */ ), deflate_test_name);