1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
8 * Author: Loic Dachary <loic@dachary.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Library Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library Public License for more details.
26 #include "include/buffer.h"
27 #include "include/buffer_raw.h"
28 #include "include/utime.h"
29 #include "include/coredumpctl.h"
30 #include "include/encoding.h"
31 #include "common/environment.h"
32 #include "common/Clock.h"
33 #include "common/safe_io.h"
35 #include "gtest/gtest.h"
39 #include "include/crc32c.h"
40 #include "common/sctp_crc32.h"
42 #define MAX_TEST 1000000
43 #define FILENAME "bufferlist"
47 struct instrumented_bptr
: public ceph::buffer::ptr
{
48 const ceph::buffer::raw
* get_raw() const {
53 TEST(Buffer
, constructors
) {
59 bufferptr
ptr(buffer::create(len
));
60 EXPECT_EQ(len
, ptr
.length());
66 char* str
= new char[len
];
67 ::memset(str
, 'X', len
);
68 bufferptr
ptr(buffer::claim_char(len
, str
));
69 EXPECT_EQ(len
, ptr
.length());
70 EXPECT_EQ(str
, ptr
.c_str());
71 bufferptr clone
= ptr
.clone();
72 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
76 // buffer::create_static
79 char* str
= new char[len
];
80 bufferptr
ptr(buffer::create_static(len
, str
));
81 EXPECT_EQ(len
, ptr
.length());
82 EXPECT_EQ(str
, ptr
.c_str());
86 // buffer::create_malloc
89 bufferptr
ptr(buffer::create_malloc(len
));
90 EXPECT_EQ(len
, ptr
.length());
91 // this doesn't throw on my x86_64 wheezy box --sage
92 //EXPECT_THROW(buffer::create_malloc((unsigned)ULLONG_MAX), buffer::bad_alloc);
95 // buffer::claim_malloc
98 char* str
= (char*)malloc(len
);
99 ::memset(str
, 'X', len
);
100 bufferptr
ptr(buffer::claim_malloc(len
, str
));
101 EXPECT_EQ(len
, ptr
.length());
102 EXPECT_EQ(str
, ptr
.c_str());
103 bufferptr clone
= ptr
.clone();
104 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
110 const std::string
expected(len
, 'X');
111 bufferptr
ptr(buffer::copy(expected
.c_str(), expected
.size()));
112 EXPECT_NE(expected
.c_str(), ptr
.c_str());
113 EXPECT_EQ(0, ::memcmp(expected
.c_str(), ptr
.c_str(), len
));
116 // buffer::create_page_aligned
119 bufferptr
ptr(buffer::create_page_aligned(len
));
120 ::memset(ptr
.c_str(), 'X', len
);
121 // doesn't throw on my x86_64 wheezy box --sage
122 //EXPECT_THROW(buffer::create_page_aligned((unsigned)ULLONG_MAX), buffer::bad_alloc);
124 ASSERT_TRUE(ptr
.is_page_aligned());
126 bufferptr clone
= ptr
.clone();
127 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
131 void bench_buffer_alloc(int size
, int num
)
133 utime_t start
= ceph_clock_now();
134 for (int i
=0; i
<num
; ++i
) {
135 bufferptr p
= buffer::create(size
);
138 utime_t end
= ceph_clock_now();
139 cout
<< num
<< " alloc of size " << size
140 << " in " << (end
- start
) << std::endl
;
143 TEST(Buffer
, BenchAlloc
) {
144 bench_buffer_alloc(16384, 1000000);
145 bench_buffer_alloc(4096, 1000000);
146 bench_buffer_alloc(1024, 1000000);
147 bench_buffer_alloc(256, 1000000);
148 bench_buffer_alloc(32, 1000000);
149 bench_buffer_alloc(4, 1000000);
152 TEST(BufferRaw
, ostream
) {
154 std::ostringstream stream
;
155 stream
<< *static_cast<instrumented_bptr
&>(ptr
).get_raw();
156 EXPECT_GT(stream
.str().size(), stream
.str().find("buffer::raw("));
157 EXPECT_GT(stream
.str().size(), stream
.str().find("len 1 nref 1)"));
161 // +-----------+ +-----+
163 // | offset +----------------+ |
165 // | length +---- | |
167 // +-----------+ \---+ |
169 // +-----------+ | raw |
172 TEST(BufferPtr
, constructors
) {
179 EXPECT_FALSE(ptr
.have_raw());
180 EXPECT_EQ((unsigned)0, ptr
.offset());
181 EXPECT_EQ((unsigned)0, ptr
.length());
187 bufferptr
ptr(buffer::create(len
));
188 EXPECT_TRUE(ptr
.have_raw());
189 EXPECT_EQ((unsigned)0, ptr
.offset());
190 EXPECT_EQ(len
, ptr
.length());
191 EXPECT_EQ(ptr
.raw_length(), ptr
.length());
192 EXPECT_EQ(1, ptr
.raw_nref());
195 // ptr::ptr(unsigned l)
199 EXPECT_TRUE(ptr
.have_raw());
200 EXPECT_EQ((unsigned)0, ptr
.offset());
201 EXPECT_EQ(len
, ptr
.length());
202 EXPECT_EQ(1, ptr
.raw_nref());
205 // ptr(const char *d, unsigned l)
208 const std::string
str(len
, 'X');
209 bufferptr
ptr(str
.c_str(), len
);
210 EXPECT_TRUE(ptr
.have_raw());
211 EXPECT_EQ((unsigned)0, ptr
.offset());
212 EXPECT_EQ(len
, ptr
.length());
213 EXPECT_EQ(1, ptr
.raw_nref());
214 EXPECT_EQ(0, ::memcmp(str
.c_str(), ptr
.c_str(), len
));
220 const std::string
str(len
, 'X');
221 bufferptr
original(str
.c_str(), len
);
222 bufferptr
ptr(original
);
223 EXPECT_TRUE(ptr
.have_raw());
224 EXPECT_EQ(static_cast<instrumented_bptr
&>(original
).get_raw(),
225 static_cast<instrumented_bptr
&>(ptr
).get_raw());
226 EXPECT_EQ(2, ptr
.raw_nref());
227 EXPECT_EQ(0, ::memcmp(original
.c_str(), ptr
.c_str(), len
));
230 // ptr(const ptr& p, unsigned o, unsigned l)
233 const std::string
str(len
, 'X');
234 bufferptr
original(str
.c_str(), len
);
235 bufferptr
ptr(original
, 0, 0);
236 EXPECT_TRUE(ptr
.have_raw());
237 EXPECT_EQ(static_cast<instrumented_bptr
&>(original
).get_raw(),
238 static_cast<instrumented_bptr
&>(ptr
).get_raw());
239 EXPECT_EQ(2, ptr
.raw_nref());
240 EXPECT_EQ(0, ::memcmp(original
.c_str(), ptr
.c_str(), len
));
241 PrCtl unset_dumpable
;
242 EXPECT_DEATH(bufferptr(original
, 0, original
.length() + 1), "");
243 EXPECT_DEATH(bufferptr(bufferptr(), 0, 0), "");
249 const std::string
str(len
, 'X');
250 bufferptr
original(str
.c_str(), len
);
251 bufferptr
ptr(std::move(original
));
252 EXPECT_TRUE(ptr
.have_raw());
253 EXPECT_FALSE(original
.have_raw());
254 EXPECT_EQ(0, ::memcmp(str
.c_str(), ptr
.c_str(), len
));
255 EXPECT_EQ(1, ptr
.raw_nref());
259 TEST(BufferPtr
, operator_assign
) {
261 // ptr& operator= (const ptr& p)
264 ptr
.copy_in(0, 3, "ABC");
267 bufferptr copy
= ptr
;
268 copy
.copy_out(1, 1, dest
);
269 ASSERT_EQ('B', dest
[0]);
273 // ptr& operator= (ptr&& p)
275 bufferptr move
= std::move(ptr
);
277 move
.copy_out(1, 1, dest
);
278 ASSERT_EQ('B', dest
[0]);
280 EXPECT_FALSE(ptr
.have_raw());
283 TEST(BufferPtr
, assignment
) {
286 // override a bufferptr set with the same raw
289 bufferptr
original(len
);
290 bufferptr
same_raw(original
);
292 unsigned length
= len
- offset
;
293 original
.set_offset(offset
);
294 original
.set_length(length
);
296 ASSERT_EQ(2, original
.raw_nref());
297 ASSERT_EQ(static_cast<instrumented_bptr
&>(same_raw
).get_raw(),
298 static_cast<instrumented_bptr
&>(original
).get_raw());
299 ASSERT_EQ(same_raw
.offset(), original
.offset());
300 ASSERT_EQ(same_raw
.length(), original
.length());
304 // self assignment is a noop
307 bufferptr
original(len
);
308 #pragma clang diagnostic push
309 #pragma clang diagnostic ignored "-Wself-assign-overloaded"
311 #pragma clang diagnostic pop
312 ASSERT_EQ(1, original
.raw_nref());
313 ASSERT_EQ((unsigned)0, original
.offset());
314 ASSERT_EQ(len
, original
.length());
318 // a copy points to the same raw
321 bufferptr
original(len
);
323 unsigned length
= len
- offset
;
324 original
.set_offset(offset
);
325 original
.set_length(length
);
328 ASSERT_EQ(2, original
.raw_nref());
329 ASSERT_EQ(static_cast<instrumented_bptr
&>(ptr
).get_raw(),
330 static_cast<instrumented_bptr
&>(original
).get_raw());
331 ASSERT_EQ(original
.offset(), ptr
.offset());
332 ASSERT_EQ(original
.length(), ptr
.length());
336 TEST(BufferPtr
, clone
) {
339 ::memset(ptr
.c_str(), 'X', len
);
340 bufferptr clone
= ptr
.clone();
341 EXPECT_EQ(0, ::memcmp(clone
.c_str(), ptr
.c_str(), len
));
344 TEST(BufferPtr
, swap
) {
348 ::memset(ptr1
.c_str(), 'X', len
);
349 unsigned ptr1_offset
= 4;
350 ptr1
.set_offset(ptr1_offset
);
351 unsigned ptr1_length
= 3;
352 ptr1
.set_length(ptr1_length
);
355 ::memset(ptr2
.c_str(), 'Y', len
);
356 unsigned ptr2_offset
= 5;
357 ptr2
.set_offset(ptr2_offset
);
358 unsigned ptr2_length
= 7;
359 ptr2
.set_length(ptr2_length
);
363 EXPECT_EQ(ptr2_length
, ptr1
.length());
364 EXPECT_EQ(ptr2_offset
, ptr1
.offset());
365 EXPECT_EQ('Y', ptr1
[0]);
367 EXPECT_EQ(ptr1_length
, ptr2
.length());
368 EXPECT_EQ(ptr1_offset
, ptr2
.offset());
369 EXPECT_EQ('X', ptr2
[0]);
372 TEST(BufferPtr
, release
) {
377 bufferptr
ptr2(ptr1
);
378 EXPECT_EQ(2, ptr1
.raw_nref());
380 EXPECT_EQ(1, ptr1
.raw_nref());
383 TEST(BufferPtr
, have_raw
) {
386 EXPECT_FALSE(ptr
.have_raw());
390 EXPECT_TRUE(ptr
.have_raw());
394 TEST(BufferPtr
, is_n_page_sized
) {
396 bufferptr
ptr(CEPH_PAGE_SIZE
);
397 EXPECT_TRUE(ptr
.is_n_page_sized());
401 EXPECT_FALSE(ptr
.is_n_page_sized());
405 TEST(BufferPtr
, is_partial
) {
407 EXPECT_FALSE(a
.is_partial());
409 EXPECT_FALSE(b
.is_partial());
410 bufferptr
c(b
, 1, 9);
411 EXPECT_TRUE(c
.is_partial());
412 bufferptr
d(b
, 0, 9);
413 EXPECT_TRUE(d
.is_partial());
416 TEST(BufferPtr
, accessors
) {
419 ptr
.c_str()[0] = 'X';
421 const bufferptr
const_ptr(ptr
);
423 EXPECT_NE((void*)nullptr, (void*)static_cast<instrumented_bptr
&>(ptr
).get_raw());
424 EXPECT_EQ('X', ptr
.c_str()[0]);
427 PrCtl unset_dumpable
;
428 EXPECT_DEATH(ptr
.c_str(), "");
429 EXPECT_DEATH(ptr
[0], "");
431 EXPECT_EQ('X', const_ptr
.c_str()[0]);
433 const bufferptr const_ptr
;
434 PrCtl unset_dumpable
;
435 EXPECT_DEATH(const_ptr
.c_str(), "");
436 EXPECT_DEATH(const_ptr
[0], "");
438 EXPECT_EQ(len
, const_ptr
.length());
439 EXPECT_EQ((unsigned)0, const_ptr
.offset());
440 EXPECT_EQ((unsigned)0, const_ptr
.start());
441 EXPECT_EQ(len
, const_ptr
.end());
442 EXPECT_EQ(len
, const_ptr
.end());
446 ptr
.set_length(ptr
.length() - unused
);
447 EXPECT_EQ(unused
, ptr
.unused_tail_length());
451 EXPECT_EQ((unsigned)0, ptr
.unused_tail_length());
454 PrCtl unset_dumpable
;
455 EXPECT_DEATH(ptr
[len
], "");
456 EXPECT_DEATH(const_ptr
[len
], "");
459 const bufferptr const_ptr
;
460 PrCtl unset_dumpable
;
461 EXPECT_DEATH(const_ptr
.raw_c_str(), "");
462 EXPECT_DEATH(const_ptr
.raw_length(), "");
463 EXPECT_DEATH(const_ptr
.raw_nref(), "");
465 EXPECT_NE((const char *)NULL
, const_ptr
.raw_c_str());
466 EXPECT_EQ(len
, const_ptr
.raw_length());
467 EXPECT_EQ(2, const_ptr
.raw_nref());
471 ptr
.set_length(ptr
.length() - wasted
* 2);
472 ptr
.set_offset(wasted
);
473 EXPECT_EQ(wasted
* 2, ptr
.wasted());
477 TEST(BufferPtr
, cmp
) {
480 bufferptr
ab("AB", 2);
481 bufferptr
af("AF", 2);
482 bufferptr
acc("ACC", 3);
483 EXPECT_GE(-1, empty
.cmp(a
));
484 EXPECT_LE(1, a
.cmp(empty
));
485 EXPECT_GE(-1, a
.cmp(ab
));
486 EXPECT_LE(1, ab
.cmp(a
));
487 EXPECT_EQ(0, ab
.cmp(ab
));
488 EXPECT_GE(-1, ab
.cmp(af
));
489 EXPECT_LE(1, af
.cmp(ab
));
490 EXPECT_GE(-1, acc
.cmp(af
));
491 EXPECT_LE(1, af
.cmp(acc
));
494 TEST(BufferPtr
, is_zero
) {
495 char str
[2] = { '\0', 'X' };
497 const bufferptr
ptr(buffer::create_static(2, str
));
498 EXPECT_FALSE(ptr
.is_zero());
501 const bufferptr
ptr(buffer::create_static(1, str
));
502 EXPECT_TRUE(ptr
.is_zero());
506 TEST(BufferPtr
, copy_out
) {
509 PrCtl unset_dumpable
;
510 EXPECT_DEATH(ptr
.copy_out((unsigned)0, (unsigned)0, NULL
), "");
514 const bufferptr
ptr(buffer::create_static(strlen(in
), in
));
515 EXPECT_THROW(ptr
.copy_out((unsigned)0, strlen(in
) + 1, NULL
), buffer::end_of_buffer
);
516 EXPECT_THROW(ptr
.copy_out(strlen(in
) + 1, (unsigned)0, NULL
), buffer::end_of_buffer
);
517 char out
[1] = { 'X' };
518 ptr
.copy_out((unsigned)1, (unsigned)1, out
);
519 EXPECT_EQ('B', out
[0]);
523 TEST(BufferPtr
, copy_out_bench
) {
524 for (int s
=1; s
<=8; s
*=2) {
525 utime_t start
= ceph_clock_now();
526 int buflen
= 1048576;
529 for (int i
=0; i
<count
; ++i
) {
530 bufferptr
bp(buflen
);
531 for (int64_t j
=0; j
<buflen
; j
+= s
) {
532 bp
.copy_out(j
, s
, (char *)&v
);
535 utime_t end
= ceph_clock_now();
536 cout
<< count
<< " fills of buffer len " << buflen
537 << " with " << s
<< " byte copy_out in"
538 << (end
- start
) << std::endl
;
542 TEST(BufferPtr
, copy_in
) {
545 PrCtl unset_dumpable
;
546 EXPECT_DEATH(ptr
.copy_in((unsigned)0, (unsigned)0, NULL
), "");
552 PrCtl unset_dumpable
;
553 EXPECT_DEATH(ptr
.copy_in((unsigned)0, strlen(in
) + 1, NULL
), "");
554 EXPECT_DEATH(ptr
.copy_in(strlen(in
) + 1, (unsigned)0, NULL
), "");
556 ptr
.copy_in((unsigned)0, (unsigned)2, in
);
557 EXPECT_EQ(in
[0], ptr
[0]);
558 EXPECT_EQ(in
[1], ptr
[1]);
562 TEST(BufferPtr
, copy_in_bench
) {
563 for (int s
=1; s
<=8; s
*=2) {
564 utime_t start
= ceph_clock_now();
565 int buflen
= 1048576;
567 for (int i
=0; i
<count
; ++i
) {
568 bufferptr
bp(buflen
);
569 for (int64_t j
=0; j
<buflen
; j
+= s
) {
570 bp
.copy_in(j
, s
, (char *)&j
, false);
573 utime_t end
= ceph_clock_now();
574 cout
<< count
<< " fills of buffer len " << buflen
575 << " with " << s
<< " byte copy_in in "
576 << (end
- start
) << std::endl
;
580 TEST(BufferPtr
, append
) {
583 PrCtl unset_dumpable
;
584 EXPECT_DEATH(ptr
.append('A'), "");
585 EXPECT_DEATH(ptr
.append("B", (unsigned)1), "");
590 PrCtl unset_dumpable
;
591 EXPECT_DEATH(ptr
.append('A'), "");
592 EXPECT_DEATH(ptr
.append("B", (unsigned)1), "");
596 EXPECT_EQ((unsigned)1, ptr
.length());
597 EXPECT_EQ('A', ptr
[0]);
598 ptr
.append("B", (unsigned)1);
599 EXPECT_EQ((unsigned)2, ptr
.length());
600 EXPECT_EQ('B', ptr
[1]);
604 TEST(BufferPtr
, append_bench
) {
606 memset(src
, 0, sizeof(src
));
607 for (int s
=4; s
<=16384; s
*=4) {
608 utime_t start
= ceph_clock_now();
609 int buflen
= 1048576;
611 for (int i
=0; i
<count
; ++i
) {
612 bufferptr
bp(buflen
);
614 for (int64_t j
=0; j
<buflen
; j
+= s
) {
615 bp
.append(src
+ j
, s
);
618 utime_t end
= ceph_clock_now();
619 cout
<< count
<< " fills of buffer len " << buflen
620 << " with " << s
<< " byte appends in "
621 << (end
- start
) << std::endl
;
625 TEST(BufferPtr
, zero
) {
627 bufferptr
ptr(buffer::create_static(strlen(str
), str
));
629 PrCtl unset_dumpable
;
630 EXPECT_DEATH(ptr
.zero(ptr
.length() + 1, 0), "");
633 EXPECT_EQ('X', ptr
[0]);
634 EXPECT_EQ('\0', ptr
[1]);
635 EXPECT_EQ('X', ptr
[2]);
637 EXPECT_EQ('\0', ptr
[0]);
640 TEST(BufferPtr
, ostream
) {
643 std::ostringstream stream
;
645 EXPECT_GT(stream
.str().size(), stream
.str().find("buffer:ptr(0~0 no raw"));
649 bufferptr
ptr(buffer::create_static(strlen(str
), str
));
650 std::ostringstream stream
;
652 EXPECT_GT(stream
.str().size(), stream
.str().find("len 4 nref 1)"));
660 // +----------+ +-----+ | | | |
661 // | append_ >-------> >--------------------> | |
662 // | buffer | +-----+ | | | |
663 // +----------+ ptr | | | |
664 // | _len | list +-----+ | | | |
665 // +----------+ +------+ ,--->+ >-----> | |
666 // | _buffers >----> >----- +-----+ | +-----+ |
667 // +----------+ +----^-+ \ ptr | raw |
668 // | last_p | / `-->+-----+ | +-----+ |
669 // +--------+-+ / + >-----> | |
670 // | ,- ,--->+-----+ | | | |
673 // +-v--+-^--+--^+-------+ | | | |
674 // | bl | ls | p | p_off >--------------->| | |
675 // +----+----+-----+-----+ | +-----+ |
676 // | | off >------------->| raw |
677 // +---------------+-----+ | |
678 // iterator +---------+
680 TEST(BufferListIterator
, constructors
) {
685 buffer::list::iterator i
;
686 EXPECT_EQ((unsigned)0, i
.get_off());
690 // iterator(list *l, unsigned o=0)
697 bufferlist::iterator
i(&bl
);
698 EXPECT_EQ((unsigned)0, i
.get_off());
702 bufferlist::iterator
i(&bl
, 1);
704 EXPECT_EQ((unsigned)2, i
.get_remaining());
709 // iterator(list *l, unsigned o, std::list<ptr>::iterator ip, unsigned po)
710 // not tested because of http://tracker.ceph.com/issues/4101
713 // iterator(const iterator& other)
718 bufferlist::iterator
i(&bl
, 1);
719 bufferlist::iterator
j(i
);
729 // const_iterator(const iterator& other)
734 bufferlist::iterator
i(&bl
);
735 bufferlist::const_iterator
ci(i
);
736 EXPECT_EQ(0u, ci
.get_off());
741 TEST(BufferListIterator
, empty_create_append_copy
) {
742 bufferlist bl
, bl2
, bl3
, out
;
748 bl
.begin().copy(6, out
);
749 ASSERT_TRUE(out
.contents_equal(bl
));
752 TEST(BufferListIterator
, operator_assign
) {
755 bufferlist::iterator
i(&bl
, 1);
757 #pragma clang diagnostic push
758 #pragma clang diagnostic ignored "-Wself-assign-overloaded"
760 #pragma clang diagnostic pop
762 bufferlist::iterator j
;
767 TEST(BufferListIterator
, get_off
) {
770 bufferlist::iterator
i(&bl
, 1);
771 EXPECT_EQ((unsigned)1, i
.get_off());
774 TEST(BufferListIterator
, get_remaining
) {
777 bufferlist::iterator
i(&bl
, 1);
778 EXPECT_EQ((unsigned)2, i
.get_remaining());
781 TEST(BufferListIterator
, end
) {
784 bufferlist::iterator
i(&bl
);
785 EXPECT_TRUE(i
.end());
789 bufferlist::iterator
i(&bl
);
790 EXPECT_FALSE(i
.end());
794 static void bench_bufferlistiter_deref(const size_t step
,
795 const size_t bufsize
,
796 const size_t bufnum
) {
797 const std::string
buf('a', bufsize
);
800 for (size_t i
= 0; i
< bufnum
; i
++) {
801 bl
.append(ceph::bufferptr(buf
.c_str(), buf
.size()));
804 utime_t start
= ceph_clock_now();
805 bufferlist::iterator iter
= bl
.begin();
806 while (iter
!= bl
.end()) {
809 utime_t end
= ceph_clock_now();
810 cout
<< bufsize
* bufnum
<< " derefs over bl with " << bufnum
811 << " buffers, each " << bufsize
<< " bytes long"
812 << " in " << (end
- start
) << std::endl
;
815 TEST(BufferListIterator
, BenchDeref
) {
816 bench_bufferlistiter_deref(1, 1, 4096000);
817 bench_bufferlistiter_deref(1, 10, 409600);
818 bench_bufferlistiter_deref(1, 100, 40960);
819 bench_bufferlistiter_deref(1, 1000, 4096);
821 bench_bufferlistiter_deref(4, 1, 1024000);
822 bench_bufferlistiter_deref(4, 10, 102400);
823 bench_bufferlistiter_deref(4, 100, 10240);
824 bench_bufferlistiter_deref(4, 1000, 1024);
827 TEST(BufferListIterator
, advance
) {
829 const std::string
one("ABC");
830 bl
.append(bufferptr(one
.c_str(), one
.size()));
831 const std::string
two("DEF");
832 bl
.append(bufferptr(two
.c_str(), two
.size()));
835 bufferlist::iterator
i(&bl
);
836 EXPECT_THROW(i
+= 200u, buffer::end_of_buffer
);
839 bufferlist::iterator
i(&bl
);
848 TEST(BufferListIterator
, iterate_with_empties
) {
850 EXPECT_EQ(bl
.get_num_buffers(), 0u);
852 bl
.push_back(ceph::buffer::create(0));
853 EXPECT_EQ(bl
.length(), 0u);
854 EXPECT_EQ(bl
.get_num_buffers(), 1u);
856 encode(int64_t(42), bl
);
857 EXPECT_EQ(bl
.get_num_buffers(), 2u);
859 bl
.push_back(ceph::buffer::create(0));
860 EXPECT_EQ(bl
.get_num_buffers(), 3u);
862 // append bufferlist with single, 0-sized ptr inside
864 ceph::bufferlist bl_with_empty_ptr
;
865 bl_with_empty_ptr
.push_back(ceph::buffer::create(0));
866 EXPECT_EQ(bl_with_empty_ptr
.length(), 0u);
867 EXPECT_EQ(bl_with_empty_ptr
.get_num_buffers(), 1u);
869 bl
.append(bl_with_empty_ptr
);
872 encode(int64_t(24), bl
);
873 EXPECT_EQ(bl
.get_num_buffers(), 5u);
875 auto i
= bl
.cbegin();
887 EXPECT_TRUE(i
== bl
.end());
892 EXPECT_FALSE(i
== bl
.end());
895 TEST(BufferListIterator
, get_ptr_and_advance
)
897 bufferptr
a("one", 3);
898 bufferptr
b("two", 3);
899 bufferptr
c("three", 5);
905 bufferlist::iterator p
= bl
.begin();
906 ASSERT_EQ(3u, p
.get_ptr_and_advance(11u, &ptr
));
907 ASSERT_EQ(bl
.length() - 3u, p
.get_remaining());
908 ASSERT_EQ(0, memcmp(ptr
, "one", 3));
909 ASSERT_EQ(2u, p
.get_ptr_and_advance(2u, &ptr
));
910 ASSERT_EQ(0, memcmp(ptr
, "tw", 2));
911 ASSERT_EQ(1u, p
.get_ptr_and_advance(4u, &ptr
));
912 ASSERT_EQ(0, memcmp(ptr
, "o", 1));
913 ASSERT_EQ(5u, p
.get_ptr_and_advance(5u, &ptr
));
914 ASSERT_EQ(0, memcmp(ptr
, "three", 5));
915 ASSERT_EQ(0u, p
.get_remaining());
918 TEST(BufferListIterator
, iterator_crc32c
) {
933 bufferlist::iterator it
= bl2
.begin();
934 ASSERT_EQ(bl1
.crc32c(0), it
.crc32c(it
.get_remaining(), 0));
935 ASSERT_EQ(0u, it
.get_remaining());
938 ASSERT_EQ(bl2
.crc32c(0), it
.crc32c(it
.get_remaining(), 0));
940 bl3
.append(s
.substr(98, 55));
943 ASSERT_EQ(bl3
.crc32c(0), it
.crc32c(55, 0));
944 ASSERT_EQ(4u, it
.get_remaining());
947 bl3
.append(s
.substr(98 + 55));
950 ASSERT_EQ(bl3
.crc32c(0), it
.crc32c(10, 0));
951 ASSERT_EQ(0u, it
.get_remaining());
954 TEST(BufferListIterator
, seek
) {
957 bufferlist::iterator
i(&bl
, 1);
963 TEST(BufferListIterator
, operator_star
) {
966 bufferlist::iterator
i(&bl
);
967 EXPECT_THROW(*i
, buffer::end_of_buffer
);
971 bufferlist::iterator
i(&bl
);
973 EXPECT_THROW(i
+= 200u, buffer::end_of_buffer
);
974 EXPECT_THROW(*i
, buffer::end_of_buffer
);
978 TEST(BufferListIterator
, operator_equal
) {
982 bufferlist::iterator
i(&bl
);
983 bufferlist::iterator
j(&bl
);
987 bufferlist::const_iterator ci
= bl
.begin();
988 bufferlist::iterator i
= bl
.begin();
994 TEST(BufferListIterator
, operator_nequal
) {
998 bufferlist::iterator
i(&bl
);
999 bufferlist::iterator
j(&bl
);
1003 bufferlist::const_iterator ci
= bl
.begin();
1004 bufferlist::const_iterator cj
= bl
.begin();
1007 bufferlist::iterator i
= bl
.begin();
1012 // tests begin(), end(), operator++() also
1016 EXPECT_EQ(s
[i
++], c
);
1021 TEST(BufferListIterator
, operator_plus_plus
) {
1024 bufferlist::iterator
i(&bl
);
1025 EXPECT_THROW(++i
, buffer::end_of_buffer
);
1027 bl
.append("ABC", 3);
1029 bufferlist::iterator
i(&bl
);
1035 TEST(BufferListIterator
, get_current_ptr
) {
1038 bufferlist::iterator
i(&bl
);
1039 EXPECT_THROW(++i
, buffer::end_of_buffer
);
1041 bl
.append("ABC", 3);
1043 bufferlist::iterator
i(&bl
, 1);
1044 const buffer::ptr ptr
= i
.get_current_ptr();
1045 EXPECT_EQ('B', ptr
[0]);
1046 EXPECT_EQ((unsigned)1, ptr
.offset());
1047 EXPECT_EQ((unsigned)2, ptr
.length());
1051 TEST(BufferListIterator
, copy
) {
1053 const char *expected
= "ABC";
1054 bl
.append(expected
, 3);
1056 // void copy(unsigned len, char *dest);
1059 char* copy
= (char*)malloc(3);
1060 ::memset(copy
, 'X', 3);
1061 bufferlist::iterator
i(&bl
);
1063 // demonstrates that it seeks back to offset if p == ls->end()
1065 EXPECT_THROW(i
+= 200u, buffer::end_of_buffer
);
1067 EXPECT_EQ(0, ::memcmp(copy
, expected
, 2));
1068 EXPECT_EQ('X', copy
[2]);
1071 EXPECT_EQ(0, ::memcmp(copy
, expected
, 3));
1075 // void copy(unsigned len, char *dest) via begin(size_t offset)
1079 EXPECT_THROW(bl
.begin((unsigned)100).copy((unsigned)100, (char*)0), buffer::end_of_buffer
);
1080 const char *expected
= "ABC";
1081 bl
.append(expected
);
1082 char *dest
= new char[2];
1083 bl
.begin(1).copy(2, dest
);
1084 EXPECT_EQ(0, ::memcmp(expected
+ 1, dest
, 2));
1088 // void buffer::list::iterator::copy_deep(unsigned len, ptr &dest)
1092 bufferlist::iterator
i(&bl
);
1093 i
.copy_deep(2, ptr
);
1094 EXPECT_EQ((unsigned)2, ptr
.length());
1095 EXPECT_EQ('A', ptr
[0]);
1096 EXPECT_EQ('B', ptr
[1]);
1099 // void buffer::list::iterator::copy_shallow(unsigned len, ptr &dest)
1103 bufferlist::iterator
i(&bl
);
1104 i
.copy_shallow(2, ptr
);
1105 EXPECT_EQ((unsigned)2, ptr
.length());
1106 EXPECT_EQ('A', ptr
[0]);
1107 EXPECT_EQ('B', ptr
[1]);
1110 // void buffer::list::iterator::copy(unsigned len, list &dest)
1114 bufferlist::iterator
i(&bl
);
1116 // demonstrates that it seeks back to offset if p == ls->end()
1118 EXPECT_THROW(i
+= 200u, buffer::end_of_buffer
);
1120 EXPECT_EQ(0, ::memcmp(copy
.c_str(), expected
, 2));
1123 EXPECT_EQ('A', copy
[0]);
1124 EXPECT_EQ('B', copy
[1]);
1125 EXPECT_EQ('A', copy
[2]);
1126 EXPECT_EQ('B', copy
[3]);
1127 EXPECT_EQ('C', copy
[4]);
1128 EXPECT_EQ((unsigned)(2 + 3), copy
.length());
1131 // void buffer::list::iterator::copy(unsigned len, list &dest) via begin(size_t offset)
1136 EXPECT_THROW(bl
.begin((unsigned)100).copy((unsigned)100, dest
), buffer::end_of_buffer
);
1137 const char *expected
= "ABC";
1138 bl
.append(expected
);
1139 bl
.begin(1).copy(2, dest
);
1140 EXPECT_EQ(0, ::memcmp(expected
+ 1, dest
.c_str(), 2));
1143 // void buffer::list::iterator::copy_all(list &dest)
1147 bufferlist::iterator
i(&bl
);
1149 // demonstrates that it seeks back to offset if p == ls->end()
1151 EXPECT_THROW(i
+= 200u, buffer::end_of_buffer
);
1153 EXPECT_EQ('A', copy
[0]);
1154 EXPECT_EQ('B', copy
[1]);
1155 EXPECT_EQ('C', copy
[2]);
1156 EXPECT_EQ((unsigned)3, copy
.length());
1159 // void copy(unsigned len, std::string &dest)
1163 bufferlist::iterator
i(&bl
);
1165 // demonstrates that it seeks back to offset if p == ls->end()
1167 EXPECT_THROW(i
+= 200u, buffer::end_of_buffer
);
1169 EXPECT_EQ(0, ::memcmp(copy
.c_str(), expected
, 2));
1172 EXPECT_EQ('A', copy
[0]);
1173 EXPECT_EQ('B', copy
[1]);
1174 EXPECT_EQ('A', copy
[2]);
1175 EXPECT_EQ('B', copy
[3]);
1176 EXPECT_EQ('C', copy
[4]);
1177 EXPECT_EQ((unsigned)(2 + 3), copy
.length());
1180 // void copy(unsigned len, std::string &dest) via begin(size_t offset)
1185 EXPECT_THROW(bl
.begin((unsigned)100).copy((unsigned)100, dest
), buffer::end_of_buffer
);
1186 const char *expected
= "ABC";
1187 bl
.append(expected
);
1188 bl
.begin(1).copy(2, dest
);
1189 EXPECT_EQ(0, ::memcmp(expected
+ 1, dest
.c_str(), 2));
1193 TEST(BufferListIterator
, copy_in
) {
1195 const char *existing
= "XXX";
1196 bl
.append(existing
, 3);
1198 // void buffer::list::iterator::copy_in(unsigned len, const char *src)
1201 bufferlist::iterator
i(&bl
);
1203 // demonstrates that it seeks back to offset if p == ls->end()
1205 EXPECT_THROW(i
+= 200u, buffer::end_of_buffer
);
1206 const char *expected
= "ABC";
1207 i
.copy_in(3, expected
);
1208 EXPECT_EQ(0, ::memcmp(bl
.c_str(), expected
, 3));
1209 EXPECT_EQ('A', bl
[0]);
1210 EXPECT_EQ('B', bl
[1]);
1211 EXPECT_EQ('C', bl
[2]);
1212 EXPECT_EQ((unsigned)3, bl
.length());
1215 // void copy_in(unsigned len, const char *src) via begin(size_t offset)
1220 EXPECT_THROW(bl
.begin((unsigned)100).copy_in((unsigned)100, (char*)0), buffer::end_of_buffer
);
1221 bl
.begin(1).copy_in(2, "AB");
1222 EXPECT_EQ(0, ::memcmp("XAB", bl
.c_str(), 3));
1225 // void buffer::list::iterator::copy_in(unsigned len, const list& otherl)
1228 bufferlist::iterator
i(&bl
);
1230 // demonstrates that it seeks back to offset if p == ls->end()
1232 EXPECT_THROW(i
+= 200u, buffer::end_of_buffer
);
1233 bufferlist expected
;
1234 expected
.append("ABC", 3);
1235 i
.copy_in(3, expected
);
1236 EXPECT_EQ(0, ::memcmp(bl
.c_str(), expected
.c_str(), 3));
1237 EXPECT_EQ('A', bl
[0]);
1238 EXPECT_EQ('B', bl
[1]);
1239 EXPECT_EQ('C', bl
[2]);
1240 EXPECT_EQ((unsigned)3, bl
.length());
1243 // void copy_in(unsigned len, const list& src) via begin(size_t offset)
1250 EXPECT_THROW(bl
.begin((unsigned)100).copy_in((unsigned)100, src
), buffer::end_of_buffer
);
1251 bl
.begin(1).copy_in(2, src
);
1252 EXPECT_EQ(0, ::memcmp("XAB", bl
.c_str(), 3));
1256 // iterator& buffer::list::const_iterator::operator++()
1257 TEST(BufferListConstIterator
, operator_plus_plus
) {
1260 bufferlist::const_iterator
i(&bl
);
1261 EXPECT_THROW(++i
, buffer::end_of_buffer
);
1263 bl
.append("ABC", 3);
1265 const bufferlist
const_bl(bl
);
1266 bufferlist::const_iterator
i(const_bl
.begin());
1273 TEST(BufferList
, constructors
) {
1279 ASSERT_EQ((unsigned)0, bl
.length());
1282 // list(unsigned prealloc)
1286 ASSERT_EQ((unsigned)0, bl
.length());
1288 ASSERT_EQ('A', bl
[0]);
1291 // list(const list& other)
1296 ASSERT_EQ('A', bl
[0]);
1297 bufferlist
copy(bl
);
1298 ASSERT_EQ('A', copy
[0]);
1301 // list(list&& other)
1306 bufferlist copy
= std::move(bl
);
1307 ASSERT_EQ(0U, bl
.length());
1308 ASSERT_EQ(1U, copy
.length());
1309 ASSERT_EQ('A', copy
[0]);
1313 TEST(BufferList
, append_after_move
) {
1315 bl
.append("ABC", 3);
1316 EXPECT_EQ(1, bl
.get_num_buffers());
1318 bufferlist
moved_to_bl(std::move(bl
));
1319 moved_to_bl
.append("123", 3);
1320 // it's expected that the list(list&&) ctor will preserve the _carriage
1321 EXPECT_EQ(1, moved_to_bl
.get_num_buffers());
1322 EXPECT_EQ(0, ::memcmp("ABC123", moved_to_bl
.c_str(), 6));
1325 void bench_bufferlist_alloc(int size
, int num
, int per
)
1327 utime_t start
= ceph_clock_now();
1328 for (int i
=0; i
<num
; ++i
) {
1330 for (int j
=0; j
<per
; ++j
)
1331 bl
.push_back(buffer::ptr_node::create(buffer::create(size
)));
1333 utime_t end
= ceph_clock_now();
1334 cout
<< num
<< " alloc of size " << size
1335 << " in " << (end
- start
) << std::endl
;
1338 TEST(BufferList
, BenchAlloc
) {
1339 bench_bufferlist_alloc(32768, 100000, 16);
1340 bench_bufferlist_alloc(25000, 100000, 16);
1341 bench_bufferlist_alloc(16384, 100000, 16);
1342 bench_bufferlist_alloc(10000, 100000, 16);
1343 bench_bufferlist_alloc(8192, 100000, 16);
1344 bench_bufferlist_alloc(6000, 100000, 16);
1345 bench_bufferlist_alloc(4096, 100000, 16);
1346 bench_bufferlist_alloc(1024, 100000, 16);
1347 bench_bufferlist_alloc(256, 100000, 16);
1348 bench_bufferlist_alloc(32, 100000, 16);
1349 bench_bufferlist_alloc(4, 100000, 16);
1352 TEST(BufferList
, append_bench_with_size_hint
) {
1353 std::array
<char, 1048576> src
= { 0, };
1355 for (size_t step
= 4; step
<= 16384; step
*= 4) {
1356 const utime_t start
= ceph_clock_now();
1358 constexpr size_t rounds
= 4000;
1359 for (size_t r
= 0; r
< rounds
; ++r
) {
1360 ceph::bufferlist
bl(std::size(src
));
1361 for (auto iter
= std::begin(src
);
1362 iter
!= std::end(src
);
1363 iter
= std::next(iter
, step
)) {
1364 bl
.append(&*iter
, step
);
1367 cout
<< rounds
<< " fills of buffer len " << src
.size()
1368 << " with " << step
<< " byte appends in "
1369 << (ceph_clock_now() - start
) << std::endl
;
1373 TEST(BufferList
, append_bench
) {
1374 std::array
<char, 1048576> src
= { 0, };
1376 for (size_t step
= 4; step
<= 16384; step
*= 4) {
1377 const utime_t start
= ceph_clock_now();
1379 constexpr size_t rounds
= 4000;
1380 for (size_t r
= 0; r
< rounds
; ++r
) {
1381 ceph::bufferlist bl
;
1382 for (auto iter
= std::begin(src
);
1383 iter
!= std::end(src
);
1384 iter
= std::next(iter
, step
)) {
1385 bl
.append(&*iter
, step
);
1388 cout
<< rounds
<< " fills of buffer len " << src
.size()
1389 << " with " << step
<< " byte appends in "
1390 << (ceph_clock_now() - start
) << std::endl
;
1394 TEST(BufferList
, operator_equal
) {
1396 // list& operator= (const list& other)
1399 bl
.append("ABC", 3);
1402 bl
.begin(1).copy(1, dest
);
1403 ASSERT_EQ('B', dest
[0]);
1406 bufferlist copy
= bl
;
1408 copy
.begin(1).copy(1, dest
);
1409 ASSERT_EQ('B', dest
[0]);
1413 // list& operator= (list&& other)
1415 bufferlist move
= std::move(bl
);
1418 move
.begin(1).copy(1, dest
);
1419 ASSERT_EQ('B', dest
[0]);
1421 EXPECT_TRUE(move
.length());
1422 EXPECT_TRUE(!bl
.length());
1425 TEST(BufferList
, buffers
) {
1427 ASSERT_EQ((unsigned)0, bl
.get_num_buffers());
1429 ASSERT_EQ((unsigned)1, bl
.get_num_buffers());
1432 TEST(BufferList
, to_str
) {
1436 ASSERT_EQ(bl
.to_str(), string("foo"));
1439 bufferptr
a("foobarbaz", 9);
1440 bufferptr
b("123456789", 9);
1441 bufferptr
c("ABCDEFGHI", 9);
1446 ASSERT_EQ(bl
.to_str(), string("foobarbaz123456789ABCDEFGHI"));
1450 TEST(BufferList
, swap
) {
1460 b1
.begin().copy(1, s1
);
1461 ASSERT_EQ('B', s1
[0]);
1464 b2
.begin().copy(1, s2
);
1465 ASSERT_EQ('A', s2
[0]);
1468 TEST(BufferList
, length
) {
1470 ASSERT_EQ((unsigned)0, bl
.length());
1472 ASSERT_EQ((unsigned)1, bl
.length());
1475 TEST(BufferList
, contents_equal
) {
1484 ASSERT_FALSE(bl1
.contents_equal(bl2
)); // different length
1487 ASSERT_TRUE(bl1
.contents_equal(bl2
)); // same length same content
1493 ASSERT_FALSE(bl1
.contents_equal(bl3
)); // same length different content
1496 TEST(BufferList
, is_aligned
) {
1497 const int SIMD_ALIGN
= 32;
1500 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1504 bufferptr
ptr(buffer::create_aligned(2, SIMD_ALIGN
));
1508 EXPECT_FALSE(bl
.is_aligned(SIMD_ALIGN
));
1509 bl
.rebuild_aligned(SIMD_ALIGN
);
1510 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1514 bufferptr
ptr(buffer::create_aligned(SIMD_ALIGN
+ 1, SIMD_ALIGN
));
1516 ptr
.set_length(SIMD_ALIGN
);
1518 EXPECT_FALSE(bl
.is_aligned(SIMD_ALIGN
));
1519 bl
.rebuild_aligned(SIMD_ALIGN
);
1520 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1524 TEST(BufferList
, is_n_align_sized
) {
1525 const int SIMD_ALIGN
= 32;
1528 EXPECT_TRUE(bl
.is_n_align_sized(SIMD_ALIGN
));
1533 EXPECT_FALSE(bl
.is_n_align_sized(SIMD_ALIGN
));
1537 bl
.append_zero(SIMD_ALIGN
);
1538 EXPECT_TRUE(bl
.is_n_align_sized(SIMD_ALIGN
));
1542 TEST(BufferList
, is_page_aligned
) {
1545 EXPECT_TRUE(bl
.is_page_aligned());
1549 bufferptr
ptr(buffer::create_page_aligned(2));
1553 EXPECT_FALSE(bl
.is_page_aligned());
1554 bl
.rebuild_page_aligned();
1555 EXPECT_TRUE(bl
.is_page_aligned());
1559 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1561 ptr
.set_length(CEPH_PAGE_SIZE
);
1563 EXPECT_FALSE(bl
.is_page_aligned());
1564 bl
.rebuild_page_aligned();
1565 EXPECT_TRUE(bl
.is_page_aligned());
1569 TEST(BufferList
, is_n_page_sized
) {
1572 EXPECT_TRUE(bl
.is_n_page_sized());
1577 EXPECT_FALSE(bl
.is_n_page_sized());
1581 bl
.append_zero(CEPH_PAGE_SIZE
);
1582 EXPECT_TRUE(bl
.is_n_page_sized());
1586 TEST(BufferList
, page_aligned_appender
) {
1588 auto a
= bl
.get_page_aligned_appender(5);
1589 a
.append("asdf", 4);
1591 cout
<< bl
<< std::endl
;
1592 ASSERT_EQ(1u, bl
.get_num_buffers());
1593 a
.append("asdf", 4);
1594 for (unsigned n
= 0; n
< 3 * CEPH_PAGE_SIZE
; ++n
) {
1598 cout
<< bl
<< std::endl
;
1599 ASSERT_EQ(1u, bl
.get_num_buffers());
1600 for (unsigned n
= 0; n
< 3 * CEPH_PAGE_SIZE
; ++n
) {
1604 cout
<< bl
<< std::endl
;
1605 ASSERT_EQ(2u, bl
.get_num_buffers());
1606 for (unsigned n
= 0; n
< 10 * CEPH_PAGE_SIZE
; ++n
) {
1607 a
.append("asdfasdfasdf", 1);
1610 cout
<< bl
<< std::endl
;
1613 TEST(BufferList
, rebuild_aligned_size_and_memory
) {
1614 const unsigned SIMD_ALIGN
= 32;
1615 const unsigned BUFFER_SIZE
= 67;
1618 // These two must be concatenated into one memory + size aligned
1621 bufferptr
ptr(buffer::create_aligned(2, SIMD_ALIGN
));
1627 bufferptr
ptr(buffer::create_aligned(BUFFER_SIZE
- 1, SIMD_ALIGN
));
1630 // This one must be left alone
1632 bufferptr
ptr(buffer::create_aligned(BUFFER_SIZE
, SIMD_ALIGN
));
1635 // These two must be concatenated into one memory + size aligned
1638 bufferptr
ptr(buffer::create_aligned(2, SIMD_ALIGN
));
1644 bufferptr
ptr(buffer::create_aligned(BUFFER_SIZE
- 1, SIMD_ALIGN
));
1647 EXPECT_FALSE(bl
.is_aligned(SIMD_ALIGN
));
1648 EXPECT_FALSE(bl
.is_n_align_sized(BUFFER_SIZE
));
1649 EXPECT_EQ(BUFFER_SIZE
* 3, bl
.length());
1650 EXPECT_FALSE(bl
.front().is_aligned(SIMD_ALIGN
));
1651 EXPECT_FALSE(bl
.front().is_n_align_sized(BUFFER_SIZE
));
1652 EXPECT_EQ(5U, bl
.get_num_buffers());
1653 bl
.rebuild_aligned_size_and_memory(BUFFER_SIZE
, SIMD_ALIGN
);
1654 EXPECT_TRUE(bl
.is_aligned(SIMD_ALIGN
));
1655 EXPECT_TRUE(bl
.is_n_align_sized(BUFFER_SIZE
));
1656 EXPECT_EQ(3U, bl
.get_num_buffers());
1659 TEST(BufferList
, is_zero
) {
1662 EXPECT_TRUE(bl
.is_zero());
1667 EXPECT_FALSE(bl
.is_zero());
1672 EXPECT_TRUE(bl
.is_zero());
1675 for (size_t i
= 1; i
<= 256; ++i
) {
1678 EXPECT_TRUE(bl
.is_zero());
1680 // ensure buffer is a single, contiguous before testing
1682 EXPECT_FALSE(bl
.is_zero());
1687 TEST(BufferList
, clear
) {
1690 bl
.append_zero(len
);
1692 EXPECT_EQ((unsigned)0, bl
.length());
1693 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1696 TEST(BufferList
, push_back
) {
1698 // void push_back(ptr& bp)
1704 EXPECT_EQ((unsigned)0, bl
.length());
1705 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1712 ptr
.c_str()[0] = 'B';
1714 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1715 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1716 EXPECT_EQ('B', bl
.back()[0]);
1717 const bufferptr
& back_bp
= bl
.back();
1718 EXPECT_EQ(static_cast<instrumented_bptr
&>(ptr
).get_raw(),
1719 static_cast<const instrumented_bptr
&>(back_bp
).get_raw());
1722 // void push_back(ptr&& bp)
1727 bl
.push_back(std::move(ptr
));
1728 EXPECT_EQ((unsigned)0, bl
.length());
1729 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1735 ptr
.c_str()[0] = 'B';
1736 bl
.push_back(std::move(ptr
));
1737 EXPECT_EQ((unsigned)(1 + len
), bl
.length());
1738 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1739 EXPECT_EQ('B', bl
.buffers().back()[0]);
1740 EXPECT_FALSE(static_cast<instrumented_bptr
&>(ptr
).get_raw());
1744 TEST(BufferList
, is_contiguous
) {
1746 EXPECT_TRUE(bl
.is_contiguous());
1747 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1749 EXPECT_TRUE(bl
.is_contiguous());
1750 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1753 EXPECT_FALSE(bl
.is_contiguous());
1754 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1757 TEST(BufferList
, rebuild
) {
1760 bufferptr
ptr(buffer::create_page_aligned(2));
1766 EXPECT_FALSE(bl
.is_page_aligned());
1768 EXPECT_EQ(1U, bl
.length());
1769 EXPECT_EQ('Y', *bl
.begin());
1773 const std::string
str(CEPH_PAGE_SIZE
, 'X');
1774 bl
.append(str
.c_str(), str
.size());
1775 bl
.append(str
.c_str(), str
.size());
1776 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1777 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
1779 EXPECT_TRUE(bl
.is_page_aligned());
1780 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1789 EXPECT_EQ((unsigned)1, bl
.length());
1790 bufferlist::iterator p
= bl
.begin();
1793 EXPECT_EQ(0, memcmp(dst
, "X", 1));
1797 TEST(BufferList
, rebuild_page_aligned
) {
1801 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1803 ptr
.set_length(CEPH_PAGE_SIZE
);
1806 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1807 EXPECT_FALSE(bl
.is_page_aligned());
1808 bl
.rebuild_page_aligned();
1809 EXPECT_TRUE(bl
.is_page_aligned());
1810 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1814 bufferptr
ptr(buffer::create_page_aligned(1));
1815 char *p
= ptr
.c_str();
1817 bl
.rebuild_page_aligned();
1818 EXPECT_EQ(p
, bl
.front().c_str());
1823 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
));
1824 EXPECT_TRUE(ptr
.is_page_aligned());
1825 EXPECT_TRUE(ptr
.is_n_page_sized());
1829 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1830 EXPECT_TRUE(ptr
.is_page_aligned());
1831 EXPECT_FALSE(ptr
.is_n_page_sized());
1835 bufferptr
ptr(buffer::create_page_aligned(2));
1838 EXPECT_FALSE(ptr
.is_page_aligned());
1839 EXPECT_FALSE(ptr
.is_n_page_sized());
1843 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
- 2));
1844 EXPECT_TRUE(ptr
.is_page_aligned());
1845 EXPECT_FALSE(ptr
.is_n_page_sized());
1849 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
));
1850 EXPECT_TRUE(ptr
.is_page_aligned());
1851 EXPECT_TRUE(ptr
.is_n_page_sized());
1855 bufferptr
ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE
+ 1));
1857 ptr
.set_length(CEPH_PAGE_SIZE
);
1858 EXPECT_FALSE(ptr
.is_page_aligned());
1859 EXPECT_TRUE(ptr
.is_n_page_sized());
1862 EXPECT_EQ((unsigned)6, bl
.get_num_buffers());
1863 EXPECT_TRUE((bl
.length() & ~CEPH_PAGE_MASK
) == 0);
1864 EXPECT_FALSE(bl
.is_page_aligned());
1865 bl
.rebuild_page_aligned();
1866 EXPECT_TRUE(bl
.is_page_aligned());
1867 EXPECT_EQ((unsigned)4, bl
.get_num_buffers());
1871 TEST(BufferList
, claim
) {
1882 EXPECT_EQ((unsigned)4, to
.length());
1883 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
1885 EXPECT_EQ((unsigned)2, to
.length());
1886 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
1887 EXPECT_EQ((unsigned)0, from
.get_num_buffers());
1888 EXPECT_EQ((unsigned)0, from
.length());
1891 TEST(BufferList
, claim_append
) {
1902 EXPECT_EQ((unsigned)4, to
.length());
1903 EXPECT_EQ((unsigned)1, to
.get_num_buffers());
1904 to
.claim_append(from
);
1905 EXPECT_EQ((unsigned)(4 + 2), to
.length());
1906 EXPECT_EQ((unsigned)4, to
.front().length());
1907 EXPECT_EQ((unsigned)2, to
.back().length());
1908 EXPECT_EQ((unsigned)2, to
.get_num_buffers());
1909 EXPECT_EQ((unsigned)0, from
.get_num_buffers());
1910 EXPECT_EQ((unsigned)0, from
.length());
1913 TEST(BufferList
, claim_append_piecewise
) {
1914 bufferlist bl
, t
, dst
;
1915 auto a
= bl
.get_page_aligned_appender(4);
1916 for (uint32_t i
= 0; i
< (CEPH_PAGE_SIZE
+ CEPH_PAGE_SIZE
- 1333); i
++)
1919 const char *p
= bl
.c_str();
1922 for (uint32_t i
= 0; i
< (CEPH_PAGE_SIZE
+ 1333); i
++)
1927 EXPECT_FALSE(t
.is_aligned_size_and_memory(CEPH_PAGE_SIZE
, CEPH_PAGE_SIZE
));
1928 dst
.claim_append_piecewise(t
);
1929 EXPECT_TRUE(dst
.is_aligned_size_and_memory(CEPH_PAGE_SIZE
, CEPH_PAGE_SIZE
));
1930 const char *p1
= dst
.c_str();
1931 EXPECT_TRUE(p
== p1
);
1934 TEST(BufferList
, begin
) {
1937 bufferlist::iterator i
= bl
.begin();
1941 TEST(BufferList
, end
) {
1944 bufferlist::iterator i
= bl
.end();
1946 EXPECT_EQ('C', bl
[i
.get_off()]);
1949 TEST(BufferList
, append
) {
1951 // void append(char c);
1955 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1957 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1958 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
1961 // void append(const char *data, unsigned len);
1964 bufferlist
bl(CEPH_PAGE_SIZE
);
1965 std::string
str(CEPH_PAGE_SIZE
* 2, 'X');
1966 bl
.append(str
.c_str(), str
.size());
1967 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1968 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.front().length());
1969 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.back().length());
1972 // void append(const std::string& s);
1975 bufferlist
bl(CEPH_PAGE_SIZE
);
1976 std::string
str(CEPH_PAGE_SIZE
* 2, 'X');
1978 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
1979 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.front().length());
1980 EXPECT_EQ(CEPH_PAGE_SIZE
, bl
.back().length());
1983 // void append(const ptr& bp);
1987 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1988 EXPECT_EQ((unsigned)0, bl
.length());
1992 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
1993 EXPECT_EQ((unsigned)0, bl
.length());
1998 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
1999 EXPECT_EQ((unsigned)3, bl
.length());
2003 // void append(const ptr& bp, unsigned off, unsigned len);
2008 bufferptr
back(bl
.back());
2010 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2011 EXPECT_EQ((unsigned)1, bl
.length());
2013 PrCtl unset_dumpable
;
2014 EXPECT_DEATH(bl
.append(in
, (unsigned)100, (unsigned)100), "");
2016 EXPECT_LT((unsigned)0, in
.unused_tail_length());
2018 bl
.append(in
, back
.end(), 1);
2019 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2020 EXPECT_EQ((unsigned)2, bl
.length());
2021 EXPECT_EQ('B', bl
[1]);
2025 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
2026 EXPECT_EQ((unsigned)0, bl
.length());
2029 ptr
.append("AB", 2);
2030 bl
.append(ptr
, 1, 1);
2031 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2032 EXPECT_EQ((unsigned)1, bl
.length());
2035 // void append(const list& bl);
2043 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2044 EXPECT_EQ('B', bl
[1]);
2047 // void append(std::istream& in);
2051 std::string
expected("ABC\nDEF\n");
2052 std::istringstream
is("ABC\n\nDEF");
2054 EXPECT_EQ(0, ::memcmp(expected
.c_str(), bl
.c_str(), expected
.size()));
2055 EXPECT_EQ(expected
.size(), bl
.length());
2058 // void append(ptr&& bp);
2062 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
2063 EXPECT_EQ((unsigned)0, bl
.length());
2066 bl
.append(std::move(ptr
));
2067 EXPECT_EQ((unsigned)0, bl
.get_num_buffers());
2068 EXPECT_EQ((unsigned)0, bl
.length());
2072 bl
.append(std::move(ptr
));
2073 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2074 EXPECT_EQ((unsigned)3, bl
.length());
2075 EXPECT_FALSE(static_cast<instrumented_bptr
&>(ptr
).get_raw());
2080 TEST(BufferList
, append_hole
) {
2083 auto filler
= bl
.append_hole(1);
2084 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2085 EXPECT_EQ((unsigned)1, bl
.length());
2088 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2089 EXPECT_EQ((unsigned)3, bl
.length());
2092 filler
.copy_in((unsigned)1, &a
);
2093 EXPECT_EQ((unsigned)3, bl
.length());
2095 EXPECT_EQ(0, ::memcmp("ABC", bl
.c_str(), 3));
2101 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2102 EXPECT_EQ((unsigned)1, bl
.length());
2104 auto filler
= bl
.append_hole(1);
2105 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2106 EXPECT_EQ((unsigned)2, bl
.length());
2109 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2110 EXPECT_EQ((unsigned)3, bl
.length());
2113 filler
.copy_in((unsigned)1, &b
);
2114 EXPECT_EQ((unsigned)3, bl
.length());
2116 EXPECT_EQ(0, ::memcmp("ABC", bl
.c_str(), 3));
2120 TEST(BufferList
, append_zero
) {
2123 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2124 EXPECT_EQ((unsigned)1, bl
.length());
2126 EXPECT_EQ((unsigned)1, bl
.get_num_buffers());
2127 EXPECT_EQ((unsigned)2, bl
.length());
2128 EXPECT_EQ('\0', bl
[1]);
2131 TEST(BufferList
, operator_brackets
) {
2133 EXPECT_THROW(bl
[1], buffer::end_of_buffer
);
2138 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2139 EXPECT_EQ('B', bl
[1]);
2142 TEST(BufferList
, c_str
) {
2144 EXPECT_EQ((const char*)NULL
, bl
.c_str());
2149 EXPECT_EQ((unsigned)2, bl
.get_num_buffers());
2150 EXPECT_EQ(0, ::memcmp("AB", bl
.c_str(), 2));
2153 TEST(BufferList
, substr_of
) {
2155 EXPECT_THROW(bl
.substr_of(bl
, 1, 1), buffer::end_of_buffer
);
2162 for (unsigned i
= 0; i
< 4; i
++) {
2163 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2166 EXPECT_EQ((unsigned)4, bl
.get_num_buffers());
2169 other
.append("TO BE CLEARED");
2170 other
.substr_of(bl
, 4, 4);
2171 EXPECT_EQ((unsigned)2, other
.get_num_buffers());
2172 EXPECT_EQ((unsigned)4, other
.length());
2173 EXPECT_EQ(0, ::memcmp("EFGH", other
.c_str(), 4));
2176 TEST(BufferList
, splice
) {
2178 EXPECT_THROW(bl
.splice(1, 1), buffer::end_of_buffer
);
2185 for (unsigned i
= 0; i
< 4; i
++) {
2186 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2189 EXPECT_EQ((unsigned)4, bl
.get_num_buffers());
2194 bl
.splice(4, 4, &other
);
2195 EXPECT_EQ((unsigned)3, other
.get_num_buffers());
2196 EXPECT_EQ((unsigned)5, other
.length());
2197 EXPECT_EQ(0, ::memcmp("XEFGH", other
.c_str(), other
.length()));
2198 EXPECT_EQ((unsigned)8, bl
.length());
2201 EXPECT_EQ(0, ::memcmp("ABCDIJKL", tmp
.c_str(), tmp
.length()));
2205 EXPECT_EQ((unsigned)4, bl
.length());
2206 EXPECT_EQ(0, ::memcmp("ABCD", bl
.c_str(), bl
.length()));
2210 bufferptr
ptr1("0123456789", 10);
2212 bufferptr
ptr2("abcdefghij", 10);
2213 bl
.append(ptr2
, 5, 5);
2215 bl
.splice(10, 4, &other
);
2216 EXPECT_EQ((unsigned)11, bl
.length());
2217 EXPECT_EQ(0, ::memcmp("fghi", other
.c_str(), other
.length()));
2221 TEST(BufferList
, write
) {
2222 std::ostringstream stream
;
2225 bl
.write(1, 2, stream
);
2226 EXPECT_EQ("BC", stream
.str());
2229 TEST(BufferList
, encode_base64
) {
2233 bl
.encode_base64(other
);
2234 const char *expected
= "QUJDRA==";
2235 EXPECT_EQ(0, ::memcmp(expected
, other
.c_str(), strlen(expected
)));
2238 TEST(BufferList
, decode_base64
) {
2240 bl
.append("QUJDRA==");
2242 other
.decode_base64(bl
);
2243 const char *expected
= "ABCD";
2244 EXPECT_EQ(0, ::memcmp(expected
, other
.c_str(), strlen(expected
)));
2245 bufferlist malformed
;
2246 malformed
.append("QUJDRA");
2247 EXPECT_THROW(other
.decode_base64(malformed
), buffer::malformed_input
);
2250 TEST(BufferList
, hexdump
) {
2252 std::ostringstream stream
;
2253 bl
.append("013245678901234\0006789012345678901234", 32);
2255 EXPECT_EQ("00000000 30 31 33 32 34 35 36 37 38 39 30 31 32 33 34 00 |013245678901234.|\n"
2256 "00000010 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 |6789012345678901|\n"
2261 TEST(BufferList
, read_file
) {
2265 EXPECT_EQ(-ENOENT
, bl
.read_file("UNLIKELY", &error
));
2266 snprintf(cmd
, sizeof(cmd
), "echo ABC > %s ; chmod 0 %s", FILENAME
, FILENAME
);
2267 EXPECT_EQ(0, ::system(cmd
));
2268 if (getuid() != 0) {
2269 EXPECT_EQ(-EACCES
, bl
.read_file(FILENAME
, &error
));
2271 snprintf(cmd
, sizeof(cmd
), "chmod +r %s", FILENAME
);
2272 EXPECT_EQ(0, ::system(cmd
));
2273 EXPECT_EQ(0, bl
.read_file(FILENAME
, &error
));
2275 EXPECT_EQ((unsigned)4, bl
.length());
2276 std::string
actual(bl
.c_str(), bl
.length());
2277 EXPECT_EQ("ABC\n", actual
);
2280 TEST(BufferList
, read_fd
) {
2283 snprintf(cmd
, sizeof(cmd
), "echo ABC > %s", FILENAME
);
2284 EXPECT_EQ(0, ::system(cmd
));
2287 EXPECT_EQ(-EBADF
, bl
.read_fd(fd
, len
));
2288 fd
= ::open(FILENAME
, O_RDONLY
);
2290 EXPECT_EQ(len
, (unsigned)bl
.read_fd(fd
, len
));
2291 //EXPECT_EQ(CEPH_BUFFER_APPEND_SIZE - len, bl.front().unused_tail_length());
2292 EXPECT_EQ(len
, bl
.length());
2297 TEST(BufferList
, write_file
) {
2301 EXPECT_EQ(-ENOENT
, bl
.write_file("un/like/ly", mode
));
2303 EXPECT_EQ(0, bl
.write_file(FILENAME
, mode
));
2305 memset(&st
, 0, sizeof(st
));
2306 ASSERT_EQ(0, ::stat(FILENAME
, &st
));
2307 EXPECT_EQ((unsigned)(mode
| S_IFREG
), st
.st_mode
);
2311 TEST(BufferList
, write_fd
) {
2313 int fd
= ::open(FILENAME
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0600);
2316 for (unsigned i
= 0; i
< IOV_MAX
* 2; i
++) {
2317 bufferptr
ptr("A", 1);
2320 EXPECT_EQ(0, bl
.write_fd(fd
));
2323 memset(&st
, 0, sizeof(st
));
2324 ASSERT_EQ(0, ::stat(FILENAME
, &st
));
2325 EXPECT_EQ(IOV_MAX
* 2, st
.st_size
);
2329 TEST(BufferList
, write_fd_offset
) {
2331 int fd
= ::open(FILENAME
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0600);
2334 for (unsigned i
= 0; i
< IOV_MAX
* 2; i
++) {
2335 bufferptr
ptr("A", 1);
2338 uint64_t offset
= 200;
2339 EXPECT_EQ(0, bl
.write_fd(fd
, offset
));
2342 memset(&st
, 0, sizeof(st
));
2343 ASSERT_EQ(0, ::stat(FILENAME
, &st
));
2344 EXPECT_EQ(IOV_MAX
* 2 + offset
, (unsigned)st
.st_size
);
2348 TEST(BufferList
, crc32c
) {
2352 crc
= bl
.crc32c(crc
);
2353 EXPECT_EQ((unsigned)0xB3109EBF, crc
);
2354 crc
= bl
.crc32c(crc
);
2355 EXPECT_EQ((unsigned)0x5FA5C0CC, crc
);
2358 TEST(BufferList
, crc32c_append
) {
2362 for (int j
= 0; j
< 200; ++j
) {
2364 for (int i
= 0; i
< 200; ++i
) {
2369 bl
.crc32c(rand()); // mess with the cached bufferptr crc values
2372 ASSERT_EQ(bl1
.crc32c(0), bl2
.crc32c(0));
2375 TEST(BufferList
, crc32c_zeros
) {
2376 char buffer
[4*1024];
2377 for (size_t i
=0; i
< sizeof(buffer
); i
++)
2385 for (size_t j
=0; j
< 1000; j
++)
2387 bufferptr
a(buffer
, sizeof(buffer
));
2390 uint32_t crca
= bla
.crc32c(111);
2393 uint32_t crcb
= ceph_crc32c(111, (unsigned char*)blb
.c_str(), blb
.length());
2395 EXPECT_EQ(crca
, crcb
);
2399 TEST(BufferList
, crc32c_append_perf
) {
2400 int len
= 256 * 1024 * 1024;
2405 std::cout
<< "populating large buffers (a, b=c=d)" << std::endl
;
2406 char *pa
= a
.c_str();
2407 char *pb
= b
.c_str();
2408 char *pc
= c
.c_str();
2409 char *pd
= c
.c_str();
2410 for (int i
=0; i
<len
; i
++) {
2411 pa
[i
] = (i
& 0xff) ^ 73;
2412 pb
[i
] = (i
& 0xff) ^ 123;
2413 pc
[i
] = (i
& 0xff) ^ 123;
2414 pd
[i
] = (i
& 0xff) ^ 123;
2417 // track usage of cached crcs
2418 buffer::track_cached_crc(true);
2420 [[maybe_unused
]] int base_cached
= buffer::get_cached_crc();
2421 [[maybe_unused
]] int base_cached_adjusted
= buffer::get_cached_crc_adjusted();
2428 utime_t start
= ceph_clock_now();
2429 uint32_t r
= bla
.crc32c(0);
2430 utime_t end
= ceph_clock_now();
2431 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2432 std::cout
<< "a.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2433 ASSERT_EQ(r
, 1138817026u);
2435 ceph_assert(buffer::get_cached_crc() == 0 + base_cached
);
2437 utime_t start
= ceph_clock_now();
2438 uint32_t r
= bla
.crc32c(0);
2439 utime_t end
= ceph_clock_now();
2440 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2441 std::cout
<< "a.crc32c(0) (again) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2442 ASSERT_EQ(r
, 1138817026u);
2444 ceph_assert(buffer::get_cached_crc() == 1 + base_cached
);
2447 utime_t start
= ceph_clock_now();
2448 uint32_t r
= bla
.crc32c(5);
2449 utime_t end
= ceph_clock_now();
2450 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2451 std::cout
<< "a.crc32c(5) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2452 ASSERT_EQ(r
, 3239494520u);
2454 ceph_assert(buffer::get_cached_crc() == 1 + base_cached
);
2455 ceph_assert(buffer::get_cached_crc_adjusted() == 1 + base_cached_adjusted
);
2457 utime_t start
= ceph_clock_now();
2458 uint32_t r
= bla
.crc32c(5);
2459 utime_t end
= ceph_clock_now();
2460 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2461 std::cout
<< "a.crc32c(5) (again) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2462 ASSERT_EQ(r
, 3239494520u);
2464 ceph_assert(buffer::get_cached_crc() == 1 + base_cached
);
2465 ceph_assert(buffer::get_cached_crc_adjusted() == 2 + base_cached_adjusted
);
2467 utime_t start
= ceph_clock_now();
2468 uint32_t r
= blb
.crc32c(0);
2469 utime_t end
= ceph_clock_now();
2470 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2471 std::cout
<< "b.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2472 ASSERT_EQ(r
, 2481791210u);
2474 ceph_assert(buffer::get_cached_crc() == 1 + base_cached
);
2476 utime_t start
= ceph_clock_now();
2477 uint32_t r
= blb
.crc32c(0);
2478 utime_t end
= ceph_clock_now();
2479 float rate
= (float)len
/ (float)(1024*1024) / (float)(end
- start
);
2480 std::cout
<< "b.crc32c(0) (again)= " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2481 ASSERT_EQ(r
, 2481791210u);
2483 ceph_assert(buffer::get_cached_crc() == 2 + base_cached
);
2489 utime_t start
= ceph_clock_now();
2490 uint32_t r
= ab
.crc32c(0);
2491 utime_t end
= ceph_clock_now();
2492 float rate
= (float)ab
.length() / (float)(1024*1024) / (float)(end
- start
);
2493 std::cout
<< "ab.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2494 ASSERT_EQ(r
, 2988268779u);
2496 ceph_assert(buffer::get_cached_crc() == 3 + base_cached
);
2497 ceph_assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted
);
2502 utime_t start
= ceph_clock_now();
2503 uint32_t r
= ac
.crc32c(0);
2504 utime_t end
= ceph_clock_now();
2505 float rate
= (float)ac
.length() / (float)(1024*1024) / (float)(end
- start
);
2506 std::cout
<< "ac.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2507 ASSERT_EQ(r
, 2988268779u);
2509 ceph_assert(buffer::get_cached_crc() == 4 + base_cached
);
2510 ceph_assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted
);
2516 utime_t start
= ceph_clock_now();
2517 uint32_t r
= ba
.crc32c(0);
2518 utime_t end
= ceph_clock_now();
2519 float rate
= (float)ba
.length() / (float)(1024*1024) / (float)(end
- start
);
2520 std::cout
<< "ba.crc32c(0) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2521 ASSERT_EQ(r
, 169240695u);
2523 ceph_assert(buffer::get_cached_crc() == 5 + base_cached
);
2524 ceph_assert(buffer::get_cached_crc_adjusted() == 4 + base_cached_adjusted
);
2526 utime_t start
= ceph_clock_now();
2527 uint32_t r
= ba
.crc32c(5);
2528 utime_t end
= ceph_clock_now();
2529 float rate
= (float)ba
.length() / (float)(1024*1024) / (float)(end
- start
);
2530 std::cout
<< "ba.crc32c(5) = " << r
<< " at " << rate
<< " MB/sec" << std::endl
;
2531 ASSERT_EQ(r
, 1265464778u);
2533 ceph_assert(buffer::get_cached_crc() == 5 + base_cached
);
2534 ceph_assert(buffer::get_cached_crc_adjusted() == 6 + base_cached_adjusted
);
2536 cout
<< "crc cache hits (same start) = " << buffer::get_cached_crc() << std::endl
;
2537 cout
<< "crc cache hits (adjusted) = " << buffer::get_cached_crc_adjusted() << std::endl
;
2540 TEST(BufferList
, compare
) {
2548 // bool operator>(bufferlist& l, bufferlist& r)
2550 ASSERT_FALSE(a
> ab
);
2551 ASSERT_TRUE(ab
> a
);
2552 ASSERT_TRUE(ac
> ab
);
2553 ASSERT_FALSE(ab
> ac
);
2554 ASSERT_FALSE(ab
> ab
);
2556 // bool operator>=(bufferlist& l, bufferlist& r)
2558 ASSERT_FALSE(a
>= ab
);
2559 ASSERT_TRUE(ab
>= a
);
2560 ASSERT_TRUE(ac
>= ab
);
2561 ASSERT_FALSE(ab
>= ac
);
2562 ASSERT_TRUE(ab
>= ab
);
2564 // bool operator<(bufferlist& l, bufferlist& r)
2566 ASSERT_TRUE(a
< ab
);
2567 ASSERT_FALSE(ab
< a
);
2568 ASSERT_FALSE(ac
< ab
);
2569 ASSERT_TRUE(ab
< ac
);
2570 ASSERT_FALSE(ab
< ab
);
2572 // bool operator<=(bufferlist& l, bufferlist& r)
2574 ASSERT_TRUE(a
<= ab
);
2575 ASSERT_FALSE(ab
<= a
);
2576 ASSERT_FALSE(ac
<= ab
);
2577 ASSERT_TRUE(ab
<= ac
);
2578 ASSERT_TRUE(ab
<= ab
);
2580 // bool operator==(bufferlist &l, bufferlist &r)
2582 ASSERT_FALSE(a
== ab
);
2583 ASSERT_FALSE(ac
== ab
);
2584 ASSERT_TRUE(ab
== ab
);
2587 TEST(BufferList
, ostream
) {
2588 std::ostringstream stream
;
2594 for (unsigned i
= 0; i
< 2; i
++) {
2595 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2599 std::cerr
<< stream
.str() << std::endl
;
2600 EXPECT_GT(stream
.str().size(), stream
.str().find("list(len=6,"));
2601 EXPECT_GT(stream
.str().size(), stream
.str().find("len 3 nref 1),\n"));
2602 EXPECT_GT(stream
.str().size(), stream
.str().find("len 3 nref 1)\n"));
2605 TEST(BufferList
, zero
) {
2612 EXPECT_EQ('A', bl
[0]);
2614 EXPECT_EQ('\0', bl
[0]);
2617 // void zero(unsigned o, unsigned l)
2627 bufferptr
ptr(s
[0], strlen(s
[0]));
2629 bl
.zero((unsigned)0, (unsigned)1);
2630 EXPECT_EQ(0, ::memcmp("\0BC", bl
.c_str(), 3));
2634 for (unsigned i
= 0; i
< 4; i
++) {
2635 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2639 PrCtl unset_dumpable
;
2640 EXPECT_DEATH(bl
.zero((unsigned)0, (unsigned)2000), "");
2642 bl
.zero((unsigned)2, (unsigned)5);
2643 EXPECT_EQ(0, ::memcmp("AB\0\0\0\0\0HIKLM", bl
.c_str(), 9));
2647 for (unsigned i
= 0; i
< 4; i
++) {
2648 bufferptr
ptr(s
[i
], strlen(s
[i
]));
2651 bl
.zero((unsigned)3, (unsigned)3);
2652 EXPECT_EQ(0, ::memcmp("ABC\0\0\0GHIKLM", bl
.c_str(), 9));
2658 memset(ptr1
.c_str(), 'a', 4);
2659 memset(ptr2
.c_str(), 'b', 4);
2662 bl
.zero((unsigned)2, (unsigned)4);
2663 EXPECT_EQ(0, ::memcmp("aa\0\0\0\0bb", bl
.c_str(), 8));
2667 TEST(BufferList
, EmptyAppend
) {
2671 ASSERT_EQ(bl
.begin().end(), 1);
2674 TEST(BufferList
, InternalCarriage
) {
2675 ceph::bufferlist bl
;
2676 EXPECT_EQ(bl
.get_num_buffers(), 0u);
2678 encode(int64_t(42), bl
);
2679 EXPECT_EQ(bl
.get_num_buffers(), 1u);
2682 ceph::bufferlist bl_with_foo
;
2683 bl_with_foo
.append("foo", 3);
2684 EXPECT_EQ(bl_with_foo
.length(), 3u);
2685 EXPECT_EQ(bl_with_foo
.get_num_buffers(), 1u);
2687 bl
.append(bl_with_foo
);
2688 EXPECT_EQ(bl
.get_num_buffers(), 2u);
2691 encode(int64_t(24), bl
);
2692 EXPECT_EQ(bl
.get_num_buffers(), 3u);
2695 TEST(BufferList
, ContiguousAppender
) {
2696 ceph::bufferlist bl
;
2697 EXPECT_EQ(bl
.get_num_buffers(), 0u);
2699 // we expect a flush in ~contiguous_appender
2701 auto ap
= bl
.get_contiguous_appender(100);
2703 denc(int64_t(42), ap
);
2704 EXPECT_EQ(bl
.get_num_buffers(), 1u);
2706 // append bufferlist with single ptr inside. This should
2707 // commit changes to bl::_len and the underlying bp::len.
2709 ceph::bufferlist bl_with_foo
;
2710 bl_with_foo
.append("foo", 3);
2711 EXPECT_EQ(bl_with_foo
.length(), 3u);
2712 EXPECT_EQ(bl_with_foo
.get_num_buffers(), 1u);
2714 ap
.append(bl_with_foo
);
2715 // 3 as the ap::append(const bl&) splits the bp with free
2717 EXPECT_EQ(bl
.get_num_buffers(), 3u);
2720 denc(int64_t(24), ap
);
2721 EXPECT_EQ(bl
.get_num_buffers(), 3u);
2722 EXPECT_EQ(bl
.length(), sizeof(int64_t) + 3u);
2724 EXPECT_EQ(bl
.length(), 2u * sizeof(int64_t) + 3u);
2727 TEST(BufferList
, TestPtrAppend
) {
2729 char correct
[MAX_TEST
];
2731 int length
= random() % 5 > 0 ? random() % 1000 : 0;
2732 while (curpos
+ length
< MAX_TEST
) {
2737 char *current
= correct
+ curpos
;
2738 for (int i
= 0; i
< length
; ++i
) {
2739 char next
= random() % 255;
2740 correct
[curpos
++] = next
;
2742 bufferptr
ptr(current
, length
);
2745 length
= random() % 5 > 0 ? random() % 1000 : 0;
2747 ASSERT_EQ(memcmp(bl
.c_str(), correct
, curpos
), 0);
2750 TEST(BufferList
, TestDirectAppend
) {
2752 char correct
[MAX_TEST
];
2754 int length
= random() % 5 > 0 ? random() % 1000 : 0;
2755 while (curpos
+ length
< MAX_TEST
) {
2756 char *current
= correct
+ curpos
;
2757 for (int i
= 0; i
< length
; ++i
) {
2758 char next
= random() % 255;
2759 correct
[curpos
++] = next
;
2761 bl
.append(current
, length
);
2762 length
= random() % 5 > 0 ? random() % 1000 : 0;
2764 ASSERT_EQ(memcmp(bl
.c_str(), correct
, curpos
), 0);
2767 TEST(BufferList
, TestCopyAll
) {
2768 const static size_t BIG_SZ
= 10737414;
2769 std::shared_ptr
<unsigned char> big(
2770 (unsigned char*)malloc(BIG_SZ
), free
);
2771 unsigned char c
= 0;
2772 for (size_t i
= 0; i
< BIG_SZ
; ++i
) {
2776 bl
.append((const char*)big
.get(), BIG_SZ
);
2777 bufferlist::iterator i
= bl
.begin();
2780 ASSERT_EQ(bl2
.length(), BIG_SZ
);
2781 std::shared_ptr
<unsigned char> big2(
2782 (unsigned char*)malloc(BIG_SZ
), free
);
2783 bl2
.begin().copy(BIG_SZ
, (char*)big2
.get());
2784 ASSERT_EQ(memcmp(big
.get(), big2
.get(), BIG_SZ
), 0);
2787 TEST(BufferList
, InvalidateCrc
) {
2788 const static size_t buffer_size
= 262144;
2789 std::shared_ptr
<unsigned char> big(
2790 (unsigned char*)malloc(buffer_size
), free
);
2791 unsigned char c
= 0;
2792 char* ptr
= (char*) big
.get();
2794 for (size_t i
= 0; i
< buffer_size
; ++i
) {
2799 // test for crashes (shouldn't crash)
2800 bl
.invalidate_crc();
2802 // put data into bufferlist
2803 bl
.append((const char*)big
.get(), buffer_size
);
2806 __u32 crc
= bl
.crc32c(0);
2808 // modify data in bl without its knowledge
2809 inptr
= (char*) bl
.c_str();
2811 for (size_t i
= 0; i
< buffer_size
; ++i
) {
2815 // make sure data in bl are now different than in big
2816 EXPECT_NE(memcmp((void*) ptr
, (void*) inptr
, buffer_size
), 0);
2818 // crc should remain the same
2819 __u32 new_crc
= bl
.crc32c(0);
2820 EXPECT_EQ(crc
, new_crc
);
2822 // force crc invalidate, check if it is updated
2823 bl
.invalidate_crc();
2824 EXPECT_NE(crc
, bl
.crc32c(0));
2827 TEST(BufferList
, TestIsProvidedBuffer
) {
2830 bl
.push_back(buffer::create_static(100, buff
));
2831 ASSERT_TRUE(bl
.is_provided_buffer(buff
));
2832 bl
.append_zero(100);
2833 ASSERT_FALSE(bl
.is_provided_buffer(buff
));
2836 TEST(BufferList
, DISABLED_DanglingLastP
) {
2839 // previously we're using the unsharable buffer type to distinguish
2840 // the last_p-specific problem from the generic crosstalk issues we
2841 // had since the very beginning:
2842 // https://gist.github.com/rzarzynski/aed18372e88aed392101adac3bd87bbc
2843 // this is no longer possible as `buffer::create_unsharable()` has
2845 bufferptr
bp(buffer::create(10));
2846 bp
.copy_in(0, 3, "XXX");
2847 bl
.push_back(std::move(bp
));
2848 EXPECT_EQ(0, ::memcmp("XXX", bl
.c_str(), 3));
2850 // let `copy_in` to set `last_p` member of bufferlist
2851 bl
.begin().copy_in(2, "AB");
2852 EXPECT_EQ(0, ::memcmp("ABX", bl
.c_str(), 3));
2856 // before the fix this would have left `last_p` unchanged leading to
2857 // the dangerous dangling state – keep in mind that the initial,
2858 // unsharable bptr will be freed.
2859 bl
= const_cast<const bufferlist
&>(empty
);
2862 // we must continue from where the previous copy_in had finished.
2863 // Otherwise `bl::copy_in` will call `seek()` and refresh `last_p`.
2864 bl
.begin(2).copy_in(1, "C");
2865 EXPECT_EQ(0, ::memcmp("12C", bl
.c_str(), 3));
2868 TEST(BufferHash
, all
) {
2873 EXPECT_EQ((unsigned)0, hash
.digest());
2875 EXPECT_EQ((unsigned)0xB3109EBF, hash
.digest());
2877 EXPECT_EQ((unsigned)0x5FA5C0CC, hash
.digest());
2883 EXPECT_EQ((unsigned)0, hash
.digest());
2884 bufferhash
& returned_hash
= hash
<< bl
;
2885 EXPECT_EQ(&returned_hash
, &hash
);
2886 EXPECT_EQ((unsigned)0xB3109EBF, hash
.digest());
2892 * compile-command: "cd .. ; make unittest_bufferlist &&
2893 * ulimit -s unlimited ; valgrind \
2894 * --max-stackframe=20000000 --tool=memcheck \
2895 * ./unittest_bufferlist # --gtest_filter=BufferList.constructors"