1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 #include "gtest/gtest.h"
5 #include "rgw/rgw_compression.h"
7 class ut_get_sink
: public RGWGetDataCB
{
11 virtual ~ut_get_sink() {}
13 int handle_data(bufferlist
& bl
, off_t bl_ofs
, off_t bl_len
) override
15 auto bl_buffers
= bl
.buffers();
16 auto i
= bl_buffers
.begin();
19 assert(i
!= bl_buffers
.end());
20 off_t len
= std::min
<off_t
>(bl_len
, i
->length());
21 sink
.append(*i
, 0, len
);
27 bufferlist
& get_sink()
33 class ut_get_sink_size
: public RGWGetDataCB
{
37 virtual ~ut_get_sink_size() {}
39 int handle_data(bufferlist
& bl
, off_t bl_ofs
, off_t bl_len
) override
41 if (bl_len
> (off_t
)max_size
)
51 class ut_put_sink
: public RGWPutObjDataProcessor
56 virtual ~ut_put_sink(){}
57 int handle_data(bufferlist
& bl
, off_t ofs
, void **phandle
, rgw_raw_obj
*pobj
, bool *again
) override
63 int throttle_data(void *handle
, const rgw_raw_obj
& obj
, uint64_t size
, bool need_to_wait
) override
67 bufferlist
& get_sink()
74 struct MockGetDataCB
: public RGWGetDataCB
{
75 int handle_data(bufferlist
& bl
, off_t bl_ofs
, off_t bl_len
) override
{
80 using range_t
= std::pair
<off_t
, off_t
>;
82 // call filter->fixup_range() and return the range as a pair. this makes it easy
83 // to fit on a single line for ASSERT_EQ()
84 range_t
fixup_range(RGWGetObj_Decompress
*filter
, off_t ofs
, off_t end
)
86 filter
->fixup_range(ofs
, end
);
91 TEST(Decompress
, FixupRangePartial
)
93 RGWCompressionInfo cs_info
;
95 // array of blocks with original len=8, compressed to len=6
96 auto& blocks
= cs_info
.blocks
;
97 blocks
.emplace_back(compression_block
{0, 0, 6});
98 blocks
.emplace_back(compression_block
{8, 6, 6});
99 blocks
.emplace_back(compression_block
{16, 12, 6});
100 blocks
.emplace_back(compression_block
{24, 18, 6});
102 const bool partial
= true;
103 RGWGetObj_Decompress
decompress(g_ceph_context
, &cs_info
, partial
, &cb
);
105 // test translation from logical ranges to compressed ranges
106 ASSERT_EQ(range_t(0, 5), fixup_range(&decompress
, 0, 1));
107 ASSERT_EQ(range_t(0, 5), fixup_range(&decompress
, 1, 7));
108 ASSERT_EQ(range_t(0, 11), fixup_range(&decompress
, 7, 8));
109 ASSERT_EQ(range_t(0, 11), fixup_range(&decompress
, 0, 9));
110 ASSERT_EQ(range_t(0, 11), fixup_range(&decompress
, 7, 9));
111 ASSERT_EQ(range_t(6, 11), fixup_range(&decompress
, 8, 9));
112 ASSERT_EQ(range_t(6, 17), fixup_range(&decompress
, 8, 16));
113 ASSERT_EQ(range_t(6, 17), fixup_range(&decompress
, 8, 17));
114 ASSERT_EQ(range_t(12, 23), fixup_range(&decompress
, 16, 24));
115 ASSERT_EQ(range_t(12, 23), fixup_range(&decompress
, 16, 999));
116 ASSERT_EQ(range_t(18, 23), fixup_range(&decompress
, 998, 999));
119 TEST(Compress
, LimitedChunkSize
)
121 CompressorRef plugin
;
122 plugin
= Compressor::create(g_ceph_context
, Compressor::COMP_ALG_ZLIB
);
123 ASSERT_NE(plugin
.get(), nullptr);
125 for (size_t s
= 100 ; s
< 10000000 ; s
= s
*5/4)
136 RGWPutObj_Compress
compressor(g_ceph_context
, plugin
, &c_sink
);
137 compressor
.handle_data(bl
, 0, &handle
, &obj
, &again
);
140 compressor
.handle_data(empty
, s
, &handle
, &obj
, &again
);
142 RGWCompressionInfo cs_info
;
143 cs_info
.compression_type
= plugin
->get_type_name();
144 cs_info
.orig_size
= s
;
145 cs_info
.blocks
= move(compressor
.get_compression_blocks());
147 ut_get_sink_size d_sink
;
148 RGWGetObj_Decompress
decompress(g_ceph_context
, &cs_info
, false, &d_sink
);
152 decompress
.fixup_range(f_begin
, f_end
);
154 decompress
.handle_data(c_sink
.get_sink(), 0, c_sink
.get_sink().length());
155 decompress
.handle_data(empty
, 0, 0);
157 ASSERT_LE(d_sink
.get_size(), (size_t)g_ceph_context
->_conf
->rgw_max_chunk_size
);
162 TEST(Compress
, BillionZeros
)
164 CompressorRef plugin
;
166 plugin
= Compressor::create(g_ceph_context
, Compressor::COMP_ALG_ZLIB
);
167 ASSERT_NE(plugin
.get(), nullptr);
168 RGWPutObj_Compress
compressor(g_ceph_context
, plugin
, &c_sink
);
170 constexpr size_t size
= 1000000;
179 for (int i
=0; i
<1000;i
++)
180 compressor
.handle_data(bl
, size
*i
, &handle
, &obj
, &again
);
183 compressor
.handle_data(empty
, size
*1000, &handle
, &obj
, &again
);
185 RGWCompressionInfo cs_info
;
186 cs_info
.compression_type
= plugin
->get_type_name();
187 cs_info
.orig_size
= size
*1000;
188 cs_info
.blocks
= move(compressor
.get_compression_blocks());
191 RGWGetObj_Decompress
decompress(g_ceph_context
, &cs_info
, false, &d_sink
);
194 off_t f_end
= size
*1000 - 1;
195 decompress
.fixup_range(f_begin
, f_end
);
197 decompress
.handle_data(c_sink
.get_sink(), 0, c_sink
.get_sink().length());
198 decompress
.handle_data(empty
, 0, 0);
200 ASSERT_EQ(d_sink
.get_sink().length() , size
*1000);