1 #include "include/buffer.h"
2 #include "include/encoding.h"
4 #include "gtest/gtest.h"
8 template < typename T >
9 static void test_encode_and_decode(const T& src)
11 bufferlist bl(1000000);
14 bufferlist::iterator i(bl.begin());
16 ASSERT_EQ(src, dst) << "Encoding roundtrip changed the string: orig=" << src << ", but new=" << dst;
19 TEST(EncodingRoundTrip, StringSimple) {
20 string my_str("I am the very model of a modern major general");
21 test_encode_and_decode < std::string >(my_str);
24 TEST(EncodingRoundTrip, StringEmpty) {
26 test_encode_and_decode < std::string >(my_str);
29 TEST(EncodingRoundTrip, StringNewline) {
30 string my_str("foo bar baz\n");
31 test_encode_and_decode < std::string >(my_str);
34 template <typename Size, typename T>
35 static void test_encode_and_nohead_nohead(Size len, const T& src)
37 bufferlist bl(1000000);
39 encode_nohead(src, bl);
41 bufferlist::iterator i(bl.begin());
43 decode_nohead(len, dst, i);
44 ASSERT_EQ(src, dst) << "Encoding roundtrip changed the string: orig=" << src << ", but new=" << dst;
47 TEST(EncodingRoundTrip, StringNoHead) {
48 const string str("The quick brown fox jumps over the lazy dog");
49 auto size = str.size();
50 test_encode_and_nohead_nohead(static_cast<int>(size), str);
51 test_encode_and_nohead_nohead(static_cast<unsigned>(size), str);
52 test_encode_and_nohead_nohead(static_cast<uint32_t>(size), str);
53 test_encode_and_nohead_nohead(static_cast<__u32>(size), str);
54 test_encode_and_nohead_nohead(static_cast<size_t>(size), str);
57 TEST(EncodingRoundTrip, BufferListNoHead) {
59 bl.append("is this a dagger which i see before me?");
60 auto size = bl.length();
61 test_encode_and_nohead_nohead(static_cast<int>(size), bl);
62 test_encode_and_nohead_nohead(static_cast<unsigned>(size), bl);
63 test_encode_and_nohead_nohead(static_cast<uint32_t>(size), bl);
64 test_encode_and_nohead_nohead(static_cast<__u32>(size), bl);
65 test_encode_and_nohead_nohead(static_cast<size_t>(size), bl);
68 typedef std::multimap < int, std::string > multimap_t;
69 typedef multimap_t::value_type my_val_ty;
72 static std::ostream& operator<<(std::ostream& oss, const multimap_t &multimap)
74 for (multimap_t::const_iterator m = multimap.begin();
78 oss << m->first << "->" << m->second << " ";
84 TEST(EncodingRoundTrip, Multimap) {
86 multimap.insert( my_val_ty(1, "foo") );
87 multimap.insert( my_val_ty(2, "bar") );
88 multimap.insert( my_val_ty(2, "baz") );
89 multimap.insert( my_val_ty(3, "lucky number 3") );
90 multimap.insert( my_val_ty(10000, "large number") );
92 test_encode_and_decode < multimap_t >(multimap);
97 ///////////////////////////////////////////////////////
99 ///////////////////////////////////////////////////////
100 template <typename T>
101 class ConstructorCounter
104 ConstructorCounter() : data(0)
109 explicit ConstructorCounter(const T& data_)
115 ConstructorCounter(const ConstructorCounter &rhs)
121 ConstructorCounter &operator=(const ConstructorCounter &rhs)
128 static void init(void)
136 static int get_default_ctor(void)
141 static int get_one_arg_ctor(void)
146 static int get_copy_ctor(void)
151 static int get_assigns(void)
156 bool operator<(const ConstructorCounter &rhs) const
158 return data < rhs.data;
161 bool operator==(const ConstructorCounter &rhs) const
163 return data == rhs.data;
166 friend void decode(ConstructorCounter &s, bufferlist::iterator& p)
171 friend void encode(const ConstructorCounter &s, bufferlist& p)
176 friend ostream& operator<<(ostream &oss, const ConstructorCounter &cc)
184 static int default_ctor;
185 static int one_arg_ctor;
186 static int copy_ctor;
190 template class ConstructorCounter <int32_t>;
191 template class ConstructorCounter <int16_t>;
193 typedef ConstructorCounter <int32_t> my_key_t;
194 typedef ConstructorCounter <int16_t> my_val_t;
195 typedef std::multimap < my_key_t, my_val_t > multimap2_t;
196 typedef multimap2_t::value_type val2_ty;
198 template <class T> int ConstructorCounter<T>::default_ctor = 0;
199 template <class T> int ConstructorCounter<T>::one_arg_ctor = 0;
200 template <class T> int ConstructorCounter<T>::copy_ctor = 0;
201 template <class T> int ConstructorCounter<T>::assigns = 0;
203 static std::ostream& operator<<(std::ostream& oss, const multimap2_t &multimap)
205 for (multimap2_t::const_iterator m = multimap.begin();
209 oss << m->first << "->" << m->second << " ";
214 TEST(EncodingRoundTrip, MultimapConstructorCounter) {
215 multimap2_t multimap2;
216 multimap2.insert( val2_ty(my_key_t(1), my_val_t(10)) );
217 multimap2.insert( val2_ty(my_key_t(2), my_val_t(20)) );
218 multimap2.insert( val2_ty(my_key_t(2), my_val_t(30)) );
219 multimap2.insert( val2_ty(my_key_t(3), my_val_t(40)) );
220 multimap2.insert( val2_ty(my_key_t(10000), my_val_t(1)) );
224 test_encode_and_decode < multimap2_t >(multimap2);
226 EXPECT_EQ(my_key_t::get_default_ctor(), 5);
227 EXPECT_EQ(my_key_t::get_one_arg_ctor(), 0);
228 EXPECT_EQ(my_key_t::get_copy_ctor(), 5);
229 EXPECT_EQ(my_key_t::get_assigns(), 0);
231 EXPECT_EQ(my_val_t::get_default_ctor(), 5);
232 EXPECT_EQ(my_val_t::get_one_arg_ctor(), 0);
233 EXPECT_EQ(my_val_t::get_copy_ctor(), 5);
234 EXPECT_EQ(my_val_t::get_assigns(), 0);
237 // make sure that the legacy encode/decode methods are selected
238 // over the ones defined using templates. the later is likely to
239 // be slower, see also the definition of "WRITE_INT_DENC" in
242 void encode<uint64_t, denc_traits<uint64_t>>(const uint64_t&,
245 static_assert(denc_traits<uint64_t>::supported,
246 "should support new encoder");
247 static_assert(!denc_traits<uint64_t>::featured,
248 "should not be featured");
250 // make sure the test fails if i get called
255 void encode<ceph_le64, denc_traits<ceph_le64>>(const ceph_le64&,
258 static_assert(denc_traits<ceph_le64>::supported,
259 "should support new encoder");
260 static_assert(!denc_traits<ceph_le64>::featured,
261 "should not be featured");
263 // make sure the test fails if i get called
267 TEST(EncodingRoundTrip, Integers) {
271 test_encode_and_decode(i);
275 test_encode_and_decode(i);
279 test_encode_and_decode(b);
283 test_encode_and_decode(b);
289 test_encode_and_decode(i);
293 const char* expected_what[] = {
294 "buffer::malformed_input: void lame_decoder(int) no longer understand old encoding version 100 < 200",
295 "buffer::malformed_input: void lame_decoder(int) decode past end of struct encoding",
298 void lame_decoder(int which) {
301 throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, 100, 200));
303 throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__));
307 TEST(EncodingException, Macros) {
308 for (unsigned i = 0; i < sizeof(expected_what)/sizeof(expected_what[0]); i++) {
311 } catch (const exception& e) {
312 ASSERT_EQ(string(expected_what[i]), string(e.what()));
318 TEST(small_encoding, varint) {
320 /* value, varint bytes, signed varint bytes, signed varint bytes (neg) */
339 {0xff00001, 4, 5, 5},
340 {0x1ff00001, 5, 5, 5},
341 {0xffff0001, 5, 5, 5},
342 {0xffffffff, 5, 5, 5},
343 {1074790401, 5, 5, 5},
346 for (unsigned i=0; v[i][1]; ++i) {
350 auto app = bl.get_contiguous_appender(16, true);
351 denc_varint(v[i][0], app);
353 cout << std::hex << v[i][0] << "\t" << v[i][1] << "\t";
354 bl.hexdump(cout, false);
356 ASSERT_EQ(bl.length(), v[i][1]);
358 auto p = bl.begin().get_current_ptr().begin();
360 ASSERT_EQ(v[i][0], u);
365 auto app = bl.get_contiguous_appender(16, true);
366 denc_signed_varint(v[i][0], app);
368 cout << std::hex << v[i][0] << "\t" << v[i][2] << "\t";
369 bl.hexdump(cout, false);
371 ASSERT_EQ(bl.length(), v[i][2]);
373 auto p = bl.begin().get_current_ptr().begin();
374 denc_signed_varint(u, p);
375 ASSERT_EQ((int32_t)v[i][0], u);
379 int64_t x = -(int64_t)v[i][0];
381 auto app = bl.get_contiguous_appender(16, true);
382 denc_signed_varint(x, app);
384 cout << std::dec << x << std::hex << "\t" << v[i][3] << "\t";
385 bl.hexdump(cout, false);
387 ASSERT_EQ(bl.length(), v[i][3]);
389 auto p = bl.begin().get_current_ptr().begin();
390 denc_signed_varint(u, p);
396 TEST(small_encoding, varint_lowz) {
398 /* value, bytes encoded */
419 {0xffff0000, 4, 4, 4},
420 {0xffffffff, 5, 5, 5},
421 {0x41000000, 3, 4, 4},
424 for (unsigned i=0; v[i][1]; ++i) {
428 auto app = bl.get_contiguous_appender(16, true);
429 denc_varint_lowz(v[i][0], app);
431 cout << std::hex << v[i][0] << "\t" << v[i][1] << "\t";
432 bl.hexdump(cout, false);
434 ASSERT_EQ(bl.length(), v[i][1]);
436 auto p = bl.begin().get_current_ptr().begin();
437 denc_varint_lowz(u, p);
438 ASSERT_EQ(v[i][0], u);
444 auto app = bl.get_contiguous_appender(16, true);
445 denc_signed_varint_lowz(x, app);
447 cout << std::hex << x << "\t" << v[i][1] << "\t";
448 bl.hexdump(cout, false);
450 ASSERT_EQ(bl.length(), v[i][2]);
452 auto p = bl.begin().get_current_ptr().begin();
453 denc_signed_varint_lowz(u, p);
458 int64_t x = -(int64_t)v[i][0];
460 auto app = bl.get_contiguous_appender(16, true);
461 denc_signed_varint_lowz(x, app);
463 cout << std::dec << x << "\t" << v[i][1] << "\t";
464 bl.hexdump(cout, false);
466 ASSERT_EQ(bl.length(), v[i][3]);
468 auto p = bl.begin().get_current_ptr().begin();
469 denc_signed_varint_lowz(u, p);
475 TEST(small_encoding, lba) {
477 /* value, bytes encoded */
492 {0x1fffffff00000, 5},
496 for (unsigned i=0; v[i][1]; ++i) {
499 auto app = bl.get_contiguous_appender(16, true);
500 denc_lba(v[i][0], app);
502 cout << std::hex << v[i][0] << "\t" << v[i][1] << "\t";
503 bl.hexdump(cout, false);
505 ASSERT_EQ(bl.length(), v[i][1]);
507 auto p = bl.begin().get_current_ptr().begin();
509 ASSERT_EQ(v[i][0], u);