diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/stream/zlib_ut.cpp |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/stream/zlib_ut.cpp')
-rw-r--r-- | util/stream/zlib_ut.cpp | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/util/stream/zlib_ut.cpp b/util/stream/zlib_ut.cpp new file mode 100644 index 00000000000..2290b4a9dee --- /dev/null +++ b/util/stream/zlib_ut.cpp @@ -0,0 +1,230 @@ +#include "zlib.h" + +#include <library/cpp/testing/unittest/registar.h> + +#include "file.h" +#include <util/system/tempfile.h> +#include <util/random/entropy.h> +#include <util/random/random.h> + +#define ZDATA "./zdata" + +class TThrowingStream: public IOutputStream { +public: + TThrowingStream(int limit) + : Limit_(limit) + { + } + + void DoWrite(const void*, size_t size) override { + if (Ignore) { + return; + } + + Limit_ -= size; + if (Limit_ < 0) { + throw yexception() << "catch this"; + } + } + + void DoFinish() override { + if (Ignore) { + return; + } + if (Limit_ < 0) { + throw yexception() << "catch this"; + } + } + + void DoFlush() override { + if (Ignore) { + return; + } + if (Limit_ < 0) { + throw yexception() << "catch this"; + } + } + + bool Ignore = false; + +private: + int Limit_; +}; + +Y_UNIT_TEST_SUITE(TZLibTest) { + static const TString DATA = "8s7d5vc6s5vc67sa4c65ascx6asd4xcv76adsfxv76s"; + static const TString DATA2 = "cn8wk2bd9vb3vdfif83g1ks94bfiovtwv"; + + Y_UNIT_TEST(Compress) { + TUnbufferedFileOutput o(ZDATA); + TZLibCompress c(&o, ZLib::ZLib); + + c.Write(DATA.data(), DATA.size()); + c.Finish(); + o.Finish(); + } + + Y_UNIT_TEST(Decompress) { + TTempFile tmpFile(ZDATA); + + { + TUnbufferedFileInput i(ZDATA); + TZLibDecompress d(&i); + + UNIT_ASSERT_EQUAL(d.ReadAll(), DATA); + } + } + + Y_UNIT_TEST(Dictionary) { + static constexpr TStringBuf data = "<html><body></body></html>"; + static constexpr TStringBuf dict = "</<html><body>"; + for (auto type : {ZLib::Raw, ZLib::ZLib}) { + TStringStream compressed; + { + TZLibCompress compressor(TZLibCompress::TParams(&compressed).SetDict(dict).SetType(type)); + compressor.Write(data); + } + + TZLibDecompress decompressor(&compressed, type, ZLib::ZLIB_BUF_LEN, dict); + UNIT_ASSERT_STRINGS_EQUAL(decompressor.ReadAll(), data); + } + } + + Y_UNIT_TEST(DecompressTwoStreams) { + // Check that Decompress(Compress(X) + Compress(Y)) == X + Y + TTempFile tmpFile(ZDATA); + { + TUnbufferedFileOutput o(ZDATA); + TZLibCompress c1(&o, ZLib::ZLib); + c1.Write(DATA.data(), DATA.size()); + c1.Finish(); + TZLibCompress c2(&o, ZLib::ZLib); + c2.Write(DATA2.data(), DATA2.size()); + c2.Finish(); + o.Finish(); + } + { + TUnbufferedFileInput i(ZDATA); + TZLibDecompress d(&i); + + UNIT_ASSERT_EQUAL(d.ReadAll(), DATA + DATA2); + } + } + + Y_UNIT_TEST(CompressionExceptionSegfault) { + TVector<char> buf(512 * 1024); + EntropyPool().Load(buf.data(), buf.size()); + + TThrowingStream o(128 * 1024); + TZLibCompress c(&o, ZLib::GZip, 4, 1 << 15); + try { + c.Write(buf.data(), buf.size()); + } catch (...) { + } + + o.Ignore = true; + TVector<char>().swap(buf); + } + + Y_UNIT_TEST(DecompressFirstOfTwoStreams) { + // Check that Decompress(Compress(X) + Compress(Y)) == X when single stream is allowed + TTempFile tmpFile(ZDATA); + { + TUnbufferedFileOutput o(ZDATA); + TZLibCompress c1(&o, ZLib::ZLib); + c1.Write(DATA.data(), DATA.size()); + c1.Finish(); + TZLibCompress c2(&o, ZLib::ZLib); + c2.Write(DATA2.data(), DATA2.size()); + c2.Finish(); + o.Finish(); + } + { + TUnbufferedFileInput i(ZDATA); + TZLibDecompress d(&i); + d.SetAllowMultipleStreams(false); + + UNIT_ASSERT_EQUAL(d.ReadAll(), DATA); + } + } + + Y_UNIT_TEST(CompressFlush) { + TString data = ""; + + for (size_t i = 0; i < 32; ++i) { + TTempFile tmpFile(ZDATA); + + TUnbufferedFileOutput output(ZDATA); + TZLibCompress compressor(&output, ZLib::ZLib); + + compressor.Write(data.data(), data.size()); + compressor.Flush(); + + { + TUnbufferedFileInput input(ZDATA); + TZLibDecompress decompressor(&input); + + UNIT_ASSERT_EQUAL(decompressor.ReadAll(), data); + } + + data += 'A' + i; + } + } + + Y_UNIT_TEST(CompressEmptyFlush) { + TTempFile tmpFile(ZDATA); + + TUnbufferedFileOutput output(ZDATA); + TZLibCompress compressor(&output, ZLib::ZLib); + + TUnbufferedFileInput input(ZDATA); + + compressor.Write(DATA.data(), DATA.size()); + compressor.Flush(); + + { + TZLibDecompress decompressor(&input); + UNIT_ASSERT_EQUAL(decompressor.ReadAll(), DATA); + } + + for (size_t i = 0; i < 10; ++i) { + compressor.Flush(); + } + + UNIT_ASSERT_EQUAL(input.ReadAll(), ""); + } + + Y_UNIT_TEST(CompressFlushSmallBuffer) { + for (size_t bufferSize = 16; bufferSize < 32; ++bufferSize) { + TString firstData = ""; + + for (size_t firstDataSize = 0; firstDataSize < 16; ++firstDataSize) { + TString secondData = ""; + + for (size_t secondDataSize = 0; secondDataSize < 16; ++secondDataSize) { + TTempFile tmpFile(ZDATA); + + TUnbufferedFileOutput output(ZDATA); + TZLibCompress compressor(TZLibCompress::TParams(&output).SetType(ZLib::ZLib).SetBufLen(bufferSize)); + + TUnbufferedFileInput input(ZDATA); + TZLibDecompress decompressor(&input); + + compressor.Write(firstData.data(), firstData.size()); + compressor.Flush(); + + UNIT_ASSERT_EQUAL(decompressor.ReadAll(), firstData); + + compressor.Write(secondData.data(), secondData.size()); + compressor.Flush(); + + UNIT_ASSERT_EQUAL(decompressor.ReadAll(), secondData); + + secondData += 'A' + secondDataSize; + } + + firstData += 'A' + firstDataSize; + } + } + } +} |